OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.content.browser; | 5 package org.chromium.content.browser; |
6 | 6 |
7 import android.content.Context; | 7 import android.content.Context; |
8 import android.graphics.Bitmap; | 8 import android.graphics.Bitmap; |
9 import android.graphics.Canvas; | 9 import android.graphics.Canvas; |
10 import android.graphics.Color; | 10 import android.graphics.Color; |
11 import android.graphics.PixelFormat; | 11 import android.graphics.PixelFormat; |
12 import android.os.Build; | |
13 import android.os.Handler; | 12 import android.os.Handler; |
14 import android.view.Surface; | 13 import android.view.Surface; |
15 import android.view.SurfaceHolder; | 14 import android.view.SurfaceHolder; |
16 import android.view.SurfaceView; | 15 import android.view.SurfaceView; |
17 import android.widget.FrameLayout; | 16 import android.widget.FrameLayout; |
18 | 17 |
19 import org.chromium.base.CalledByNative; | 18 import org.chromium.base.CalledByNative; |
20 import org.chromium.base.JNINamespace; | 19 import org.chromium.base.JNINamespace; |
21 import org.chromium.base.ObserverList; | |
22 import org.chromium.base.ObserverList.RewindableIterator; | |
23 import org.chromium.base.TraceEvent; | 20 import org.chromium.base.TraceEvent; |
24 import org.chromium.ui.base.WindowAndroid; | 21 import org.chromium.ui.base.WindowAndroid; |
25 | 22 |
26 /*** | 23 /*** |
27 * This view is used by a ContentView to render its content. | 24 * This view is used by a ContentView to render its content. |
28 * Call {@link #setCurrentContentViewCore(ContentViewCore)} with the contentView Core that should be | 25 * Call {@link #setCurrentContentViewCore(ContentViewCore)} with the contentView Core that should be |
29 * managing the view. | 26 * managing the view. |
30 * Note that only one ContentViewCore can be shown at a time. | 27 * Note that only one ContentViewCore can be shown at a time. |
31 */ | 28 */ |
32 @JNINamespace("content") | 29 @JNINamespace("content") |
33 public class ContentViewRenderView extends FrameLayout { | 30 public class ContentViewRenderView extends FrameLayout implements WindowAndroid. VSyncClient { |
David Trainor- moved to gerrit
2014/04/16 06:18:20
Indent +8
no sievers
2014/04/25 22:23:33
there's actually no line break here :)
| |
34 private static final int MAX_SWAP_BUFFER_COUNT = 2; | 31 private static final int MAX_SWAP_BUFFER_COUNT = 2; |
35 | 32 |
36 // The native side of this object. | 33 // The native side of this object. |
37 private long mNativeContentViewRenderView; | 34 private long mNativeContentViewRenderView; |
38 private final SurfaceHolder.Callback mSurfaceCallback; | 35 private final SurfaceHolder.Callback mSurfaceCallback; |
39 | 36 |
40 private final SurfaceView mSurfaceView; | 37 private final SurfaceView mSurfaceView; |
41 private final VSyncAdapter mVSyncAdapter; | 38 private final WindowAndroid mRootWindow; |
42 | 39 |
43 private int mPendingRenders; | 40 private int mPendingRenders; |
44 private int mPendingSwapBuffers; | 41 private int mPendingSwapBuffers; |
45 private boolean mNeedToRender; | 42 private boolean mNeedToRender; |
46 | 43 |
47 private ContentViewCore mContentViewCore; | 44 private ContentViewCore mContentViewCore; |
48 | 45 |
49 private final Runnable mRenderRunnable = new Runnable() { | 46 private final Runnable mRenderRunnable = new Runnable() { |
50 @Override | 47 @Override |
51 public void run() { | 48 public void run() { |
52 render(); | 49 render(); |
53 } | 50 } |
54 }; | 51 }; |
55 | 52 |
56 /** | 53 /** |
57 * Constructs a new ContentViewRenderView that should be can to a view hiera rchy. | 54 * Constructs a new ContentViewRenderView that should be can to a view hiera rchy. |
58 * Native code should add/remove the layers to be rendered through the Conte ntViewLayerRenderer. | 55 * Native code should add/remove the layers to be rendered through the Conte ntViewLayerRenderer. |
59 * @param context The context used to create this. | 56 * @param context The context used to create this. |
60 */ | 57 */ |
61 public ContentViewRenderView(Context context, WindowAndroid rootWindow) { | 58 public ContentViewRenderView(Context context, WindowAndroid rootWindow) { |
62 super(context); | 59 super(context); |
63 assert rootWindow != null; | 60 assert rootWindow != null; |
64 mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer()) ; | 61 mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer()) ; |
65 assert mNativeContentViewRenderView != 0; | 62 assert mNativeContentViewRenderView != 0; |
66 | 63 |
64 mRootWindow = rootWindow; | |
65 rootWindow.setVSyncClient(this); | |
67 mSurfaceView = createSurfaceView(getContext()); | 66 mSurfaceView = createSurfaceView(getContext()); |
68 mSurfaceView.setZOrderMediaOverlay(true); | 67 mSurfaceView.setZOrderMediaOverlay(true); |
69 mSurfaceCallback = new SurfaceHolder.Callback() { | 68 mSurfaceCallback = new SurfaceHolder.Callback() { |
70 @Override | 69 @Override |
71 public void surfaceChanged(SurfaceHolder holder, int format, int wid th, int height) { | 70 public void surfaceChanged(SurfaceHolder holder, int format, int wid th, int height) { |
72 assert mNativeContentViewRenderView != 0; | 71 assert mNativeContentViewRenderView != 0; |
73 nativeSurfaceChanged(mNativeContentViewRenderView, | 72 nativeSurfaceChanged(mNativeContentViewRenderView, |
74 format, width, height, holder.getSurface()); | 73 format, width, height, holder.getSurface()); |
75 if (mContentViewCore != null) { | 74 if (mContentViewCore != null) { |
76 mContentViewCore.onPhysicalBackingSizeChanged( | 75 mContentViewCore.onPhysicalBackingSizeChanged( |
(...skipping 15 matching lines...) Expand all Loading... | |
92 } | 91 } |
93 | 92 |
94 @Override | 93 @Override |
95 public void surfaceDestroyed(SurfaceHolder holder) { | 94 public void surfaceDestroyed(SurfaceHolder holder) { |
96 assert mNativeContentViewRenderView != 0; | 95 assert mNativeContentViewRenderView != 0; |
97 nativeSurfaceDestroyed(mNativeContentViewRenderView); | 96 nativeSurfaceDestroyed(mNativeContentViewRenderView); |
98 } | 97 } |
99 }; | 98 }; |
100 mSurfaceView.getHolder().addCallback(mSurfaceCallback); | 99 mSurfaceView.getHolder().addCallback(mSurfaceCallback); |
101 | 100 |
102 mVSyncAdapter = new VSyncAdapter(getContext()); | |
103 addView(mSurfaceView, | 101 addView(mSurfaceView, |
104 new FrameLayout.LayoutParams( | 102 new FrameLayout.LayoutParams( |
105 FrameLayout.LayoutParams.MATCH_PARENT, | 103 FrameLayout.LayoutParams.MATCH_PARENT, |
106 FrameLayout.LayoutParams.MATCH_PARENT)); | 104 FrameLayout.LayoutParams.MATCH_PARENT)); |
107 } | 105 } |
108 | 106 |
109 private class VSyncAdapter implements VSyncManager.Provider, VSyncMonitor.Li stener { | 107 @Override |
110 private final VSyncMonitor mVSyncMonitor; | 108 public void onVSync(long vsyncTimeMicros) { |
111 private boolean mVSyncNotificationEnabled; | 109 if (mNeedToRender) { |
112 private VSyncManager.Listener mVSyncListener; | 110 if (mPendingSwapBuffers + mPendingRenders <= MAX_SWAP_BUFFER_COUNT) { |
113 private final ObserverList<VSyncManager.Listener> mCurrentVSyncListeners ; | 111 mNeedToRender = false; |
114 private final RewindableIterator<VSyncManager.Listener> mCurrentVSyncLis tenersIterator; | 112 mPendingRenders++; |
115 | 113 render(); |
116 // The VSyncMonitor gives the timebase for the actual vsync, but we don' t want render until | 114 } else { |
117 // we have had a chance for input events to propagate to the compositor thread. This takes | 115 TraceEvent.instant("ContentViewRenderView:bail"); |
118 // 3 ms typically, so we adjust the vsync timestamps forward by a bit to give input events a | |
119 // chance to arrive. | |
120 private static final long INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS = 3200 ; | |
Sami
2014/04/16 17:26:54
Should probably verify with a trace, but does the
no sievers
2014/04/25 22:23:33
I thought that the deadline scheduler and retroact
| |
121 | |
122 VSyncAdapter(Context context) { | |
123 mVSyncMonitor = new VSyncMonitor(context, this); | |
124 mCurrentVSyncListeners = new ObserverList<VSyncManager.Listener>(); | |
125 mCurrentVSyncListenersIterator = mCurrentVSyncListeners.rewindableIt erator(); | |
126 } | 116 } |
127 | 117 } |
128 @Override | |
129 public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) { | |
130 if (mNeedToRender) { | |
131 if (mPendingSwapBuffers + mPendingRenders <= MAX_SWAP_BUFFER_COU NT) { | |
132 mNeedToRender = false; | |
133 mPendingRenders++; | |
134 render(); | |
135 } else { | |
136 TraceEvent.instant("ContentViewRenderView:bail"); | |
137 } | |
138 } | |
139 | |
140 if (mVSyncListener != null) { | |
141 if (mVSyncNotificationEnabled) { | |
142 for (mCurrentVSyncListenersIterator.rewind(); | |
143 mCurrentVSyncListenersIterator.hasNext();) { | |
144 mCurrentVSyncListenersIterator.next().onVSync(vsyncTimeM icros); | |
145 } | |
146 mVSyncMonitor.requestUpdate(); | |
147 } else { | |
148 // Compensate for input event lag. Input events are delivere d immediately on | |
149 // pre-JB releases, so this adjustment is only done for late r versions. | |
150 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { | |
151 vsyncTimeMicros += INPUT_EVENT_LAG_FROM_VSYNC_MICROSECON DS; | |
152 } | |
153 mVSyncListener.updateVSync(vsyncTimeMicros, | |
154 mVSyncMonitor.getVSyncPeriodInMicroseconds()); | |
155 } | |
156 } | |
157 } | |
158 | |
159 @Override | |
160 public void registerVSyncListener(VSyncManager.Listener listener) { | |
161 if (!mVSyncNotificationEnabled) mVSyncMonitor.requestUpdate(); | |
162 mCurrentVSyncListeners.addObserver(listener); | |
163 mVSyncNotificationEnabled = true; | |
164 } | |
165 | |
166 @Override | |
167 public void unregisterVSyncListener(VSyncManager.Listener listener) { | |
168 mCurrentVSyncListeners.removeObserver(listener); | |
169 if (mCurrentVSyncListeners.isEmpty()) { | |
170 mVSyncNotificationEnabled = false; | |
171 } | |
172 } | |
173 | |
174 void setVSyncListener(VSyncManager.Listener listener) { | |
175 mVSyncListener = listener; | |
176 if (mVSyncListener != null) mVSyncMonitor.requestUpdate(); | |
177 } | |
178 | |
179 void requestUpdate() { | |
180 mVSyncMonitor.requestUpdate(); | |
181 } | |
182 } | 118 } |
183 | 119 |
184 /** | 120 /** |
185 * Sets the background color of the surface view. This method is necessary because the | 121 * Sets the background color of the surface view. This method is necessary because the |
186 * background color of ContentViewRenderView itself is covered by the backgr ound of | 122 * background color of ContentViewRenderView itself is covered by the backgr ound of |
187 * SurfaceView. | 123 * SurfaceView. |
188 * @param color The color of the background. | 124 * @param color The color of the background. |
189 */ | 125 */ |
190 public void setSurfaceViewBackgroundColor(int color) { | 126 public void setSurfaceViewBackgroundColor(int color) { |
191 if (mSurfaceView != null) { | 127 if (mSurfaceView != null) { |
192 mSurfaceView.setBackgroundColor(color); | 128 mSurfaceView.setBackgroundColor(color); |
193 } | 129 } |
194 } | 130 } |
195 | 131 |
196 /** | 132 /** |
197 * Should be called when the ContentViewRenderView is not needed anymore so its associated | 133 * Should be called when the ContentViewRenderView is not needed anymore so its associated |
198 * native resource can be freed. | 134 * native resource can be freed. |
199 */ | 135 */ |
200 public void destroy() { | 136 public void destroy() { |
137 mRootWindow.setVSyncClient(null); | |
201 mSurfaceView.getHolder().removeCallback(mSurfaceCallback); | 138 mSurfaceView.getHolder().removeCallback(mSurfaceCallback); |
202 nativeDestroy(mNativeContentViewRenderView); | 139 nativeDestroy(mNativeContentViewRenderView); |
203 mNativeContentViewRenderView = 0; | 140 mNativeContentViewRenderView = 0; |
204 } | 141 } |
205 | 142 |
206 /** | 143 /** |
207 * Makes the passed ContentView the one displayed by this ContentViewRenderV iew. | 144 * Makes the passed ContentView the one displayed by this ContentViewRenderV iew. |
208 * TODO(yfriedman): Remove once this rolls downstream and callers are update d. | 145 * TODO(yfriedman): Remove once this rolls downstream and callers are update d. |
209 */ | 146 */ |
210 @Deprecated | 147 @Deprecated |
211 public void setCurrentContentView(ContentView contentView) { | 148 public void setCurrentContentView(ContentView contentView) { |
212 setCurrentContentViewCore(contentView != null ? contentView.getContentVi ewCore() : null); | 149 setCurrentContentViewCore(contentView != null ? contentView.getContentVi ewCore() : null); |
213 } | 150 } |
214 | 151 |
215 | 152 |
216 public void setCurrentContentViewCore(ContentViewCore contentViewCore) { | 153 public void setCurrentContentViewCore(ContentViewCore contentViewCore) { |
217 assert mNativeContentViewRenderView != 0; | 154 assert mNativeContentViewRenderView != 0; |
218 mContentViewCore = contentViewCore; | 155 mContentViewCore = contentViewCore; |
219 | 156 |
220 if (mContentViewCore != null) { | 157 if (mContentViewCore != null) { |
221 mContentViewCore.onPhysicalBackingSizeChanged(getWidth(), getHeight( )); | 158 mContentViewCore.onPhysicalBackingSizeChanged(getWidth(), getHeight( )); |
222 mVSyncAdapter.setVSyncListener(mContentViewCore.getVSyncListener(mVS yncAdapter)); | |
223 nativeSetCurrentContentViewCore(mNativeContentViewRenderView, | 159 nativeSetCurrentContentViewCore(mNativeContentViewRenderView, |
224 mContentViewCore.getNativeContentVie wCore()); | 160 mContentViewCore.getNativeContentVie wCore()); |
225 } else { | 161 } else { |
226 nativeSetCurrentContentViewCore(mNativeContentViewRenderView, 0); | 162 nativeSetCurrentContentViewCore(mNativeContentViewRenderView, 0); |
227 } | 163 } |
228 } | 164 } |
229 | 165 |
230 /** | 166 /** |
231 * This method should be subclassed to provide actions to be performed once the view is ready to | 167 * This method should be subclassed to provide actions to be performed once the view is ready to |
232 * render. | 168 * render. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 | 220 |
285 // The handler can be null if we are detached from the window. Call ing | 221 // The handler can be null if we are detached from the window. Call ing |
286 // {@link View#post(Runnable)} properly handles this case, but we lo se the front of | 222 // {@link View#post(Runnable)} properly handles this case, but we lo se the front of |
287 // queue behavior. That is okay for this edge case. | 223 // queue behavior. That is okay for this edge case. |
288 Handler handler = getHandler(); | 224 Handler handler = getHandler(); |
289 if (handler != null) { | 225 if (handler != null) { |
290 handler.postAtFrontOfQueue(mRenderRunnable); | 226 handler.postAtFrontOfQueue(mRenderRunnable); |
291 } else { | 227 } else { |
292 post(mRenderRunnable); | 228 post(mRenderRunnable); |
293 } | 229 } |
294 mVSyncAdapter.requestUpdate(); | |
295 } else if (mPendingRenders <= 0) { | 230 } else if (mPendingRenders <= 0) { |
296 assert mPendingRenders == 0; | 231 assert mPendingRenders == 0; |
297 TraceEvent.instant("requestRender:later"); | 232 TraceEvent.instant("requestRender:later"); |
298 mNeedToRender = true; | 233 mNeedToRender = true; |
299 mVSyncAdapter.requestUpdate(); | 234 mRootWindow.requestVSyncUpdate(); |
300 } | 235 } |
301 } | 236 } |
302 | 237 |
303 @CalledByNative | 238 @CalledByNative |
304 private void onSwapBuffersCompleted() { | 239 private void onSwapBuffersCompleted() { |
305 TraceEvent.instant("onSwapBuffersCompleted"); | 240 TraceEvent.instant("onSwapBuffersCompleted"); |
306 | 241 |
307 if (mPendingSwapBuffers == MAX_SWAP_BUFFER_COUNT && mNeedToRender) reque stRender(); | 242 if (mPendingSwapBuffers == MAX_SWAP_BUFFER_COUNT && mNeedToRender) reque stRender(); |
308 if (mPendingSwapBuffers > 0) mPendingSwapBuffers--; | 243 if (mPendingSwapBuffers > 0) mPendingSwapBuffers--; |
309 } | 244 } |
(...skipping 27 matching lines...) Expand all Loading... | |
337 long nativeContentViewCore); | 272 long nativeContentViewCore); |
338 private native void nativeSurfaceCreated(long nativeContentViewRenderView); | 273 private native void nativeSurfaceCreated(long nativeContentViewRenderView); |
339 private native void nativeSurfaceDestroyed(long nativeContentViewRenderView) ; | 274 private native void nativeSurfaceDestroyed(long nativeContentViewRenderView) ; |
340 private native void nativeSurfaceChanged(long nativeContentViewRenderView, | 275 private native void nativeSurfaceChanged(long nativeContentViewRenderView, |
341 int format, int width, int height, Surface surface); | 276 int format, int width, int height, Surface surface); |
342 private native boolean nativeComposite(long nativeContentViewRenderView); | 277 private native boolean nativeComposite(long nativeContentViewRenderView); |
343 private native boolean nativeCompositeToBitmap(long nativeContentViewRenderV iew, Bitmap bitmap); | 278 private native boolean nativeCompositeToBitmap(long nativeContentViewRenderV iew, Bitmap bitmap); |
344 private native void nativeSetOverlayVideoMode(long nativeContentViewRenderVi ew, | 279 private native void nativeSetOverlayVideoMode(long nativeContentViewRenderVi ew, |
345 boolean enabled); | 280 boolean enabled); |
346 } | 281 } |
OLD | NEW |