• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 package org.chromium.content.browser;
6 
7 import android.content.Context;
8 import android.graphics.Color;
9 import android.graphics.PixelFormat;
10 import android.view.Surface;
11 import android.view.SurfaceHolder;
12 import android.view.SurfaceView;
13 import android.widget.FrameLayout;
14 
15 import org.chromium.base.CalledByNative;
16 import org.chromium.base.JNINamespace;
17 import org.chromium.ui.base.WindowAndroid;
18 
19 /***
20  * This view is used by a ContentView to render its content.
21  * Call {@link #setCurrentContentViewCore(ContentViewCore)} with the contentViewCore that should be
22  * managing the view.
23  * Note that only one ContentViewCore can be shown at a time.
24  */
25 @JNINamespace("content")
26 public class ContentViewRenderView extends FrameLayout {
27     // The native side of this object.
28     private long mNativeContentViewRenderView;
29     private SurfaceHolder.Callback mSurfaceCallback;
30 
31     private final SurfaceView mSurfaceView;
32     protected ContentViewCore mContentViewCore;
33 
34     private ContentReadbackHandler mContentReadbackHandler;
35 
36     /**
37      * Constructs a new ContentViewRenderView.
38      * This should be called and the {@link ContentViewRenderView} should be added to the view
39      * hierarchy before the first draw to avoid a black flash that is seen every time a
40      * {@link SurfaceView} is added.
41      * @param context The context used to create this.
42      */
ContentViewRenderView(Context context)43     public ContentViewRenderView(Context context) {
44         super(context);
45 
46         mSurfaceView = createSurfaceView(getContext());
47         mSurfaceView.setZOrderMediaOverlay(true);
48 
49         setSurfaceViewBackgroundColor(Color.WHITE);
50         addView(mSurfaceView,
51                 new FrameLayout.LayoutParams(
52                         FrameLayout.LayoutParams.MATCH_PARENT,
53                         FrameLayout.LayoutParams.MATCH_PARENT));
54         mSurfaceView.setVisibility(GONE);
55     }
56 
57     /**
58      * Initialization that requires native libraries should be done here.
59      * Native code should add/remove the layers to be rendered through the ContentViewLayerRenderer.
60      * @param rootWindow The {@link WindowAndroid} this render view should be linked to.
61      */
onNativeLibraryLoaded(WindowAndroid rootWindow)62     public void onNativeLibraryLoaded(WindowAndroid rootWindow) {
63         assert !mSurfaceView.getHolder().getSurface().isValid() :
64                 "Surface created before native library loaded.";
65         assert rootWindow != null;
66         mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer());
67         assert mNativeContentViewRenderView != 0;
68         mSurfaceCallback = new SurfaceHolder.Callback() {
69             @Override
70             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
71                 assert mNativeContentViewRenderView != 0;
72                 nativeSurfaceChanged(mNativeContentViewRenderView,
73                         format, width, height, holder.getSurface());
74                 if (mContentViewCore != null) {
75                     mContentViewCore.onPhysicalBackingSizeChanged(
76                             width, height);
77                 }
78             }
79 
80             @Override
81             public void surfaceCreated(SurfaceHolder holder) {
82                 assert mNativeContentViewRenderView != 0;
83                 nativeSurfaceCreated(mNativeContentViewRenderView);
84 
85                 onReadyToRender();
86             }
87 
88             @Override
89             public void surfaceDestroyed(SurfaceHolder holder) {
90                 assert mNativeContentViewRenderView != 0;
91                 nativeSurfaceDestroyed(mNativeContentViewRenderView);
92             }
93         };
94         mSurfaceView.getHolder().addCallback(mSurfaceCallback);
95         mSurfaceView.setVisibility(VISIBLE);
96 
97         mContentReadbackHandler = new ContentReadbackHandler() {
98             @Override
99             protected boolean readyForReadback() {
100                 return mNativeContentViewRenderView != 0 && mContentViewCore != null;
101             }
102         };
103         mContentReadbackHandler.initNativeContentReadbackHandler();
104     }
105 
106     /**
107      * @return The content readback handler.
108      */
getContentReadbackHandler()109     public ContentReadbackHandler getContentReadbackHandler() {
110         return mContentReadbackHandler;
111     }
112 
113     /**
114      * Sets the background color of the surface view.  This method is necessary because the
115      * background color of ContentViewRenderView itself is covered by the background of
116      * SurfaceView.
117      * @param color The color of the background.
118      */
setSurfaceViewBackgroundColor(int color)119     public void setSurfaceViewBackgroundColor(int color) {
120         if (mSurfaceView != null) {
121             mSurfaceView.setBackgroundColor(color);
122         }
123     }
124 
125     /**
126      * Should be called when the ContentViewRenderView is not needed anymore so its associated
127      * native resource can be freed.
128      */
destroy()129     public void destroy() {
130         mContentReadbackHandler.destroy();
131         mContentReadbackHandler = null;
132         mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
133         nativeDestroy(mNativeContentViewRenderView);
134         mNativeContentViewRenderView = 0;
135     }
136 
setCurrentContentViewCore(ContentViewCore contentViewCore)137     public void setCurrentContentViewCore(ContentViewCore contentViewCore) {
138         assert mNativeContentViewRenderView != 0;
139         mContentViewCore = contentViewCore;
140 
141         if (mContentViewCore != null) {
142             mContentViewCore.onPhysicalBackingSizeChanged(getWidth(), getHeight());
143             nativeSetCurrentContentViewCore(mNativeContentViewRenderView,
144                                             mContentViewCore.getNativeContentViewCore());
145         } else {
146             nativeSetCurrentContentViewCore(mNativeContentViewRenderView, 0);
147         }
148     }
149 
150     /**
151      * Trigger a redraw of the compositor.  This is only needed if the UI changes something that
152      * does not trigger a redraw itself by updating the layer tree.
153      */
setNeedsComposite()154     public void setNeedsComposite() {
155         if (mNativeContentViewRenderView == 0) return;
156         nativeSetNeedsComposite(mNativeContentViewRenderView);
157     }
158 
159     /**
160      * This method should be subclassed to provide actions to be performed once the view is ready to
161      * render.
162      */
onReadyToRender()163     protected void onReadyToRender() {
164     }
165 
166     /**
167      * This method could be subclassed optionally to provide a custom SurfaceView object to
168      * this ContentViewRenderView.
169      * @param context The context used to create the SurfaceView object.
170      * @return The created SurfaceView object.
171      */
createSurfaceView(Context context)172     protected SurfaceView createSurfaceView(Context context) {
173         return new SurfaceView(context);
174     }
175 
176     /**
177      * @return whether the surface view is initialized and ready to render.
178      */
isInitialized()179     public boolean isInitialized() {
180         return mSurfaceView.getHolder().getSurface() != null;
181     }
182 
183     /**
184      * Enter or leave overlay video mode.
185      * @param enabled Whether overlay mode is enabled.
186      */
setOverlayVideoMode(boolean enabled)187     public void setOverlayVideoMode(boolean enabled) {
188         int format = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
189         mSurfaceView.getHolder().setFormat(format);
190         nativeSetOverlayVideoMode(mNativeContentViewRenderView, enabled);
191     }
192 
193     /**
194      * Set the native layer tree helper for this {@link ContentViewRenderView}.
195      * @param layerTreeBuildHelperNativePtr Native pointer to the layer tree build helper.
196      */
setLayerTreeBuildHelper(long layerTreeBuildHelperNativePtr)197     public void setLayerTreeBuildHelper(long layerTreeBuildHelperNativePtr) {
198         nativeSetLayerTreeBuildHelper(mNativeContentViewRenderView, layerTreeBuildHelperNativePtr);
199     }
200 
201     @CalledByNative
onCompositorLayout()202     protected void onCompositorLayout() {
203     }
204 
205     @CalledByNative
onSwapBuffersCompleted()206     private void onSwapBuffersCompleted() {
207         if (mSurfaceView.getBackground() != null) {
208             post(new Runnable() {
209                 @Override public void run() {
210                     mSurfaceView.setBackgroundResource(0);
211                 }
212             });
213         }
214     }
215 
216     /**
217      * @return Native pointer for the UI resource provider taken from the compositor.
218      */
getUIResourceProvider()219     public long getUIResourceProvider() {
220         return nativeGetUIResourceProvider(mNativeContentViewRenderView);
221     }
222 
nativeInit(long rootWindowNativePointer)223     private native long nativeInit(long rootWindowNativePointer);
nativeGetUIResourceProvider(long nativeContentViewRenderView)224     private native long nativeGetUIResourceProvider(long nativeContentViewRenderView);
nativeDestroy(long nativeContentViewRenderView)225     private native void nativeDestroy(long nativeContentViewRenderView);
nativeSetCurrentContentViewCore(long nativeContentViewRenderView, long nativeContentViewCore)226     private native void nativeSetCurrentContentViewCore(long nativeContentViewRenderView,
227             long nativeContentViewCore);
nativeSetLayerTreeBuildHelper(long nativeContentViewRenderView, long buildHelperNativePtr)228     private native void nativeSetLayerTreeBuildHelper(long nativeContentViewRenderView,
229             long buildHelperNativePtr);
nativeSurfaceCreated(long nativeContentViewRenderView)230     private native void nativeSurfaceCreated(long nativeContentViewRenderView);
nativeSurfaceDestroyed(long nativeContentViewRenderView)231     private native void nativeSurfaceDestroyed(long nativeContentViewRenderView);
nativeSurfaceChanged(long nativeContentViewRenderView, int format, int width, int height, Surface surface)232     private native void nativeSurfaceChanged(long nativeContentViewRenderView,
233             int format, int width, int height, Surface surface);
nativeSetOverlayVideoMode(long nativeContentViewRenderView, boolean enabled)234     private native void nativeSetOverlayVideoMode(long nativeContentViewRenderView,
235             boolean enabled);
nativeSetNeedsComposite(long nativeContentViewRenderView)236     private native void nativeSetNeedsComposite(long nativeContentViewRenderView);
237 }
238