ContentViewRenderView.java revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 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 5package org.chromium.content.browser; 6 7import android.content.Context; 8import android.os.Build; 9import android.view.Surface; 10import android.view.SurfaceView; 11import android.view.SurfaceHolder; 12import android.widget.FrameLayout; 13 14import org.chromium.base.JNINamespace; 15 16/*** 17 * This view is used by a ContentView to render its content. 18 * Call {@link #setCurrentContentView(ContentView)} with the contentView that should be displayed. 19 * Note that only one ContentView can be shown at a time. 20 */ 21@JNINamespace("content") 22public class ContentViewRenderView extends FrameLayout { 23 24 // The native side of this object. 25 private int mNativeContentViewRenderView = 0; 26 27 private SurfaceView mSurfaceView; 28 29 private ContentView mCurrentContentView; 30 31 private final VSyncMonitor mVSyncMonitor; 32 33 // The VSyncMonitor gives the timebase for the actual vsync, but we don't want render until 34 // we have had a chance for input events to propagate to the compositor thread. This takes 35 // 3 ms typically, so we adjust the vsync timestamps forward by a bit to give input events a 36 // chance to arrive. 37 private static final long INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS = 3200; 38 39 /** 40 * Constructs a new ContentViewRenderView that should be can to a view hierarchy. 41 * Native code should add/remove the layers to be rendered through the ContentViewLayerRenderer. 42 * @param context The context used to create this. 43 */ 44 public ContentViewRenderView(Context context) { 45 super(context); 46 47 mNativeContentViewRenderView = nativeInit(); 48 assert mNativeContentViewRenderView != 0; 49 50 mSurfaceView = new SurfaceView(getContext()); 51 mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { 52 @Override 53 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 54 nativeSurfaceSetSize(mNativeContentViewRenderView, width, height); 55 if (mCurrentContentView != null) { 56 mCurrentContentView.getContentViewCore().onPhysicalBackingSizeChanged( 57 width, height); 58 } 59 } 60 61 @Override 62 public void surfaceCreated(SurfaceHolder holder) { 63 nativeSurfaceCreated(mNativeContentViewRenderView, holder.getSurface()); 64 onReadyToRender(); 65 } 66 67 @Override 68 public void surfaceDestroyed(SurfaceHolder holder) { 69 nativeSurfaceDestroyed(mNativeContentViewRenderView); 70 } 71 }); 72 73 mVSyncMonitor = new VSyncMonitor(getContext(), new VSyncMonitor.Listener() { 74 @Override 75 public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) { 76 if (mCurrentContentView == null) return; 77 // Compensate for input event lag. Input events are delivered immediately on 78 // pre-JB releases, so this adjustment is only done for later versions. 79 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 80 vsyncTimeMicros += INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS; 81 } 82 mCurrentContentView.getContentViewCore().updateVSync(vsyncTimeMicros, 83 mVSyncMonitor.getVSyncPeriodInMicroseconds()); 84 } 85 }); 86 87 addView(mSurfaceView, 88 new FrameLayout.LayoutParams( 89 FrameLayout.LayoutParams.MATCH_PARENT, 90 FrameLayout.LayoutParams.MATCH_PARENT)); 91 } 92 93 /** 94 * Should be called when the ContentViewRenderView is not needed anymore so its associated 95 * native resource can be freed. 96 */ 97 public void destroy() { 98 nativeDestroy(mNativeContentViewRenderView); 99 } 100 101 /** 102 * Makes the passed ContentView the one displayed by this ContentViewRenderView. 103 */ 104 public void setCurrentContentView(ContentView contentView) { 105 nativeSetCurrentContentView(mNativeContentViewRenderView, 106 contentView.getContentViewCore().getNativeContentViewCore()); 107 108 mCurrentContentView = contentView; 109 mCurrentContentView.getContentViewCore().onPhysicalBackingSizeChanged( 110 getWidth(), getHeight()); 111 mVSyncMonitor.requestUpdate(); 112 } 113 114 /** 115 * This method should be subclassed to provide actions to be performed once the view is ready to 116 * render. 117 */ 118 protected void onReadyToRender() { 119 } 120 121 /** 122 * @return whether the surface view is initialized and ready to render. 123 */ 124 public boolean isInitialized() { 125 return mSurfaceView.getHolder().getSurface() != null; 126 } 127 128 private static native int nativeInit(); 129 private native void nativeDestroy(int nativeContentViewRenderView); 130 private native void nativeSetCurrentContentView(int nativeContentViewRenderView, 131 int nativeContentView); 132 private native void nativeSurfaceCreated(int nativeContentViewRenderView, Surface surface); 133 private native void nativeSurfaceDestroyed(int nativeContentViewRenderView); 134 private native void nativeSurfaceSetSize(int nativeContentViewRenderView, 135 int width, int height); 136} 137