diff options
author | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-01 00:16:46 +0000 |
---|---|---|
committer | sievers@chromium.org <sievers@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-01 00:16:46 +0000 |
commit | 15c0ba4241581b49a7241ed9081840307a66b0d1 (patch) | |
tree | fadea6e555b19b1bfe68cb5c5a22c73c40166e89 /content | |
parent | edec252702b2027ebe5564746c1582b7dd4e9752 (diff) | |
download | chromium_src-15c0ba4241581b49a7241ed9081840307a66b0d1.zip chromium_src-15c0ba4241581b49a7241ed9081840307a66b0d1.tar.gz chromium_src-15c0ba4241581b49a7241ed9081840307a66b0d1.tar.bz2 |
ContentShell rendering support on Android.
This renders to a SurfaceView using texture sharing on the GPU
thread. There is a bit of a public interface added to let the
app create a cmdbuffer (we want run GL contexts on the same thread
when sharing resources on Android) and perform the handshaking
needed for sharing the two compositor buffers.
It has bugs, such as that it doesn't handle it yet when the UI
surface handle changes (e.g. when hiding and restoring the app).
BUG=136923
Review URL: https://chromiumcodereview.appspot.com/10823051
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149327 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/android/draw_delegate_impl.cc | 38 | ||||
-rw-r--r-- | content/browser/android/draw_delegate_impl.h | 42 | ||||
-rw-r--r-- | content/browser/android/graphics_context.cc | 116 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_android.cc | 18 | ||||
-rw-r--r-- | content/content_browser.gypi | 5 | ||||
-rw-r--r-- | content/content_shell.gypi | 2 | ||||
-rw-r--r-- | content/public/browser/android/draw_delegate.h | 41 | ||||
-rw-r--r-- | content/public/browser/android/graphics_context.h | 31 | ||||
-rw-r--r-- | content/shell/android/draw_context.cc | 117 | ||||
-rw-r--r-- | content/shell/android/draw_context.h | 49 | ||||
-rw-r--r-- | content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java | 13 | ||||
-rw-r--r-- | content/shell/android/java/src/org/chromium/content_shell/Shell.java | 18 | ||||
-rw-r--r-- | content/shell/android/java/src/org/chromium/content_shell/ShellManager.java | 38 | ||||
-rw-r--r-- | content/shell/android/shell_manager.cc | 66 | ||||
-rw-r--r-- | content/shell/shell_android.cc | 5 | ||||
-rw-r--r-- | content/shell/shell_browser_main_parts.cc | 6 |
16 files changed, 591 insertions, 14 deletions
diff --git a/content/browser/android/draw_delegate_impl.cc b/content/browser/android/draw_delegate_impl.cc new file mode 100644 index 0000000..43fc1a0 --- /dev/null +++ b/content/browser/android/draw_delegate_impl.cc @@ -0,0 +1,38 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/android/draw_delegate_impl.h" + +#include "base/memory/singleton.h" + +namespace content { + +// static +DrawDelegate* DrawDelegate::GetInstance() { + return DrawDelegateImpl::GetInstance(); +} + +// static +DrawDelegateImpl* DrawDelegateImpl::GetInstance() { + return Singleton<DrawDelegateImpl>::get(); +} + +DrawDelegateImpl::DrawDelegateImpl() { +} + +DrawDelegateImpl::~DrawDelegateImpl() { +} + +void DrawDelegateImpl::SetUpdateCallback( + const SurfaceUpdatedCallback& callback) { + draw_callback_ = callback; +} + +void DrawDelegateImpl::OnSurfaceUpdated( + uint64 texture, RenderWidgetHostView* view, + const SurfacePresentedCallback& present_callback) { + draw_callback_.Run(texture, view, present_callback); +} + +} // namespace content diff --git a/content/browser/android/draw_delegate_impl.h b/content/browser/android/draw_delegate_impl.h new file mode 100644 index 0000000..c66fb56 --- /dev/null +++ b/content/browser/android/draw_delegate_impl.h @@ -0,0 +1,42 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_ANDROID_DRAW_DELEGATE_IMPL_H_ +#define CONTENT_BROWSER_ANDROID_DRAW_DELEGATE_IMPL_H_ + +#include "base/callback.h" +#include "content/public/browser/android/draw_delegate.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" + +namespace content { + +class DrawDelegateImpl : public DrawDelegate { + public: + static DrawDelegateImpl* GetInstance(); + DrawDelegateImpl(); + virtual ~DrawDelegateImpl(); + + // DrawDelegate implementation. + virtual void SetUpdateCallback( + const SurfaceUpdatedCallback& callback) OVERRIDE; + virtual void SetBounds(const gfx::Size& size) OVERRIDE { size_ = size; } + + void SetDrawSurface(gfx::GLSurfaceHandle handle) { handle_ = handle; } + void OnSurfaceUpdated(uint64 texture, RenderWidgetHostView* view, + const SurfacePresentedCallback& present_callback); + gfx::Size GetBounds() { return size_; } + gfx::GLSurfaceHandle GetDrawSurface() { return handle_; } + + protected: + SurfaceUpdatedCallback draw_callback_; + gfx::GLSurfaceHandle handle_; + gfx::Size size_; + + DISALLOW_COPY_AND_ASSIGN(DrawDelegateImpl); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ANDROID_DRAW_DELEGATE_IMPL_H_ diff --git a/content/browser/android/graphics_context.cc b/content/browser/android/graphics_context.cc new file mode 100644 index 0000000..29b7ad6f --- /dev/null +++ b/content/browser/android/graphics_context.cc @@ -0,0 +1,116 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/public/browser/android/graphics_context.h" + +#include "base/memory/scoped_ptr.h" +#include "content/browser/android/draw_delegate_impl.h" +#include "content/browser/gpu/browser_gpu_channel_host_factory.h" +#include "content/browser/gpu/gpu_surface_tracker.h" +#include "content/common/gpu/client/gpu_channel_host.h" +#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" +#include "content/common/gpu/gpu_process_launch_causes.h" +#include "ui/gfx/native_widget_types.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h" + +#include <android/native_window_jni.h> + +using content::BrowserGpuChannelHostFactory; + +namespace { + +// GraphicsContext implementation using a gpu command buffer. +class CmdBufferGraphicsContext : public content::GraphicsContext { + public: + CmdBufferGraphicsContext(WebGraphicsContext3DCommandBufferImpl* context, + int surface_id, + ANativeWindow* window, + int texture_id1, + int texture_id2) + : context_(context), + surface_id_(surface_id), + window_(window) { + texture_id_[0] = texture_id1; + texture_id_[1] = texture_id2; + } + + virtual ~CmdBufferGraphicsContext() { + context_->makeContextCurrent(); + context_->deleteTexture(texture_id_[0]); + context_->deleteTexture(texture_id_[1]); + context_->finish(); + GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); + tracker->RemoveSurface(surface_id_); + ANativeWindow_release(window_); + } + + virtual WebKit::WebGraphicsContext3D* GetContext3D() { + return context_.get(); + } + virtual uint32 InsertSyncPoint() { + return context_->insertSyncPoint(); + } + + private: + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_; + int surface_id_; + ANativeWindow* window_; + int texture_id_[2]; +}; + +} // anonymous namespace + +namespace content { + +// static +GraphicsContext* GraphicsContext::CreateForUI( + ANativeWindow* window) { + DCHECK(window); + GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); + + ANativeWindow_acquire(window); + int surface_id = tracker->AddSurfaceForNativeWidget(window); + + tracker->SetSurfaceHandle( + surface_id, + gfx::GLSurfaceHandle(gfx::kDummyPluginWindow, false)); + + WebKit::WebGraphicsContext3D::Attributes attrs; + attrs.shareResources = true; + GpuChannelHostFactory* factory = BrowserGpuChannelHostFactory::instance(); + GURL url("chrome://gpu/GpuProcessTransportHelper::CreateContext"); + base::WeakPtr<WebGraphicsContext3DSwapBuffersClient> swap_client; + scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context( + new WebGraphicsContext3DCommandBufferImpl( + surface_id, + url, + factory, + swap_client)); + if (!context->Initialize( + attrs, + false, + CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE)) { + return NULL; + } + + context->makeContextCurrent(); + + gfx::GLSurfaceHandle handle = gfx::GLSurfaceHandle( + gfx::kNullPluginWindow, true); + handle.parent_gpu_process_id = context->GetGPUProcessID(); + handle.parent_client_id = context->GetChannelID(); + handle.parent_context_id = context->GetContextID(); + handle.parent_texture_id[0] = context->createTexture(); + handle.parent_texture_id[1] = context->createTexture(); + handle.sync_point = context->insertSyncPoint(); + + DrawDelegateImpl::GetInstance()->SetDrawSurface(handle); + + return new CmdBufferGraphicsContext( + context.release(), surface_id, window, + handle.parent_texture_id[0], + handle.parent_texture_id[1]); +} + +} // namespace content diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index 0315bdc..22e2021 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -4,13 +4,16 @@ #include "content/browser/renderer_host/render_widget_host_view_android.h" +#include "base/bind.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/utf_string_conversions.h" #include "content/browser/android/content_view_core_impl.h" +#include "content/browser/android/draw_delegate_impl.h" #include "content/browser/gpu/gpu_surface_tracker.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/android/device_info.h" +#include "content/common/gpu/gpu_messages.h" #include "content/common/view_messages.h" namespace content { @@ -150,6 +153,10 @@ bool RenderWidgetHostViewAndroid::IsShowing() { } gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const { + gfx::Size bounds = DrawDelegateImpl::GetInstance()->GetBounds(); + if (!bounds.IsEmpty()) + return gfx::Rect(bounds); + if (content_view_core_) { return content_view_core_->GetBounds(); } else { @@ -258,7 +265,11 @@ void RenderWidgetHostViewAndroid::OnAcceleratedCompositingStateChange() { void RenderWidgetHostViewAndroid::AcceleratedSurfaceBuffersSwapped( const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params, int gpu_host_id) { - NOTREACHED(); + DrawDelegateImpl::GetInstance()->OnSurfaceUpdated( + params.surface_handle, + this, + base::Bind(&RenderWidgetHostImpl::AcknowledgeBufferPresent, + params.route_id, gpu_host_id)); } void RenderWidgetHostViewAndroid::AcceleratedSurfacePostSubBuffer( @@ -284,6 +295,11 @@ void RenderWidgetHostViewAndroid::StartContentIntent( } gfx::GLSurfaceHandle RenderWidgetHostViewAndroid::GetCompositingSurface() { + gfx::GLSurfaceHandle handle = + DrawDelegateImpl::GetInstance()->GetDrawSurface(); + if (!handle.is_null()) + return handle; + // On Android, we cannot generate a window handle that can be passed to the // GPU process through the native side. Instead, we send the surface handle // through Binder after the compositing context has been created. diff --git a/content/content_browser.gypi b/content/content_browser.gypi index 351143d..b264cf4 100644 --- a/content/content_browser.gypi +++ b/content/content_browser.gypi @@ -33,6 +33,8 @@ 'public/browser/access_token_store.h', 'public/browser/android/content_view_core.h', 'public/browser/android/devtools_server.h', + 'public/browser/android/draw_delegate.h', + 'public/browser/android/graphics_context.h', 'public/browser/browser_accessibility_state.h', 'public/browser/browser_child_process_host.h', 'public/browser/browser_child_process_host_delegate.cc', @@ -210,6 +212,9 @@ 'browser/android/devtools_server.cc', 'browser/android/download_controller.cc', 'browser/android/download_controller.h', + 'browser/android/draw_delegate_impl.h', + 'browser/android/draw_delegate_impl.cc', + 'browser/android/graphics_context.cc', 'browser/android/ime_utils.cc', 'browser/android/ime_utils.h', 'browser/android/remote_debugging_controller.cc', diff --git a/content/content_shell.gypi b/content/content_shell.gypi index cd57406..a2a00af 100644 --- a/content/content_shell.gypi +++ b/content/content_shell.gypi @@ -42,6 +42,8 @@ '..', ], 'sources': [ + 'shell/android/draw_context.cc', + 'shell/android/draw_context.h', 'shell/geolocation/shell_access_token_store.cc', 'shell/geolocation/shell_access_token_store.h', 'shell/layout_test_controller.cc', diff --git a/content/public/browser/android/draw_delegate.h b/content/public/browser/android/draw_delegate.h new file mode 100644 index 0000000..b1a8eff --- /dev/null +++ b/content/public/browser/android/draw_delegate.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_DRAW_DELEGATE_H_ +#define CONTENT_PUBLIC_BROWSER_ANDROID_DRAW_DELEGATE_H_ + +#include "base/callback.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" + +namespace content { + +class RenderWidgetHostView; + +// This interface facilitates the communication between compositor and +// UI with respect to new frames arriving and acknowledging when they +// have been presented. +class DrawDelegate { + public: + static DrawDelegate* GetInstance(); + virtual ~DrawDelegate() { } + + // Callback to be run after the frame has been drawn. It passes back + // a synchronization point identifier. + typedef base::Callback<void(uint32)> SurfacePresentedCallback; + + // Notification to the UI that the surface identified by the texture id + // has been updated. + typedef base::Callback<void( + uint64, + RenderWidgetHostView*, + const SurfacePresentedCallback&)> SurfaceUpdatedCallback; + + virtual void SetUpdateCallback(const SurfaceUpdatedCallback& callback) = 0; + virtual void SetBounds(const gfx::Size& size) = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_ANDROID_DRAW_DELEGATE_H_ diff --git a/content/public/browser/android/graphics_context.h b/content/public/browser/android/graphics_context.h new file mode 100644 index 0000000..a8d8285 --- /dev/null +++ b/content/public/browser/android/graphics_context.h @@ -0,0 +1,31 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_GRAPHICS_CONTEXT_H_ +#define CONTENT_PUBLIC_BROWSER_ANDROID_GRAPHICS_CONTEXT_H_ + +#include "ui/gfx/native_widget_types.h" + +struct ANativeWindow; + +namespace WebKit { +class WebGraphicsContext3D; +} + +namespace content { + +class GraphicsContext { + public: + virtual ~GraphicsContext() { } + + // Create a UI graphics context that renders to the given surface. + static GraphicsContext* CreateForUI(ANativeWindow* ui_window); + + virtual WebKit::WebGraphicsContext3D* GetContext3D() = 0; + virtual uint32 InsertSyncPoint() = 0; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_ANDROID_GRAPHICS_CONTEXT_H_ diff --git a/content/shell/android/draw_context.cc b/content/shell/android/draw_context.cc new file mode 100644 index 0000000..d5a8fc7 --- /dev/null +++ b/content/shell/android/draw_context.cc @@ -0,0 +1,117 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/shell/android/draw_context.h" + +#include "base/logging.h" +#include "content/public/browser/android/graphics_context.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h" + +namespace { + +static const char g_vertex_shader[] = + "attribute vec4 a_Position;" + "attribute vec2 a_texCoord;" + "varying vec2 v_texCoord;" + "void main() {" + " gl_Position = a_Position;" + " v_texCoord = a_texCoord;" + "}"; + +// Minimal texture mapping pixel shader. +static const char g_fragment_shader[] = + "precision mediump float;" + "varying vec2 v_texCoord;" + "uniform sampler2D s_texture;" + "void main() {" + " gl_FragColor = texture2D(s_texture, v_texCoord);" + "}"; + +} // anonymous namespace + +namespace content { + +DrawContext::DrawContext(ANativeWindow* window) + : program_(GL_ZERO), + vertex_shader_(0), + fragment_shader_(0), + texture_uniform_(GL_ZERO), + vertex_buffer_(GL_ZERO), + context_(content::GraphicsContext::CreateForUI(window)) { + const GLfloat attribs[] = { + -1.0f, -1.0f, + 1.0f, -1.0f, + -1.0f, 1.0f, + 1.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f }; + WebKit::WebGraphicsContext3D* context3D = context_->GetContext3D(); + vertex_buffer_ = context3D->createBuffer(); + context3D->bindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + context3D->bufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), attribs, + GL_STATIC_DRAW); + + vertex_shader_ = context3D->createShader(GL_VERTEX_SHADER); + context3D->shaderSource(vertex_shader_, g_vertex_shader); + context3D->compileShader(vertex_shader_); + + fragment_shader_ = context3D->createShader(GL_FRAGMENT_SHADER); + context3D->shaderSource(fragment_shader_, g_fragment_shader); + context3D->compileShader(fragment_shader_); + + program_ = context3D->createProgram(); + context3D->attachShader(program_, vertex_shader_); + context3D->attachShader(program_, fragment_shader_); + context3D->linkProgram(program_); + + texture_uniform_ = context3D->getUniformLocation(program_, "s_texture"); +} + +DrawContext::~DrawContext() { + if (vertex_buffer_ != GL_ZERO) + context_->GetContext3D()->deleteBuffer(vertex_buffer_); + if (program_ != GL_ZERO) + context_->GetContext3D()->deleteProgram(program_); +} + +uint32 DrawContext::Draw(int texture) { + DCHECK(program_ != GL_ZERO); + WebKit::WebGraphicsContext3D* context3D = context_->GetContext3D(); + + context3D->useProgram(program_); + + context3D->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + context3D->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + context3D->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + context3D->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + context3D->uniform1i(texture_uniform_, 0); + context3D->activeTexture(GL_TEXTURE0); + context3D->bindTexture(GL_TEXTURE_2D, texture); + + context3D->bindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + context3D->enableVertexAttribArray(0); + context3D->vertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0); + context3D->bindAttribLocation(program_, 0, "a_Position"); + context3D->enableVertexAttribArray(1); + context3D->vertexAttribPointer( + 1, 2, GL_FLOAT, GL_FALSE, 0, 8 * sizeof(GLfloat)); + context3D->bindAttribLocation(program_, 1, "a_texCoord"); + + context3D->drawArrays(GL_TRIANGLE_STRIP, 0, 4); + + context3D->prepareTexture(); + + return context_->InsertSyncPoint(); +} + +void DrawContext::Reshape(int width, int height) { + WebKit::WebGraphicsContext3D* context3D = context_->GetContext3D(); + context3D->viewport(0, 0, width, height); + context3D->reshape(width, height); +} + +} // namespace content diff --git a/content/shell/android/draw_context.h b/content/shell/android/draw_context.h new file mode 100644 index 0000000..c6f5094 --- /dev/null +++ b/content/shell/android/draw_context.h @@ -0,0 +1,49 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_SHELL_ANDROID_DRAW_CONTEXT_H_ +#define CONTENT_SHELL_ANDROID_DRAW_CONTEXT_H_ + +#include "base/memory/scoped_ptr.h" +#include "base/synchronization/lock.h" +#include "ui/gfx/native_widget_types.h" + +#include <GLES2/gl2.h> + +namespace content { +class GraphicsContext; + +// Helper class for drawing content textures to the UI window surface. +class DrawContext { + public: + DrawContext(ANativeWindow* window); + ~DrawContext(); + + // Draws the given texture to the UI and returns a + // SyncPoint identifier. + uint32 Draw(int texture); + + void Reshape(int width, int height); + + private: + // The shader program. + int program_; + int vertex_shader_; + int fragment_shader_; + + // Shader uniform locations. + int texture_uniform_; + + // The vertex attribute array used to draw a simple quad. + unsigned int vertex_buffer_; + + // The graphics context used for drawing. + scoped_ptr<content::GraphicsContext> context_; + + DISALLOW_COPY_AND_ASSIGN(DrawContext); +}; + +} // namespace content + +#endif // CONTENT_SHELL_ANDROID_DRAW_CONTEXT_H_ diff --git a/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java b/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java index c4ca176..039bef5 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java +++ b/content/shell/android/java/src/org/chromium/content_shell/ContentShellActivity.java @@ -25,7 +25,7 @@ public class ContentShellActivity extends Activity { private static final String TAG = ContentShellActivity.class.getName(); private static final String ACTIVE_SHELL_URL_KEY = "activeUrl"; - private static final String DEFAULT_SHELL_URL = "http://www.google.com"; + public static final String DEFAULT_SHELL_URL = "http://www.google.com"; private ShellManager mShellManager; @@ -35,11 +35,6 @@ public class ContentShellActivity extends Activity { // Initializing the command line must occur before loading the library. if (!CommandLine.isInitialized()) CommandLine.initFromFile(COMMAND_LINE_FILE); - String startupUrl = getUrlFromIntent(getIntent()); - if (!TextUtils.isEmpty(startupUrl)) { - CommandLine.getInstance().appendSwitchesAndArguments( - new String[] {Shell.sanitizeUrl(startupUrl)}); - } waitForDebuggerIfNeeded(); LibraryLoader.loadAndInitSync(); @@ -47,6 +42,12 @@ public class ContentShellActivity extends Activity { setContentView(R.layout.content_shell_activity); mShellManager = (ShellManager) findViewById(R.id.shell_container); + + String startupUrl = getUrlFromIntent(getIntent()); + if (!TextUtils.isEmpty(startupUrl)) { + mShellManager.setStartupUrl(Shell.sanitizeUrl(startupUrl)); + } + if (!ContentView.enableMultiProcess(this, ContentView.MAX_RENDERERS_AUTOMATIC)) { String shellUrl = DEFAULT_SHELL_URL; if (savedInstanceState != null diff --git a/content/shell/android/java/src/org/chromium/content_shell/Shell.java b/content/shell/android/java/src/org/chromium/content_shell/Shell.java index b9eb8f0..69414cd 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/Shell.java +++ b/content/shell/android/java/src/org/chromium/content_shell/Shell.java @@ -46,6 +46,8 @@ public class Shell extends LinearLayout { private ClipDrawable mProgressDrawable; + private View mSurfaceView; + /** * Constructor for inflating via XML. */ @@ -53,17 +55,27 @@ public class Shell extends LinearLayout { super(context, attrs); } + /** + * Set the SurfaceView being renderered to as soon as it is available. + */ + public void setSurfaceView(View surfaceView) { + mSurfaceView = surfaceView; + ((FrameLayout) findViewById(R.id.contentview_holder)).addView(mSurfaceView, + new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT)); + } + @Override protected void onFinishInflate() { super.onFinishInflate(); mProgressDrawable = (ClipDrawable) findViewById(R.id.toolbar).getBackground(); - - initilizeUrlField(); + initializeUrlField(); initializeNavigationButtons(); } - private void initilizeUrlField() { + private void initializeUrlField() { mUrlTextView = (EditText) findViewById(R.id.url); mUrlTextView.setOnEditorActionListener(new OnEditorActionListener() { @Override diff --git a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java index feb6c84..e97ba20 100644 --- a/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java +++ b/content/shell/android/java/src/org/chromium/content_shell/ShellManager.java @@ -7,6 +7,9 @@ package org.chromium.content_shell; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; +import android.view.Surface; +import android.view.SurfaceView; +import android.view.SurfaceHolder; import android.widget.FrameLayout; import org.chromium.base.CalledByNative; @@ -20,12 +23,43 @@ public class ShellManager extends FrameLayout { private Shell mActiveShell; + private String mStartupUrl = ContentShellActivity.DEFAULT_SHELL_URL; + + // The target for all content rendering. + private SurfaceView mSurfaceView; + /** * Constructor for inflating via XML. */ public ShellManager(Context context, AttributeSet attrs) { super(context, attrs); nativeInit(this); + + mSurfaceView = new SurfaceView(context); + mSurfaceView.getHolder().addCallback(new SurfaceHolder.Callback() { + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + nativeSurfaceSetSize(width, height); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + nativeSurfaceCreated(holder.getSurface()); + mActiveShell.loadUrl(mStartupUrl); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + nativeSurfaceDestroyed(); + } + }); + } + + /** + * Sets the startup URL for new shell windows. + */ + public void setStartupUrl(String url) { + mStartupUrl = url; } /** @@ -49,6 +83,7 @@ public class ShellManager extends FrameLayout { LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); Shell shellView = (Shell) inflater.inflate(R.layout.shell_view, null); + shellView.setSurfaceView(mSurfaceView); removeAllViews(); addView(shellView, new FrameLayout.LayoutParams( @@ -60,4 +95,7 @@ public class ShellManager extends FrameLayout { private static native void nativeInit(Object shellManagerInstance); private static native void nativeLaunchShell(String url); + private static native void nativeSurfaceCreated(Surface surface); + private static native void nativeSurfaceDestroyed(); + private static native void nativeSurfaceSetSize(int width, int height); } diff --git a/content/shell/android/shell_manager.cc b/content/shell/android/shell_manager.cc index 5972409..26c2240 100644 --- a/content/shell/android/shell_manager.cc +++ b/content/shell/android/shell_manager.cc @@ -7,24 +7,54 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/bind.h" #include "base/lazy_instance.h" #include "content/shell/shell.h" #include "content/shell/shell_browser_context.h" #include "content/shell/shell_content_browser_client.h" +#include "content/public/browser/android/draw_delegate.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "content/shell/android/draw_context.h" +#include "content/shell/shell.h" #include "googleurl/src/gurl.h" #include "jni/ShellManager_jni.h" +#include "ui/gfx/size.h" + +#include <android/native_window_jni.h> using base::android::ScopedJavaLocalRef; +using content::DrawContext; +using content::DrawDelegate; + +namespace { + +struct GlobalState { + GlobalState() + : context(NULL) { + } + base::android::ScopedJavaGlobalRef<jobject> j_obj; + DrawContext* context; +}; + +base::LazyInstance<GlobalState> g_global_state = LAZY_INSTANCE_INITIALIZER; + +static void SurfaceUpdated( + uint64 texture, + content::RenderWidgetHostView* view, + const DrawDelegate::SurfacePresentedCallback& callback) { + uint32 sync_point = g_global_state.Get().context->Draw(texture); + callback.Run(sync_point); +} -base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject> > - g_content_shell_manager = LAZY_INSTANCE_INITIALIZER; +} // anonymous namespace namespace content { jobject CreateShellView() { JNIEnv* env = base::android::AttachCurrentThread(); return Java_ShellManager_createShell( - env, g_content_shell_manager.Get().obj()).Release(); + env, g_global_state.Get().j_obj.obj()).Release(); } // Register native methods @@ -33,8 +63,36 @@ bool RegisterShellManager(JNIEnv* env) { } static void Init(JNIEnv* env, jclass clazz, jobject obj) { - g_content_shell_manager.Get().Reset( + g_global_state.Get().j_obj.Reset( base::android::ScopedJavaLocalRef<jobject>(env, obj)); + DrawDelegate::SurfaceUpdatedCallback cb = base::Bind( + &SurfaceUpdated); + DrawDelegate::GetInstance()->SetUpdateCallback(cb); +} + +static void SurfaceCreated( + JNIEnv* env, jclass clazz, jobject jsurface) { + ANativeWindow* native_window = ANativeWindow_fromSurface(env, jsurface); + if (native_window) { + if (g_global_state.Get().context) + delete g_global_state.Get().context; + + g_global_state.Get().context = new DrawContext(native_window); + ANativeWindow_release(native_window); + } +} + +static void SurfaceDestroyed(JNIEnv* env, jclass clazz) { + if (g_global_state.Get().context) + delete g_global_state.Get().context; +} + +static void SurfaceSetSize( + JNIEnv* env, jclass clazz, jint width, jint height) { + gfx::Size size = gfx::Size(width, height); + DrawDelegate::GetInstance()->SetBounds(size); + DCHECK(g_global_state.Get().context); + g_global_state.Get().context->Reshape(width, height); } void LaunchShell(JNIEnv* env, jclass clazz, jstring jurl) { diff --git a/content/shell/shell_android.cc b/content/shell/shell_android.cc index 242651c..cbf0b13 100644 --- a/content/shell/shell_android.cc +++ b/content/shell/shell_android.cc @@ -8,8 +8,10 @@ #include "base/android/scoped_java_ref.h" #include "base/android/jni_string.h" +#include "base/command_line.h" #include "base/logging.h" #include "base/string_piece.h" +#include "content/public/common/content_switches.h" #include "content/shell/android/shell_manager.h" #include "jni/Shell_jni.h" @@ -23,6 +25,9 @@ base::StringPiece Shell::PlatformResourceProvider(int key) { } void Shell::PlatformInitialize() { + CommandLine* command_line = CommandLine::ForCurrentProcess(); + DCHECK(command_line->HasSwitch(switches::kForceCompositingMode)); + DCHECK(command_line->HasSwitch(switches::kEnableThreadedCompositing)); } void Shell::PlatformCleanUp() { diff --git a/content/shell/shell_browser_main_parts.cc b/content/shell/shell_browser_main_parts.cc index a557549..b8ba066 100644 --- a/content/shell/shell_browser_main_parts.cc +++ b/content/shell/shell_browser_main_parts.cc @@ -32,6 +32,12 @@ static GURL GetStartupURL() { if (command_line->HasSwitch(switches::kContentBrowserTest)) return GURL(); const CommandLine::StringVector& args = command_line->GetArgs(); + +#if defined(OS_ANDROID) + // Delay renderer creation on Android until surface is ready. + return GURL(); +#endif + if (args.empty()) return GURL("http://www.google.com/"); |