blob: 60d7c7877a96c9baa52c5fee0dc54a434e8620f7 [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.SystemClock;
23import android.os.Trace;
John Reckcec24ae2013-11-05 13:27:50 -080024import android.view.Surface.OutOfResourcesException;
25import android.view.View.AttachInfo;
26
27import java.io.PrintWriter;
John Reckcec24ae2013-11-05 13:27:50 -080028
29/**
30 * Hardware renderer that proxies the rendering to a render thread. Most calls
John Reck4f02bf42014-01-03 18:09:17 -080031 * are currently synchronous.
32 * TODO: Make draw() async.
33 * TODO: Figure out how to share the DisplayList between two threads (global lock?)
John Reckcec24ae2013-11-05 13:27:50 -080034 *
35 * The UI thread can block on the RenderThread, but RenderThread must never
36 * block on the UI thread.
37 *
John Reck4f02bf42014-01-03 18:09:17 -080038 * 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 *
John Reckcec24ae2013-11-05 13:27:50 -080042 * 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
John Reck4f02bf42014-01-03 18:09:17 -080053 private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1);
John Reckcec24ae2013-11-05 13:27:50 -080054
John Reckcec24ae2013-11-05 13:27:50 -080055 private int mWidth, mHeight;
John Reck4f02bf42014-01-03 18:09:17 -080056 private long mNativeProxy;
John Reckf7d9c1d2014-04-09 10:01:03 -070057 private boolean mInitialized = false;
John Reckbc0cc022014-04-11 16:08:14 -070058 private RenderNode mRootNode;
John Reckcec24ae2013-11-05 13:27:50 -080059
John Reck3dfe19f2013-12-13 14:25:19 -080060 ThreadedRenderer(boolean translucent) {
John Reck4f02bf42014-01-03 18:09:17 -080061 mNativeProxy = nCreateProxy(translucent);
John Reckbc0cc022014-04-11 16:08:14 -070062 mRootNode = RenderNode.create("RootNode");
63 mRootNode.setClipToBounds(false);
John Reckcec24ae2013-11-05 13:27:50 -080064 }
65
66 @Override
67 void destroy(boolean full) {
John Reckf7d9c1d2014-04-09 10:01:03 -070068 mInitialized = false;
69 updateEnabledState(null);
John Reckfae904d2014-04-14 11:01:57 -070070 nDestroyCanvasAndSurface(mNativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -080071 }
72
John Reckf7d9c1d2014-04-09 10:01:03 -070073 private void updateEnabledState(Surface surface) {
74 if (surface == null || !surface.isValid()) {
75 setEnabled(false);
76 } else {
77 setEnabled(mInitialized);
78 }
79 }
80
John Reckcec24ae2013-11-05 13:27:50 -080081 @Override
82 boolean initialize(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -070083 mInitialized = true;
84 updateEnabledState(surface);
John Reck4f02bf42014-01-03 18:09:17 -080085 return nInitialize(mNativeProxy, surface);
John Reckcec24ae2013-11-05 13:27:50 -080086 }
87
88 @Override
89 void updateSurface(Surface surface) throws OutOfResourcesException {
John Reckf7d9c1d2014-04-09 10:01:03 -070090 updateEnabledState(surface);
John Reck4f02bf42014-01-03 18:09:17 -080091 nUpdateSurface(mNativeProxy, surface);
John Reckcec24ae2013-11-05 13:27:50 -080092 }
93
94 @Override
John Reckf7d9c1d2014-04-09 10:01:03 -070095 void pauseSurface(Surface surface) {
96 nPauseSurface(mNativeProxy, surface);
97 }
98
99 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800100 void destroyHardwareResources(View view) {
John Reck4f02bf42014-01-03 18:09:17 -0800101 destroyResources(view);
102 // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
103 }
104
105 private static void destroyResources(View view) {
106 view.destroyHardwareResources();
107
108 if (view instanceof ViewGroup) {
109 ViewGroup group = (ViewGroup) view;
110
111 int count = group.getChildCount();
112 for (int i = 0; i < count; i++) {
113 destroyResources(group.getChildAt(i));
114 }
115 }
John Reckcec24ae2013-11-05 13:27:50 -0800116 }
117
118 @Override
119 void invalidate(Surface surface) {
John Reck4f02bf42014-01-03 18:09:17 -0800120 updateSurface(surface);
John Reckcec24ae2013-11-05 13:27:50 -0800121 }
122
123 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800124 boolean safelyRun(Runnable action) {
John Reckfc53ef272014-02-11 10:40:25 -0800125 nRunWithGlContext(mNativeProxy, action);
126 return true;
John Reckcec24ae2013-11-05 13:27:50 -0800127 }
128
129 @Override
130 void setup(int width, int height) {
131 mWidth = width;
132 mHeight = height;
John Reckbc0cc022014-04-11 16:08:14 -0700133 mRootNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
John Reck4f02bf42014-01-03 18:09:17 -0800134 nSetup(mNativeProxy, width, height);
John Reckcec24ae2013-11-05 13:27:50 -0800135 }
136
137 @Override
138 int getWidth() {
139 return mWidth;
140 }
141
142 @Override
143 int getHeight() {
144 return mHeight;
145 }
146
147 @Override
148 void dumpGfxInfo(PrintWriter pw) {
149 // TODO Auto-generated method stub
150 }
151
152 @Override
153 long getFrameCount() {
154 // TODO Auto-generated method stub
155 return 0;
156 }
157
158 @Override
159 boolean loadSystemProperties() {
John Reck4f02bf42014-01-03 18:09:17 -0800160 return false;
John Reckcec24ae2013-11-05 13:27:50 -0800161 }
162
John Reckcec24ae2013-11-05 13:27:50 -0800163 /**
164 * TODO: Remove
165 * Temporary hack to allow RenderThreadTest prototype app to trigger
166 * replaying a DisplayList after modifying the displaylist properties
167 *
168 * @hide */
169 public void repeatLastDraw() {
John Reckcec24ae2013-11-05 13:27:50 -0800170 }
171
John Reckbc0cc022014-04-11 16:08:14 -0700172 private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
John Reckcec24ae2013-11-05 13:27:50 -0800173 view.mPrivateFlags |= View.PFLAG_DRAWN;
174
175 view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
176 == View.PFLAG_INVALIDATED;
177 view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
178
179 Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
John Reckbc0cc022014-04-11 16:08:14 -0700180 HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
181 callbacks.onHardwarePostDraw(canvas);
182 canvas.drawDisplayList(view.getDisplayList());
183 callbacks.onHardwarePostDraw(canvas);
184 mRootNode.end(canvas);
John Reckcec24ae2013-11-05 13:27:50 -0800185 Trace.traceEnd(Trace.TRACE_TAG_VIEW);
186
187 view.mRecreateDisplayList = false;
John Reckbc0cc022014-04-11 16:08:14 -0700188 }
189
190 @Override
191 void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
192 attachInfo.mIgnoreDirtyState = true;
193 attachInfo.mDrawingTime = SystemClock.uptimeMillis();
194
195 updateRootDisplayList(view, callbacks);
John Reckcec24ae2013-11-05 13:27:50 -0800196
John Reck6313b922014-04-16 18:59:21 -0700197 attachInfo.mIgnoreDirtyState = false;
198
John Reck4f02bf42014-01-03 18:09:17 -0800199 if (dirty == null) {
200 dirty = NULL_RECT;
201 }
John Reckbc0cc022014-04-11 16:08:14 -0700202 nDrawDisplayList(mNativeProxy, mRootNode.getNativeDisplayList(),
John Reck4f02bf42014-01-03 18:09:17 -0800203 dirty.left, dirty.top, dirty.right, dirty.bottom);
John Reckcec24ae2013-11-05 13:27:50 -0800204 }
205
206 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000207 void detachFunctor(long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700208 // no-op, we never attach functors to need to detach them
John Reckcec24ae2013-11-05 13:27:50 -0800209 }
210
211 @Override
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000212 void attachFunctor(AttachInfo attachInfo, long functor) {
John Reckd3d8daf2014-04-10 15:00:13 -0700213 invokeFunctor(functor, true);
John Reckcec24ae2013-11-05 13:27:50 -0800214 }
215
216 @Override
John Reck0d1f6342014-03-28 20:30:27 -0700217 public void invokeFunctor(long functor, boolean waitForCompletion) {
218 nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
219 }
220
221 @Override
John Reck19b6bcf2014-02-14 20:03:38 -0800222 HardwareLayer createDisplayListLayer(int width, int height) {
223 long layer = nCreateDisplayListLayer(mNativeProxy, width, height);
224 return HardwareLayer.adoptDisplayListLayer(this, layer);
225 }
226
227 @Override
228 HardwareLayer createTextureLayer() {
229 long layer = nCreateTextureLayer(mNativeProxy);
230 return HardwareLayer.adoptTextureLayer(this, layer);
231 }
232
233 @Override
234 SurfaceTexture createSurfaceTexture(final HardwareLayer layer) {
235 final SurfaceTexture[] ret = new SurfaceTexture[1];
236 nRunWithGlContext(mNativeProxy, new Runnable() {
237 @Override
238 public void run() {
239 ret[0] = layer.createSurfaceTexture();
240 }
241 });
242 return ret[0];
243 }
244
245 @Override
246 boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) {
247 return nCopyLayerInto(mNativeProxy,
248 layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap);
249 }
250
251 @Override
252 void pushLayerUpdate(HardwareLayer layer) {
253 // TODO: Remove this, it's not needed outside of GLRenderer
254 }
255
256 @Override
257 void onLayerCreated(HardwareLayer layer) {
258 // TODO: Is this actually useful?
259 }
260
261 @Override
262 void flushLayerUpdates() {
263 // TODO: Figure out what this should do or remove it
264 }
265
266 @Override
267 void onLayerDestroyed(HardwareLayer layer) {
268 nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater());
269 }
270
271 @Override
John Reckcec24ae2013-11-05 13:27:50 -0800272 void setName(String name) {
John Reckcec24ae2013-11-05 13:27:50 -0800273 }
274
John Reck4f02bf42014-01-03 18:09:17 -0800275 @Override
John Reck28ad7b52014-04-07 16:59:25 -0700276 void fence() {
277 nFence(mNativeProxy);
278 }
279
280 @Override
John Reck4f02bf42014-01-03 18:09:17 -0800281 protected void finalize() throws Throwable {
282 try {
283 nDeleteProxy(mNativeProxy);
John Reck0ed751d2014-04-08 14:10:17 -0700284 mNativeProxy = 0;
John Reck4f02bf42014-01-03 18:09:17 -0800285 } finally {
286 super.finalize();
John Reckcec24ae2013-11-05 13:27:50 -0800287 }
288 }
289
290 /** @hide */
291 public static native void postToRenderThread(Runnable runnable);
John Reck4f02bf42014-01-03 18:09:17 -0800292
293 private static native long nCreateProxy(boolean translucent);
294 private static native void nDeleteProxy(long nativeProxy);
295
296 private static native boolean nInitialize(long nativeProxy, Surface window);
297 private static native void nUpdateSurface(long nativeProxy, Surface window);
John Reckf7d9c1d2014-04-09 10:01:03 -0700298 private static native void nPauseSurface(long nativeProxy, Surface window);
John Reck4f02bf42014-01-03 18:09:17 -0800299 private static native void nSetup(long nativeProxy, int width, int height);
John Reckbe34f2f2014-03-10 08:58:44 -0700300 private static native void nSetDisplayListData(long nativeProxy, long displayList,
John Reck44fd8d22014-02-26 11:00:11 -0800301 long newData);
John Reck4f02bf42014-01-03 18:09:17 -0800302 private static native void nDrawDisplayList(long nativeProxy, long displayList,
303 int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
John Reckfc53ef272014-02-11 10:40:25 -0800304 private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
John Reckfae904d2014-04-14 11:01:57 -0700305 private static native void nDestroyCanvasAndSurface(long nativeProxy);
John Reck4f02bf42014-01-03 18:09:17 -0800306
John Reck0d1f6342014-03-28 20:30:27 -0700307 private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
John Reck19b6bcf2014-02-14 20:03:38 -0800308
309 private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
310 private static native long nCreateTextureLayer(long nativeProxy);
311 private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap);
312 private static native void nDestroyLayer(long nativeProxy, long layer);
John Reck28ad7b52014-04-07 16:59:25 -0700313
314 private static native void nFence(long nativeProxy);
John Reckcec24ae2013-11-05 13:27:50 -0800315}