Chromium Code Reviews| Index: chrome/browser/android/vr_shell/vr_shell.cc |
| diff --git a/chrome/browser/android/vr_shell/vr_shell.cc b/chrome/browser/android/vr_shell/vr_shell.cc |
| index ba595ae5bf5dd9ef7d0c95cf17f634cc532c5eb2..901af313520bfbe15d0a613558c8c2ea1a188b50 100644 |
| --- a/chrome/browser/android/vr_shell/vr_shell.cc |
| +++ b/chrome/browser/android/vr_shell/vr_shell.cc |
| @@ -25,6 +25,7 @@ |
| #include "chrome/browser/android/vr_shell/vr_input_manager.h" |
| #include "chrome/browser/android/vr_shell/vr_shell_delegate.h" |
| #include "chrome/browser/android/vr_shell/vr_shell_gl.h" |
| +#include "chrome/browser/android/vr_shell/vr_shell_gpu_renderer.h" |
| #include "chrome/browser/android/vr_shell/vr_usage_monitor.h" |
| #include "chrome/browser/android/vr_shell/vr_web_contents_observer.h" |
| #include "content/public/browser/navigation_controller.h" |
| @@ -46,6 +47,12 @@ |
| #include "ui/gfx/transform.h" |
| #include "ui/gfx/transform_util.h" |
| +#include "services/ui/public/cpp/gpu/context_provider_command_buffer.h" |
| +#include "content/browser/renderer_host/context_provider_factory_impl_android.h" |
| +#include "gpu/command_buffer/client/gles2_interface.h" |
| +//#include "cc/output/output_surface.h" |
| +#include "gpu/command_buffer/common/mailbox.h" |
| + |
| using base::android::JavaParamRef; |
| using base::android::JavaRef; |
| @@ -103,6 +110,81 @@ VrShell::VrShell(JNIEnv* env, |
| for_web_vr ? UiInterface::Mode::WEB_VR : UiInterface::Mode::STANDARD); |
| } |
| +void VrShell::OnWebVrGpuChannelEstablished( |
|
mthiesse
2017/03/01 16:38:21
Should this code all live in vr_shell_gl?
klausw
2017/03/02 08:16:13
Done.
|
| + scoped_refptr<gpu::GpuChannelHost> gpu_channel_host, |
| + ui::ContextProviderFactory::GpuChannelHostResult result) { |
| + |
| + VLOG(1) << __FUNCTION__ << ";;;"; |
| + switch (result) { |
| + // Don't retry if we are shutting down. |
| + case ui::ContextProviderFactory::GpuChannelHostResult:: |
| + FAILURE_FACTORY_SHUTDOWN: |
| + break; |
| + case ui::ContextProviderFactory::GpuChannelHostResult:: |
| + FAILURE_GPU_PROCESS_INITIALIZATION_FAILED: |
| + //HandlePendingCompositorFrameSinkRequest(); |
| + break; |
| + case ui::ContextProviderFactory::GpuChannelHostResult::SUCCESS: |
| + VLOG(1) << __FUNCTION__ << ";;; Success!"; |
| + |
| + const size_t full_screen_texture_size_in_bytes = 4000 * 3000 * 4; |
| + gpu::SharedMemoryLimits limits; |
| + limits.command_buffer_size = 64 * 1024; |
| + limits.start_transfer_buffer_size = 64 * 1024; |
| + limits.min_transfer_buffer_size = 64 * 1024; |
| + limits.max_transfer_buffer_size = full_screen_texture_size_in_bytes; |
| + limits.mapped_memory_reclaim_limit = full_screen_texture_size_in_bytes; |
| + |
| + gpu::gles2::ContextCreationAttribHelper attributes; |
| + attributes.alpha_size = 0; |
| + attributes.stencil_size = 0; |
| + attributes.depth_size = 0; |
| + attributes.samples = 0; |
| + attributes.sample_buffers = 0; |
| + attributes.bind_generates_resource = false; |
| + |
| + scoped_refptr<cc::ContextProvider> context_provider = |
| + content::ContextProviderFactoryImpl::GetInstance() |
| + ->CreateDisplayContextProvider( |
| + webvr_surface_handle_, limits, |
| + attributes, |
| + false /*support_locking*/, false /*automatic_flushes*/, |
| + std::move(gpu_channel_host)); |
| + |
| + webvr_context_provider_command_buffer_ = |
| + static_cast<ui::ContextProviderCommandBuffer*>( |
| + context_provider.get()); |
| + |
| + VLOG(1) << __FUNCTION__ << ";;; webvr_context_provider_command_buffer=" << |
| + webvr_context_provider_command_buffer_; |
| + if (!webvr_context_provider_command_buffer_->BindToCurrentThread()) { |
| + LOG(ERROR) << __FUNCTION__ << ": failed to init ContextProvider"; |
| + break; |
| + } |
| + VLOG(1) << __FUNCTION__ << ";;; bind succeeded"; |
| + |
| +#if 0 |
| + auto display_output_surface = base::MakeUnique<AndroidOutputSurface>( |
| + std::move(context_provider_command_buffer)); |
| + InitializeDisplay(std::move(display_output_surface), nullptr, |
| + std::move(context_provider)); |
| +#endif |
| + |
| + webvr_surface_gl_ = webvr_context_provider_command_buffer_->ContextGL(); |
| + VLOG(1) << __FUNCTION__ << ";;; webvr_surface_gl_=" << webvr_surface_gl_; |
| + |
| +#if 0 |
| + auto gl = webvr_surface_gl_; |
| + VLOG(1) << __FUNCTION__ << ";;; drawing some stuff"; |
| + gl->ClearColor(1.0f, 0.0f, 0.0f, 1.0f); |
| + gl->Clear(GL_COLOR_BUFFER_BIT); |
| + //gl->ResizeCHROMIUM(1888, 888, 1.0f, true); |
| + VLOG(1) << __FUNCTION__ << ";;; drawing done"; |
| +#endif |
| + break; |
| + } |
| +} |
| + |
| void VrShell::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) { |
| delete this; |
| } |
| @@ -324,7 +406,91 @@ void VrShell::SetWebVRSecureOrigin(bool secure_origin) { |
| html_interface_->SetWebVRSecureOrigin(secure_origin); |
| } |
| -void VrShell::SubmitWebVRFrame() {} |
| +void VrShell::SubmitWebVRFrame(int frame_index, const gpu::Mailbox& mailbox) { |
| + auto gl = webvr_surface_gl_; |
| + if (!gl) { |
| + VLOG(1) << __FUNCTION__ << ";;; drop, no GL context"; |
| + return; |
| + } |
| + VLOG(1) << __FUNCTION__ << ";;; frame=" << frame_index << " gl=" << gl; |
| + |
| + // Default viewport size seems ok, don't set one here and leave it |
| + //alone elsewhere. |
| + //gl->Viewport(0, 0, 2560, 1440); // FIXME! |
| + |
| + static GpuRenderer* copyRenderer = nullptr; |
| + if (!copyRenderer) { |
| + copyRenderer = new GpuRenderer(gl); |
| + } |
| + |
| +#if 0 |
| + gl->ClearColor((frame_index & 255) / 255.0f, |
| + ((frame_index >> 16) & 255) / 255.0f, 1.0f, 1.0f); |
| + gl->Clear(GL_COLOR_BUFFER_BIT); |
| +#endif |
| + |
| + //if (mailbox.HasSyncToken()) |
| + // gl->WaitSyncTokenCHROMIUM(mailbox.GetSyncTokenData()); |
| + //gpu::SyncToken sync_token; |
| + //cc::TextureMailbox texture_mailbox(mailbox, sync_token, GL_TEXTURE_2D); |
| + VLOG(1) << __FUNCTION__ << ";;; got mailbox, name=" << |
| + (int)mailbox.name[0] << "," << (int)mailbox.name[1] << "..."; |
| + GLuint vrSourceTexture = gl->CreateAndConsumeTextureCHROMIUM( |
| + GL_TEXTURE_2D, mailbox.name); |
| + VLOG(1) << __FUNCTION__ << ";;; vrSourceTexture=" << vrSourceTexture; |
| + |
| + bool skip_this_frame = false; |
| + GLint err; |
| + |
| + if ((err = gl->GetError()) != GL_NO_ERROR) { |
| + VLOG(1) << __FUNCTION__ << ";;; Got GL error: " << err; |
| + skip_this_frame = true; |
| + } |
| + if (webvr_frames_in_surface_queue_) { |
| + // We've consumed the texture, but we can't draw it to the surface, the |
| + // previous one hasn't been consumed yet. Swapping twice loses frames. |
| + // This should be rare, it's a waste of resources and can suppress useful |
| + // frames. |
| + VLOG(1) << __FUNCTION__ << ";;; Dropping frame, got one queued already."; |
| + skip_this_frame = true; |
| + } |
| + |
| + copyRenderer->DrawQuad(gl, vrSourceTexture); |
| + if ((err = gl->GetError()) != GL_NO_ERROR) { |
| + VLOG(1) << __FUNCTION__ << ";;; Got GL error: " << err; |
| + skip_this_frame = true; |
| + } |
| + |
| + if (skip_this_frame) { |
| + PostToGlThreadWhenReady( |
| + base::Bind(&VrShellGl::DropWebVRFrame, |
| + gl_thread_->GetVrShellGl(), frame_index)); |
| + return; |
| + } |
| + |
| + // If we get here, we're committed to drawing and swapBuffers. |
| + // Continue after errors. |
| + PostToGlThreadWhenReady(base::Bind(&VrShellGl::ScheduleWebVRFrame, |
| + gl_thread_->GetVrShellGl(), frame_index)); |
| + |
| + // This is a load-bearing glFlush(). Removing it breaks rendering. WTF. |
| + // FIXME: check if this is still true. |
| + gl->Flush(); |
| + gl->SwapBuffers(); |
| + VLOG(1) << __FUNCTION__ << ";;; swapped, webvr_frames_in_surface_queue " << |
| + webvr_frames_in_surface_queue_ << " => " << |
| + (webvr_frames_in_surface_queue_ + 1); |
| + ++webvr_frames_in_surface_queue_; |
| + gl->Flush(); |
| +} |
| + |
| +void VrShell::WebVRFrameCompleted(int frame_index) { |
| + VLOG(1) << __FUNCTION__ << ";;; frame_index=" << frame_index << |
| + ", webvr_frames_in_surface_queue " << |
| + webvr_frames_in_surface_queue_ << " => " << |
| + (webvr_frames_in_surface_queue_ - 1); |
| + --webvr_frames_in_surface_queue_; |
| +} |
| void VrShell::UpdateWebVRTextureBounds(int16_t frame_index, |
| const gvr::Rectf& left_bounds, |
| @@ -377,6 +543,17 @@ void VrShell::ContentSurfaceChanged(jobject surface) { |
| Java_VrShellImpl_contentSurfaceChanged(env, j_vr_shell_.obj()); |
| } |
| +void VrShell::WebVRSurfaceChanged(int surface_handle) { |
| + VLOG(1) << __FUNCTION__ << ";;; Got WebVR surface, handle=" << surface_handle; |
| + webvr_surface_handle_ = surface_handle; |
| + |
| + VLOG(1) << __FUNCTION__ << ";;; RequestGpuChannelHost start"; |
| + ui::ContextProviderFactory::GetInstance()->RequestGpuChannelHost(base::Bind( |
| + &VrShell::OnWebVrGpuChannelEstablished, weak_ptr_factory_.GetWeakPtr())); |
| + VLOG(1) << __FUNCTION__ << ";;; RequestGpuChannelHost end"; |
| +} |
| + |
| + |
| void VrShell::GvrDelegateReady() { |
| delegate_provider_->SetDelegate(this, gvr_api_); |
| } |