Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(517)

Side by Side Diff: chrome/android/java_staging/src/org/chromium/chrome/browser/compositor/CompositorView.java

Issue 1141283003: Upstream oodles of Chrome for Android code into Chromium. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: final patch? Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.compositor;
6
7 import android.app.Activity;
8 import android.content.Context;
9 import android.graphics.Color;
10 import android.graphics.PixelFormat;
11 import android.graphics.Rect;
12 import android.view.MotionEvent;
13 import android.view.Surface;
14 import android.view.SurfaceHolder;
15 import android.view.SurfaceView;
16 import android.view.View;
17
18 import com.google.android.apps.chrome.R;
19
20 import org.chromium.base.CalledByNative;
21 import org.chromium.base.CommandLine;
22 import org.chromium.base.JNINamespace;
23 import org.chromium.base.Log;
24 import org.chromium.base.TraceEvent;
25 import org.chromium.base.VisibleForTesting;
26 import org.chromium.chrome.browser.ChromeSwitches;
27 import org.chromium.chrome.browser.ChromiumApplication;
28 import org.chromium.chrome.browser.compositor.layouts.Layout;
29 import org.chromium.chrome.browser.compositor.layouts.Layout.SizingFlags;
30 import org.chromium.chrome.browser.compositor.layouts.LayoutProvider;
31 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
32 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
33 import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvi der;
34 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
35 import org.chromium.chrome.browser.compositor.resources.StaticResourcePreloads;
36 import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
37 import org.chromium.chrome.browser.device.DeviceClassManager;
38 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
39 import org.chromium.chrome.browser.tabmodel.TabModelBase;
40 import org.chromium.content.browser.ContentReadbackHandler;
41 import org.chromium.ui.base.DeviceFormFactor;
42 import org.chromium.ui.base.WindowAndroid;
43 import org.chromium.ui.resources.AndroidResourceType;
44 import org.chromium.ui.resources.ResourceManager;
45
46 /**
47 * The is the {@link View} displaying the ui compositor results; including webpa ges and tabswitcher.
48 */
49 @JNINamespace("chrome::android")
50 public class CompositorView
51 extends SurfaceView implements ContentOffsetProvider, SurfaceHolder.Call back2 {
52 private static final String TAG = "CompositorView";
53
54 // Cache objects that should not be created every frame
55 private final Rect mCacheViewport = new Rect();
56 private final Rect mCacheAppRect = new Rect();
57 private final Rect mCacheVisibleViewport = new Rect();
58 private final int[] mCacheViewPosition = new int[2];
59
60 private long mNativeCompositorView;
61 private final LayoutRenderHost mRenderHost;
62 private boolean mEnableTabletTabStack;
63 private int mPreviousWindowTop = -1;
64
65 private int mLastLayerCount;
66
67 // Resource Management
68 private ResourceManager mResourceManager;
69
70 // Lazily populated as it is needed.
71 private View mRootActivityView;
72 private WindowAndroid mWindowAndroid;
73 private LayerTitleCache mLayerTitleCache;
74 private TabContentManager mTabContentManager;
75
76 private View mRootView;
77 private int mSurfaceWidth;
78 private int mSurfaceHeight;
79 private boolean mPreloadedResources;
80
81 private ContentReadbackHandler mContentReadbackHandler;
82
83 // The current SurfaceView pixel format. Defaults to OPAQUE.
84 private int mCurrentPixelFormat = PixelFormat.OPAQUE;
85
86 /**
87 * Creates a {@link CompositorView}. This can be called only after the nativ e library is
88 * properly loaded.
89 * @param c The Context to create this {@link CompositorView} in.
90 * @param host The renderer host owning this view.
91 */
92 public CompositorView(Context c, LayoutRenderHost host) {
93 super(c);
94 mRenderHost = host;
95 resetFlags();
96 setVisibility(View.INVISIBLE);
97 setZOrderMediaOverlay(true);
98 mContentReadbackHandler = new ContentReadbackHandler() {
99 @Override
100 protected boolean readyForReadback() {
101 return mNativeCompositorView != 0;
102 }
103 };
104 }
105
106 /**
107 * @param view The root view of the hierarchy.
108 */
109 public void setRootView(View view) {
110 mRootView = view;
111 }
112
113 /**
114 * Reset the commandline flags. This gets called after we switch over to the
115 * native command line.
116 */
117 public void resetFlags() {
118 CommandLine commandLine = CommandLine.getInstance();
119 mEnableTabletTabStack = commandLine.hasSwitch(ChromeSwitches.ENABLE_TABL ET_TAB_STACK)
120 && DeviceFormFactor.isTablet(getContext());
121 }
122
123 @Override
124 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
125 if (mRootView != null) {
126 mRootView.getWindowVisibleDisplayFrame(mCacheAppRect);
127
128 // Check whether the top position of the window has changed as we al ways must
129 // resize in that case to the specified height spec. On certain ver sions of
130 // Android when you change the top position (i.e. by leaving fullscr een) and
131 // do not shrink the SurfaceView, it will appear to be pinned to the top of
132 // the screen under the notification bar and all touch offsets will be wrong
133 // as well as a gap will appear at the bottom of the screen.
134 int windowTop = mCacheAppRect.top;
135 boolean topChanged = windowTop != mPreviousWindowTop;
136 mPreviousWindowTop = windowTop;
137
138 Activity activity = mWindowAndroid != null ? mWindowAndroid.getActiv ity().get() : null;
139 ChromiumApplication application =
140 (ChromiumApplication) getContext().getApplicationContext();
141 boolean isMultiWindow = application.isMultiWindow(activity);
142
143 // If the measured width is the same as the allowed width (i.e. the orientation has
144 // not changed) and multi-window mode is off, use the largest measur ed height seen thus
145 // far. This will prevent surface resizes as a result of showing th e keyboard.
146 if (!topChanged && !isMultiWindow
147 && getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpe c)
148 && getMeasuredHeight() > MeasureSpec.getSize(heightMeasureSp ec)) {
149 heightMeasureSpec =
150 MeasureSpec.makeMeasureSpec(getMeasuredHeight(), Measure Spec.EXACTLY);
151 }
152 }
153 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
154 }
155
156 @Override
157 protected void onLayout(boolean changed, int left, int top, int right, int b ottom) {
158 super.onLayout(changed, left, top, right, bottom);
159 mRenderHost.onOverdrawBottomHeightChanged(getOverdrawBottomHeight());
160 }
161
162 @Override
163 protected void onDetachedFromWindow() {
164 super.onDetachedFromWindow();
165 mPreviousWindowTop = -1;
166 }
167
168 /**
169 * @return The content readback handler.
170 */
171 public ContentReadbackHandler getContentReadbackHandler() {
172 return mContentReadbackHandler;
173 }
174
175 /**
176 * @return The ResourceManager.
177 */
178 public ResourceManager getResourceManager() {
179 return mResourceManager;
180 }
181
182 /**
183 * @return The amount the surface view is overdrawing the window bounds.
184 */
185 public int getOverdrawBottomHeight() {
186 if (mRootActivityView == null) {
187 mRootActivityView = mRootView.findViewById(android.R.id.content);
188 }
189 if (mRootActivityView != null) {
190 int compositorHeight = getHeight();
191 int rootViewHeight = mRootActivityView.getHeight();
192 return Math.max(0, compositorHeight - rootViewHeight);
193 }
194 return 0;
195 }
196
197 /**
198 * Should be called for cleanup when the CompositorView instance is no longe r used.
199 */
200 public void shutDown() {
201 getHolder().removeCallback(this);
202 mContentReadbackHandler.destroy();
203 mContentReadbackHandler = null;
204 if (mNativeCompositorView != 0) nativeDestroy(mNativeCompositorView);
205 mNativeCompositorView = 0;
206 }
207
208 /**
209 * Initializes the {@link CompositorView}'s native parts (e.g. the rendering parts).
210 * @param lowMemDevice If this is a low memory device.
211 * @param windowAndroid A {@link WindowAndroid} instance.
212 * @param layerTitleCache A {@link LayerTitleCache} instance.
213 * @param tabContentManager A {@link TabContentManager} instance.
214 */
215 public void initNativeCompositor(boolean lowMemDevice, WindowAndroid windowA ndroid,
216 LayerTitleCache layerTitleCache, TabContentManager tabContentManager ) {
217 mWindowAndroid = windowAndroid;
218 mLayerTitleCache = layerTitleCache;
219 mTabContentManager = tabContentManager;
220
221 mNativeCompositorView =
222 nativeInit(lowMemDevice, getResources().getColor(R.color.tab_swi tcher_background),
223 windowAndroid.getNativePointer(), layerTitleCache, tabCo ntentManager);
224
225 assert !getHolder().getSurface().isValid()
226 : "Surface created before native library loaded.";
227 getHolder().addCallback(this);
228
229 // Cover the black surface before it has valid content.
230 setBackgroundColor(Color.WHITE);
231 setVisibility(View.VISIBLE);
232
233 // Grab the Resource Manager
234 mResourceManager = nativeGetResourceManager(mNativeCompositorView);
235
236 mContentReadbackHandler.initNativeContentReadbackHandler();
237 }
238
239 @Override
240 public boolean onTouchEvent(MotionEvent e) {
241 return super.onTouchEvent(e);
242 }
243
244 /**
245 * Enables/disables overlay video mode. Affects alpha blending on this view.
246 * @param enabled Whether to enter or leave overlay video mode.
247 */
248 public void setOverlayVideoMode(boolean enabled) {
249 mCurrentPixelFormat = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OP AQUE;
250 getHolder().setFormat(mCurrentPixelFormat);
251 nativeSetOverlayVideoMode(mNativeCompositorView, enabled);
252 }
253
254 @Override
255 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
256 if (mNativeCompositorView == 0) return;
257 nativeSurfaceChanged(mNativeCompositorView, format, width, height, holde r.getSurface());
258 mRenderHost.onPhysicalBackingSizeChanged(width, height);
259 mSurfaceWidth = width;
260 mSurfaceHeight = height;
261 }
262
263 @Override
264 public void surfaceCreated(SurfaceHolder holder) {
265 if (mNativeCompositorView == 0) return;
266 nativeSurfaceCreated(mNativeCompositorView);
267 mRenderHost.onSurfaceCreated();
268 }
269
270 @Override
271 public void surfaceDestroyed(SurfaceHolder holder) {
272 if (mNativeCompositorView == 0) return;
273 nativeSurfaceDestroyed(mNativeCompositorView);
274 }
275
276 @Override
277 public void surfaceRedrawNeeded(SurfaceHolder holder) {}
278
279 @CalledByNative
280 private void onCompositorLayout() {
281 mRenderHost.onCompositorLayout();
282 }
283
284 /*
285 * On JellyBean there is a known bug where a crashed producer process
286 * (i.e. GPU process) does not properly disconnect from the BufferQueue,
287 * which means we won't be able to reconnect to it ever again.
288 * This workaround forces the creation of a new Surface.
289 */
290 @CalledByNative
291 private void onJellyBeanSurfaceDisconnectWorkaround(boolean inOverlayMode) {
292 // There is a bug in JellyBean because of which we will not be able to
293 // reconnect to the existing Surface after we launch a new GPU process.
294 // We simply trick the JB Android code to allocate a new Surface.
295 // It does a strict comparison between the current format and the reques ted
296 // one, even if they are the same in practice. Furthermore, the format
297 // does not matter here since the producer-side EGL config overwrites it
298 // (but transparency might matter).
299 switch (mCurrentPixelFormat) {
300 case PixelFormat.OPAQUE:
301 mCurrentPixelFormat = PixelFormat.RGBA_8888;
302 break;
303 case PixelFormat.RGBA_8888:
304 mCurrentPixelFormat = inOverlayMode
305 ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
306 break;
307 case PixelFormat.TRANSLUCENT:
308 mCurrentPixelFormat = PixelFormat.RGBA_8888;
309 break;
310 default:
311 assert false;
312 Log.e(TAG, "Unknown current pixel format.");
313 }
314 getHolder().setFormat(mCurrentPixelFormat);
315 }
316
317 /**
318 * Request compositor view to render a frame.
319 */
320 public void requestRender() {
321 if (mNativeCompositorView != 0) nativeSetNeedsComposite(mNativeComposito rView);
322 }
323
324 @CalledByNative
325 private void onSwapBuffersCompleted(int pendingSwapBuffersCount) {
326 // Clear the color used to cover the uninitialized surface.
327 if (getBackground() != null) {
328 post(new Runnable() {
329 @Override
330 public void run() {
331 setBackgroundResource(0);
332 }
333 });
334 }
335
336 mRenderHost.onSwapBuffersCompleted(pendingSwapBuffersCount);
337 }
338
339 private void updateToolbarLayer(LayoutProvider provider, boolean forRotation ) {
340 if (forRotation || !DeviceClassManager.enableFullscreen()) return;
341
342 ChromeFullscreenManager fullscreenManager = provider.getFullscreenManage r();
343 if (fullscreenManager == null) return;
344
345 float offset = fullscreenManager.getControlOffset();
346 boolean useTexture = fullscreenManager.drawControlsAsTexture() || offset == 0;
347
348 float dpToPx = getContext().getResources().getDisplayMetrics().density;
349 float layoutOffsetDp = provider.getActiveLayout().getTopControlsOffset(o ffset / dpToPx);
350 boolean validLayoutOffset = !Float.isNaN(layoutOffsetDp);
351
352 if (validLayoutOffset) {
353 offset = layoutOffsetDp * dpToPx;
354 useTexture = true;
355 }
356
357 fullscreenManager.setHideTopControlsAndroidView(validLayoutOffset && lay outOffsetDp != 0.f);
358
359 int flags = provider.getActiveLayout().getSizingFlags();
360 if ((flags & SizingFlags.REQUIRE_FULLSCREEN_SIZE) != 0
361 && (flags & SizingFlags.ALLOW_TOOLBAR_HIDE) == 0
362 && (flags & SizingFlags.ALLOW_TOOLBAR_ANIMATE) == 0) {
363 useTexture = false;
364 }
365
366 nativeUpdateToolbarLayer(
367 mNativeCompositorView, R.id.control_container, R.id.progress, of fset, useTexture);
368 }
369
370 /**
371 * Converts the layout into compositor layers. This is to be called on every frame the layout
372 * is changing.
373 * @param provider Provides the layout to be rendered.
374 * @param forRotation Whether or not this is a special draw durin g a rotation.
375 */
376 public void finalizeLayers(final LayoutProvider provider, boolean forRotatio n) {
377 TraceEvent.begin("CompositorView:finalizeLayers");
378 Layout layout = provider.getActiveLayout();
379 if (layout == null || mNativeCompositorView == 0) {
380 TraceEvent.end("CompositorView:finalizeLayers");
381 return;
382 }
383
384 if (!mPreloadedResources) {
385 // Attempt to prefetch any necessary resources
386 mResourceManager.preloadResources(AndroidResourceType.STATIC,
387 StaticResourcePreloads.getSynchronousResources(getContext()) ,
388 StaticResourcePreloads.getAsynchronousResources());
389 mPreloadedResources = true;
390 }
391
392 // IMPORTANT: Do not do anything that impacts the compositor layer tree before this line.
393 // If you do, you could inadvertently trigger follow up renders. For fu rther information
394 // see dtrainor@, tedchoc@, or klobag@.
395
396 // TODO(jscholler): change 1.0f to dpToPx once the native part is fully supporting dp.
397 mRenderHost.getVisibleViewport(mCacheVisibleViewport);
398 provider.getViewportPixel(mCacheViewport);
399 nativeSetLayoutViewport(mNativeCompositorView, mCacheViewport.left, mCac heViewport.top,
400 mCacheViewport.width(), mCacheViewport.height(), mCacheVisibleVi ewport.left,
401 mCacheVisibleViewport.top, mRenderHost.getCurrentOverdrawBottomH eight(), 1.0f);
402
403 mCacheVisibleViewport.right = mCacheVisibleViewport.left + mSurfaceWidth ;
404 mCacheVisibleViewport.bottom = mCacheVisibleViewport.top
405 + Math.max(mSurfaceHeight - mRenderHost.getCurrentOverdrawBottom Height(), 0);
406
407 // TODO(changwan): move to treeprovider.
408 updateToolbarLayer(provider, forRotation);
409
410 SceneLayer sceneLayer =
411 layout.getUpdatedSceneLayer(mCacheViewport, mCacheVisibleViewpor t, mLayerTitleCache,
412 mTabContentManager, mResourceManager, provider.getFullsc reenManager());
413
414 nativeSetSceneLayer(mNativeCompositorView, sceneLayer);
415
416 final LayoutTab[] tabs = layout.getLayoutTabsToRender();
417 final int tabsCount = tabs != null ? tabs.length : 0;
418 mLastLayerCount = tabsCount;
419 TabModelBase.flushActualTabSwitchLatencyMetric();
420 nativeFinalizeLayers(mNativeCompositorView);
421 TraceEvent.end("CompositorView:finalizeLayers");
422 }
423
424 /**
425 * @return The number of layer put the last frame.
426 */
427 @VisibleForTesting
428 public int getLastLayerCount() {
429 return mLastLayerCount;
430 }
431
432 @Override
433 public int getOverlayTranslateY() {
434 return mRenderHost.areTopControlsPermanentlyHidden()
435 ? mRenderHost.getTopControlsHeightPixels()
436 : mRenderHost.getVisibleViewport(mCacheVisibleViewport).top;
437 }
438
439 // Implemented in native
440 private native long nativeInit(boolean lowMemDevice, int emptyColor, long na tiveWindowAndroid,
441 LayerTitleCache layerTitleCache, TabContentManager tabContentManager );
442 private native void nativeDestroy(long nativeCompositorView);
443 private native ResourceManager nativeGetResourceManager(long nativeComposito rView);
444 private native void nativeSurfaceCreated(long nativeCompositorView);
445 private native void nativeSurfaceDestroyed(long nativeCompositorView);
446 private native void nativeSurfaceChanged(
447 long nativeCompositorView, int format, int width, int height, Surfac e surface);
448 private native void nativeFinalizeLayers(long nativeCompositorView);
449 private native void nativeSetNeedsComposite(long nativeCompositorView);
450 private native void nativeSetLayoutViewport(long nativeCompositorView, float x, float y,
451 float width, float height, float visibleXOffset, float visibleYOffse t,
452 float overdrawBottomHeight, float dpToPixel);
453 private native void nativeUpdateToolbarLayer(long nativeCompositorView, int resourceId,
454 int progressResourceId, float topOffset, boolean visible);
455 private native void nativeSetOverlayVideoMode(long nativeCompositorView, boo lean enabled);
456 private native void nativeSetSceneLayer(long nativeCompositorView, SceneLaye r sceneLayer);
457 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698