ContentViewRenderView.java revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1e62c1185bee05facc25d1d725434f517261d308bChris Lattner// Copyright 2012 The Chromium Authors. All rights reserved.
23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// Use of this source code is governed by a BSD-style license that can be
301d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswell// found in the LICENSE file.
401d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswell
53060910e290949a9ac5eda8726d030790c4d60ffChris Lattnerpackage org.chromium.content.browser;
63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner
73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukmanimport android.content.Context;
801d45827a1e512f3b19ba857772bf02baa3c0c4eJohn Criswellimport android.graphics.Bitmap;
9e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.graphics.Canvas;
1014d7c59491347a2f8f29e120fd75a4cad42f68e7Chris Lattnerimport android.graphics.Color;
1114d7c59491347a2f8f29e120fd75a4cad42f68e7Chris Lattnerimport android.graphics.PixelFormat;
12e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.os.Build;
13e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.os.Handler;
14e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.view.Surface;
15e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.view.SurfaceHolder;
16e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.view.SurfaceView;
17e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport android.widget.FrameLayout;
18099e198ae84c1a6cfe2a7c79ee9f47fa67caac8fChris Lattner
193cc52ea33c0b96d1682f14fc45c45b57df0f39b6Michael J. Spencerimport org.chromium.base.CalledByNative;
201a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarimport org.chromium.base.JNINamespace;
21e62c1185bee05facc25d1d725434f517261d308bChris Lattnerimport org.chromium.base.ObserverList;
22028936ada14335bb04f377d46a6261dc4c66dafdJohn Criswellimport org.chromium.base.ObserverList.RewindableIterator;
23d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekeimport org.chromium.base.TraceEvent;
241a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarimport org.chromium.ui.base.WindowAndroid;
2521870411d9c1807526b613d04c2ebae5a43c263bBob Wilson
267dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner/***
277cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner * This view is used by a ContentView to render its content.
287cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner * Call {@link #setCurrentContentView(ContentView)} with the contentView that should be displayed.
297cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner * Note that only one ContentView can be shown at a time.
307cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner */
317cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner@JNINamespace("content")
327cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattnerpublic class ContentViewRenderView extends FrameLayout {
3340f71134b9fef0ca06c516f033cc9403394a913cChris Lattner    private static final int MAX_SWAP_BUFFER_COUNT = 2;
347cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
357cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    // The native side of this object.
367dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner    private long mNativeContentViewRenderView;
371fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner    private final SurfaceHolder.Callback mSurfaceCallback;
38e62c1185bee05facc25d1d725434f517261d308bChris Lattner
39e62c1185bee05facc25d1d725434f517261d308bChris Lattner    private final SurfaceView mSurfaceView;
40e62c1185bee05facc25d1d725434f517261d308bChris Lattner    private final VSyncAdapter mVSyncAdapter;
41e62c1185bee05facc25d1d725434f517261d308bChris Lattner
42e62c1185bee05facc25d1d725434f517261d308bChris Lattner    private int mPendingRenders;
43e3a1d054483d6e2551a43232f2c968fc7ce523f2Chris Lattner    private int mPendingSwapBuffers;
44e62c1185bee05facc25d1d725434f517261d308bChris Lattner    private boolean mNeedToRender;
45e6c27de069225e1122c78385ad22a2ff656db8e6David Greene
46711e5d96aa648ebe96b09483d0775f3b16283e3dChris Lattner    private ContentView mCurrentContentView;
474afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene
48e62c1185bee05facc25d1d725434f517261d308bChris Lattner    private final Runnable mRenderRunnable = new Runnable() {
498e9a9774eb12b5242f74b8ac5b20e0a938ec9c53Chris Lattner        @Override
50b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner        public void run() {
51b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner            render();
52a1651900e1772b05afd2280308e9acc5a58cefb8Chris Lattner        }
53b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner    };
541dba7abdd77e19c230f0426825a5ae4879471dccChris Lattner
557cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    /**
567dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner     * Constructs a new ContentViewRenderView that should be can to a view hierarchy.
57e62c1185bee05facc25d1d725434f517261d308bChris Lattner     * Native code should add/remove the layers to be rendered through the ContentViewLayerRenderer.
587dda395004eb962cef1c1554b1e8b2ad069760e0Chris Lattner     * @param context The context used to create this.
59293b13350c2fbae8a64b0b0beb440cb859968c8cBob Wilson     */
60e62c1185bee05facc25d1d725434f517261d308bChris Lattner    public ContentViewRenderView(Context context, WindowAndroid rootWindow) {
61e62c1185bee05facc25d1d725434f517261d308bChris Lattner        super(context);
62e62c1185bee05facc25d1d725434f517261d308bChris Lattner        assert rootWindow != null;
63e62c1185bee05facc25d1d725434f517261d308bChris Lattner        mNativeContentViewRenderView = nativeInit(rootWindow.getNativePointer());
64e62c1185bee05facc25d1d725434f517261d308bChris Lattner        assert mNativeContentViewRenderView != 0;
65e62c1185bee05facc25d1d725434f517261d308bChris Lattner
66e62c1185bee05facc25d1d725434f517261d308bChris Lattner        mSurfaceView = createSurfaceView(getContext());
67e62c1185bee05facc25d1d725434f517261d308bChris Lattner        mSurfaceView.setZOrderMediaOverlay(true);
6899ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner        mSurfaceCallback = new SurfaceHolder.Callback() {
691a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar            @Override
707cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
717cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                assert mNativeContentViewRenderView != 0;
727cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                nativeSurfaceChanged(mNativeContentViewRenderView,
737cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                        format, width, height, holder.getSurface());
747cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                if (mCurrentContentView != null) {
757cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                    mCurrentContentView.getContentViewCore().onPhysicalBackingSizeChanged(
767cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                            width, height);
77e62c1185bee05facc25d1d725434f517261d308bChris Lattner                }
78e62c1185bee05facc25d1d725434f517261d308bChris Lattner            }
79e62c1185bee05facc25d1d725434f517261d308bChris Lattner
80e62c1185bee05facc25d1d725434f517261d308bChris Lattner            @Override
81e62c1185bee05facc25d1d725434f517261d308bChris Lattner            public void surfaceCreated(SurfaceHolder holder) {
82e62c1185bee05facc25d1d725434f517261d308bChris Lattner                setSurfaceViewBackgroundColor(Color.WHITE);
83e6c27de069225e1122c78385ad22a2ff656db8e6David Greene
84e6c27de069225e1122c78385ad22a2ff656db8e6David Greene                assert mNativeContentViewRenderView != 0;
85e6c27de069225e1122c78385ad22a2ff656db8e6David Greene                nativeSurfaceCreated(mNativeContentViewRenderView);
86e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene
87e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene                mPendingSwapBuffers = 0;
88e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene                mPendingRenders = 0;
894afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene
904afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene                onReadyToRender();
914afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene            }
92e3a1d054483d6e2551a43232f2c968fc7ce523f2Chris Lattner
93e62c1185bee05facc25d1d725434f517261d308bChris Lattner            @Override
94e62c1185bee05facc25d1d725434f517261d308bChris Lattner            public void surfaceDestroyed(SurfaceHolder holder) {
958e9a9774eb12b5242f74b8ac5b20e0a938ec9c53Chris Lattner                assert mNativeContentViewRenderView != 0;
96b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner                nativeSurfaceDestroyed(mNativeContentViewRenderView);
97b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner            }
98b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner        };
99b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner        mSurfaceView.getHolder().addCallback(mSurfaceCallback);
100b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner
101b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner        mVSyncAdapter = new VSyncAdapter(getContext());
102b45b3b3cd14faaf5a3ea5226af7e1e3cd653e6cbChris Lattner        addView(mSurfaceView,
103e62c1185bee05facc25d1d725434f517261d308bChris Lattner                new FrameLayout.LayoutParams(
1047cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                        FrameLayout.LayoutParams.MATCH_PARENT,
1057cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                        FrameLayout.LayoutParams.MATCH_PARENT));
1067cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    }
1077cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
1087cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    private class VSyncAdapter implements VSyncManager.Provider, VSyncMonitor.Listener {
1097cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        private final VSyncMonitor mVSyncMonitor;
1107cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        private boolean mVSyncNotificationEnabled;
1117cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        private VSyncManager.Listener mVSyncListener;
1127cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        private final ObserverList<VSyncManager.Listener> mCurrentVSyncListeners;
11340f71134b9fef0ca06c516f033cc9403394a913cChris Lattner        private final RewindableIterator<VSyncManager.Listener> mCurrentVSyncListenersIterator;
1147cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
115e62c1185bee05facc25d1d725434f517261d308bChris Lattner        // The VSyncMonitor gives the timebase for the actual vsync, but we don't want render until
116e62c1185bee05facc25d1d725434f517261d308bChris Lattner        // we have had a chance for input events to propagate to the compositor thread. This takes
1171a55180238dbcf11113f610aea010447e51f595bDaniel Dunbar        // 3 ms typically, so we adjust the vsync timestamps forward by a bit to give input events a
118e62c1185bee05facc25d1d725434f517261d308bChris Lattner        // chance to arrive.
119e62c1185bee05facc25d1d725434f517261d308bChris Lattner        private static final long INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS = 3200;
120e62c1185bee05facc25d1d725434f517261d308bChris Lattner
121e62c1185bee05facc25d1d725434f517261d308bChris Lattner        VSyncAdapter(Context context) {
12207278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner            mVSyncMonitor = new VSyncMonitor(context, this);
12307278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner            mCurrentVSyncListeners = new ObserverList<VSyncManager.Listener>();
12407278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner            mCurrentVSyncListenersIterator = mCurrentVSyncListeners.rewindableIterator();
1251fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner        }
1261fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner
127ead87b671278379f92890fddd859a301bb68f462Reid Spencer        @Override
128ead87b671278379f92890fddd859a301bb68f462Reid Spencer        public void onVSync(VSyncMonitor monitor, long vsyncTimeMicros) {
129ead87b671278379f92890fddd859a301bb68f462Reid Spencer            if (mNeedToRender) {
130ead87b671278379f92890fddd859a301bb68f462Reid Spencer                if (mPendingSwapBuffers + mPendingRenders <= MAX_SWAP_BUFFER_COUNT) {
131ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    mNeedToRender = false;
132ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    mPendingRenders++;
133ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    render();
134ead87b671278379f92890fddd859a301bb68f462Reid Spencer                } else {
135ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    TraceEvent.instant("ContentViewRenderView:bail");
136ead87b671278379f92890fddd859a301bb68f462Reid Spencer                }
137e6c27de069225e1122c78385ad22a2ff656db8e6David Greene            }
138e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene
1394afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene            if (mVSyncListener != null) {
140ead87b671278379f92890fddd859a301bb68f462Reid Spencer                if (mVSyncNotificationEnabled) {
141ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    for (mCurrentVSyncListenersIterator.rewind();
142ead87b671278379f92890fddd859a301bb68f462Reid Spencer                            mCurrentVSyncListenersIterator.hasNext();) {
143e62c1185bee05facc25d1d725434f517261d308bChris Lattner                        mCurrentVSyncListenersIterator.next().onVSync(vsyncTimeMicros);
14499ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner                    }
1457cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                    mVSyncMonitor.requestUpdate();
1467cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                } else {
1477cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                    // Compensate for input event lag. Input events are delivered immediately on
1487cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                    // pre-JB releases, so this adjustment is only done for later versions.
149ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
150ead87b671278379f92890fddd859a301bb68f462Reid Spencer                        vsyncTimeMicros += INPUT_EVENT_LAG_FROM_VSYNC_MICROSECONDS;
151ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    }
152ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    mVSyncListener.updateVSync(vsyncTimeMicros,
153ead87b671278379f92890fddd859a301bb68f462Reid Spencer                            mVSyncMonitor.getVSyncPeriodInMicroseconds());
154ead87b671278379f92890fddd859a301bb68f462Reid Spencer                }
155ead87b671278379f92890fddd859a301bb68f462Reid Spencer            }
156ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
157ead87b671278379f92890fddd859a301bb68f462Reid Spencer
158e62c1185bee05facc25d1d725434f517261d308bChris Lattner        @Override
159e62c1185bee05facc25d1d725434f517261d308bChris Lattner        public void registerVSyncListener(VSyncManager.Listener listener) {
16007278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner            if (!mVSyncNotificationEnabled) mVSyncMonitor.requestUpdate();
161234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            mCurrentVSyncListeners.addObserver(listener);
162234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            mVSyncNotificationEnabled = true;
16307278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner        }
164e62c1185bee05facc25d1d725434f517261d308bChris Lattner
165e62c1185bee05facc25d1d725434f517261d308bChris Lattner        @Override
166e62c1185bee05facc25d1d725434f517261d308bChris Lattner        public void unregisterVSyncListener(VSyncManager.Listener listener) {
1671002c0203450620594a85454c6a095ca94b87cb2Dan Gohman            mCurrentVSyncListeners.removeObserver(listener);
168e62c1185bee05facc25d1d725434f517261d308bChris Lattner            mCurrentVSyncListenersIterator.rewind();
169e62c1185bee05facc25d1d725434f517261d308bChris Lattner            if (!mCurrentVSyncListenersIterator.hasNext()) {
170e62c1185bee05facc25d1d725434f517261d308bChris Lattner                mVSyncNotificationEnabled = false;
171ead87b671278379f92890fddd859a301bb68f462Reid Spencer            }
172ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
173ead87b671278379f92890fddd859a301bb68f462Reid Spencer
174ead87b671278379f92890fddd859a301bb68f462Reid Spencer        void setVSyncListener(VSyncManager.Listener listener) {
175ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mVSyncListener = listener;
176ead87b671278379f92890fddd859a301bb68f462Reid Spencer            if (mVSyncListener != null) mVSyncMonitor.requestUpdate();
177ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
178ead87b671278379f92890fddd859a301bb68f462Reid Spencer
179ead87b671278379f92890fddd859a301bb68f462Reid Spencer        void requestUpdate() {
180ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mVSyncMonitor.requestUpdate();
181e6c27de069225e1122c78385ad22a2ff656db8e6David Greene        }
182e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene    }
1834afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene
184ead87b671278379f92890fddd859a301bb68f462Reid Spencer    /**
185ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * Sets the background color of the surface view.  This method is necessary because the
186ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * background color of ContentViewRenderView itself is covered by the background of
187ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * SurfaceView.
18899ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner     * @param color The color of the background.
1897cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner     */
1907cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    public void setSurfaceViewBackgroundColor(int color) {
1917cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        if (mSurfaceView != null) {
1927cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner            mSurfaceView.setBackgroundColor(color);
193ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
194ead87b671278379f92890fddd859a301bb68f462Reid Spencer    }
1957cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
1967cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    /**
197ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * Should be called when the ContentViewRenderView is not needed anymore so its associated
198ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * native resource can be freed.
199ead87b671278379f92890fddd859a301bb68f462Reid Spencer     */
200ead87b671278379f92890fddd859a301bb68f462Reid Spencer    public void destroy() {
201ead87b671278379f92890fddd859a301bb68f462Reid Spencer        mSurfaceView.getHolder().removeCallback(mSurfaceCallback);
202ead87b671278379f92890fddd859a301bb68f462Reid Spencer        nativeDestroy(mNativeContentViewRenderView);
203ead87b671278379f92890fddd859a301bb68f462Reid Spencer        mNativeContentViewRenderView = 0;
204e62c1185bee05facc25d1d725434f517261d308bChris Lattner    }
205e62c1185bee05facc25d1d725434f517261d308bChris Lattner
20607278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner    /**
20707278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner     * Makes the passed ContentView the one displayed by this ContentViewRenderView.
20807278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner     */
2091fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner    public void setCurrentContentView(ContentView contentView) {
2101fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner        assert mNativeContentViewRenderView != 0;
211ead87b671278379f92890fddd859a301bb68f462Reid Spencer        mCurrentContentView = contentView;
212ead87b671278379f92890fddd859a301bb68f462Reid Spencer
213ead87b671278379f92890fddd859a301bb68f462Reid Spencer        ContentViewCore contentViewCore =
214ead87b671278379f92890fddd859a301bb68f462Reid Spencer                contentView != null ? contentView.getContentViewCore() : null;
215ead87b671278379f92890fddd859a301bb68f462Reid Spencer
216ead87b671278379f92890fddd859a301bb68f462Reid Spencer        nativeSetCurrentContentView(mNativeContentViewRenderView,
217ead87b671278379f92890fddd859a301bb68f462Reid Spencer                contentViewCore != null ? contentViewCore.getNativeContentViewCore() : 0);
218ead87b671278379f92890fddd859a301bb68f462Reid Spencer
219ead87b671278379f92890fddd859a301bb68f462Reid Spencer        if (contentViewCore != null) {
220ead87b671278379f92890fddd859a301bb68f462Reid Spencer            contentViewCore.onPhysicalBackingSizeChanged(getWidth(), getHeight());
221e6c27de069225e1122c78385ad22a2ff656db8e6David Greene            mVSyncAdapter.setVSyncListener(contentViewCore.getVSyncListener(mVSyncAdapter));
222e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene        }
2234afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene    }
224ead87b671278379f92890fddd859a301bb68f462Reid Spencer
225ead87b671278379f92890fddd859a301bb68f462Reid Spencer    /**
226ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * This method should be subclassed to provide actions to be performed once the view is ready to
227ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * render.
22899ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner     */
2297cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    protected void onReadyToRender() {
2307cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    }
2317cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
2327cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    /**
2337cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner     * This method could be subclassed optionally to provide a custom SurfaceView object to
234ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * this ContentViewRenderView.
235ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * @param context The context used to create the SurfaceView object.
236ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * @return The created SurfaceView object.
237ead87b671278379f92890fddd859a301bb68f462Reid Spencer     */
238ead87b671278379f92890fddd859a301bb68f462Reid Spencer    protected SurfaceView createSurfaceView(Context context) {
239ead87b671278379f92890fddd859a301bb68f462Reid Spencer        return new SurfaceView(context) {
240ead87b671278379f92890fddd859a301bb68f462Reid Spencer            @Override
241ead87b671278379f92890fddd859a301bb68f462Reid Spencer            public void onDraw(Canvas canvas) {
242ead87b671278379f92890fddd859a301bb68f462Reid Spencer                // We only need to draw to software canvases, which are used for taking screenshots.
243e62c1185bee05facc25d1d725434f517261d308bChris Lattner                if (canvas.isHardwareAccelerated()) return;
244e62c1185bee05facc25d1d725434f517261d308bChris Lattner                Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(),
24507278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner                        Bitmap.Config.ARGB_8888);
24607278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner                if (nativeCompositeToBitmap(mNativeContentViewRenderView, bitmap)) {
2471fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner                    canvas.drawBitmap(bitmap, 0, 0, null);
2481fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner                }
249ead87b671278379f92890fddd859a301bb68f462Reid Spencer            }
250ead87b671278379f92890fddd859a301bb68f462Reid Spencer        };
251ead87b671278379f92890fddd859a301bb68f462Reid Spencer    }
252ead87b671278379f92890fddd859a301bb68f462Reid Spencer
253ead87b671278379f92890fddd859a301bb68f462Reid Spencer    /**
254ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * @return whether the surface view is initialized and ready to render.
255e6c27de069225e1122c78385ad22a2ff656db8e6David Greene     */
256711e5d96aa648ebe96b09483d0775f3b16283e3dChris Lattner    public boolean isInitialized() {
2574afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene        return mSurfaceView.getHolder().getSurface() != null;
258d418c1b768b5ff26afe05a5ce84d920bbbc99583David Greene    }
259ead87b671278379f92890fddd859a301bb68f462Reid Spencer
260ead87b671278379f92890fddd859a301bb68f462Reid Spencer    /**
261ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * Enter or leave overlay video mode.
262ead87b671278379f92890fddd859a301bb68f462Reid Spencer     * @param enabled Whether overlay mode is enabled.
263ead87b671278379f92890fddd859a301bb68f462Reid Spencer     */
264ead87b671278379f92890fddd859a301bb68f462Reid Spencer    public void setOverlayVideoMode(boolean enabled) {
265ead87b671278379f92890fddd859a301bb68f462Reid Spencer        int format = enabled ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
266ead87b671278379f92890fddd859a301bb68f462Reid Spencer        mSurfaceView.getHolder().setFormat(format);
26799ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner        nativeSetOverlayVideoMode(mNativeContentViewRenderView, enabled);
2687cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    }
2697cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner
2707cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    @CalledByNative
2717cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner    private void requestRender() {
2727cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        ContentViewCore contentViewCore = mCurrentContentView != null ?
273ead87b671278379f92890fddd859a301bb68f462Reid Spencer                mCurrentContentView.getContentViewCore() : null;
274ead87b671278379f92890fddd859a301bb68f462Reid Spencer
275ead87b671278379f92890fddd859a301bb68f462Reid Spencer        boolean rendererHasFrame =
2767cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                contentViewCore != null && contentViewCore.consumePendingRendererFrame();
277ead87b671278379f92890fddd859a301bb68f462Reid Spencer
278ead87b671278379f92890fddd859a301bb68f462Reid Spencer        if (rendererHasFrame && mPendingSwapBuffers + mPendingRenders < MAX_SWAP_BUFFER_COUNT) {
279ead87b671278379f92890fddd859a301bb68f462Reid Spencer            TraceEvent.instant("requestRender:now");
280ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mNeedToRender = false;
281e62c1185bee05facc25d1d725434f517261d308bChris Lattner            mPendingRenders++;
282e62c1185bee05facc25d1d725434f517261d308bChris Lattner
283234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            // The handler can be null if we are detached from the window.  Calling
284234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            // {@link View#post(Runnable)} properly handles this case, but we lose the front of
285234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            // queue behavior.  That is okay for this edge case.
286234b3ec8795e0661af56aa1d1a978a41d80686c5Misha Brukman            Handler handler = getHandler();
28707278e48dc27d8ac64b5ff7ed6361536c2f38ea1Chris Lattner            if (handler != null) {
288e62c1185bee05facc25d1d725434f517261d308bChris Lattner                handler.postAtFrontOfQueue(mRenderRunnable);
2897cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner            } else {
290e62c1185bee05facc25d1d725434f517261d308bChris Lattner                post(mRenderRunnable);
2911002c0203450620594a85454c6a095ca94b87cb2Dan Gohman            }
292f1b36f9a71eb267f04b7bd3a32aca9bc69f71e97Chris Lattner            mVSyncAdapter.requestUpdate();
2937cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        } else if (mPendingRenders <= 0) {
294f1b36f9a71eb267f04b7bd3a32aca9bc69f71e97Chris Lattner            assert mPendingRenders == 0;
295ead87b671278379f92890fddd859a301bb68f462Reid Spencer            TraceEvent.instant("requestRender:later");
296ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mNeedToRender = true;
297ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mVSyncAdapter.requestUpdate();
298ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
299ead87b671278379f92890fddd859a301bb68f462Reid Spencer    }
300ead87b671278379f92890fddd859a301bb68f462Reid Spencer
301ead87b671278379f92890fddd859a301bb68f462Reid Spencer    @CalledByNative
302ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private void onSwapBuffersCompleted() {
303ead87b671278379f92890fddd859a301bb68f462Reid Spencer        TraceEvent.instant("onSwapBuffersCompleted");
304ead87b671278379f92890fddd859a301bb68f462Reid Spencer
305e6c27de069225e1122c78385ad22a2ff656db8e6David Greene        if (mPendingSwapBuffers == MAX_SWAP_BUFFER_COUNT && mNeedToRender) requestRender();
306e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene        if (mPendingSwapBuffers > 0) mPendingSwapBuffers--;
3074afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene    }
308ead87b671278379f92890fddd859a301bb68f462Reid Spencer
309ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private void render() {
310ead87b671278379f92890fddd859a301bb68f462Reid Spencer        if (mPendingRenders > 0) mPendingRenders--;
3113da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman
31299ba1f7b8deaf2a296c98600dbf593754cbd43a2Chris Lattner        // Waiting for the content view contents to be ready avoids compositing
3137cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        // when the surface texture is still empty.
3147cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        if (mCurrentContentView == null) return;
3157cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        ContentViewCore contentViewCore = mCurrentContentView.getContentViewCore();
3167cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner        if (contentViewCore == null || !contentViewCore.isReady()) {
3177cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner            return;
318ead87b671278379f92890fddd859a301bb68f462Reid Spencer        }
319ead87b671278379f92890fddd859a301bb68f462Reid Spencer
320ead87b671278379f92890fddd859a301bb68f462Reid Spencer        boolean didDraw = nativeComposite(mNativeContentViewRenderView);
321ead87b671278379f92890fddd859a301bb68f462Reid Spencer        if (didDraw) {
322ead87b671278379f92890fddd859a301bb68f462Reid Spencer            mPendingSwapBuffers++;
3233da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman            if (mSurfaceView.getBackground() != null) {
3247cf0ce4b8d122575c3348b5fa4947014c3d8432dChris Lattner                post(new Runnable() {
325ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    @Override
326ead87b671278379f92890fddd859a301bb68f462Reid Spencer                    public void run() {
327ead87b671278379f92890fddd859a301bb68f462Reid Spencer                        mSurfaceView.setBackgroundResource(0);
328e62c1185bee05facc25d1d725434f517261d308bChris Lattner                    }
329e62c1185bee05facc25d1d725434f517261d308bChris Lattner                });
330f05760de76b4ec26474da18c97770ca369972cfdChris Lattner            }
331f05760de76b4ec26474da18c97770ca369972cfdChris Lattner        }
3321fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner    }
3331fca5ff62bb2ecb5bfc8974f4dbfc56e9d3ca721Chris Lattner
334ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native long nativeInit(long rootWindowNativePointer);
335ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native void nativeDestroy(long nativeContentViewRenderView);
336ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native void nativeSetCurrentContentView(long nativeContentViewRenderView,
337ead87b671278379f92890fddd859a301bb68f462Reid Spencer            long nativeContentView);
338ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native void nativeSurfaceCreated(long nativeContentViewRenderView);
339ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native void nativeSurfaceDestroyed(long nativeContentViewRenderView);
340ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native void nativeSurfaceChanged(long nativeContentViewRenderView,
341ead87b671278379f92890fddd859a301bb68f462Reid Spencer            int format, int width, int height, Surface surface);
342ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native boolean nativeComposite(long nativeContentViewRenderView);
343ead87b671278379f92890fddd859a301bb68f462Reid Spencer    private native boolean nativeCompositeToBitmap(long nativeContentViewRenderView, Bitmap bitmap);
344e6c27de069225e1122c78385ad22a2ff656db8e6David Greene    private native void nativeSetOverlayVideoMode(long nativeContentViewRenderView,
345e8cf21e8e3db64dd49777d6bf6c867d47e9f5407David Greene            boolean enabled);
3464afc509b7ffe2c4ea234dfd7af5105feb21685d9David Greene}
347ead87b671278379f92890fddd859a301bb68f462Reid Spencer