OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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.chrome.browser.compositor; | 5 package org.chromium.chrome.browser.compositor; |
6 | 6 |
7 import android.app.Activity; | 7 import android.app.Activity; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.graphics.Color; | 9 import android.graphics.Color; |
10 import android.graphics.PixelFormat; | 10 import android.graphics.PixelFormat; |
11 import android.graphics.Rect; | 11 import android.graphics.Rect; |
12 import android.graphics.drawable.Drawable; | |
12 import android.os.Build; | 13 import android.os.Build; |
13 import android.view.Display; | 14 import android.view.Display; |
14 import android.view.MotionEvent; | 15 import android.view.MotionEvent; |
15 import android.view.Surface; | 16 import android.view.Surface; |
16 import android.view.SurfaceHolder; | 17 import android.view.SurfaceHolder; |
17 import android.view.SurfaceView; | 18 import android.view.SurfaceView; |
18 import android.view.View; | 19 import android.view.View; |
20 import android.view.ViewGroup; | |
19 import android.view.WindowManager; | 21 import android.view.WindowManager; |
22 import android.widget.FrameLayout; | |
20 | 23 |
21 import org.chromium.base.CommandLine; | 24 import org.chromium.base.CommandLine; |
22 import org.chromium.base.Log; | 25 import org.chromium.base.Log; |
23 import org.chromium.base.TraceEvent; | 26 import org.chromium.base.TraceEvent; |
24 import org.chromium.base.VisibleForTesting; | 27 import org.chromium.base.VisibleForTesting; |
25 import org.chromium.base.annotations.CalledByNative; | 28 import org.chromium.base.annotations.CalledByNative; |
26 import org.chromium.base.annotations.JNINamespace; | 29 import org.chromium.base.annotations.JNINamespace; |
27 import org.chromium.chrome.browser.ChromeSwitches; | 30 import org.chromium.chrome.browser.ChromeSwitches; |
28 import org.chromium.chrome.browser.compositor.layouts.Layout; | 31 import org.chromium.chrome.browser.compositor.layouts.Layout; |
29 import org.chromium.chrome.browser.compositor.layouts.LayoutProvider; | 32 import org.chromium.chrome.browser.compositor.layouts.LayoutProvider; |
(...skipping 10 matching lines...) Expand all Loading... | |
40 import org.chromium.ui.base.DeviceFormFactor; | 43 import org.chromium.ui.base.DeviceFormFactor; |
41 import org.chromium.ui.base.WindowAndroid; | 44 import org.chromium.ui.base.WindowAndroid; |
42 import org.chromium.ui.resources.AndroidResourceType; | 45 import org.chromium.ui.resources.AndroidResourceType; |
43 import org.chromium.ui.resources.ResourceManager; | 46 import org.chromium.ui.resources.ResourceManager; |
44 | 47 |
45 /** | 48 /** |
46 * The is the {@link View} displaying the ui compositor results; including webpa ges and tabswitcher. | 49 * The is the {@link View} displaying the ui compositor results; including webpa ges and tabswitcher. |
47 */ | 50 */ |
48 @JNINamespace("android") | 51 @JNINamespace("android") |
49 public class CompositorView | 52 public class CompositorView |
50 extends SurfaceView implements ContentOffsetProvider, SurfaceHolder.Call back { | 53 extends FrameLayout implements ContentOffsetProvider, SurfaceHolder.Call back { |
51 private static final String TAG = "CompositorView"; | 54 private static final String TAG = "CompositorView"; |
52 private static final long NANOSECONDS_PER_MILLISECOND = 1000000; | 55 private static final long NANOSECONDS_PER_MILLISECOND = 1000000; |
53 | 56 |
54 // Cache objects that should not be created every frame | 57 // Cache objects that should not be created every frame |
55 private final Rect mCacheViewport = new Rect(); | 58 private final Rect mCacheViewport = new Rect(); |
56 private final Rect mCacheAppRect = new Rect(); | 59 private final Rect mCacheAppRect = new Rect(); |
57 private final Rect mCacheVisibleViewport = new Rect(); | 60 private final Rect mCacheVisibleViewport = new Rect(); |
58 private final int[] mCacheViewPosition = new int[2]; | 61 private final int[] mCacheViewPosition = new int[2]; |
59 | 62 |
63 // If true, then we'll use one surface, and always make it translucent. | |
64 // This can have power implications unless the compositor is using a format | |
65 // that does not have an alpha channel for opaque rendering (e.g., 565), or | |
66 // if the hardware is optimized for it (e.g., some QC GPUs). | |
67 private boolean mAlwaysTranslucent; | |
68 | |
69 // Set of SurfaceViews that we maintain. | |
70 // CompositorViewHolder might be a more natural place to maintain these, | |
71 // except that we own the compositor. | |
boliu
2016/10/12 23:33:34
I'd prefer to refactor the code first, and avoid y
liberato (no reviews please)
2016/11/14 22:12:34
i've refactored all of the new code out into a sep
| |
72 private SurfaceView mForegroundSurfaceView; | |
boliu
2016/10/12 23:33:35
suggestion: webview had a similar pattern for full
liberato (no reviews please)
2016/11/14 22:12:34
yes, you're quite right. good catch.
i've refact
| |
73 | |
74 // This will be null if |mAlwaysTranslucent|, since we never switch the | |
75 // pixel format in that case. | |
76 private SurfaceView mBackgroundSurfaceView; | |
77 | |
78 // Are we waiting to hide mBackgroundSurfaceView until the foreground SV | |
79 // has something to display? | |
80 private boolean mHideBackgroundPending; | |
81 | |
82 // How many frames remain until we hide the newly-swapped background? | |
83 private int mFramesUntilHide; | |
84 | |
85 // Cache of setWillNotDraw, which we keep up to date if we switch SVs. | |
86 private boolean mWillNotDraw; | |
87 | |
60 private long mNativeCompositorView; | 88 private long mNativeCompositorView; |
61 private final LayoutRenderHost mRenderHost; | 89 private final LayoutRenderHost mRenderHost; |
62 private boolean mEnableTabletTabStack; | 90 private boolean mEnableTabletTabStack; |
63 private int mPreviousWindowTop = -1; | 91 private int mPreviousWindowTop = -1; |
64 | 92 |
65 private int mLastLayerCount; | 93 private int mLastLayerCount; |
66 | 94 |
67 // A conservative estimate of when a frame is guaranteed to be presented aft er being submitted. | 95 // A conservative estimate of when a frame is guaranteed to be presented aft er being submitted. |
68 private long mFramePresentationDelay; | 96 private long mFramePresentationDelay; |
69 | 97 |
70 // Resource Management | 98 // Resource Management |
71 private ResourceManager mResourceManager; | 99 private ResourceManager mResourceManager; |
72 | 100 |
73 // Lazily populated as it is needed. | 101 // Lazily populated as it is needed. |
74 private View mRootActivityView; | 102 private View mRootActivityView; |
75 private WindowAndroid mWindowAndroid; | 103 private WindowAndroid mWindowAndroid; |
76 private LayerTitleCache mLayerTitleCache; | 104 private LayerTitleCache mLayerTitleCache; |
77 private TabContentManager mTabContentManager; | 105 private TabContentManager mTabContentManager; |
78 | 106 |
79 private View mRootView; | 107 private View mRootView; |
80 private int mSurfaceWidth; | 108 private int mSurfaceWidth; |
81 private int mSurfaceHeight; | 109 private int mSurfaceHeight; |
82 private boolean mPreloadedResources; | 110 private boolean mPreloadedResources; |
83 | 111 |
84 // The current SurfaceView pixel format. Defaults to OPAQUE. | 112 // The pixel format that we've told the compositor about. |
85 private int mCurrentPixelFormat = PixelFormat.OPAQUE; | 113 private int mVirtualPixelFormat = PixelFormat.OPAQUE; |
114 | |
115 // The current SurfaceView pixel format. Defaults to OPAQUE. This will be | |
116 // the same as mVirtualPixelFormat unless we're mAlwaysTranslucent. | |
117 private int mActualPixelFormat = PixelFormat.OPAQUE; | |
86 | 118 |
87 /** | 119 /** |
88 * Creates a {@link CompositorView}. This can be called only after the nativ e library is | 120 * Creates a {@link CompositorView}. This can be called only after the nativ e library is |
89 * properly loaded. | 121 * properly loaded. |
90 * @param c The Context to create this {@link CompositorView} in. | 122 * @param c The Context to create this {@link CompositorView} in. |
91 * @param host The renderer host owning this view. | 123 * @param host The renderer host owning this view. |
92 */ | 124 */ |
93 public CompositorView(Context c, LayoutRenderHost host) { | 125 public CompositorView(Context c, LayoutRenderHost host) { |
94 super(c); | 126 super(c); |
95 mRenderHost = host; | 127 mRenderHost = host; |
96 resetFlags(); | 128 resetFlags(); |
129 | |
130 mForegroundSurfaceView = createSurfaceView(); | |
131 attachSurfaceView(mForegroundSurfaceView); | |
132 | |
97 setVisibility(View.INVISIBLE); | 133 setVisibility(View.INVISIBLE); |
98 setZOrderMediaOverlay(true); | 134 bringChildToFront(mForegroundSurfaceView); |
99 } | 135 } |
100 | 136 |
101 /** | 137 /** |
102 * @param view The root view of the hierarchy. | 138 * @param view The root view of the hierarchy. |
103 */ | 139 */ |
104 public void setRootView(View view) { | 140 public void setRootView(View view) { |
105 mRootView = view; | 141 mRootView = view; |
106 } | 142 } |
107 | 143 |
108 /** | 144 /** |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
157 * @return The ResourceManager. | 193 * @return The ResourceManager. |
158 */ | 194 */ |
159 public ResourceManager getResourceManager() { | 195 public ResourceManager getResourceManager() { |
160 return mResourceManager; | 196 return mResourceManager; |
161 } | 197 } |
162 | 198 |
163 /** | 199 /** |
164 * Should be called for cleanup when the CompositorView instance is no longe r used. | 200 * Should be called for cleanup when the CompositorView instance is no longe r used. |
165 */ | 201 */ |
166 public void shutDown() { | 202 public void shutDown() { |
167 getHolder().removeCallback(this); | 203 mForegroundSurfaceView.getHolder().removeCallback(this); |
204 if (mBackgroundSurfaceView != null) mBackgroundSurfaceView.getHolder().r emoveCallback(this); | |
168 if (mNativeCompositorView != 0) nativeDestroy(mNativeCompositorView); | 205 if (mNativeCompositorView != 0) nativeDestroy(mNativeCompositorView); |
169 mNativeCompositorView = 0; | 206 mNativeCompositorView = 0; |
170 } | 207 } |
171 | 208 |
172 /** | 209 /** |
173 * Initializes the {@link CompositorView}'s native parts (e.g. the rendering parts). | 210 * Initializes the {@link CompositorView}'s native parts (e.g. the rendering parts). |
174 * @param lowMemDevice If this is a low memory device. | 211 * @param lowMemDevice If this is a low memory device. |
175 * @param windowAndroid A {@link WindowAndroid} instance. | 212 * @param windowAndroid A {@link WindowAndroid} instance. |
176 * @param layerTitleCache A {@link LayerTitleCache} instance. | 213 * @param layerTitleCache A {@link LayerTitleCache} instance. |
177 * @param tabContentManager A {@link TabContentManager} instance. | 214 * @param tabContentManager A {@link TabContentManager} instance. |
178 */ | 215 */ |
179 public void initNativeCompositor(boolean lowMemDevice, WindowAndroid windowA ndroid, | 216 public void initNativeCompositor(boolean lowMemDevice, WindowAndroid windowA ndroid, |
180 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ) { | 217 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ) { |
181 mWindowAndroid = windowAndroid; | 218 mWindowAndroid = windowAndroid; |
182 mLayerTitleCache = layerTitleCache; | 219 mLayerTitleCache = layerTitleCache; |
183 mTabContentManager = tabContentManager; | 220 mTabContentManager = tabContentManager; |
184 | 221 |
222 // compositor_impl_android.cc will use 565 EGL surfaces if and only if | |
223 // we're using a low memory device, and no alpha channel is desired. | |
224 // Otherwise, it will use 8888. Since SurfaceFlinger doesn't need | |
225 // the eOpaque flag to optimize out alpha blending during composition if | |
226 // the buffer has no alpha channel, we can avoid using the extra | |
227 // background surface (and the memory it requires) in the low memory | |
228 // case. The output buffer will either have an alpha channel or not, | |
229 // depending on whether the compositor needs it. | |
230 // We can keep the surface translucent all the times without worrying | |
231 // about the impact on power usage during SurfaceFlinger composition. | |
232 // We might also want to set |mAlwaysTranslucent| on non-low memory | |
233 // devices , if we are running on hardware that implements efficient | |
234 // alpha blending. | |
235 mAlwaysTranslucent = lowMemDevice; | |
236 if (mAlwaysTranslucent) { | |
237 mActualPixelFormat = PixelFormat.TRANSLUCENT; | |
238 mForegroundSurfaceView.getHolder().setFormat(mActualPixelFormat); | |
239 } else { | |
240 // We will switch between background and foreground SurfaceViews. | |
241 mBackgroundSurfaceView = createSurfaceView(); | |
242 } | |
243 | |
185 mNativeCompositorView = nativeInit(lowMemDevice, | 244 mNativeCompositorView = nativeInit(lowMemDevice, |
186 windowAndroid.getNativePointer(), layerTitleCache, tabContentMan ager); | 245 windowAndroid.getNativePointer(), layerTitleCache, tabContentMan ager); |
187 | 246 |
188 assert !getHolder().getSurface().isValid() | 247 assert !getHolder().getSurface().isValid() |
189 : "Surface created before native library loaded."; | 248 : "Surface created before native library loaded."; |
190 getHolder().addCallback(this); | 249 mForegroundSurfaceView.getHolder().addCallback(this); |
250 if (mBackgroundSurfaceView != null) mBackgroundSurfaceView.getHolder().a ddCallback(this); | |
191 | 251 |
192 // Cover the black surface before it has valid content. | 252 // Cover the black surface before it has valid content. |
193 setBackgroundColor(Color.WHITE); | 253 setBackgroundColor(Color.WHITE); |
194 setVisibility(View.VISIBLE); | 254 setVisibility(View.VISIBLE); |
255 mForegroundSurfaceView.setVisibility(View.VISIBLE); | |
195 | 256 |
196 mFramePresentationDelay = 0; | 257 mFramePresentationDelay = 0; |
197 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { | 258 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) { |
198 Display display = | 259 Display display = |
199 ((WindowManager) getContext().getSystemService(Context.WINDO W_SERVICE)) | 260 ((WindowManager) getContext().getSystemService(Context.WINDO W_SERVICE)) |
200 .getDefaultDisplay(); | 261 .getDefaultDisplay(); |
201 long presentationDeadline = display.getPresentationDeadlineNanos() | 262 long presentationDeadline = display.getPresentationDeadlineNanos() |
202 / NANOSECONDS_PER_MILLISECOND; | 263 / NANOSECONDS_PER_MILLISECOND; |
203 long vsyncPeriod = mWindowAndroid.getVsyncPeriodInMillis(); | 264 long vsyncPeriod = mWindowAndroid.getVsyncPeriodInMillis(); |
204 mFramePresentationDelay = Math.min(3 * vsyncPeriod, | 265 mFramePresentationDelay = Math.min(3 * vsyncPeriod, |
205 ((presentationDeadline + vsyncPeriod - 1) / vsyncPeriod) * v syncPeriod); | 266 ((presentationDeadline + vsyncPeriod - 1) / vsyncPeriod) * v syncPeriod); |
206 } | 267 } |
207 | 268 |
208 // Grab the Resource Manager | 269 // Grab the Resource Manager |
209 mResourceManager = nativeGetResourceManager(mNativeCompositorView); | 270 mResourceManager = nativeGetResourceManager(mNativeCompositorView); |
210 } | 271 } |
211 | 272 |
212 @Override | 273 @Override |
213 public boolean onTouchEvent(MotionEvent e) { | 274 public boolean onTouchEvent(MotionEvent e) { |
214 return super.onTouchEvent(e); | 275 return super.onTouchEvent(e); |
215 } | 276 } |
216 | 277 |
217 /** | 278 /** |
218 * Enables/disables overlay video mode. Affects alpha blending on this view. | 279 * Enables/disables overlay video mode. Affects alpha blending on this view. |
219 * @param enabled Whether to enter or leave overlay video mode. | 280 * @param enabled Whether to enter or leave overlay video mode. |
220 */ | 281 */ |
221 public void setOverlayVideoMode(boolean enabled) { | 282 public void setOverlayVideoMode(boolean enabled) { |
222 mCurrentPixelFormat = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OP AQUE; | 283 int oldFormat = mVirtualPixelFormat; |
223 getHolder().setFormat(mCurrentPixelFormat); | 284 mVirtualPixelFormat = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OP AQUE; |
boliu
2016/10/12 23:33:34
would it be easier to just keep a boolean mOverlay
liberato (no reviews please)
2016/11/14 22:12:34
changed significantly due to the refactor.
| |
224 nativeSetOverlayVideoMode(mNativeCompositorView, enabled); | 285 if (mVirtualPixelFormat == oldFormat) return; |
286 | |
287 // Figure out what we want to tell the surface. | |
288 mActualPixelFormat = mAlwaysTranslucent ? PixelFormat.TRANSLUCENT : mVir tualPixelFormat; | |
289 | |
290 if (!mForegroundSurfaceView.getHolder().getSurface().isValid()) { | |
291 // No current view -- just set the format on it. The compositor | |
292 // will get a surfaceCreated message later. | |
293 getHolder().setFormat(mActualPixelFormat); | |
294 nativeSetOverlayVideoMode(mNativeCompositorView, enabled); | |
295 return; | |
296 } | |
297 | |
298 if (mAlwaysTranslucent) { | |
299 // Update the compositor by pretending that the surface changed. We | |
300 // don't need to update the actual pixel format, though. | |
301 nativeSurfaceDestroyed(mNativeCompositorView); | |
boliu
2016/10/12 23:33:34
is Destroy/Created needed here? previous code didn
liberato (no reviews please)
2016/11/14 22:12:34
it did, via the real surfaceCreated / Destroyed ca
| |
302 nativeSetOverlayVideoMode(mNativeCompositorView, enabled); | |
303 nativeSurfaceCreated(mNativeCompositorView); | |
304 return; | |
305 } | |
306 | |
307 // Update the actual pixel format by switching to the other SurfaceView. | |
308 // The rest of the transition will happen when the surface is ready. | |
309 mBackgroundSurfaceView.getHolder().setFormat(mActualPixelFormat); | |
310 attachSurfaceView(mBackgroundSurfaceView); | |
311 mBackgroundSurfaceView.setVisibility(View.VISIBLE); | |
312 requestLayout(); | |
boliu
2016/10/12 23:33:35
is invalidate by itself not enough?
also use post
liberato (no reviews please)
2016/11/14 22:12:34
Done.
| |
313 invalidate(); | |
314 } | |
315 | |
316 public SurfaceHolder getHolder() { | |
317 return mForegroundSurfaceView.getHolder(); | |
225 } | 318 } |
226 | 319 |
227 @Override | 320 @Override |
228 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { | 321 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { |
229 if (mNativeCompositorView == 0) return; | 322 if (mNativeCompositorView == 0) return; |
323 | |
324 if (isBackgroundHolder(holder)) return; | |
boliu
2016/10/12 23:33:34
suggestion: might be useful have an inner static c
liberato (no reviews please)
2016/11/14 22:12:35
after refactoring, i'm not sure that this is still
| |
325 | |
230 nativeSurfaceChanged(mNativeCompositorView, format, width, height, holde r.getSurface()); | 326 nativeSurfaceChanged(mNativeCompositorView, format, width, height, holde r.getSurface()); |
231 mRenderHost.onPhysicalBackingSizeChanged(width, height); | 327 mRenderHost.onPhysicalBackingSizeChanged(width, height); |
232 mSurfaceWidth = width; | 328 mSurfaceWidth = width; |
233 mSurfaceHeight = height; | 329 mSurfaceHeight = height; |
234 } | 330 } |
235 | 331 |
236 @Override | 332 @Override |
237 public void surfaceCreated(SurfaceHolder holder) { | 333 public void surfaceCreated(SurfaceHolder holder) { |
238 if (mNativeCompositorView == 0) return; | 334 if (mNativeCompositorView == 0) return; |
335 | |
336 if (isBackgroundHolder(holder)) { | |
337 // We requested that background view as part of a surface swap. | |
338 // Switch the compositor. | |
339 nativeSurfaceDestroyed(mNativeCompositorView); | |
340 nativeSetOverlayVideoMode( | |
341 mNativeCompositorView, mVirtualPixelFormat == PixelFormat.TR ANSLUCENT); | |
342 | |
343 // Switch the primary and secondary surfaces. | |
344 SurfaceView tmp = mForegroundSurfaceView; | |
345 mForegroundSurfaceView = mBackgroundSurfaceView; | |
346 mBackgroundSurfaceView = tmp; | |
347 | |
348 // We will wait to actually hide the new background surface until | |
349 // the foreground surface has something to show. Note that, | |
350 // unfortunately, the new foreground surface is actually z-ordered | |
351 // below the new background, so mBackgroundSurfaceView will prevent | |
352 // new compositor updates from showing until we hide it. | |
353 mHideBackgroundPending = true; | |
354 mFramesUntilHide = 1; | |
355 | |
356 // Refresh any properties that we proxy for the SurfaceView. | |
357 mForegroundSurfaceView.setWillNotDraw(mWillNotDraw); | |
358 mForegroundSurfaceView.setBackground(getBackground()); | |
359 } | |
360 | |
239 nativeSurfaceCreated(mNativeCompositorView); | 361 nativeSurfaceCreated(mNativeCompositorView); |
240 mRenderHost.onSurfaceCreated(); | 362 mRenderHost.onSurfaceCreated(); |
241 } | 363 } |
242 | 364 |
243 @Override | 365 @Override |
244 public void surfaceDestroyed(SurfaceHolder holder) { | 366 public void surfaceDestroyed(SurfaceHolder holder) { |
245 if (mNativeCompositorView == 0) return; | 367 if (mNativeCompositorView == 0) return; |
368 | |
369 // If the non-primary surface has been destroyed, then ignore it. | |
370 if (isBackgroundHolder(holder)) return; | |
371 | |
246 nativeSurfaceDestroyed(mNativeCompositorView); | 372 nativeSurfaceDestroyed(mNativeCompositorView); |
247 } | 373 } |
248 | 374 |
249 @Override | 375 @Override |
250 public void onWindowVisibilityChanged(int visibility) { | 376 public void onWindowVisibilityChanged(int visibility) { |
251 super.onWindowVisibilityChanged(visibility); | 377 super.onWindowVisibilityChanged(visibility); |
252 if (mWindowAndroid == null) return; | 378 if (mWindowAndroid == null) return; |
253 if (visibility == View.GONE) { | 379 if (visibility == View.GONE) { |
254 mWindowAndroid.onVisibilityChanged(false); | 380 mWindowAndroid.onVisibilityChanged(false); |
255 } else if (visibility == View.VISIBLE) { | 381 } else if (visibility == View.VISIBLE) { |
(...skipping 15 matching lines...) Expand all Loading... | |
271 */ | 397 */ |
272 @CalledByNative | 398 @CalledByNative |
273 private void onJellyBeanSurfaceDisconnectWorkaround(boolean inOverlayMode) { | 399 private void onJellyBeanSurfaceDisconnectWorkaround(boolean inOverlayMode) { |
274 // There is a bug in JellyBean because of which we will not be able to | 400 // There is a bug in JellyBean because of which we will not be able to |
275 // reconnect to the existing Surface after we launch a new GPU process. | 401 // reconnect to the existing Surface after we launch a new GPU process. |
276 // We simply trick the JB Android code to allocate a new Surface. | 402 // We simply trick the JB Android code to allocate a new Surface. |
277 // It does a strict comparison between the current format and the reques ted | 403 // It does a strict comparison between the current format and the reques ted |
278 // one, even if they are the same in practice. Furthermore, the format | 404 // one, even if they are the same in practice. Furthermore, the format |
279 // does not matter here since the producer-side EGL config overwrites it | 405 // does not matter here since the producer-side EGL config overwrites it |
280 // (but transparency might matter). | 406 // (but transparency might matter). |
281 switch (mCurrentPixelFormat) { | 407 switch (mActualPixelFormat) { |
282 case PixelFormat.OPAQUE: | 408 case PixelFormat.OPAQUE: |
283 mCurrentPixelFormat = PixelFormat.RGBA_8888; | 409 mActualPixelFormat = PixelFormat.RGBA_8888; |
284 break; | 410 break; |
285 case PixelFormat.RGBA_8888: | 411 case PixelFormat.RGBA_8888: |
286 mCurrentPixelFormat = inOverlayMode | 412 mActualPixelFormat = inOverlayMode ? PixelFormat.TRANSLUCENT : P ixelFormat.OPAQUE; |
287 ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; | |
288 break; | 413 break; |
289 case PixelFormat.TRANSLUCENT: | 414 case PixelFormat.TRANSLUCENT: |
290 mCurrentPixelFormat = PixelFormat.RGBA_8888; | 415 mActualPixelFormat = PixelFormat.RGBA_8888; |
291 break; | 416 break; |
292 default: | 417 default: |
293 assert false; | 418 assert false; |
294 Log.e(TAG, "Unknown current pixel format."); | 419 Log.e(TAG, "Unknown current pixel format."); |
295 } | 420 } |
296 getHolder().setFormat(mCurrentPixelFormat); | 421 getHolder().setFormat(mActualPixelFormat); |
297 } | 422 } |
298 | 423 |
299 /** | 424 /** |
300 * Request compositor view to render a frame. | 425 * Request compositor view to render a frame. |
301 */ | 426 */ |
302 public void requestRender() { | 427 public void requestRender() { |
303 if (mNativeCompositorView != 0) nativeSetNeedsComposite(mNativeComposito rView); | 428 if (mNativeCompositorView != 0) nativeSetNeedsComposite(mNativeComposito rView); |
304 } | 429 } |
305 | 430 |
431 private boolean isBackgroundHolder(SurfaceHolder holder) { | |
432 return mBackgroundSurfaceView != null && holder == mBackgroundSurfaceVie w.getHolder(); | |
433 } | |
434 | |
306 @CalledByNative | 435 @CalledByNative |
307 private void onSwapBuffersCompleted(int pendingSwapBuffersCount) { | 436 private void onSwapBuffersCompleted(int pendingSwapBuffersCount) { |
308 // Clear the color used to cover the uninitialized surface. | 437 // Clear the color used to cover the uninitialized surface. |
309 if (getBackground() != null) { | 438 if (getBackground() != null) { |
310 postDelayed(new Runnable() { | 439 postDelayed(new Runnable() { |
311 @Override | 440 @Override |
312 public void run() { | 441 public void run() { |
313 setBackgroundResource(0); | 442 setBackgroundResource(0); |
314 } | 443 } |
315 }, mFramePresentationDelay); | 444 }, mFramePresentationDelay); |
316 } | 445 } |
317 | 446 |
447 // If we're in the middle of a surface swap, then see if we've received | |
448 // enough frames to hide the outgoing surface. | |
449 if (mHideBackgroundPending) { | |
450 if (mFramesUntilHide > 0) { | |
boliu
2016/10/12 23:33:34
I'm not sure what the two frame delay is for. The
liberato (no reviews please)
2016/11/14 22:12:34
arbitrary delay, unfortunately.
| |
451 mFramesUntilHide--; | |
452 // Make sure that there actually will be a frame. | |
453 requestRender(); | |
454 } else { | |
455 // Remove the background so that we're sure that the underlying | |
456 // Surface is destroyed. | |
457 removeView(mBackgroundSurfaceView); | |
458 mHideBackgroundPending = false; | |
459 } | |
460 } | |
461 | |
318 mRenderHost.onSwapBuffersCompleted(pendingSwapBuffersCount); | 462 mRenderHost.onSwapBuffersCompleted(pendingSwapBuffersCount); |
319 } | 463 } |
320 | 464 |
321 /** | 465 /** |
322 * Converts the layout into compositor layers. This is to be called on every frame the layout | 466 * Converts the layout into compositor layers. This is to be called on every frame the layout |
323 * is changing. | 467 * is changing. |
324 * @param provider Provides the layout to be rendered. | 468 * @param provider Provides the layout to be rendered. |
325 * @param forRotation Whether or not this is a special draw durin g a rotation. | 469 * @param forRotation Whether or not this is a special draw durin g a rotation. |
326 */ | 470 */ |
327 public void finalizeLayers(final LayoutProvider provider, boolean forRotatio n, | 471 public void finalizeLayers(final LayoutProvider provider, boolean forRotatio n, |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 return mLastLayerCount; | 522 return mLastLayerCount; |
379 } | 523 } |
380 | 524 |
381 @Override | 525 @Override |
382 public int getOverlayTranslateY() { | 526 public int getOverlayTranslateY() { |
383 return mRenderHost.areTopControlsPermanentlyHidden() | 527 return mRenderHost.areTopControlsPermanentlyHidden() |
384 ? mRenderHost.getTopControlsHeightPixels() | 528 ? mRenderHost.getTopControlsHeightPixels() |
385 : mRenderHost.getVisibleViewport(mCacheVisibleViewport).top; | 529 : mRenderHost.getVisibleViewport(mCacheVisibleViewport).top; |
386 } | 530 } |
387 | 531 |
532 @Override | |
533 public void setWillNotDraw(boolean willNotDraw) { | |
534 mWillNotDraw = willNotDraw; | |
535 mForegroundSurfaceView.setWillNotDraw(mWillNotDraw); | |
536 } | |
537 | |
538 @Override | |
539 public void setBackgroundDrawable(Drawable background) { | |
540 // We override setBackgroundDrawable since that's the common entry point | |
541 // from all the setBackground* calls in View. We still call to | |
542 // setBackground on the SurfaceView because SetBackgroundDrawable is | |
543 // depricated, and the semantics are the same I think. | |
544 super.setBackgroundDrawable(background); | |
545 mForegroundSurfaceView.setBackground(background); | |
546 } | |
547 | |
548 /** | |
549 * Helper to create and attach a SurfaceView | |
550 */ | |
551 private SurfaceView createSurfaceView() { | |
552 SurfaceView surfaceView = new SurfaceView(getContext()); | |
553 surfaceView.setZOrderMediaOverlay(true); | |
554 surfaceView.setVisibility(View.INVISIBLE); | |
555 return surfaceView; | |
556 } | |
557 | |
558 private void attachSurfaceView(SurfaceView surfaceView) { | |
559 FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams( | |
560 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATC H_PARENT); | |
561 addView(surfaceView, lp); | |
562 } | |
563 | |
388 // Implemented in native | 564 // Implemented in native |
389 private native long nativeInit(boolean lowMemDevice, long nativeWindowAndroi d, | 565 private native long nativeInit(boolean lowMemDevice, long nativeWindowAndroi d, |
390 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ); | 566 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ); |
391 private native void nativeDestroy(long nativeCompositorView); | 567 private native void nativeDestroy(long nativeCompositorView); |
392 private native ResourceManager nativeGetResourceManager(long nativeComposito rView); | 568 private native ResourceManager nativeGetResourceManager(long nativeComposito rView); |
393 private native void nativeSurfaceCreated(long nativeCompositorView); | 569 private native void nativeSurfaceCreated(long nativeCompositorView); |
394 private native void nativeSurfaceDestroyed(long nativeCompositorView); | 570 private native void nativeSurfaceDestroyed(long nativeCompositorView); |
395 private native void nativeSurfaceChanged( | 571 private native void nativeSurfaceChanged( |
396 long nativeCompositorView, int format, int width, int height, Surfac e surface); | 572 long nativeCompositorView, int format, int width, int height, Surfac e surface); |
397 private native void nativeFinalizeLayers(long nativeCompositorView); | 573 private native void nativeFinalizeLayers(long nativeCompositorView); |
398 private native void nativeSetNeedsComposite(long nativeCompositorView); | 574 private native void nativeSetNeedsComposite(long nativeCompositorView); |
399 private native void nativeSetLayoutViewport(long nativeCompositorView, float x, float y, | 575 private native void nativeSetLayoutViewport(long nativeCompositorView, float x, float y, |
400 float width, float height, float visibleXOffset, float visibleYOffse t, | 576 float width, float height, float visibleXOffset, float visibleYOffse t, |
401 float dpToPixel); | 577 float dpToPixel); |
402 private native void nativeSetOverlayVideoMode(long nativeCompositorView, boo lean enabled); | 578 private native void nativeSetOverlayVideoMode(long nativeCompositorView, boo lean enabled); |
403 private native void nativeSetSceneLayer(long nativeCompositorView, SceneLaye r sceneLayer); | 579 private native void nativeSetSceneLayer(long nativeCompositorView, SceneLaye r sceneLayer); |
404 } | 580 } |
OLD | NEW |