VR: Add Skia surface provider for command buffer

This is the last piece necessary in the VR UI to support the
command buffer.

Re-enable pixeltest for Windows.

Bug: 884256, 771794
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:linux_vr;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I8c0a67021c859a88b0af519ace97266a142ec7d7
Reviewed-on: https://chromium-review.googlesource.com/1238816
Commit-Queue: Aldo Culquicondor <[email protected]>
Reviewed-by: John Budorick <[email protected]>
Reviewed-by: Tibor Goldschwendt <[email protected]>
Cr-Commit-Position: refs/heads/master@{#593933}
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn
index c6aac0c..f79a4475 100644
--- a/chrome/browser/vr/BUILD.gn
+++ b/chrome/browser/vr/BUILD.gn
@@ -203,7 +203,15 @@
   ]
 
   if (use_command_buffer) {
-    sources += [ "skia_surface_provider_factory_cmd_buffer.cc" ]
+    sources += [
+      "cmd_buffer_surface_provider.cc",
+      "cmd_buffer_surface_provider.h",
+      "skia_surface_provider_factory_cmd_buffer.cc",
+    ]
+    deps += [
+      "//gpu/command_buffer/client:gles2_implementation",
+      "//gpu/skia_bindings",
+    ]
   } else {
     sources += [
       "native_gl_surface_provider.cc",
diff --git a/chrome/browser/vr/cmd_buffer_surface_provider.cc b/chrome/browser/vr/cmd_buffer_surface_provider.cc
new file mode 100644
index 0000000..b148eaeb
--- /dev/null
+++ b/chrome/browser/vr/cmd_buffer_surface_provider.cc
@@ -0,0 +1,58 @@
+// Copyright 2018 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 "chrome/browser/vr/cmd_buffer_surface_provider.h"
+
+#include "base/logging.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/gles2_lib.h"
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace vr {
+
+CmdBufferSurfaceProvider::CmdBufferSurfaceProvider() {
+  auto* gles2_implementation =
+      static_cast<gpu::gles2::GLES2Implementation*>(gles2::GetGLContext());
+  DCHECK(gles2_implementation);
+  sk_sp<const GrGLInterface> gr_interface =
+      skia_bindings::CreateGLES2InterfaceBindings(gles2_implementation,
+                                                  gles2_implementation);
+  gr_context_ = GrContext::MakeGL(std::move(gr_interface));
+  DCHECK(gr_context_);
+  glGetIntegerv(GL_FRAMEBUFFER_BINDING, &main_fbo_);
+}
+
+CmdBufferSurfaceProvider::~CmdBufferSurfaceProvider() = default;
+
+sk_sp<SkSurface> CmdBufferSurfaceProvider::MakeSurface(const gfx::Size& size) {
+  return SkSurface::MakeRenderTarget(
+      gr_context_.get(), SkBudgeted::kNo,
+      SkImageInfo::MakeN32Premul(size.width(), size.height()), 0,
+      kTopLeft_GrSurfaceOrigin, nullptr);
+}
+
+GLuint CmdBufferSurfaceProvider::FlushSurface(SkSurface* surface,
+                                              GLuint reuse_texture_id) {
+  surface->getCanvas()->flush();
+  GrBackendTexture backend_texture =
+      surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
+  DCHECK(backend_texture.isValid());
+  GrGLTextureInfo info;
+  bool result = backend_texture.getGLTextureInfo(&info);
+  DCHECK(result);
+  GLuint texture_id = info.fID;
+  DCHECK_NE(texture_id, 0u);
+  surface->getCanvas()->getGrContext()->resetContext();
+  glBindFramebuffer(GL_FRAMEBUFFER, main_fbo_);
+
+  return texture_id;
+}
+
+}  // namespace vr
diff --git a/chrome/browser/vr/cmd_buffer_surface_provider.h b/chrome/browser/vr/cmd_buffer_surface_provider.h
new file mode 100644
index 0000000..a8e72976
--- /dev/null
+++ b/chrome/browser/vr/cmd_buffer_surface_provider.h
@@ -0,0 +1,30 @@
+// Copyright 2017 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 CHROME_BROWSER_VR_CMD_BUFFER_SURFACE_PROVIDER_H_
+#define CHROME_BROWSER_VR_CMD_BUFFER_SURFACE_PROVIDER_H_
+
+#include "chrome/browser/vr/skia_surface_provider.h"
+#include "chrome/browser/vr/vr_ui_export.h"
+
+class GrContext;
+
+namespace vr {
+
+class VR_UI_EXPORT CmdBufferSurfaceProvider : public SkiaSurfaceProvider {
+ public:
+  CmdBufferSurfaceProvider();
+  ~CmdBufferSurfaceProvider() override;
+
+  sk_sp<SkSurface> MakeSurface(const gfx::Size& size) override;
+  GLuint FlushSurface(SkSurface* surface, GLuint reuse_texture_id) override;
+
+ private:
+  sk_sp<GrContext> gr_context_;
+  GLint main_fbo_ = 0;
+};
+
+}  // namespace vr
+
+#endif  // CHROME_BROWSER_VR_CMD_BUFFER_SURFACE_PROVIDER_H_
diff --git a/chrome/browser/vr/skia_surface_provider_factory_cmd_buffer.cc b/chrome/browser/vr/skia_surface_provider_factory_cmd_buffer.cc
index 42702c7..3af44fc 100644
--- a/chrome/browser/vr/skia_surface_provider_factory_cmd_buffer.cc
+++ b/chrome/browser/vr/skia_surface_provider_factory_cmd_buffer.cc
@@ -4,14 +4,12 @@
 
 #include "chrome/browser/vr/skia_surface_provider_factory.h"
 
-#include "base/logging.h"
+#include "chrome/browser/vr/cmd_buffer_surface_provider.h"
 
 namespace vr {
 
 std::unique_ptr<SkiaSurfaceProvider> SkiaSurfaceProviderFactory::Create() {
-  // TODO(crbug/884256): Implement a surface provider using the command buffer.
-  NOTIMPLEMENTED();
-  return nullptr;
+  return std::make_unique<CmdBufferSurfaceProvider>();
 }
 
 }  // namespace vr
diff --git a/chrome/browser/vr/test/gl_test_environment_unittest.cc b/chrome/browser/vr/test/gl_test_environment_unittest.cc
index 783e727..ee62da2 100644
--- a/chrome/browser/vr/test/gl_test_environment_unittest.cc
+++ b/chrome/browser/vr/test/gl_test_environment_unittest.cc
@@ -10,13 +10,9 @@
 namespace vr {
 
 TEST(GlTestEnvironmentTest, InitializeAndCleanup) {
-// TODO(crbug/771794): Test temporarily disabled on Windows because it crashes
-// on trybots. Fix before enabling Windows support.
-#ifndef OS_WIN
   GlTestEnvironment gl_test_environment(gfx::Size(100, 100));
   EXPECT_NE(gl_test_environment.GetFrameBufferForTesting(), 0u);
   EXPECT_EQ(glGetError(), (GLenum)GL_NO_ERROR);
-#endif
   // We just test that clean up doesn't crash.
 }
 
diff --git a/chrome/browser/vr/test/run_all_perftests.cc b/chrome/browser/vr/test/run_all_perftests.cc
index 9b7663af..cec581f 100644
--- a/chrome/browser/vr/test/run_all_perftests.cc
+++ b/chrome/browser/vr/test/run_all_perftests.cc
@@ -4,13 +4,13 @@
 
 #include "base/bind.h"
 #include "base/test/launcher/unit_test_launcher.h"
-#include "chrome/browser/vr/test/vr_test_suite.h"
+#include "chrome/browser/vr/test/vr_gl_test_suite.h"
 
 int main(int argc, char** argv) {
-  vr::VrTestSuite test_suite(argc, argv);
+  vr::VrGlTestSuite test_suite(argc, argv);
 
   return base::LaunchUnitTestsSerially(
       argc, argv,
-      base::BindRepeating(&vr::VrTestSuite::Run,
+      base::BindRepeating(&vr::VrGlTestSuite::Run,
                           base::Unretained(&test_suite)));
 }
diff --git a/chrome/browser/vr/test/ui_pixel_test.cc b/chrome/browser/vr/test/ui_pixel_test.cc
index b0b20c9..b5062b3 100644
--- a/chrome/browser/vr/test/ui_pixel_test.cc
+++ b/chrome/browser/vr/test/ui_pixel_test.cc
@@ -21,9 +21,6 @@
 UiPixelTest::~UiPixelTest() = default;
 
 void UiPixelTest::SetUp() {
-// TODO(crbug/771794): Test temporarily disabled on Windows because it crashes
-// on trybots. Fix before enabling Windows support.
-#ifndef OS_WIN
   gl_test_environment_ =
       std::make_unique<GlTestEnvironment>(frame_buffer_size_);
 
@@ -36,17 +33,12 @@
   ASSERT_EQ(glGetError(), (GLenum)GL_NO_ERROR);
 
   browser_ = std::make_unique<MockUiBrowserInterface>();
-#endif
 }
 
 void UiPixelTest::TearDown() {
-// TODO(crbug/771794): Test temporarily disabled on Windows because it crashes
-// on trybots. Fix before enabling Windows support.
-#ifndef OS_WIN
   ui_.reset();
   glDeleteTextures(1, &content_texture_);
   gl_test_environment_.reset();
-#endif
 }
 
 void UiPixelTest::MakeUi(const UiInitialState& ui_initial_state,
diff --git a/chrome/browser/vr/test/vr_gl_test_suite.cc b/chrome/browser/vr/test/vr_gl_test_suite.cc
index e5af480..d47e18d 100644
--- a/chrome/browser/vr/test/vr_gl_test_suite.cc
+++ b/chrome/browser/vr/test/vr_gl_test_suite.cc
@@ -8,10 +8,11 @@
 #include "ui/gl/test/gl_image_test_support.h"
 
 #if defined(VR_USE_COMMAND_BUFFER)
-#include "gpu/config/gpu_info_collector.h"      // nogncheck
-#include "gpu/config/gpu_preferences.h"         // nogncheck
-#include "gpu/config/gpu_util.h"                // nogncheck
-#include "gpu/ipc/in_process_command_buffer.h"  // nogncheck
+#include "gpu/command_buffer/client/gles2_lib.h"  // nogncheck
+#include "gpu/config/gpu_info_collector.h"        // nogncheck
+#include "gpu/config/gpu_preferences.h"           // nogncheck
+#include "gpu/config/gpu_util.h"                  // nogncheck
+#include "gpu/ipc/in_process_command_buffer.h"    // nogncheck
 #endif  // defined(VR_USE_COMMAND_BUFFER)
 
 namespace vr {
@@ -36,6 +37,7 @@
       gpu::kGpuFeatureStatusEnabled;
   gpu::InProcessCommandBuffer::InitializeDefaultServiceForTesting(
       gpu_feature_info);
+  gles2::Initialize();
 #endif  // defined(VR_USE_COMMAND_BUFFER)
 }
 
diff --git a/chrome/browser/vr/text_perftest.cc b/chrome/browser/vr/text_perftest.cc
index 3fa2b15..172d674 100644
--- a/chrome/browser/vr/text_perftest.cc
+++ b/chrome/browser/vr/text_perftest.cc
@@ -36,6 +36,7 @@
 
   void TearDown() override {
     text_element_.reset();
+    provider_.reset();
     gl_test_environment_.reset();
   }
 
@@ -59,8 +60,8 @@
   cc::LapTimer timer_;
 
  private:
-  std::unique_ptr<GlTestEnvironment> gl_test_environment_;
   std::unique_ptr<SkiaSurfaceProvider> provider_;
+  std::unique_ptr<GlTestEnvironment> gl_test_environment_;
 };
 
 TEST_F(TextPerfTest, RenderLoremIpsum100Chars) {
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc
index 2d29e12..64c15d3 100644
--- a/chrome/browser/vr/ui_pixeltest.cc
+++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -14,19 +14,11 @@
 
 namespace {
 
-static const gfx::Transform kIdentity;
+constexpr gfx::Transform kIdentity;
 
 }  // namespace
 
-// TODO(crbug/771794): Test temporarily disabled on Windows because it crashes
-// on trybots. Fix before enabling Windows support.
-#if defined(OS_WIN)
-#define MAYBE(x) DISABLED_##x
-#else
-#define MAYBE(x) x
-#endif
-
-TEST_F(UiPixelTest, MAYBE(DrawVrBrowsingMode)) {
+TEST_F(UiPixelTest, DrawVrBrowsingMode) {
   // Set up scene.
   UiInitialState ui_initial_state;
   ui_initial_state.in_web_vr = false;