• Home
  • 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      * This method should be subclassed to provide actions to be performed once the view is ready to
152      * render.
153      */
onReadyToRender()154     protected void onReadyToRender() {
155     }
156 
157     /**
158      * This method could be subclassed optionally to provide a custom SurfaceView object to
159      * this ContentViewRenderView.
160      * @param context The context used to create the SurfaceView object.
161      * @return The created SurfaceView object.
162      */
createSurfaceView(Context context)163     protected SurfaceView createSurfaceView(Context context) {
164         return new SurfaceView(context);
165     }
166 
167     /**
168      * @return whether the surface view is initialized and ready to render.
169      */
isInitialized()170     public boolean isInitialized() {
171         return mSurfaceView.getHolder().getSurface() != null;
172     }
173 
174     /**
175      * Enter or leave overlay video mode.
176      * @param enabled Whether overlay mode is enabled.
177      */
setOverlayVideoMode(boolean enabled)178     public void setOverlayVideoMode(boolean enabled) {
179         int format = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
180         mSurfaceView.getHolder().setFormat(format);
181         nativeSetOverlayVideoMode(mNativeContentViewRenderView, enabled);
182     }
183 
184     /**
185      * Set the native layer tree helper for this {@link ContentViewRenderView}.
186      * @param layerTreeBuildHelperNativePtr Native pointer to the layer tree build helper.
187      */
setLayerTreeBuildHelper(long layerTreeBuildHelperNativePtr)188     public void setLayerTreeBuildHelper(long layerTreeBuildHelperNativePtr) {
189         nativeSetLayerTreeBuildHelper(mNativeContentViewRenderView, layerTreeBuildHelperNativePtr);
190     }
191 
192     @CalledByNative
onCompositorLayout()193     protected void onCompositorLayout() {
194     }
195 
196     @CalledByNative
onSwapBuffersCompleted()197     private void onSwapBuffersCompleted() {
198         if (mSurfaceView.getBackground() != null) {
199             post(new Runnable() {
200                 @Override public void run() {
201                     mSurfaceView.setBackgroundResource(0);
202                 }
203             });
204         }
205     }
206 
nativeInit(long rootWindowNativePointer)207     private native long nativeInit(long rootWindowNativePointer);
nativeDestroy(long nativeContentViewRenderView)208     private native void nativeDestroy(long nativeContentViewRenderView);
nativeSetCurrentContentViewCore(long nativeContentViewRenderView, long nativeContentViewCore)209     private native void nativeSetCurrentContentViewCore(long nativeContentViewRenderView,
210             long nativeContentViewCore);
nativeSetLayerTreeBuildHelper(long nativeContentViewRenderView, long buildHelperNativePtr)211     private native void nativeSetLayerTreeBuildHelper(long nativeContentViewRenderView,
212             long buildHelperNativePtr);
nativeSurfaceCreated(long nativeContentViewRenderView)213     private native void nativeSurfaceCreated(long nativeContentViewRenderView);
nativeSurfaceDestroyed(long nativeContentViewRenderView)214     private native void nativeSurfaceDestroyed(long nativeContentViewRenderView);
nativeSurfaceChanged(long nativeContentViewRenderView, int format, int width, int height, Surface surface)215     private native void nativeSurfaceChanged(long nativeContentViewRenderView,
216             int format, int width, int height, Surface surface);
nativeSetOverlayVideoMode(long nativeContentViewRenderView, boolean enabled)217     private native void nativeSetOverlayVideoMode(long nativeContentViewRenderView,
218             boolean enabled);
219 }
220