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_); |
} |