ThreadedRenderer.java revision 04fc583c3dd3144bc6b718fcac4b3e1afdfdb067
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 // TODO: 117 return false; 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 nDestroyCanvas(long nativeProxy); 260 261 private static native void nAttachFunctor(long nativeProxy, long functor); 262 private static native void nDetachFunctor(long nativeProxy, long functor); 263} 264