Chromium Code Reviews| 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 |