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.