[go: nahoru, domu]

Add an overlay candidate validator for Android

Add a validator that uses the underlay strategy to
support underlaying fullscreen video frames.

BUG=533630

Review URL: https://codereview.chromium.org/1436113002

Cr-Commit-Position: refs/heads/master@{#361500}
diff --git a/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.cc b/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.cc
new file mode 100644
index 0000000..12e4a768
--- /dev/null
+++ b/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.cc
@@ -0,0 +1,50 @@
+// Copyright 2015 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/compositor/browser_compositor_overlay_candidate_validator_android.h"
+
+#include "cc/output/overlay_processor.h"
+#include "cc/output/overlay_strategy_underlay.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+
+namespace content {
+
+BrowserCompositorOverlayCandidateValidatorAndroid::
+    BrowserCompositorOverlayCandidateValidatorAndroid() {}
+
+BrowserCompositorOverlayCandidateValidatorAndroid::
+    ~BrowserCompositorOverlayCandidateValidatorAndroid() {}
+
+void BrowserCompositorOverlayCandidateValidatorAndroid::GetStrategies(
+    cc::OverlayProcessor::StrategyList* strategies) {
+  strategies->push_back(make_scoped_ptr(new cc::OverlayStrategyUnderlay(this)));
+}
+
+void BrowserCompositorOverlayCandidateValidatorAndroid::CheckOverlaySupport(
+    cc::OverlayCandidateList* candidates) {
+  // There should only be at most a single overlay candidate: the video quad.
+  // There's no check that the presented candidate is really a video frame for
+  // a fullscreen video. Instead it's assumed that if a quad is marked as
+  // overlayable, it's a fullscreen video quad.
+  DCHECK_LE(candidates->size(), 1u);
+
+  if (!candidates->empty()) {
+    cc::OverlayCandidate& candidate = candidates->front();
+    candidate.display_rect =
+        gfx::RectF(gfx::ToEnclosingRect(candidate.display_rect));
+    candidate.overlay_handled = true;
+    candidate.plane_z_order = -1;
+  }
+}
+
+bool BrowserCompositorOverlayCandidateValidatorAndroid::AllowCALayerOverlays() {
+  return false;
+}
+
+// Overlays will still be allowed when software mirroring is enabled, even
+// though they won't appear in the mirror.
+void BrowserCompositorOverlayCandidateValidatorAndroid::SetSoftwareMirrorMode(
+    bool enabled) {}
+
+}  // namespace content
diff --git a/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h b/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h
new file mode 100644
index 0000000..6cbb1a9
--- /dev/null
+++ b/content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h
@@ -0,0 +1,40 @@
+// Copyright 2015 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_COMPOSITOR_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
+#define CONTENT_BROWSER_COMPOSITOR_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
+
+#include "base/macros.h"
+#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// An overlay validator for supporting fullscreen video underlays on Android.
+// Things are a bit different on Android compared with other platforms. By the
+// time a video frame is marked as overlayable it means the video decoder was
+// outputting to a Surface that we can't read back from. As a result, the
+// overlay must always succeed, or the video won't be visible. This is one of of
+// the reasons that only fullscreen is supported: we have to be sure that
+// nothing will cause the overlay to be rejected, because there's no fallback to
+// gl compositing.
+class CONTENT_EXPORT BrowserCompositorOverlayCandidateValidatorAndroid
+    : public BrowserCompositorOverlayCandidateValidator {
+ public:
+  BrowserCompositorOverlayCandidateValidatorAndroid();
+  ~BrowserCompositorOverlayCandidateValidatorAndroid() override;
+
+  void GetStrategies(cc::OverlayProcessor::StrategyList* strategies) override;
+  void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
+  bool AllowCALayerOverlays() override;
+
+  void SetSoftwareMirrorMode(bool enabled) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BrowserCompositorOverlayCandidateValidatorAndroid);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_COMPOSITOR_OVERLAY_CANDIDATE_VALIDATOR_ANDROID_H_
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index 5c08731..45719ac 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -72,6 +72,8 @@
 #include "content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.h"
 #include "content/browser/compositor/software_output_device_mac.h"
 #include "ui/base/cocoa/remote_layer_api.h"
+#elif defined(OS_ANDROID)
+#include "content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h"
 #endif
 
 using cc::ContextProvider;
@@ -180,6 +182,7 @@
 
 scoped_ptr<BrowserCompositorOverlayCandidateValidator>
 CreateOverlayCandidateValidator(gfx::AcceleratedWidget widget) {
+  scoped_ptr<BrowserCompositorOverlayCandidateValidator> validator;
 #if defined(USE_OZONE)
   scoped_ptr<ui::OverlayCandidatesOzone> overlay_candidates =
       ui::OzonePlatform::GetInstance()
@@ -189,18 +192,19 @@
   if (overlay_candidates &&
       (command_line->HasSwitch(switches::kEnableHardwareOverlays) ||
        command_line->HasSwitch(switches::kOzoneTestSingleOverlaySupport))) {
-    return scoped_ptr<BrowserCompositorOverlayCandidateValidator>(
-        new BrowserCompositorOverlayCandidateValidatorOzone(
-            widget, overlay_candidates.Pass()));
+    validator.reset(new BrowserCompositorOverlayCandidateValidatorOzone(
+        widget, overlay_candidates.Pass()));
   }
 #elif defined(OS_MACOSX)
   // Overlays are only supported through the remote layer API.
   if (ui::RemoteLayerAPISupported()) {
-    return make_scoped_ptr(
-        new BrowserCompositorOverlayCandidateValidatorMac(widget));
+    validator.reset(new BrowserCompositorOverlayCandidateValidatorMac(widget));
   }
+#elif defined(OS_ANDROID)
+  validator.reset(new BrowserCompositorOverlayCandidateValidatorAndroid());
 #endif
-  return scoped_ptr<BrowserCompositorOverlayCandidateValidator>();
+
+  return validator.Pass();
 }
 
 static bool ShouldCreateGpuOutputSurface(ui::Compositor* compositor) {
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index 3f2ee64..1e2abf7 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -39,6 +39,7 @@
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/layer_tree_settings.h"
 #include "content/browser/android/child_process_launcher_android.h"
+#include "content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h"
 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
 #include "content/browser/gpu/compositor_util.h"
@@ -85,7 +86,9 @@
         populate_gpu_capabilities_callback_(populate_gpu_capabilities_callback),
         swap_buffers_completion_callback_(
             base::Bind(&OutputSurfaceWithoutParent::OnSwapBuffersCompleted,
-                       base::Unretained(this))) {
+                       base::Unretained(this))),
+        overlay_candidate_validator_(
+            new BrowserCompositorOverlayCandidateValidatorAndroid()) {
     capabilities_.adjust_deadline_for_parent = false;
     capabilities_.max_frames_pending = kMaxDisplaySwapBuffers;
   }
@@ -114,6 +117,10 @@
     return true;
   }
 
+  cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
+    return overlay_candidate_validator_.get();
+  }
+
  private:
   CommandBufferProxyImpl* GetCommandBufferProxy() {
     ContextProviderCommandBuffer* provider_command_buffer =
@@ -141,6 +148,7 @@
   base::CancelableCallback<void(const std::vector<ui::LatencyInfo>&,
                                 gfx::SwapResult)>
       swap_buffers_completion_callback_;
+  scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator_;
 };
 
 static bool g_initialized = false;
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 276af0c..dc511d6 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -1618,6 +1618,8 @@
         'browser/android/tracing_controller_android.h',
         'browser/android/web_contents_observer_proxy.cc',
         'browser/android/web_contents_observer_proxy.h',
+        'browser/compositor/browser_compositor_overlay_candidate_validator_android.cc',
+        'browser/compositor/browser_compositor_overlay_candidate_validator_android.h',
         'browser/power_save_blocker_android.cc',
         'browser/renderer_host/compositor_impl_android.cc',
         'browser/renderer_host/compositor_impl_android.h',
@@ -1673,6 +1675,8 @@
       'browser/compositor/browser_compositor_output_surface.cc',
       'browser/compositor/browser_compositor_output_surface.h',
       'browser/compositor/browser_compositor_overlay_candidate_validator.h',
+      'browser/compositor/browser_compositor_overlay_candidate_validator_android.cc',
+      'browser/compositor/browser_compositor_overlay_candidate_validator_android.h',
       'browser/compositor/browser_compositor_overlay_candidate_validator_mac.h',
       'browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm',
       'browser/compositor/browser_compositor_overlay_candidate_validator_ozone.cc',
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 677c356..8352ff6 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -19,6 +19,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gl/egl_util.h"
 #include "ui/gl/gl_context.h"
+#include "ui/gl/gl_image.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_stub.h"
 #include "ui/gl/gl_switches.h"
@@ -758,6 +759,23 @@
   return vsync_provider_.get();
 }
 
+bool NativeViewGLSurfaceEGL::ScheduleOverlayPlane(int z_order,
+                                                  OverlayTransform transform,
+                                                  gl::GLImage* image,
+                                                  const Rect& bounds_rect,
+                                                  const RectF& crop_rect) {
+#if defined(OS_ANDROID)
+  // Overlay planes are used on Android for fullscreen video. The image is
+  // expected to update the plane as soon as possible to display the video frame
+  // chosen for this vsync interval.
+  return image->ScheduleOverlayPlane(window_, z_order, transform, bounds_rect,
+                                     crop_rect);
+#else
+  NOTIMPLEMENTED();
+  return false;
+#endif
+}
+
 void NativeViewGLSurfaceEGL::OnSetSwapInterval(int interval) {
   swap_interval_ = interval;
 }
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index f5606d9..8fb84a0 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -88,6 +88,11 @@
   bool SupportsPostSubBuffer() override;
   gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
   VSyncProvider* GetVSyncProvider() override;
+  bool ScheduleOverlayPlane(int z_order,
+                            OverlayTransform transform,
+                            gl::GLImage* image,
+                            const Rect& bounds_rect,
+                            const RectF& crop_rect) override;
 
   // Create a NativeViewGLSurfaceEGL with an externally provided VSyncProvider.
   // Takes ownership of the VSyncProvider.