summaryrefslogtreecommitdiff
path: root/chromium/components/viz/service
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/viz/service')
-rw-r--r--chromium/components/viz/service/BUILD.gn25
-rw-r--r--chromium/components/viz/service/display/DEPS1
-rw-r--r--chromium/components/viz/service/display/bsp_tree_perftest.cc2
-rw-r--r--chromium/components/viz/service/display/ca_layer_overlay.cc19
-rw-r--r--chromium/components/viz/service/display/ca_layer_overlay.h7
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.cc41
-rw-r--r--chromium/components/viz/service/display/dc_layer_overlay.h12
-rw-r--r--chromium/components/viz/service/display/direct_renderer.cc21
-rw-r--r--chromium/components/viz/service/display/direct_renderer.h13
-rw-r--r--chromium/components/viz/service/display/display.cc113
-rw-r--r--chromium/components/viz/service/display/display.h41
-rw-r--r--chromium/components/viz/service/display/display_client.h9
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.cc972
-rw-r--r--chromium/components/viz/service/display/display_resource_provider.h397
-rw-r--r--chromium/components/viz/service/display/display_resource_provider_unittest.cc1389
-rw-r--r--chromium/components/viz/service/display/display_unittest.cc125
-rw-r--r--chromium/components/viz/service/display/gl_renderer.cc155
-rw-r--r--chromium/components/viz/service/display/gl_renderer.h16
-rw-r--r--chromium/components/viz/service/display/gl_renderer_copier.cc186
-rw-r--r--chromium/components/viz/service/display/gl_renderer_copier.h2
-rw-r--r--chromium/components/viz/service/display/gl_renderer_unittest.cc512
-rw-r--r--chromium/components/viz/service/display/output_surface.cc72
-rw-r--r--chromium/components/viz/service/display/output_surface.h76
-rw-r--r--chromium/components/viz/service/display/output_surface_client.h11
-rw-r--r--chromium/components/viz/service/display/output_surface_frame.h1
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.cc397
-rw-r--r--chromium/components/viz/service/display/overlay_candidate.h144
-rw-r--r--chromium/components/viz/service/display/overlay_candidate_validator.h4
-rw-r--r--chromium/components/viz/service/display/overlay_processor.cc43
-rw-r--r--chromium/components/viz/service/display/overlay_processor.h34
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_fullscreen.cc22
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_fullscreen.h6
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_single_on_top.cc26
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_single_on_top.h10
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay.cc27
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay.h22
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc26
-rw-r--r--chromium/components/viz/service/display/overlay_strategy_underlay_cast.h6
-rw-r--r--chromium/components/viz/service/display/overlay_unittest.cc695
-rw-r--r--chromium/components/viz/service/display/renderer_pixeltest.cc609
-rw-r--r--chromium/components/viz/service/display/scoped_render_pass_texture.h1
-rw-r--r--chromium/components/viz/service/display/shader.cc85
-rw-r--r--chromium/components/viz/service/display/shader_unittest.cc27
-rw-r--r--chromium/components/viz/service/display/skia_output_surface.cc15
-rw-r--r--chromium/components/viz/service/display/skia_output_surface.h98
-rw-r--r--chromium/components/viz/service/display/skia_renderer.cc527
-rw-r--r--chromium/components/viz/service/display/skia_renderer.h57
-rw-r--r--chromium/components/viz/service/display/software_output_device.cc19
-rw-r--r--chromium/components/viz/service/display/software_output_device.h21
-rw-r--r--chromium/components/viz/service/display/software_output_device_client.h26
-rw-r--r--chromium/components/viz/service/display/software_renderer.cc36
-rw-r--r--chromium/components/viz/service/display/software_renderer.h12
-rw-r--r--chromium/components/viz/service/display/software_renderer_unittest.cc60
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.cc36
-rw-r--r--chromium/components/viz/service/display/surface_aggregator.h9
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_perftest.cc4
-rw-r--r--chromium/components/viz/service/display/surface_aggregator_unittest.cc59
-rw-r--r--chromium/components/viz/service/display/vulkan_renderer.cc2
-rw-r--r--chromium/components/viz/service/display/vulkan_renderer.h8
-rw-r--r--chromium/components/viz/service/display_embedder/DEPS12
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.cc14
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h2
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h2
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.cc6
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h2
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h2
-rw-r--r--chromium/components/viz/service/display_embedder/display_provider.h2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface.cc81
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface.h25
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc7
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h7
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_mac.h2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_ozone.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_ozone.h13
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_win.cc2
-rw-r--r--chromium/components/viz/service/display_embedder/gl_output_surface_win.h2
-rw-r--r--chromium/components/viz/service/display_embedder/gpu_display_provider.cc70
-rw-r--r--chromium/components/viz/service/display_embedder/gpu_display_provider.h14
-rw-r--r--chromium/components/viz/service/display_embedder/output_device_backing.cc102
-rw-r--r--chromium/components/viz/service/display_embedder/output_device_backing.h65
-rw-r--r--chromium/components/viz/service/display_embedder/output_device_backing_unittest.cc112
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc50
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h3
-rw-r--r--chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc56
-rw-r--r--chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc79
-rw-r--r--chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h63
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc516
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl.h141
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc398
-rw-r--r--chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h173
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_mac.cc42
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_mac.h19
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_mac_unittest.mm5
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc3
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_win.cc457
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_device_win.h66
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_surface.cc52
-rw-r--r--chromium/components/viz/service/display_embedder/software_output_surface.h15
-rw-r--r--chromium/components/viz/service/display_embedder/viz_process_context_provider.cc151
-rw-r--r--chromium/components/viz/service/display_embedder/viz_process_context_provider.h87
-rw-r--r--chromium/components/viz/service/frame_sinks/DEPS7
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc27
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h22
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc81
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h20
-rw-r--r--chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc54
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc134
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h13
-rw-r--r--chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc38
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc30
-rw-r--r--chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h12
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc19
-rw-r--r--chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h17
-rw-r--r--chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc35
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/OWNERS2
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h13
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc35
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h9
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc120
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc6
-rw-r--r--chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h4
-rw-r--r--chromium/components/viz/service/frame_sinks/video_detector.h1
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.cc37
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl.h15
-rw-r--r--chromium/components/viz/service/gl/gpu_service_impl_unittest.cc4
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.cc125
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator.h60
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h15
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc714
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.cc23
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager.h14
-rw-r--r--chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc68
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.cc13
-rw-r--r--chromium/components/viz/service/main/viz_main_impl.h1
-rw-r--r--chromium/components/viz/service/surfaces/surface.cc3
-rw-r--r--chromium/components/viz/service/surfaces/surface.h2
-rw-r--r--chromium/components/viz/service/surfaces/surface_client.h8
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.cc2
-rw-r--r--chromium/components/viz/service/surfaces/surface_dependency_deadline.h4
-rw-r--r--chromium/components/viz/service/surfaces/surface_hittest.cc12
-rw-r--r--chromium/components/viz/service/surfaces/surface_hittest_unittest.cc107
144 files changed, 9087 insertions, 3158 deletions
diff --git a/chromium/components/viz/service/BUILD.gn b/chromium/components/viz/service/BUILD.gn
index 154fb88b827..cfec9fbec12 100644
--- a/chromium/components/viz/service/BUILD.gn
+++ b/chromium/components/viz/service/BUILD.gn
@@ -27,6 +27,8 @@ viz_component("service") {
"display/display.cc",
"display/display.h",
"display/display_client.h",
+ "display/display_resource_provider.cc",
+ "display/display_resource_provider.h",
"display/display_scheduler.cc",
"display/display_scheduler.h",
"display/draw_polygon.cc",
@@ -48,6 +50,8 @@ viz_component("service") {
"display/output_surface_client.h",
"display/output_surface_frame.cc",
"display/output_surface_frame.h",
+ "display/overlay_candidate.cc",
+ "display/overlay_candidate.h",
"display/overlay_candidate_validator.h",
"display/overlay_processor.cc",
"display/overlay_processor.h",
@@ -69,6 +73,8 @@ viz_component("service") {
"display/scoped_render_pass_texture.h",
"display/shader.cc",
"display/shader.h",
+ "display/skia_output_surface.cc",
+ "display/skia_output_surface.h",
"display/skia_renderer.cc",
"display/skia_renderer.h",
"display/software_output_device.cc",
@@ -101,10 +107,14 @@ viz_component("service") {
"display_embedder/in_process_gpu_memory_buffer_manager.h",
"display_embedder/server_shared_bitmap_manager.cc",
"display_embedder/server_shared_bitmap_manager.h",
- "display_embedder/shared_bitmap_allocation_notifier_impl.cc",
- "display_embedder/shared_bitmap_allocation_notifier_impl.h",
+ "display_embedder/skia_output_surface_impl.cc",
+ "display_embedder/skia_output_surface_impl.h",
+ "display_embedder/skia_output_surface_impl_on_gpu.cc",
+ "display_embedder/skia_output_surface_impl_on_gpu.h",
"display_embedder/software_output_surface.cc",
"display_embedder/software_output_surface.h",
+ "display_embedder/viz_process_context_provider.cc",
+ "display_embedder/viz_process_context_provider.h",
"frame_sinks/compositor_frame_sink_impl.cc",
"frame_sinks/compositor_frame_sink_impl.h",
"frame_sinks/compositor_frame_sink_support.cc",
@@ -168,12 +178,16 @@ viz_component("service") {
"//cc/paint",
"//components/crash/core/common:crash_key",
"//components/viz/common",
+ "//gpu/command_buffer/client:gles2_implementation",
+ "//gpu/command_buffer/client:raster",
+ "//gpu/command_buffer/service:gles2",
"//gpu/ipc:gl_in_process_context",
# Note that dependency on //gpu/ipc/client is for GpuMemoryBufferImpl. This
# dependency should not be in public_deps.
"//gpu/ipc/client",
"//gpu/ipc/service",
+ "//gpu/skia_bindings:skia_bindings",
"//gpu/vulkan:buildflags",
"//media",
"//media/capture:capture_lib",
@@ -249,6 +263,8 @@ viz_component("service") {
"display_embedder/compositor_overlay_candidate_validator_win.h",
"display_embedder/gl_output_surface_win.cc",
"display_embedder/gl_output_surface_win.h",
+ "display_embedder/output_device_backing.cc",
+ "display_embedder/output_device_backing.h",
"display_embedder/software_output_device_win.cc",
"display_embedder/software_output_device_win.h",
]
@@ -264,6 +280,7 @@ viz_source_set("unit_tests") {
sources = [
"display/bsp_tree_unittest.cc",
"display/copy_output_scaling_pixeltest.cc",
+ "display/display_resource_provider_unittest.cc",
"display/display_scheduler_unittest.cc",
"display/display_unittest.cc",
"display/draw_polygon_unittest.cc",
@@ -343,6 +360,10 @@ viz_source_set("unit_tests") {
sources += [ "display_embedder/software_output_device_mac_unittest.mm" ]
libs = [ "IOSurface.framework" ]
}
+
+ if (is_win) {
+ sources += [ "display_embedder/output_device_backing_unittest.cc" ]
+ }
}
viz_source_set("perf_tests") {
diff --git a/chromium/components/viz/service/display/DEPS b/chromium/components/viz/service/display/DEPS
index 314ebb3a28c..3560a35a10b 100644
--- a/chromium/components/viz/service/display/DEPS
+++ b/chromium/components/viz/service/display/DEPS
@@ -19,6 +19,7 @@ include_rules = [
"+ui/latency",
"+ui/gl/ca_renderer_layer_params.h",
"+ui/gl/dc_renderer_layer_params.h",
+ "+ui/gl/trace_util.h",
]
specific_include_rules = {
diff --git a/chromium/components/viz/service/display/bsp_tree_perftest.cc b/chromium/components/viz/service/display/bsp_tree_perftest.cc
index 76ea2e10eff..93df78fa388 100644
--- a/chromium/components/viz/service/display/bsp_tree_perftest.cc
+++ b/chromium/components/viz/service/display/bsp_tree_perftest.cc
@@ -59,7 +59,7 @@ class BspTreePerfTest : public cc::LayerTreeTest {
void ReadTestFile(const std::string& name) {
base::FilePath test_data_dir;
- ASSERT_TRUE(PathService::Get(Paths::DIR_TEST_DATA, &test_data_dir));
+ ASSERT_TRUE(base::PathService::Get(Paths::DIR_TEST_DATA, &test_data_dir));
base::FilePath json_file = test_data_dir.AppendASCII(name + ".json");
ASSERT_TRUE(base::ReadFileToString(json_file, &json_));
}
diff --git a/chromium/components/viz/service/display/ca_layer_overlay.cc b/chromium/components/viz/service/display/ca_layer_overlay.cc
index eb6c8aa9982..284ccf3a565 100644
--- a/chromium/components/viz/service/display/ca_layer_overlay.cc
+++ b/chromium/components/viz/service/display/ca_layer_overlay.cc
@@ -7,12 +7,12 @@
#include <algorithm>
#include "base/metrics/histogram_macros.h"
-#include "cc/resources/display_resource_provider.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/stream_video_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
namespace viz {
@@ -75,7 +75,7 @@ bool FilterOperationSupported(const cc::FilterOperation& operation) {
}
CALayerResult FromRenderPassQuad(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const RenderPassDrawQuad* quad,
const base::flat_map<RenderPassId, cc::FilterOperations*>&
render_pass_filters,
@@ -104,10 +104,9 @@ CALayerResult FromRenderPassQuad(
return CA_LAYER_SUCCESS;
}
-CALayerResult FromStreamVideoQuad(
- cc::DisplayResourceProvider* resource_provider,
- const StreamVideoDrawQuad* quad,
- CALayerOverlay* ca_layer_overlay) {
+CALayerResult FromStreamVideoQuad(DisplayResourceProvider* resource_provider,
+ const StreamVideoDrawQuad* quad,
+ CALayerOverlay* ca_layer_overlay) {
unsigned resource_id = quad->resource_id();
if (!resource_provider->IsOverlayCandidate(resource_id))
return CA_LAYER_FAILED_STREAM_VIDEO_NOT_CANDIDATE;
@@ -132,7 +131,7 @@ CALayerResult FromSolidColorDrawQuad(const SolidColorDrawQuad* quad,
return CA_LAYER_SUCCESS;
}
-CALayerResult FromTextureQuad(cc::DisplayResourceProvider* resource_provider,
+CALayerResult FromTextureQuad(DisplayResourceProvider* resource_provider,
const TextureDrawQuad* quad,
CALayerOverlay* ca_layer_overlay) {
unsigned resource_id = quad->resource_id();
@@ -160,7 +159,7 @@ CALayerResult FromTextureQuad(cc::DisplayResourceProvider* resource_provider,
return CA_LAYER_SUCCESS;
}
-CALayerResult FromTileQuad(cc::DisplayResourceProvider* resource_provider,
+CALayerResult FromTileQuad(DisplayResourceProvider* resource_provider,
const TileDrawQuad* quad,
CALayerOverlay* ca_layer_overlay) {
unsigned resource_id = quad->resource_id();
@@ -177,7 +176,7 @@ CALayerResult FromTileQuad(cc::DisplayResourceProvider* resource_provider,
class CALayerOverlayProcessor {
public:
CALayerResult FromDrawQuad(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
const DrawQuad* quad,
const base::flat_map<RenderPassId, cc::FilterOperations*>&
@@ -277,7 +276,7 @@ CALayerOverlay::CALayerOverlay(const CALayerOverlay& other) = default;
CALayerOverlay::~CALayerOverlay() {}
bool ProcessForCALayerOverlays(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
const QuadList& quad_list,
const base::flat_map<RenderPassId, cc::FilterOperations*>&
diff --git a/chromium/components/viz/service/display/ca_layer_overlay.h b/chromium/components/viz/service/display/ca_layer_overlay.h
index 248fbeeebd3..ac52d0eb783 100644
--- a/chromium/components/viz/service/display/ca_layer_overlay.h
+++ b/chromium/components/viz/service/display/ca_layer_overlay.h
@@ -14,11 +14,8 @@
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gl/ca_renderer_layer_params.h"
-namespace cc {
-class DisplayResourceProvider;
-}
-
namespace viz {
+class DisplayResourceProvider;
class DrawQuad;
class RenderPassDrawQuad;
@@ -77,7 +74,7 @@ typedef std::vector<CALayerOverlay> CALayerOverlayList;
// Returns true if all quads in the root render pass have been replaced by
// CALayerOverlays.
bool ProcessForCALayerOverlays(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
const QuadList& quad_list,
const base::flat_map<RenderPassId, cc::FilterOperations*>&
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.cc b/chromium/components/viz/service/display/dc_layer_overlay.cc
index 592eb099581..288b1703c71 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.cc
+++ b/chromium/components/viz/service/display/dc_layer_overlay.cc
@@ -6,10 +6,10 @@
#include "base/metrics/histogram_macros.h"
#include "cc/base/math_util.h"
-#include "cc/resources/display_resource_provider.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/yuv_video_draw_quad.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gl/gl_switches.h"
@@ -19,18 +19,19 @@ namespace viz {
namespace {
DCLayerOverlayProcessor::DCLayerResult FromYUVQuad(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const YUVVideoDrawQuad* quad,
- DCLayerOverlay* ca_layer_overlay) {
+ DCLayerOverlay* dc_layer_overlay) {
for (const auto& resource : quad->resources) {
if (!resource_provider->IsOverlayCandidate(resource))
return DCLayerOverlayProcessor::DC_LAYER_FAILED_TEXTURE_NOT_CANDIDATE;
}
- ca_layer_overlay->resources = quad->resources;
- ca_layer_overlay->contents_rect = quad->ya_tex_coord_rect;
- ca_layer_overlay->filter = GL_LINEAR;
- ca_layer_overlay->color_space = quad->video_color_space;
- ca_layer_overlay->require_overlay = quad->require_overlay;
+ dc_layer_overlay->resources = quad->resources;
+ dc_layer_overlay->contents_rect = quad->ya_tex_coord_rect;
+ dc_layer_overlay->filter = GL_LINEAR;
+ dc_layer_overlay->color_space = quad->video_color_space;
+ dc_layer_overlay->require_overlay = quad->require_overlay;
+ dc_layer_overlay->is_protected_video = quad->is_protected_video;
return DCLayerOverlayProcessor::DC_LAYER_SUCCESS;
}
@@ -90,11 +91,11 @@ DCLayerOverlayProcessor::DCLayerOverlayProcessor() = default;
DCLayerOverlayProcessor::~DCLayerOverlayProcessor() = default;
DCLayerOverlayProcessor::DCLayerResult DCLayerOverlayProcessor::FromDrawQuad(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
QuadList::ConstIterator quad_list_begin,
QuadList::ConstIterator quad,
- DCLayerOverlay* ca_layer_overlay) {
+ DCLayerOverlay* dc_layer_overlay) {
if (quad->shared_quad_state->blend_mode != SkBlendMode::kSrcOver)
return DC_LAYER_FAILED_QUAD_BLEND_MODE;
@@ -103,7 +104,7 @@ DCLayerOverlayProcessor::DCLayerResult DCLayerOverlayProcessor::FromDrawQuad(
case DrawQuad::YUV_VIDEO_CONTENT:
result =
FromYUVQuad(resource_provider, YUVVideoDrawQuad::MaterialCast(*quad),
- ca_layer_overlay);
+ dc_layer_overlay);
break;
default:
return DC_LAYER_FAILED_UNSUPPORTED_QUAD;
@@ -123,19 +124,19 @@ DCLayerOverlayProcessor::DCLayerResult DCLayerOverlayProcessor::FromDrawQuad(
overlay_shared_state->transform =
quad->shared_quad_state->quad_to_target_transform.matrix();
- ca_layer_overlay->shared_state = overlay_shared_state;
- ca_layer_overlay->bounds_rect = gfx::RectF(quad->rect);
+ dc_layer_overlay->shared_state = overlay_shared_state;
+ dc_layer_overlay->bounds_rect = gfx::RectF(quad->rect);
return result;
}
void DCLayerOverlayProcessor::Process(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPassList* render_passes,
gfx::Rect* overlay_damage_rect,
gfx::Rect* damage_rect,
- DCLayerOverlayList* ca_layer_overlays) {
+ DCLayerOverlayList* dc_layer_overlays) {
DCHECK(pass_info_.empty());
processed_overlay_in_frame_ = false;
if (base::FeatureList::IsEnabled(
@@ -145,12 +146,12 @@ void DCLayerOverlayProcessor::Process(
ProcessRenderPass(resource_provider, display_rect, pass.get(), is_root,
overlay_damage_rect,
is_root ? damage_rect : &pass->damage_rect,
- ca_layer_overlays);
+ dc_layer_overlays);
}
} else {
ProcessRenderPass(resource_provider, display_rect,
render_passes->back().get(), true, overlay_damage_rect,
- damage_rect, ca_layer_overlays);
+ damage_rect, dc_layer_overlays);
}
pass_info_.clear();
}
@@ -218,13 +219,13 @@ QuadList::Iterator DCLayerOverlayProcessor::ProcessRenderPassDrawQuad(
}
void DCLayerOverlayProcessor::ProcessRenderPass(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPass* render_pass,
bool is_root,
gfx::Rect* overlay_damage_rect,
gfx::Rect* damage_rect,
- DCLayerOverlayList* ca_layer_overlays) {
+ DCLayerOverlayList* dc_layer_overlays) {
gfx::Rect this_frame_underlay_rect;
QuadList* quad_list = &render_pass->quad_list;
@@ -286,7 +287,7 @@ void DCLayerOverlayProcessor::ProcessRenderPass(
overlay_damage_rect->Union(rect_in_root);
RecordDCLayerResult(DC_LAYER_SUCCESS);
- ca_layer_overlays->push_back(dc_layer);
+ dc_layer_overlays->push_back(dc_layer);
if (!base::FeatureList::IsEnabled(
features::kDirectCompositionNonrootOverlays)) {
// Only allow one overlay for now.
diff --git a/chromium/components/viz/service/display/dc_layer_overlay.h b/chromium/components/viz/service/display/dc_layer_overlay.h
index 280b8dfe2ff..34d118dccd0 100644
--- a/chromium/components/viz/service/display/dc_layer_overlay.h
+++ b/chromium/components/viz/service/display/dc_layer_overlay.h
@@ -14,11 +14,8 @@
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gl/dc_renderer_layer_params.h"
-namespace cc {
-class DisplayResourceProvider;
-}
-
namespace viz {
+class DisplayResourceProvider;
class VIZ_SERVICE_EXPORT DCLayerOverlaySharedState
: public base::RefCounted<DCLayerOverlaySharedState> {
@@ -71,6 +68,7 @@ class VIZ_SERVICE_EXPORT DCLayerOverlay {
gfx::ColorSpace color_space;
bool require_overlay = false;
+ bool is_protected_video = false;
};
typedef std::vector<DCLayerOverlay> DCLayerOverlayList;
@@ -96,7 +94,7 @@ class DCLayerOverlayProcessor {
DCLayerOverlayProcessor();
~DCLayerOverlayProcessor();
- void Process(cc::DisplayResourceProvider* resource_provider,
+ void Process(DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPassList* render_passes,
gfx::Rect* overlay_damage_rect,
@@ -108,7 +106,7 @@ class DCLayerOverlayProcessor {
}
private:
- DCLayerResult FromDrawQuad(cc::DisplayResourceProvider* resource_provider,
+ DCLayerResult FromDrawQuad(DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
QuadList::ConstIterator quad_list_begin,
QuadList::ConstIterator quad,
@@ -117,7 +115,7 @@ class DCLayerOverlayProcessor {
QuadList::Iterator ProcessRenderPassDrawQuad(RenderPass* render_pass,
gfx::Rect* damage_rect,
QuadList::Iterator it);
- void ProcessRenderPass(cc::DisplayResourceProvider* resource_provider,
+ void ProcessRenderPass(DisplayResourceProvider* resource_provider,
const gfx::RectF& display_rect,
RenderPass* render_pass,
bool is_root,
diff --git a/chromium/components/viz/service/display/direct_renderer.cc b/chromium/components/viz/service/display/direct_renderer.cc
index 4e6823d2780..2e79ba0f068 100644
--- a/chromium/components/viz/service/display/direct_renderer.cc
+++ b/chromium/components/viz/service/display/direct_renderer.cc
@@ -80,7 +80,7 @@ DirectRenderer::DrawingFrame::~DrawingFrame() = default;
DirectRenderer::DirectRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+ DisplayResourceProvider* resource_provider)
: settings_(settings),
output_surface_(output_surface),
resource_provider_(resource_provider),
@@ -273,7 +273,7 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
// Create the overlay candidate for the output surface, and mark it as
// always handled.
if (output_surface_->IsDisplayedAsOverlayPlane()) {
- cc::OverlayCandidate output_surface_plane;
+ OverlayCandidate output_surface_plane;
output_surface_plane.display_rect =
gfx::RectF(device_viewport_size.width(), device_viewport_size.height());
output_surface_plane.resource_size_in_pixels = device_viewport_size;
@@ -328,8 +328,23 @@ void DirectRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
if (!skip_drawing_root_render_pass && !use_partial_swap_)
current_frame()->root_damage_rect = gfx::Rect(device_viewport_size);
- if (!skip_drawing_root_render_pass)
+ if (!skip_drawing_root_render_pass) {
DrawRenderPassAndExecuteCopyRequests(root_render_pass);
+ // Use a fence to synchronize display of the surface overlay. Note that
+ // gpu_fence_id may have the special value 0 ("no fence") if fences are not
+ // supported. In that case synchronization will happen through other means
+ // on the service side.
+ // TODO(crbug.com/840805): We currently only use fences for root render
+ // passes but we may also need to use fences for non-root passes in some
+ // cases (e.g. WebGL canvas).
+ auto gpu_fence_id = output_surface_->UpdateGpuFence();
+ for (auto& overlay : current_frame()->overlay_list) {
+ if (overlay.use_output_surface_for_resource) {
+ overlay.gpu_fence_id = gpu_fence_id;
+ break;
+ }
+ }
+ }
FinishDrawingFrame();
render_passes_in_draw_order->clear();
diff --git a/chromium/components/viz/service/display/direct_renderer.h b/chromium/components/viz/service/display/direct_renderer.h
index 63be93b71c4..5cf6c6840aa 100644
--- a/chromium/components/viz/service/display/direct_renderer.h
+++ b/chromium/components/viz/service/display/direct_renderer.h
@@ -12,10 +12,10 @@
#include "base/containers/circular_deque.h"
#include "base/containers/flat_map.h"
#include "base/macros.h"
-#include "cc/resources/display_resource_provider.h"
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/service/display/ca_layer_overlay.h"
#include "components/viz/service/display/dc_layer_overlay.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/overlay_processor.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
@@ -25,7 +25,6 @@
namespace cc {
class FilterOperations;
-class OutputSurface;
} // namespace cc
namespace gfx {
@@ -35,6 +34,7 @@ class ColorSpace;
namespace viz {
class BspWalkActionDrawPolygon;
class DrawPolygon;
+class OutputSurface;
class RendererSettings;
class RenderPass;
@@ -46,7 +46,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
public:
DirectRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider);
+ DisplayResourceProvider* resource_provider);
virtual ~DirectRenderer();
void Initialize();
@@ -61,7 +61,8 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
const gfx::Size& device_viewport_size);
// Public interface implemented by subclasses.
- virtual void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) = 0;
+ virtual void SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) = 0;
virtual void SwapBuffersComplete() {}
virtual void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) {}
@@ -82,7 +83,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
gfx::Transform projection_matrix;
gfx::Transform window_matrix;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
CALayerOverlayList ca_layer_overlay_list;
DCLayerOverlayList dc_layer_overlay_list;
};
@@ -201,7 +202,7 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
const RendererSettings* const settings_;
OutputSurface* const output_surface_;
- cc::DisplayResourceProvider* const resource_provider_;
+ DisplayResourceProvider* const resource_provider_;
// This can be replaced by test implementations.
std::unique_ptr<OverlayProcessor> overlay_processor_;
diff --git a/chromium/components/viz/service/display/display.cc b/chromium/components/viz/service/display/display.cc
index ef3b32de61b..178708effd2 100644
--- a/chromium/components/viz/service/display/display.cc
+++ b/chromium/components/viz/service/display/display.cc
@@ -24,6 +24,7 @@
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display/gl_renderer.h"
#include "components/viz/service/display/output_surface.h"
+#include "components/viz/service/display/skia_output_surface.h"
#include "components/viz/service/display/skia_renderer.h"
#include "components/viz/service/display/software_renderer.h"
#include "components/viz/service/display/surface_aggregator.h"
@@ -44,10 +45,12 @@ Display::Display(
const FrameSinkId& frame_sink_id,
std::unique_ptr<OutputSurface> output_surface,
std::unique_ptr<DisplayScheduler> scheduler,
- scoped_refptr<base::SingleThreadTaskRunner> current_task_runner)
+ scoped_refptr<base::SingleThreadTaskRunner> current_task_runner,
+ SkiaOutputSurface* skia_output_surface)
: bitmap_manager_(bitmap_manager),
settings_(settings),
frame_sink_id_(frame_sink_id),
+ skia_output_surface_(skia_output_surface),
output_surface_(std::move(output_surface)),
scheduler_(std::move(scheduler)),
current_task_runner_(std::move(current_task_runner)) {
@@ -58,17 +61,11 @@ Display::Display(
}
Display::~Display() {
- for (auto& callbacks : previous_presented_callbacks_) {
- for (auto& callback : callbacks)
+ for (auto& callback_list : pending_presented_callbacks_) {
+ for (auto& callback : callback_list)
std::move(callback).Run(base::TimeTicks(), base::TimeDelta(), 0);
}
- for (auto& callback : active_presented_callbacks_)
- std::move(callback).Run(base::TimeTicks(), base::TimeDelta(), 0);
-
- for (auto& callback : presented_callbacks_)
- std::move(callback).Run(base::TimeTicks(), base::TimeDelta(), 0);
-
// Only do this if Initialize() happened.
if (client_) {
if (auto* context = output_surface_->context_provider())
@@ -95,6 +92,9 @@ void Display::Initialize(DisplayClient* client,
surface_manager_->AddObserver(scheduler_.get());
output_surface_->BindToClient(this);
+ if (output_surface_->software_device())
+ output_surface_->software_device()->BindToClient(this);
+
InitializeRenderer();
// This depends on assumptions that Display::Initialize will happen on the
@@ -205,7 +205,7 @@ void Display::SetOutputIsSecure(bool secure) {
}
void Display::InitializeRenderer() {
- resource_provider_ = std::make_unique<cc::DisplayResourceProvider>(
+ resource_provider_ = std::make_unique<DisplayResourceProvider>(
output_surface_->context_provider(), bitmap_manager_);
if (output_surface_->context_provider()) {
@@ -214,15 +214,15 @@ void Display::InitializeRenderer() {
&settings_, output_surface_.get(), resource_provider_.get(),
current_task_runner_);
} else {
+ DCHECK(output_surface_);
renderer_ = std::make_unique<SkiaRenderer>(
- &settings_, output_surface_.get(), resource_provider_.get());
+ &settings_, output_surface_.get(), resource_provider_.get(),
+ skia_output_surface_);
}
- } else if (output_surface_->vulkan_context_provider()) {
#if BUILDFLAG(ENABLE_VULKAN)
+ } else if (output_surface_->vulkan_context_provider()) {
renderer_ = std::make_unique<SkiaRenderer>(
&settings_, output_surface_.get(), resource_provider_.get());
-#else
- NOTREACHED();
#endif
} else {
auto renderer = std::make_unique<SoftwareRenderer>(
@@ -307,7 +307,8 @@ bool Display::DrawAndSwap() {
gfx::Size surface_size;
bool have_damage = false;
auto& last_render_pass = *frame.render_pass_list.back();
- if (last_render_pass.output_rect.size() != current_surface_size_ &&
+ if (settings_.auto_resize_output_surface &&
+ last_render_pass.output_rect.size() != current_surface_size_ &&
last_render_pass.damage_rect == last_render_pass.output_rect &&
!current_surface_size_.IsEmpty()) {
// Resize the output rect to the current surface size so that we won't
@@ -323,15 +324,6 @@ bool Display::DrawAndSwap() {
TRACE_EVENT_INSTANT0("viz", "Size mismatch.", TRACE_EVENT_SCOPE_THREAD);
bool should_draw = have_copy_requests || (have_damage && size_matches);
-
- // If the surface is suspended then the resources to be used by the draw are
- // likely destroyed.
- if (output_surface_->SurfaceIsSuspendForRecycle()) {
- TRACE_EVENT_INSTANT0("viz", "Surface is suspended for recycle.",
- TRACE_EVENT_SCOPE_THREAD);
- should_draw = false;
- }
-
client_->DisplayWillDrawAndSwap(should_draw, frame.render_pass_list);
if (should_draw) {
@@ -375,24 +367,28 @@ bool Display::DrawAndSwap() {
if (scheduler_) {
frame.metadata.latency_info.emplace_back(ui::SourceEventType::FRAME);
frame.metadata.latency_info.back().AddLatencyNumberWithTimestamp(
- ui::LATENCY_BEGIN_FRAME_DISPLAY_COMPOSITOR_COMPONENT, 0, 0,
+ ui::LATENCY_BEGIN_FRAME_DISPLAY_COMPOSITOR_COMPONENT, 0,
scheduler_->current_frame_time(), 1);
}
- DLOG_IF(WARNING, !presented_callbacks_.empty())
- << "DidReceiveSwapBuffersAck() is not called for the last SwapBuffers!";
+ std::vector<Surface::PresentedCallback> callbacks;
for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
Surface* surface = surface_manager_->GetSurfaceForId(id_entry.first);
Surface::PresentedCallback callback;
- if (surface && surface->TakePresentedCallback(&callback))
- presented_callbacks_.push_back(std::move(callback));
+ if (surface && surface->TakePresentedCallback(&callback)) {
+ callbacks.emplace_back(std::move(callback));
+ }
}
+ bool need_presentation_feedback = !callbacks.empty();
+ if (need_presentation_feedback)
+ pending_presented_callbacks_.emplace_back(std::move(callbacks));
ui::LatencyInfo::TraceIntermediateFlowEvents(frame.metadata.latency_info,
"Display::DrawAndSwap");
cc::benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
- renderer_->SwapBuffers(std::move(frame.metadata.latency_info));
+ renderer_->SwapBuffers(std::move(frame.metadata.latency_info),
+ need_presentation_feedback);
if (scheduler_)
scheduler_->DidSwapBuffers();
} else {
@@ -413,13 +409,11 @@ bool Display::DrawAndSwap() {
base::TimeTicks now = base::TimeTicks::Now();
while (!frame.metadata.latency_info.empty()) {
auto& latency = frame.metadata.latency_info.back();
- if (latency.FindLatency(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT,
- nullptr)) {
+ if (latency.Snapshots().size()) {
stored_latency_info_.push_back(std::move(latency));
} else {
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, 0, now,
- 1);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_NO_SWAP_COMPONENT, 0, now, 1);
}
frame.metadata.latency_info.pop_back();
}
@@ -441,17 +435,7 @@ bool Display::DrawAndSwap() {
return true;
}
-void Display::DidReceiveSwapBuffersAck(uint64_t swap_id) {
- // TODO(penghuang): Remove it when we can get accurate presentation time from
- // GPU for every SwapBuffers. https://crbug.com/776877
- if (!active_presented_callbacks_.empty() ||
- !previous_presented_callbacks_.empty()) {
- DLOG(WARNING) << "VSync for last SwapBuffers is not received!";
- previous_presented_callbacks_.push_back(
- std::move(active_presented_callbacks_));
- }
- active_presented_callbacks_ = std::move(presented_callbacks_);
-
+void Display::DidReceiveSwapBuffersAck() {
if (scheduler_)
scheduler_->DidReceiveSwapBuffersAck();
if (renderer_)
@@ -471,25 +455,28 @@ void Display::DidReceiveCALayerParams(
}
void Display::DidReceivePresentationFeedback(
- uint64_t swap_id,
const gfx::PresentationFeedback& feedback) {
- // TODO(penghuang): Remove it when we can get accurate presentation time from
- // GPU for every SwapBuffers. https://crbug.com/776877
- base::TimeTicks previous_timebase =
- feedback.timestamp -
- feedback.interval * previous_presented_callbacks_.size();
- for (auto& callbacks : previous_presented_callbacks_) {
- for (auto& callback : callbacks)
- std::move(callback).Run(previous_timebase, feedback.interval, 0);
- previous_timebase += feedback.interval;
- }
- previous_presented_callbacks_.clear();
-
- for (auto& callback : active_presented_callbacks_) {
+ DCHECK(!pending_presented_callbacks_.empty());
+ auto& callbacks = pending_presented_callbacks_.front();
+ for (auto& callback : callbacks) {
std::move(callback).Run(feedback.timestamp, feedback.interval,
feedback.flags);
}
- active_presented_callbacks_.clear();
+ pending_presented_callbacks_.pop_front();
+}
+
+void Display::DidFinishLatencyInfo(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ std::vector<ui::LatencyInfo> latency_info_with_snapshot_component;
+ for (const auto& latency : latency_info) {
+ if (latency.Snapshots().size())
+ latency_info_with_snapshot_component.push_back(latency);
+ }
+
+ if (!latency_info_with_snapshot_component.empty()) {
+ client_->DidSwapAfterSnapshotRequestReceived(
+ latency_info_with_snapshot_component);
+ }
}
void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
@@ -561,6 +548,12 @@ LocalSurfaceId Display::GetSurfaceAtAggregation(
return it->second;
}
+void Display::SoftwareDeviceUpdatedCALayerParams(
+ const gfx::CALayerParams& ca_layer_params) {
+ if (client_)
+ client_->DisplayDidReceiveCALayerParams(ca_layer_params);
+}
+
void Display::ForceImmediateDrawAndSwapIfPossible() {
if (scheduler_)
scheduler_->ForceImmediateSwapIfPossible();
diff --git a/chromium/components/viz/service/display/display.h b/chromium/components/viz/service/display/display.h
index 7759c67aa47..51312be163e 100644
--- a/chromium/components/viz/service/display/display.h
+++ b/chromium/components/viz/service/display/display.h
@@ -8,16 +8,19 @@
#include <memory>
#include <vector>
+#include "base/containers/circular_deque.h"
#include "base/macros.h"
#include "base/observer_list.h"
-#include "cc/resources/display_resource_provider.h"
+#include "base/single_thread_task_runner.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/gpu/context_lost_observer.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_id.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display/output_surface_client.h"
+#include "components/viz/service/display/software_output_device_client.h"
#include "components/viz/service/display/surface_aggregator.h"
#include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -26,11 +29,6 @@
#include "ui/gfx/color_space.h"
#include "ui/latency/latency_info.h"
-namespace cc {
-class DisplayResourceProvider;
-class RendererSettings;
-} // namespace cc
-
namespace gfx {
class Size;
}
@@ -38,8 +36,11 @@ class Size;
namespace viz {
class DirectRenderer;
class DisplayClient;
+class DisplayResourceProvider;
class OutputSurface;
+class RendererSettings;
class SharedBitmapManager;
+class SkiaOutputSurface;
class SoftwareRenderer;
class VIZ_SERVICE_EXPORT DisplayObserver {
@@ -55,18 +56,22 @@ class VIZ_SERVICE_EXPORT DisplayObserver {
class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
public OutputSurfaceClient,
public ContextLostObserver,
- public LatestLocalSurfaceIdLookupDelegate {
+ public LatestLocalSurfaceIdLookupDelegate,
+ public SoftwareOutputDeviceClient {
public:
// The |begin_frame_source| and |scheduler| may be null (together). In that
// case, DrawAndSwap must be called externally when needed.
// The |current_task_runner| may be null if the Display is on a thread without
// a MessageLoop.
+ // TODO(penghuang): Remove skia_output_surface when all DirectRenderer
+ // subclasses are replaced by SkiaRenderer.
Display(SharedBitmapManager* bitmap_manager,
const RendererSettings& settings,
const FrameSinkId& frame_sink_id,
std::unique_ptr<OutputSurface> output_surface,
std::unique_ptr<DisplayScheduler> scheduler,
- scoped_refptr<base::SingleThreadTaskRunner> current_task_runner);
+ scoped_refptr<base::SingleThreadTaskRunner> current_task_runner,
+ SkiaOutputSurface* skia_output_surface = nullptr);
~Display() override;
@@ -101,19 +106,24 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
// OutputSurfaceClient implementation.
void SetNeedsRedrawRect(const gfx::Rect& damage_rect) override;
- void DidReceiveSwapBuffersAck(uint64_t swap_id) override;
+ void DidReceiveSwapBuffersAck() override;
void DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) override;
void DidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) override;
void DidReceivePresentationFeedback(
- uint64_t swap_id,
const gfx::PresentationFeedback& feedback) override;
+ void DidFinishLatencyInfo(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
// LatestLocalSurfaceIdLookupDelegate implementation.
LocalSurfaceId GetSurfaceAtAggregation(
const FrameSinkId& frame_sink_id) const override;
+ // SoftwareOutputDeviceClient implementation
+ void SoftwareDeviceUpdatedCALayerParams(
+ const gfx::CALayerParams& ca_layer_params) override;
+
bool has_scheduler() const { return !!scheduler_; }
DirectRenderer* renderer_for_testing() const { return renderer_.get(); }
@@ -144,9 +154,10 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
bool swapped_since_resize_ = false;
bool output_is_secure_ = false;
+ SkiaOutputSurface* skia_output_surface_;
std::unique_ptr<OutputSurface> output_surface_;
std::unique_ptr<DisplayScheduler> scheduler_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
// This may be null if the Display is on a thread without a MessageLoop.
scoped_refptr<base::SingleThreadTaskRunner> current_task_runner_;
@@ -154,12 +165,8 @@ class VIZ_SERVICE_EXPORT Display : public DisplaySchedulerClient,
SoftwareRenderer* software_renderer_ = nullptr;
std::vector<ui::LatencyInfo> stored_latency_info_;
- using PresentedCallbacks = std::vector<Surface::PresentedCallback>;
- PresentedCallbacks presented_callbacks_;
- PresentedCallbacks active_presented_callbacks_;
- // TODO(penghuang): Remove it when we can get accurate presentation time from
- // GPU for every SwapBuffers. https://crbug.com/776877
- std::vector<PresentedCallbacks> previous_presented_callbacks_;
+ base::circular_deque<std::vector<Surface::PresentedCallback>>
+ pending_presented_callbacks_;
private:
DISALLOW_COPY_AND_ASSIGN(Display);
diff --git a/chromium/components/viz/service/display/display_client.h b/chromium/components/viz/service/display/display_client.h
index 286aa158ff3..9734040a581 100644
--- a/chromium/components/viz/service/display/display_client.h
+++ b/chromium/components/viz/service/display/display_client.h
@@ -11,6 +11,10 @@ namespace gfx {
struct CALayerParams;
} // namespace gfx
+namespace ui {
+class LatencyInfo;
+} // namespace ui
+
namespace viz {
class DisplayClient {
@@ -22,6 +26,11 @@ class DisplayClient {
virtual void DisplayDidDrawAndSwap() = 0;
virtual void DisplayDidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) = 0;
+
+ // Notifies that a swap has occured after some latency info with snapshot
+ // component reached the display.
+ virtual void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/display/display_resource_provider.cc b/chromium/components/viz/service/display/display_resource_provider.cc
new file mode 100644
index 00000000000..2b78a9662b5
--- /dev/null
+++ b/chromium/components/viz/service/display/display_resource_provider.cc
@@ -0,0 +1,972 @@
+// 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.
+
+#include "components/viz/service/display/display_resource_provider.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/numerics/safe_math.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/trace_event.h"
+#include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "components/viz/common/resources/resource_sizes.h"
+#include "components/viz/common/resources/shared_bitmap_manager.h"
+#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "third_party/skia/include/gpu/GrBackendSurface.h"
+#include "ui/gl/trace_util.h"
+
+using gpu::gles2::GLES2Interface;
+
+namespace viz {
+
+namespace {
+
+// Generates process-unique IDs to use for tracing resources.
+base::AtomicSequenceNumber g_next_display_resource_provider_tracing_id;
+
+} // namespace
+
+static GLint GetActiveTextureUnit(GLES2Interface* gl) {
+ GLint active_unit = 0;
+ gl->GetIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
+ return active_unit;
+}
+
+class ScopedSetActiveTexture {
+ public:
+ ScopedSetActiveTexture(GLES2Interface* gl, GLenum unit)
+ : gl_(gl), unit_(unit) {
+ DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
+
+ if (unit_ != GL_TEXTURE0)
+ gl_->ActiveTexture(unit_);
+ }
+
+ ~ScopedSetActiveTexture() {
+ // Active unit being GL_TEXTURE0 is effectively the ground state.
+ if (unit_ != GL_TEXTURE0)
+ gl_->ActiveTexture(GL_TEXTURE0);
+ }
+
+ private:
+ GLES2Interface* gl_;
+ GLenum unit_;
+};
+
+DisplayResourceProvider::DisplayResourceProvider(
+ ContextProvider* compositor_context_provider,
+ SharedBitmapManager* shared_bitmap_manager)
+ : compositor_context_provider_(compositor_context_provider),
+ shared_bitmap_manager_(shared_bitmap_manager),
+ tracing_id_(g_next_display_resource_provider_tracing_id.GetNext()) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
+ // Don't register a dump provider in these cases.
+ // TODO(crbug.com/517156): Get this working in Android Webview.
+ if (base::ThreadTaskRunnerHandle::IsSet()) {
+ base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ this, "cc::ResourceProvider", base::ThreadTaskRunnerHandle::Get());
+ }
+}
+
+DisplayResourceProvider::~DisplayResourceProvider() {
+ while (!children_.empty())
+ DestroyChildInternal(children_.begin(), FOR_SHUTDOWN);
+
+ GLES2Interface* gl = ContextGL();
+ if (gl)
+ gl->Finish();
+
+ while (!resources_.empty())
+ DeleteResourceInternal(resources_.begin(), FOR_SHUTDOWN);
+
+ if (compositor_context_provider_) {
+ // Check that all GL resources has been deleted.
+ for (const auto& pair : resources_)
+ DCHECK(!pair.second.is_gpu_resource_type());
+ }
+
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
+}
+
+bool DisplayResourceProvider::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ for (const auto& resource_entry : resources_) {
+ const auto& resource = resource_entry.second;
+
+ bool backing_memory_allocated = false;
+ switch (resource.type) {
+ case ResourceType::kTexture:
+ backing_memory_allocated = !!resource.gl_id;
+ break;
+ case ResourceType::kBitmap:
+ backing_memory_allocated = !!resource.shared_bitmap;
+ break;
+ }
+
+ if (!backing_memory_allocated) {
+ // Don't log unallocated resources - they have no backing memory.
+ continue;
+ }
+
+ // ResourceIds are not process-unique, so log with the ResourceProvider's
+ // unique id.
+ std::string dump_name =
+ base::StringPrintf("cc/resource_memory/provider_%d/resource_%d",
+ tracing_id_, resource_entry.first);
+ base::trace_event::MemoryAllocatorDump* dump =
+ pmd->CreateAllocatorDump(dump_name);
+
+ // Texture resources may not come with a size, in which case don't report
+ // one.
+ if (!resource.size.IsEmpty()) {
+ uint64_t total_bytes = ResourceSizes::UncheckedSizeInBytesAligned<size_t>(
+ resource.size, resource.format);
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes,
+ static_cast<uint64_t>(total_bytes));
+ }
+
+ // Resources may be shared across processes and require a shared GUID to
+ // prevent double counting the memory.
+ base::trace_event::MemoryAllocatorDumpGuid guid;
+ base::UnguessableToken shared_memory_guid;
+ switch (resource.type) {
+ case ResourceType::kTexture:
+ DCHECK(resource.gl_id);
+ guid = gl::GetGLTextureClientGUIDForTracing(
+ compositor_context_provider_->ContextSupport()
+ ->ShareGroupTracingGUID(),
+ resource.gl_id);
+ break;
+ case ResourceType::kBitmap:
+ // If the resource comes from out of process, it will have this id,
+ // which we prefer. Otherwise, we fall back to the SharedBitmapGUID
+ // which can be generated for in-process bitmaps.
+ shared_memory_guid = resource.shared_bitmap->GetCrossProcessGUID();
+ if (shared_memory_guid.is_empty())
+ guid = GetSharedBitmapGUIDForTracing(resource.shared_bitmap_id);
+ break;
+ }
+
+ DCHECK(!shared_memory_guid.is_empty() || !guid.empty());
+
+ // The client that owns the resource will use a higher importance (2), and
+ // the GPU service will use a lower one (0).
+ const int importance = 1;
+ if (!shared_memory_guid.is_empty()) {
+ pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
+ importance);
+ } else {
+ pmd->CreateSharedGlobalAllocatorDump(guid);
+ pmd->AddOwnershipEdge(dump->guid(), guid, importance);
+ }
+ }
+
+ return true;
+}
+
+#if defined(OS_ANDROID)
+void DisplayResourceProvider::SendPromotionHints(
+ const OverlayCandidateList::PromotionHintInfoMap& promotion_hints) {
+ GLES2Interface* gl = ContextGL();
+ if (!gl)
+ return;
+
+ for (const auto& id : wants_promotion_hints_set_) {
+ auto it = resources_.find(id);
+ if (it == resources_.end())
+ continue;
+
+ if (it->second.marked_for_deletion)
+ continue;
+
+ const internal::Resource* resource = LockForRead(id);
+ // TODO(ericrk): We should never fail LockForRead, but we appear to be
+ // doing so on Android in rare cases. Handle this gracefully until a better
+ // solution can be found. https://crbug.com/811858
+ if (!resource)
+ return;
+
+ DCHECK(resource->wants_promotion_hint);
+
+ // Insist that this is backed by a GPU texture.
+ if (resource->is_gpu_resource_type()) {
+ DCHECK(resource->gl_id);
+ auto iter = promotion_hints.find(id);
+ bool promotable = iter != promotion_hints.end();
+ gl->OverlayPromotionHintCHROMIUM(resource->gl_id, promotable,
+ promotable ? iter->second.x() : 0,
+ promotable ? iter->second.y() : 0,
+ promotable ? iter->second.width() : 0,
+ promotable ? iter->second.height() : 0);
+ }
+ UnlockForRead(id);
+ }
+}
+
+bool DisplayResourceProvider::IsBackedBySurfaceTexture(ResourceId id) {
+ internal::Resource* resource = GetResource(id);
+ return resource->is_backed_by_surface_texture;
+}
+
+bool DisplayResourceProvider::WantsPromotionHintForTesting(ResourceId id) {
+ return wants_promotion_hints_set_.count(id) > 0;
+}
+
+size_t DisplayResourceProvider::CountPromotionHintRequestsForTesting() {
+ return wants_promotion_hints_set_.size();
+}
+#endif
+
+bool DisplayResourceProvider::IsOverlayCandidate(ResourceId id) {
+ internal::Resource* resource = TryGetResource(id);
+ // TODO(ericrk): We should never fail TryGetResource, but we appear to
+ // be doing so on Android in rare cases. Handle this gracefully until a
+ // better solution can be found. https://crbug.com/811858
+ return resource && resource->is_overlay_candidate;
+}
+
+ResourceType DisplayResourceProvider::GetResourceType(ResourceId id) {
+ return GetResource(id)->type;
+}
+
+GLenum DisplayResourceProvider::GetResourceTextureTarget(ResourceId id) {
+ return GetResource(id)->target;
+}
+
+gfx::BufferFormat DisplayResourceProvider::GetBufferFormat(ResourceId id) {
+ internal::Resource* resource = GetResource(id);
+ return resource->buffer_format;
+}
+
+void DisplayResourceProvider::WaitSyncToken(ResourceId id) {
+ internal::Resource* resource = TryGetResource(id);
+ // TODO(ericrk): We should never fail TryGetResource, but we appear to
+ // be doing so on Android in rare cases. Handle this gracefully until a
+ // better solution can be found. https://crbug.com/811858
+ if (!resource)
+ return;
+ WaitSyncTokenInternal(resource);
+#if defined(OS_ANDROID)
+ // Now that the resource is synced, we may send it a promotion hint. We could
+ // sync all |wants_promotion_hint| resources elsewhere, and send 'no' to all
+ // resources that weren't used. However, there's no real advantage.
+ if (resource->wants_promotion_hint)
+ wants_promotion_hints_set_.insert(id);
+#endif // OS_ANDROID
+}
+
+int DisplayResourceProvider::CreateChild(
+ const ReturnCallback& return_callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ Child child_info;
+ child_info.return_callback = return_callback;
+
+ int child = next_child_++;
+ children_[child] = child_info;
+ return child;
+}
+
+void DisplayResourceProvider::SetChildNeedsSyncTokens(int child_id,
+ bool needs) {
+ auto it = children_.find(child_id);
+ DCHECK(it != children_.end());
+ it->second.needs_sync_tokens = needs;
+}
+
+void DisplayResourceProvider::DestroyChild(int child_id) {
+ auto it = children_.find(child_id);
+ DCHECK(it != children_.end());
+ DestroyChildInternal(it, NORMAL);
+}
+
+void DisplayResourceProvider::ReceiveFromChild(
+ int child,
+ const std::vector<TransferableResource>& resources) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ GLES2Interface* gl = ContextGL();
+ Child& child_info = children_.find(child)->second;
+ DCHECK(!child_info.marked_for_deletion);
+ for (std::vector<TransferableResource>::const_iterator it = resources.begin();
+ it != resources.end(); ++it) {
+ auto resource_in_map_it = child_info.child_to_parent_map.find(it->id);
+ if (resource_in_map_it != child_info.child_to_parent_map.end()) {
+ internal::Resource* resource = GetResource(resource_in_map_it->second);
+ resource->marked_for_deletion = false;
+ resource->imported_count++;
+ continue;
+ }
+
+ if ((!it->is_software && !gl) ||
+ (it->is_software && !shared_bitmap_manager_)) {
+ TRACE_EVENT0(
+ "cc", "DisplayResourceProvider::ReceiveFromChild dropping invalid");
+ std::vector<ReturnedResource> to_return;
+ to_return.push_back(it->ToReturnedResource());
+ child_info.return_callback.Run(to_return);
+ continue;
+ }
+
+ ResourceId local_id = next_id_++;
+ internal::Resource* resource = nullptr;
+ if (it->is_software) {
+ DCHECK(IsBitmapFormatSupported(it->format));
+ resource = InsertResource(
+ local_id, internal::Resource(it->size, ResourceType::kBitmap,
+ it->format, it->color_space));
+ resource->has_shared_bitmap_id = true;
+ resource->shared_bitmap_id = it->mailbox_holder.mailbox;
+ } else {
+ resource = InsertResource(
+ local_id, internal::Resource(it->size, ResourceType::kTexture,
+ it->format, it->color_space));
+ resource->target = it->mailbox_holder.texture_target;
+ resource->filter = it->filter;
+ resource->original_filter = it->filter;
+ resource->min_filter = it->filter;
+ resource->buffer_format = it->buffer_format;
+ resource->mailbox = it->mailbox_holder.mailbox;
+ resource->UpdateSyncToken(it->mailbox_holder.sync_token);
+ resource->read_lock_fences_enabled = it->read_lock_fences_enabled;
+ resource->is_overlay_candidate = it->is_overlay_candidate;
+#if defined(OS_ANDROID)
+ resource->is_backed_by_surface_texture = it->is_backed_by_surface_texture;
+ resource->wants_promotion_hint = it->wants_promotion_hint;
+#endif
+ }
+ resource->child_id = child;
+ resource->imported_count = 1;
+ resource->id_in_child = it->id;
+ child_info.child_to_parent_map[it->id] = local_id;
+ }
+}
+
+void DisplayResourceProvider::DeclareUsedResourcesFromChild(
+ int child,
+ const ResourceIdSet& resources_from_child) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ auto child_it = children_.find(child);
+ DCHECK(child_it != children_.end());
+ Child& child_info = child_it->second;
+ DCHECK(!child_info.marked_for_deletion);
+
+ std::vector<ResourceId> unused;
+ for (auto it = child_info.child_to_parent_map.begin();
+ it != child_info.child_to_parent_map.end(); ++it) {
+ ResourceId local_id = it->second;
+ bool resource_is_in_use = resources_from_child.count(it->first) > 0;
+ if (!resource_is_in_use)
+ unused.push_back(local_id);
+ }
+ DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
+}
+
+const std::unordered_map<ResourceId, ResourceId>&
+DisplayResourceProvider::GetChildToParentMap(int child) const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ ChildMap::const_iterator it = children_.find(child);
+ DCHECK(it != children_.end());
+ DCHECK(!it->second.marked_for_deletion);
+ return it->second.child_to_parent_map;
+}
+
+bool DisplayResourceProvider::InUse(ResourceId id) {
+ internal::Resource* resource = GetResource(id);
+ return resource->lock_for_read_count > 0 || resource->locked_for_external_use;
+}
+
+internal::Resource* DisplayResourceProvider::InsertResource(
+ ResourceId id,
+ internal::Resource resource) {
+ auto result =
+ resources_.insert(ResourceMap::value_type(id, std::move(resource)));
+ DCHECK(result.second);
+ return &result.first->second;
+}
+
+internal::Resource* DisplayResourceProvider::GetResource(ResourceId id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(id);
+ auto it = resources_.find(id);
+ DCHECK(it != resources_.end());
+ return &it->second;
+}
+
+internal::Resource* DisplayResourceProvider::TryGetResource(ResourceId id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (!id)
+ return nullptr;
+ auto it = resources_.find(id);
+ if (it == resources_.end())
+ return nullptr;
+ return &it->second;
+}
+
+void DisplayResourceProvider::PopulateSkBitmapWithResource(
+ SkBitmap* sk_bitmap,
+ const internal::Resource* resource) {
+ DCHECK(IsBitmapFormatSupported(resource->format));
+ SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
+ resource->size.height());
+ bool pixels_installed =
+ sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
+ DCHECK(pixels_installed);
+}
+
+void DisplayResourceProvider::DeleteResourceInternal(ResourceMap::iterator it,
+ DeleteStyle style) {
+ TRACE_EVENT0("cc", "DosplayResourceProvider::DeleteResourceInternal");
+ internal::Resource* resource = &it->second;
+
+ if (resource->gl_id) {
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ gl->DeleteTextures(1, &resource->gl_id);
+ resource->gl_id = 0;
+ }
+
+ if (resource->owned_shared_bitmap) {
+ DCHECK_EQ(ResourceType::kBitmap, resource->type);
+ resource->shared_bitmap = nullptr;
+ resource->pixels = nullptr;
+ resource->owned_shared_bitmap = nullptr;
+ }
+
+ resources_.erase(it);
+}
+
+void DisplayResourceProvider::WaitSyncTokenInternal(
+ internal::Resource* resource) {
+ DCHECK(resource);
+ if (!resource->ShouldWaitSyncToken())
+ return;
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ // In the case of context lost, this sync token may be empty (see comment in
+ // the UpdateSyncToken() function). The WaitSyncTokenCHROMIUM() function
+ // handles empty sync tokens properly so just wait anyways and update the
+ // state the synchronized.
+ gl->WaitSyncTokenCHROMIUM(resource->sync_token().GetConstData());
+ resource->SetSynchronized();
+}
+
+GLES2Interface* DisplayResourceProvider::ContextGL() const {
+ ContextProvider* context_provider = compositor_context_provider_;
+ return context_provider ? context_provider->ContextGL() : nullptr;
+}
+
+const internal::Resource* DisplayResourceProvider::LockForRead(ResourceId id) {
+ // TODO(ericrk): We should never fail TryGetResource, but we appear to be
+ // doing so on Android in rare cases. Handle this gracefully until a better
+ // solution can be found. https://crbug.com/811858
+ internal::Resource* resource = TryGetResource(id);
+ if (!resource)
+ return nullptr;
+
+ // Mailbox sync_tokens must be processed by a call to WaitSyncToken() prior to
+ // calling LockForRead().
+ DCHECK_NE(internal::Resource::NEEDS_WAIT, resource->synchronization_state());
+
+ if (resource->is_gpu_resource_type() && !resource->gl_id) {
+ DCHECK(!resource->mailbox.IsZero());
+
+ GLES2Interface* gl = ContextGL();
+ DCHECK(gl);
+ resource->gl_id =
+ gl->CreateAndConsumeTextureCHROMIUM(resource->mailbox.name);
+ resource->SetLocallyUsed();
+ }
+
+ if (!resource->pixels && resource->has_shared_bitmap_id &&
+ shared_bitmap_manager_) {
+ std::unique_ptr<SharedBitmap> bitmap =
+ shared_bitmap_manager_->GetSharedBitmapFromId(
+ resource->size, resource->format, resource->shared_bitmap_id);
+ if (bitmap) {
+ resource->SetSharedBitmap(bitmap.get());
+ resource->owned_shared_bitmap = std::move(bitmap);
+ }
+ }
+
+ resource->lock_for_read_count++;
+ if (resource->read_lock_fences_enabled) {
+ if (current_read_lock_fence_.get())
+ current_read_lock_fence_->Set();
+ resource->read_lock_fence = current_read_lock_fence_;
+ }
+
+ return resource;
+}
+
+void DisplayResourceProvider::UnlockForRead(ResourceId id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ auto it = resources_.find(id);
+ // TODO(ericrk): We should never fail to find id, but we appear to be
+ // doing so on Android in rare cases. Handle this gracefully until a better
+ // solution can be found. https://crbug.com/811858
+ if (it == resources_.end())
+ return;
+
+ internal::Resource* resource = &it->second;
+ DCHECK_GT(resource->lock_for_read_count, 0);
+ resource->lock_for_read_count--;
+ TryReleaseResource(it);
+}
+
+ResourceMetadata DisplayResourceProvider::LockForExternalUse(ResourceId id) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ auto it = resources_.find(id);
+ DCHECK(it != resources_.end());
+
+ internal::Resource* resource = &it->second;
+ ResourceMetadata metadata;
+ // Make sure there is no outstanding LockForExternalUse without calling
+ // UnlockForExternalUse.
+ DCHECK(!resource->locked_for_external_use);
+ // TODO(penghuang): support software resource.
+ DCHECK(resource->is_gpu_resource_type());
+
+ metadata.mailbox = resource->mailbox;
+ metadata.backend_format = GrBackendFormat::MakeGL(
+ TextureStorageFormat(resource->format), resource->target);
+ metadata.size = resource->size;
+ metadata.mip_mapped = GrMipMapped::kNo;
+ metadata.origin = kTopLeft_GrSurfaceOrigin;
+ metadata.color_type =
+ ResourceFormatToClosestSkColorType(!IsSoftware(), resource->format);
+ metadata.alpha_type = kPremul_SkAlphaType;
+ metadata.color_space = nullptr;
+ metadata.sync_token = resource->sync_token();
+
+ resource->locked_for_external_use = true;
+ return metadata;
+}
+
+void DisplayResourceProvider::UnlockForExternalUse(
+ ResourceId id,
+ const gpu::SyncToken& sync_token) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ auto it = resources_.find(id);
+ DCHECK(it != resources_.end());
+ DCHECK(sync_token.verified_flush());
+
+ internal::Resource* resource = &it->second;
+ DCHECK(resource->locked_for_external_use);
+ // TODO(penghuang): support software resource.
+ DCHECK(resource->is_gpu_resource_type());
+
+ // Update the resource sync token to |sync_token|. When the next frame is
+ // being composited, the DeclareUsedResourcesFromChild() will be called with
+ // resources belong to every child for the next frame. If the resource is not
+ // used by the next frame, the resource will be returned to a child which
+ // owns it with the |sync_token|. The child is responsible for issuing a
+ // WaitSyncToken GL command with the |sync_token| before reusing it.
+ resource->UpdateSyncToken(sync_token);
+ resource->locked_for_external_use = false;
+
+ TryReleaseResource(it);
+}
+
+void DisplayResourceProvider::TryReleaseResource(ResourceMap::iterator it) {
+ ResourceId id = it->first;
+ internal::Resource* resource = &it->second;
+ if (resource->marked_for_deletion && !resource->lock_for_read_count &&
+ !resource->locked_for_external_use) {
+ if (!resource->child_id) {
+// The resource belongs to this instance, so it can be destroyed.
+// TODO(danakj): Is this dead code?
+#if defined(OS_ANDROID)
+ DeletePromotionHint(it, NORMAL);
+#endif
+ DeleteResourceInternal(it, NORMAL);
+ } else {
+ if (batch_return_resources_) {
+ batched_returning_resources_[resource->child_id].push_back(id);
+ } else {
+ auto child_it = children_.find(resource->child_id);
+ std::vector<ResourceId> unused;
+ unused.push_back(id);
+ DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, unused);
+ }
+ }
+ }
+}
+
+GLenum DisplayResourceProvider::BindForSampling(ResourceId resource_id,
+ GLenum unit,
+ GLenum filter) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ GLES2Interface* gl = ContextGL();
+ auto it = resources_.find(resource_id);
+ // TODO(ericrk): We should never fail to find resource_id, but we appear to
+ // be doing so on Android in rare cases. Handle this gracefully until a
+ // better solution can be found. https://crbug.com/811858
+ if (it == resources_.end())
+ return GL_TEXTURE_2D;
+
+ internal::Resource* resource = &it->second;
+ DCHECK(resource->lock_for_read_count);
+
+ ScopedSetActiveTexture scoped_active_tex(gl, unit);
+ GLenum target = resource->target;
+ gl->BindTexture(target, resource->gl_id);
+ GLenum min_filter = filter;
+ if (min_filter != resource->min_filter) {
+ gl->TexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter);
+ resource->min_filter = min_filter;
+ }
+ if (filter != resource->filter) {
+ gl->TexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
+ resource->filter = filter;
+ }
+
+ return target;
+}
+
+bool DisplayResourceProvider::ReadLockFenceHasPassed(
+ const internal::Resource* resource) {
+ return !resource->read_lock_fence || resource->read_lock_fence->HasPassed();
+}
+
+#if defined(OS_ANDROID)
+void DisplayResourceProvider::DeletePromotionHint(ResourceMap::iterator it,
+ DeleteStyle style) {
+ internal::Resource* resource = &it->second;
+ // If this resource was interested in promotion hints, then remove it from
+ // the set of resources that we'll notify.
+ if (resource->wants_promotion_hint)
+ wants_promotion_hints_set_.erase(it->first);
+}
+#endif
+
+void DisplayResourceProvider::DeleteAndReturnUnusedResourcesToChild(
+ ChildMap::iterator child_it,
+ DeleteStyle style,
+ const std::vector<ResourceId>& unused) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(child_it != children_.end());
+ Child* child_info = &child_it->second;
+
+ if (unused.empty() && !child_info->marked_for_deletion)
+ return;
+
+ std::vector<ReturnedResource> to_return;
+ to_return.reserve(unused.size());
+ std::vector<ReturnedResource*> need_synchronization_resources;
+ std::vector<GLbyte*> unverified_sync_tokens;
+ std::vector<size_t> to_return_indices_unverified;
+
+ GLES2Interface* gl = ContextGL();
+
+ for (ResourceId local_id : unused) {
+ auto it = resources_.find(local_id);
+ CHECK(it != resources_.end());
+ internal::Resource& resource = it->second;
+
+ ResourceId child_id = resource.id_in_child;
+ DCHECK(child_info->child_to_parent_map.count(child_id));
+
+ bool is_lost = (resource.is_gpu_resource_type() && lost_context_provider_);
+ if (resource.lock_for_read_count > 0 || resource.locked_for_external_use) {
+ if (style != FOR_SHUTDOWN) {
+ // Defer this resource deletion.
+ resource.marked_for_deletion = true;
+ continue;
+ }
+ // We can't postpone the deletion, so we'll have to lose it.
+ is_lost = true;
+ } else if (!ReadLockFenceHasPassed(&resource)) {
+ // TODO(dcastagna): see if it's possible to use this logic for
+ // the branch above too, where the resource is locked or still exported.
+ if (style != FOR_SHUTDOWN && !child_info->marked_for_deletion) {
+ // Defer this resource deletion.
+ resource.marked_for_deletion = true;
+ continue;
+ }
+ // We can't postpone the deletion, so we'll have to lose it.
+ is_lost = true;
+ }
+
+ if (resource.is_gpu_resource_type() &&
+ resource.filter != resource.original_filter) {
+ DCHECK(resource.target);
+ DCHECK(resource.gl_id);
+ DCHECK(gl);
+ gl->BindTexture(resource.target, resource.gl_id);
+ gl->TexParameteri(resource.target, GL_TEXTURE_MIN_FILTER,
+ resource.original_filter);
+ gl->TexParameteri(resource.target, GL_TEXTURE_MAG_FILTER,
+ resource.original_filter);
+ resource.SetLocallyUsed();
+ }
+
+ ReturnedResource returned;
+ returned.id = child_id;
+ returned.sync_token = resource.sync_token();
+ returned.count = resource.imported_count;
+ returned.lost = is_lost;
+ to_return.push_back(returned);
+
+ if (resource.is_gpu_resource_type() && child_info->needs_sync_tokens) {
+ if (resource.needs_sync_token()) {
+ need_synchronization_resources.push_back(&to_return.back());
+ } else if (returned.sync_token.HasData() &&
+ !returned.sync_token.verified_flush()) {
+ // Before returning any sync tokens, they must be verified. Store an
+ // index into |to_return| instead of a pointer as vectors may realloc
+ // and move their data.
+ to_return_indices_unverified.push_back(to_return.size() - 1);
+ }
+ }
+
+ child_info->child_to_parent_map.erase(child_id);
+ resource.imported_count = 0;
+#if defined(OS_ANDROID)
+ DeletePromotionHint(it, style);
+#endif
+ DeleteResourceInternal(it, style);
+ }
+
+ for (size_t i : to_return_indices_unverified)
+ unverified_sync_tokens.push_back(to_return[i].sync_token.GetData());
+
+ gpu::SyncToken new_sync_token;
+ if (!need_synchronization_resources.empty()) {
+ DCHECK(child_info->needs_sync_tokens);
+ DCHECK(gl);
+ gl->GenUnverifiedSyncTokenCHROMIUM(new_sync_token.GetData());
+ unverified_sync_tokens.push_back(new_sync_token.GetData());
+ }
+
+ if (!unverified_sync_tokens.empty()) {
+ DCHECK(child_info->needs_sync_tokens);
+ DCHECK(gl);
+ gl->VerifySyncTokensCHROMIUM(unverified_sync_tokens.data(),
+ unverified_sync_tokens.size());
+ }
+
+ // Set sync token after verification.
+ for (ReturnedResource* returned : need_synchronization_resources)
+ returned->sync_token = new_sync_token;
+
+ if (!to_return.empty())
+ child_info->return_callback.Run(to_return);
+
+ if (child_info->marked_for_deletion &&
+ child_info->child_to_parent_map.empty()) {
+ children_.erase(child_it);
+ }
+}
+
+void DisplayResourceProvider::DestroyChildInternal(ChildMap::iterator it,
+ DeleteStyle style) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ Child& child = it->second;
+ DCHECK(style == FOR_SHUTDOWN || !child.marked_for_deletion);
+
+ std::vector<ResourceId> resources_for_child;
+
+ for (auto child_it = child.child_to_parent_map.begin();
+ child_it != child.child_to_parent_map.end(); ++child_it) {
+ ResourceId id = child_it->second;
+ resources_for_child.push_back(id);
+ }
+
+ child.marked_for_deletion = true;
+
+ DeleteAndReturnUnusedResourcesToChild(it, style, resources_for_child);
+}
+
+void DisplayResourceProvider::SetBatchReturnResources(bool batch) {
+ DCHECK_NE(batch_return_resources_, batch);
+ batch_return_resources_ = batch;
+ if (!batch) {
+ for (const auto& resources : batched_returning_resources_) {
+ auto child_it = children_.find(resources.first);
+ DCHECK(child_it != children_.end());
+ DeleteAndReturnUnusedResourcesToChild(child_it, NORMAL, resources.second);
+ }
+ batched_returning_resources_.clear();
+ }
+}
+
+DisplayResourceProvider::ScopedReadLockGL::ScopedReadLockGL(
+ DisplayResourceProvider* resource_provider,
+ ResourceId resource_id)
+ : resource_provider_(resource_provider), resource_id_(resource_id) {
+ const internal::Resource* resource =
+ resource_provider->LockForRead(resource_id);
+ // TODO(ericrk): We should never fail LockForRead, but we appear to be
+ // doing so on Android in rare cases. Handle this gracefully until a better
+ // solution can be found. https://crbug.com/811858
+ if (!resource)
+ return;
+
+ texture_id_ = resource->gl_id;
+ target_ = resource->target;
+ size_ = resource->size;
+ color_space_ = resource->color_space;
+}
+
+DisplayResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() {
+ resource_provider_->UnlockForRead(resource_id_);
+}
+
+DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
+ DisplayResourceProvider* resource_provider,
+ ResourceId resource_id,
+ GLenum filter)
+ : resource_lock_(resource_provider, resource_id),
+ unit_(GL_TEXTURE0),
+ target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}
+
+DisplayResourceProvider::ScopedSamplerGL::ScopedSamplerGL(
+ DisplayResourceProvider* resource_provider,
+ ResourceId resource_id,
+ GLenum unit,
+ GLenum filter)
+ : resource_lock_(resource_provider, resource_id),
+ unit_(unit),
+ target_(resource_provider->BindForSampling(resource_id, unit_, filter)) {}
+
+DisplayResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() = default;
+
+DisplayResourceProvider::ScopedReadLockSkImage::ScopedReadLockSkImage(
+ DisplayResourceProvider* resource_provider,
+ ResourceId resource_id)
+ : resource_provider_(resource_provider), resource_id_(resource_id) {
+ const internal::Resource* resource =
+ resource_provider->LockForRead(resource_id);
+ DCHECK(resource);
+ if (resource_provider_->resource_sk_image_.find(resource_id) !=
+ resource_provider_->resource_sk_image_.end()) {
+ // Use cached sk_image.
+ sk_image_ =
+ resource_provider_->resource_sk_image_.find(resource_id)->second;
+ } else if (resource->gl_id) {
+ GrGLTextureInfo texture_info;
+ texture_info.fID = resource->gl_id;
+ texture_info.fTarget = resource->target;
+ texture_info.fFormat = TextureStorageFormat(resource->format);
+ GrBackendTexture backend_texture(resource->size.width(),
+ resource->size.height(), GrMipMapped::kNo,
+ texture_info);
+ sk_image_ = SkImage::MakeFromTexture(
+ resource_provider->compositor_context_provider_->GrContext(),
+ backend_texture, kTopLeft_GrSurfaceOrigin,
+ ResourceFormatToClosestSkColorType(!resource_provider->IsSoftware(),
+ resource->format),
+ kPremul_SkAlphaType, nullptr);
+ } else if (resource->pixels) {
+ SkBitmap sk_bitmap;
+ resource_provider->PopulateSkBitmapWithResource(&sk_bitmap, resource);
+ sk_bitmap.setImmutable();
+ sk_image_ = SkImage::MakeFromBitmap(sk_bitmap);
+ } else {
+ // During render process shutdown, ~RenderMessageFilter which calls
+ // ~HostSharedBitmapClient (which deletes shared bitmaps from child)
+ // can race with OnBeginFrameDeadline which draws a frame.
+ // In these cases, shared bitmaps (and this read lock) won't be valid.
+ // Renderers need to silently handle locks failing until this race
+ // is fixed. DCHECK that this is the only case where there are no pixels.
+ DCHECK(!resource->shared_bitmap_id.IsZero());
+ }
+}
+
+DisplayResourceProvider::ScopedReadLockSkImage::~ScopedReadLockSkImage() {
+ resource_provider_->UnlockForRead(resource_id_);
+}
+
+DisplayResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
+ DisplayResourceProvider* resource_provider,
+ ResourceId resource_id)
+ : resource_provider_(resource_provider), resource_id_(resource_id) {
+ const internal::Resource* resource =
+ resource_provider->LockForRead(resource_id);
+ DCHECK(resource);
+ resource_provider->PopulateSkBitmapWithResource(&sk_bitmap_, resource);
+}
+
+DisplayResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() {
+ resource_provider_->UnlockForRead(resource_id_);
+}
+
+DisplayResourceProvider::LockSetForExternalUse::LockSetForExternalUse(
+ DisplayResourceProvider* resource_provider)
+ : resource_provider_(resource_provider) {}
+
+DisplayResourceProvider::LockSetForExternalUse::~LockSetForExternalUse() {
+ DCHECK(resources_.empty());
+}
+
+ResourceMetadata DisplayResourceProvider::LockSetForExternalUse::LockResource(
+ ResourceId id) {
+ DCHECK(std::find(resources_.begin(), resources_.end(), id) ==
+ resources_.end());
+ resources_.push_back(id);
+ return resource_provider_->LockForExternalUse(id);
+}
+
+void DisplayResourceProvider::LockSetForExternalUse::UnlockResources(
+ const gpu::SyncToken& sync_token) {
+ for (const auto& id : resources_)
+ resource_provider_->UnlockForExternalUse(id, sync_token);
+ resources_.clear();
+}
+
+DisplayResourceProvider::SynchronousFence::SynchronousFence(
+ gpu::gles2::GLES2Interface* gl)
+ : gl_(gl), has_synchronized_(true) {}
+
+DisplayResourceProvider::SynchronousFence::~SynchronousFence() = default;
+
+void DisplayResourceProvider::SynchronousFence::Set() {
+ has_synchronized_ = false;
+}
+
+bool DisplayResourceProvider::SynchronousFence::HasPassed() {
+ if (!has_synchronized_) {
+ has_synchronized_ = true;
+ Synchronize();
+ }
+ return true;
+}
+
+void DisplayResourceProvider::SynchronousFence::Wait() {
+ HasPassed();
+}
+
+void DisplayResourceProvider::SynchronousFence::Synchronize() {
+ TRACE_EVENT0("cc", "DisplayResourceProvider::SynchronousFence::Synchronize");
+ gl_->Finish();
+}
+
+DisplayResourceProvider::ScopedBatchReturnResources::ScopedBatchReturnResources(
+ DisplayResourceProvider* resource_provider)
+ : resource_provider_(resource_provider) {
+ resource_provider_->SetBatchReturnResources(true);
+}
+
+DisplayResourceProvider::ScopedBatchReturnResources::
+ ~ScopedBatchReturnResources() {
+ resource_provider_->SetBatchReturnResources(false);
+}
+
+DisplayResourceProvider::Child::Child() = default;
+DisplayResourceProvider::Child::Child(const Child& other) = default;
+DisplayResourceProvider::Child::~Child() = default;
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/display_resource_provider.h b/chromium/components/viz/service/display/display_resource_provider.h
new file mode 100644
index 00000000000..d81e561bee8
--- /dev/null
+++ b/chromium/components/viz/service/display/display_resource_provider.h
@@ -0,0 +1,397 @@
+// 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 COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
+
+#include <stddef.h>
+#include <map>
+#include <unordered_map>
+#include <vector>
+
+#include "base/containers/flat_map.h"
+#include "base/containers/small_map.h"
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "base/trace_event/memory_dump_provider.h"
+#include "build/build_config.h"
+#include "components/viz/common/resources/resource.h"
+#include "components/viz/common/resources/resource_fence.h"
+#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/common/resources/resource_metadata.h"
+#include "components/viz/common/resources/return_callback.h"
+#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/service/display/overlay_candidate.h"
+#include "components/viz/service/viz_service_export.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace gfx {
+class ColorSpace;
+class Size;
+} // namespace gfx
+
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+} // namespace gpu
+
+namespace viz {
+class ContextProvider;
+class SharedBitmapManager;
+
+// This class provides abstractions for receiving and using resources from other
+// modules/threads/processes. It abstracts away GL textures vs GpuMemoryBuffers
+// vs software bitmaps behind a single ResourceId so that code in common can
+// hold onto ResourceIds, as long as the code using them knows the correct type.
+// It accepts as input TransferableResources which it holds internally, tracks
+// state on, and exposes as a ResourceId.
+//
+// The resource's underlying type is accessed through locks that help to
+// scope and safeguard correct usage with DCHECKs.
+//
+// This class is not thread-safe and can only be called from the thread it was
+// created on.
+class VIZ_SERVICE_EXPORT DisplayResourceProvider
+ : public base::trace_event::MemoryDumpProvider {
+ public:
+ DisplayResourceProvider(ContextProvider* compositor_context_provider,
+ SharedBitmapManager* shared_bitmap_manager);
+ ~DisplayResourceProvider() override;
+
+ bool IsSoftware() const { return !compositor_context_provider_; }
+ void DidLoseContextProvider() { lost_context_provider_ = true; }
+ size_t num_resources() const { return resources_.size(); }
+
+ // base::trace_event::MemoryDumpProvider implementation.
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
+#if defined(OS_ANDROID)
+ // Send an overlay promotion hint to all resources that requested it via
+ // |wants_promotion_hints_set_|. |promotable_hints| contains all the
+ // resources that should be told that they're promotable. Others will be told
+ // that they're not promotable right now.
+ void SendPromotionHints(
+ const OverlayCandidateList::PromotionHintInfoMap& promotion_hints);
+
+ // Indicates if this resource is backed by an Android SurfaceTexture, and thus
+ // can't really be promoted to an overlay.
+ bool IsBackedBySurfaceTexture(ResourceId id);
+
+ // Indicates if this resource wants to receive promotion hints.
+ bool WantsPromotionHintForTesting(ResourceId id);
+
+ // Return the number of resources that request promotion hints.
+ size_t CountPromotionHintRequestsForTesting();
+#endif
+
+ ResourceType GetResourceType(ResourceId id);
+ GLenum GetResourceTextureTarget(ResourceId id);
+ // Return the format of the underlying buffer that can be used for scanout.
+ gfx::BufferFormat GetBufferFormat(ResourceId id);
+ // Indicates if this resource may be used for a hardware overlay plane.
+ bool IsOverlayCandidate(ResourceId id);
+
+ void WaitSyncToken(ResourceId id);
+
+ // Checks whether a resource is in use.
+ bool InUse(ResourceId id);
+
+ // The following lock classes are part of the DisplayResourceProvider API and
+ // are needed to read the resource contents. The user must ensure that they
+ // only use GL locks on GL resources, etc, and this is enforced by assertions.
+ class VIZ_SERVICE_EXPORT ScopedReadLockGL {
+ public:
+ ScopedReadLockGL(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id);
+ ~ScopedReadLockGL();
+
+ GLuint texture_id() const { return texture_id_; }
+ GLenum target() const { return target_; }
+ const gfx::Size& size() const { return size_; }
+ const gfx::ColorSpace& color_space() const { return color_space_; }
+
+ private:
+ DisplayResourceProvider* const resource_provider_;
+ const ResourceId resource_id_;
+
+ GLuint texture_id_ = 0;
+ GLenum target_ = GL_TEXTURE_2D;
+ gfx::Size size_;
+ gfx::ColorSpace color_space_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedReadLockGL);
+ };
+
+ class VIZ_SERVICE_EXPORT ScopedSamplerGL {
+ public:
+ ScopedSamplerGL(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id,
+ GLenum filter);
+ ScopedSamplerGL(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id,
+ GLenum unit,
+ GLenum filter);
+ ~ScopedSamplerGL();
+
+ GLuint texture_id() const { return resource_lock_.texture_id(); }
+ GLenum target() const { return target_; }
+ const gfx::ColorSpace& color_space() const {
+ return resource_lock_.color_space();
+ }
+
+ private:
+ const ScopedReadLockGL resource_lock_;
+ const GLenum unit_;
+ const GLenum target_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSamplerGL);
+ };
+
+ class VIZ_SERVICE_EXPORT ScopedReadLockSkImage {
+ public:
+ ScopedReadLockSkImage(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id);
+ ~ScopedReadLockSkImage();
+
+ const SkImage* sk_image() const { return sk_image_.get(); }
+
+ bool valid() const { return !!sk_image_; }
+
+ private:
+ DisplayResourceProvider* const resource_provider_;
+ const ResourceId resource_id_;
+ sk_sp<SkImage> sk_image_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSkImage);
+ };
+
+ class VIZ_SERVICE_EXPORT ScopedReadLockSoftware {
+ public:
+ ScopedReadLockSoftware(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id);
+ ~ScopedReadLockSoftware();
+
+ const SkBitmap* sk_bitmap() const {
+ DCHECK(valid());
+ return &sk_bitmap_;
+ }
+
+ bool valid() const { return !!sk_bitmap_.getPixels(); }
+
+ private:
+ DisplayResourceProvider* const resource_provider_;
+ const ResourceId resource_id_;
+ SkBitmap sk_bitmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedReadLockSoftware);
+ };
+
+ // Maintains set of lock for external use.
+ class VIZ_SERVICE_EXPORT LockSetForExternalUse {
+ public:
+ explicit LockSetForExternalUse(DisplayResourceProvider* resource_provider);
+ ~LockSetForExternalUse();
+
+ // Lock a resource for external use.
+ ResourceMetadata LockResource(ResourceId resource_id);
+
+ // Unlock all locked resources with a |sync_token|.
+ // See UnlockForExternalUse for the detail. All resources must be unlocked
+ // before destroying this class.
+ void UnlockResources(const gpu::SyncToken& sync_token);
+
+ private:
+ DisplayResourceProvider* const resource_provider_;
+ std::vector<ResourceId> resources_;
+
+ DISALLOW_COPY_AND_ASSIGN(LockSetForExternalUse);
+ };
+
+ // All resources that are returned to children while an instance of this
+ // class exists will be stored and returned when the instance is destroyed.
+ class VIZ_SERVICE_EXPORT ScopedBatchReturnResources {
+ public:
+ explicit ScopedBatchReturnResources(
+ DisplayResourceProvider* resource_provider);
+ ~ScopedBatchReturnResources();
+
+ private:
+ DisplayResourceProvider* const resource_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedBatchReturnResources);
+ };
+
+ class VIZ_SERVICE_EXPORT SynchronousFence : public ResourceFence {
+ public:
+ explicit SynchronousFence(gpu::gles2::GLES2Interface* gl);
+
+ // ResourceFence implementation.
+ void Set() override;
+ bool HasPassed() override;
+ void Wait() override;
+
+ // Returns true if fence has been set but not yet synchornized.
+ bool has_synchronized() const { return has_synchronized_; }
+
+ private:
+ ~SynchronousFence() override;
+
+ void Synchronize();
+
+ gpu::gles2::GLES2Interface* gl_;
+ bool has_synchronized_;
+
+ DISALLOW_COPY_AND_ASSIGN(SynchronousFence);
+ };
+
+ // Sets the current read fence. If a resource is locked for read
+ // and has read fences enabled, the resource will not allow writes
+ // until this fence has passed.
+ void SetReadLockFence(ResourceFence* fence) {
+ current_read_lock_fence_ = fence;
+ }
+
+ // Creates accounting for a child. Returns a child ID.
+ int CreateChild(const ReturnCallback& return_callback);
+
+ // Destroys accounting for the child, deleting all accounted resources.
+ void DestroyChild(int child);
+
+ // Sets whether resources need sync points set on them when returned to this
+ // child. Defaults to true.
+ void SetChildNeedsSyncTokens(int child, bool needs_sync_tokens);
+
+ // Gets the child->parent resource ID map.
+ const std::unordered_map<ResourceId, ResourceId>& GetChildToParentMap(
+ int child) const;
+
+ // Receives resources from a child, moving them from mailboxes. ResourceIds
+ // passed are in the child namespace, and will be translated to the parent
+ // namespace, added to the child->parent map.
+ // This adds the resources to the working set in the ResourceProvider without
+ // declaring which resources are in use. Use DeclareUsedResourcesFromChild
+ // after calling this method to do that. All calls to ReceiveFromChild should
+ // be followed by a DeclareUsedResourcesFromChild.
+ // NOTE: if the sync_token is set on any TransferableResource, this will
+ // wait on it.
+ void ReceiveFromChild(
+ int child,
+ const std::vector<TransferableResource>& transferable_resources);
+
+ // Once a set of resources have been received, they may or may not be used.
+ // This declares what set of resources are currently in use from the child,
+ // releasing any other resources back to the child.
+ void DeclareUsedResourcesFromChild(int child,
+ const ResourceIdSet& resources_from_child);
+
+ private:
+ struct Child {
+ Child();
+ Child(const Child& other);
+ ~Child();
+
+ std::unordered_map<ResourceId, ResourceId> child_to_parent_map;
+ ReturnCallback return_callback;
+ bool marked_for_deletion = false;
+ bool needs_sync_tokens = true;
+ };
+
+ enum DeleteStyle {
+ NORMAL,
+ FOR_SHUTDOWN,
+ };
+
+ using ChildMap = std::unordered_map<int, Child>;
+ using ResourceMap = std::unordered_map<ResourceId, internal::Resource>;
+
+ internal::Resource* InsertResource(ResourceId id,
+ internal::Resource resource);
+ internal::Resource* GetResource(ResourceId id);
+
+ // TODO(ericrk): TryGetResource is part of a temporary workaround for cases
+ // where resources which should be available are missing. This version may
+ // return nullptr if a resource is not found. https://crbug.com/811858
+ internal::Resource* TryGetResource(ResourceId id);
+
+ void PopulateSkBitmapWithResource(SkBitmap* sk_bitmap,
+ const internal::Resource* resource);
+
+ void DeleteResourceInternal(ResourceMap::iterator it, DeleteStyle style);
+
+ void WaitSyncTokenInternal(internal::Resource* resource);
+
+ // Returns null if we do not have a ContextProvider.
+ gpu::gles2::GLES2Interface* ContextGL() const;
+
+ const internal::Resource* LockForRead(ResourceId id);
+ void UnlockForRead(ResourceId id);
+
+ // Lock a resource for external use.
+ ResourceMetadata LockForExternalUse(ResourceId id);
+
+ // Unlock a resource which locked by LockForExternalUse.
+ // The |sync_token| should be waited on before reusing the resouce's backing
+ // to ensure that any external use of it is completed. This |sync_token|
+ // should have been verified.
+ void UnlockForExternalUse(ResourceId id, const gpu::SyncToken& sync_token);
+
+ void TryReleaseResource(ResourceMap::iterator it);
+ // Binds the given GL resource to a texture target for sampling using the
+ // specified filter for both minification and magnification. Returns the
+ // texture target used. The resource must be locked for reading.
+ GLenum BindForSampling(ResourceId resource_id, GLenum unit, GLenum filter);
+ bool ReadLockFenceHasPassed(const internal::Resource* resource);
+#if defined(OS_ANDROID)
+ void DeletePromotionHint(ResourceMap::iterator it, DeleteStyle style);
+#endif
+
+ void DeleteAndReturnUnusedResourcesToChild(
+ ChildMap::iterator child_it,
+ DeleteStyle style,
+ const std::vector<ResourceId>& unused);
+ void DestroyChildInternal(ChildMap::iterator it, DeleteStyle style);
+
+ void SetBatchReturnResources(bool aggregate);
+
+ THREAD_CHECKER(thread_checker_);
+ ContextProvider* const compositor_context_provider_;
+ SharedBitmapManager* const shared_bitmap_manager_;
+
+ ResourceMap resources_;
+ ChildMap children_;
+ base::flat_map<ResourceId, sk_sp<SkImage>> resource_sk_image_;
+ // Maps from a child id to the set of resources to be returned to it.
+ base::small_map<std::map<int, std::vector<ResourceId>>>
+ batched_returning_resources_;
+ scoped_refptr<ResourceFence> current_read_lock_fence_;
+ // Keep track of whether deleted resources should be batched up or returned
+ // immediately.
+ bool batch_return_resources_ = false;
+ // Set to true when the ContextProvider becomes lost, to inform that resources
+ // modified by this class are now in an indeterminate state.
+ bool lost_context_provider_ = false;
+ // The ResourceIds in DisplayResourceProvider start from 2 to avoid
+ // conflicts with id from LayerTreeResourceProvider.
+ ResourceId next_id_ = 2;
+ // Used as child id when creating a child.
+ int next_child_ = 1;
+ // A process-unique ID used for disambiguating memory dumps from different
+ // resource providers.
+ int tracing_id_;
+
+#if defined(OS_ANDROID)
+ // Set of ResourceIds that would like to be notified about promotion hints.
+ ResourceIdSet wants_promotion_hints_set_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(DisplayResourceProvider);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_DISPLAY_RESOURCE_PROVIDER_H_
diff --git a/chromium/components/viz/service/display/display_resource_provider_unittest.cc b/chromium/components/viz/service/display/display_resource_provider_unittest.cc
new file mode 100644
index 00000000000..af4d091a81a
--- /dev/null
+++ b/chromium/components/viz/service/display/display_resource_provider_unittest.cc
@@ -0,0 +1,1389 @@
+// 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 "components/viz/service/display/display_resource_provider.h"
+#include "cc/resources/layer_tree_resource_provider.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <algorithm>
+#include <map>
+#include <memory>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "build/build_config.h"
+#include "cc/test/render_pass_test_utils.h"
+#include "cc/test/resource_provider_test_utils.h"
+#include "components/viz/common/quads/shared_bitmap.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "components/viz/common/resources/returned_resource.h"
+#include "components/viz/common/resources/shared_bitmap_manager.h"
+#include "components/viz/common/resources/single_release_callback.h"
+#include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_gpu_memory_buffer_manager.h"
+#include "components/viz/test/test_shared_bitmap_manager.h"
+#include "components/viz/test/test_texture.h"
+#include "components/viz/test/test_web_graphics_context_3d.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+
+using testing::_;
+using testing::Return;
+using testing::SaveArg;
+
+namespace viz {
+namespace {
+
+class MockReleaseCallback {
+ public:
+ MOCK_METHOD2(Released, void(const gpu::SyncToken& token, bool lost));
+};
+
+MATCHER_P(MatchesSyncToken, sync_token, "") {
+ gpu::SyncToken other;
+ memcpy(&other, arg, sizeof(other));
+ return other == sync_token;
+}
+
+static void CollectResources(std::vector<ReturnedResource>* array,
+ const std::vector<ReturnedResource>& returned) {
+ array->insert(array->end(), returned.begin(), returned.end());
+}
+
+static SharedBitmapId CreateAndFillSharedBitmap(SharedBitmapManager* manager,
+ const gfx::Size& size,
+ ResourceFormat format,
+ uint32_t value) {
+ SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
+
+ std::unique_ptr<base::SharedMemory> shm =
+ bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888);
+ manager->ChildAllocatedSharedBitmap(
+ bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size,
+ RGBA_8888),
+ shared_bitmap_id);
+
+ std::fill_n(static_cast<uint32_t*>(shm->memory()), size.GetArea(), value);
+ return shared_bitmap_id;
+}
+
+// Shared data between multiple ResourceProviderContext. This contains mailbox
+// contents as well as information about sync points.
+class ContextSharedData {
+ public:
+ static std::unique_ptr<ContextSharedData> Create() {
+ return base::WrapUnique(new ContextSharedData());
+ }
+
+ uint32_t InsertFenceSync() { return next_fence_sync_++; }
+
+ void GenMailbox(GLbyte* mailbox) {
+ memset(mailbox, 0, GL_MAILBOX_SIZE_CHROMIUM);
+ memcpy(mailbox, &next_mailbox_, sizeof(next_mailbox_));
+ ++next_mailbox_;
+ }
+
+ void ProduceTexture(const GLbyte* mailbox_name,
+ const gpu::SyncToken& sync_token,
+ scoped_refptr<TestTexture> texture) {
+ uint32_t sync_point = static_cast<uint32_t>(sync_token.release_count());
+
+ unsigned mailbox = 0;
+ memcpy(&mailbox, mailbox_name, sizeof(mailbox));
+ ASSERT_TRUE(mailbox && mailbox < next_mailbox_);
+ textures_[mailbox] = texture;
+ ASSERT_LT(sync_point_for_mailbox_[mailbox], sync_point);
+ sync_point_for_mailbox_[mailbox] = sync_point;
+ }
+
+ scoped_refptr<TestTexture> ConsumeTexture(const GLbyte* mailbox_name,
+ const gpu::SyncToken& sync_token) {
+ unsigned mailbox = 0;
+ memcpy(&mailbox, mailbox_name, sizeof(mailbox));
+ DCHECK(mailbox && mailbox < next_mailbox_);
+
+ // If the latest sync point the context has waited on is before the sync
+ // point for when the mailbox was set, pretend we never saw that
+ // ProduceTexture.
+ if (sync_point_for_mailbox_[mailbox] > sync_token.release_count()) {
+ NOTREACHED();
+ return scoped_refptr<TestTexture>();
+ }
+ return textures_[mailbox];
+ }
+
+ private:
+ ContextSharedData() : next_fence_sync_(1), next_mailbox_(1) {}
+
+ uint64_t next_fence_sync_;
+ unsigned next_mailbox_;
+ using TextureMap = std::unordered_map<unsigned, scoped_refptr<TestTexture>>;
+ TextureMap textures_;
+ std::unordered_map<unsigned, uint32_t> sync_point_for_mailbox_;
+};
+
+class ResourceProviderContext : public TestWebGraphicsContext3D {
+ public:
+ static std::unique_ptr<ResourceProviderContext> Create(
+ ContextSharedData* shared_data) {
+ return base::WrapUnique(new ResourceProviderContext(shared_data));
+ }
+
+ void genSyncToken(GLbyte* sync_token) override {
+ uint64_t fence_sync = shared_data_->InsertFenceSync();
+ gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x123),
+ fence_sync);
+ sync_token_data.SetVerifyFlush();
+ // Commit the ProduceTextureDirectCHROMIUM calls at this point, so that
+ // they're associated with the sync point.
+ for (const std::unique_ptr<PendingProduceTexture>& pending_texture :
+ pending_produce_textures_) {
+ shared_data_->ProduceTexture(pending_texture->mailbox, sync_token_data,
+ pending_texture->texture);
+ }
+ pending_produce_textures_.clear();
+ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
+ }
+
+ void waitSyncToken(const GLbyte* sync_token) override {
+ gpu::SyncToken sync_token_data;
+ if (sync_token)
+ memcpy(&sync_token_data, sync_token, sizeof(sync_token_data));
+
+ if (sync_token_data.release_count() >
+ last_waited_sync_token_.release_count()) {
+ last_waited_sync_token_ = sync_token_data;
+ }
+ }
+
+ const gpu::SyncToken& last_waited_sync_token() const {
+ return last_waited_sync_token_;
+ }
+
+ void texStorage2DEXT(GLenum target,
+ GLint levels,
+ GLuint internalformat,
+ GLint width,
+ GLint height) override {
+ CheckTextureIsBound(target);
+ ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
+ ASSERT_EQ(1, levels);
+ GLenum format = GL_RGBA;
+ switch (internalformat) {
+ case GL_RGBA8_OES:
+ break;
+ case GL_BGRA8_EXT:
+ format = GL_BGRA_EXT;
+ break;
+ default:
+ NOTREACHED();
+ }
+ AllocateTexture(gfx::Size(width, height), format);
+ }
+
+ void texImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override {
+ CheckTextureIsBound(target);
+ ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
+ ASSERT_FALSE(level);
+ ASSERT_EQ(internalformat, format);
+ ASSERT_FALSE(border);
+ ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
+ AllocateTexture(gfx::Size(width, height), format);
+ if (pixels)
+ SetPixels(0, 0, width, height, pixels);
+ }
+
+ void texSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset,
+ GLint yoffset,
+ GLsizei width,
+ GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) override {
+ CheckTextureIsBound(target);
+ ASSERT_EQ(static_cast<unsigned>(GL_TEXTURE_2D), target);
+ ASSERT_FALSE(level);
+ ASSERT_EQ(static_cast<unsigned>(GL_UNSIGNED_BYTE), type);
+ {
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ ASSERT_EQ(GLDataFormat(BoundTexture(target)->format), format);
+ }
+ ASSERT_TRUE(pixels);
+ SetPixels(xoffset, yoffset, width, height, pixels);
+ }
+
+ void genMailboxCHROMIUM(GLbyte* mailbox) override {
+ return shared_data_->GenMailbox(mailbox);
+ }
+
+ void produceTextureDirectCHROMIUM(GLuint texture,
+ const GLbyte* mailbox) override {
+ // Delay moving the texture into the mailbox until the next
+ // sync token, so that it is not visible to other contexts that
+ // haven't waited on that sync point.
+ std::unique_ptr<PendingProduceTexture> pending(new PendingProduceTexture);
+ memcpy(pending->mailbox, mailbox, sizeof(pending->mailbox));
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ pending->texture = UnboundTexture(texture);
+ pending_produce_textures_.push_back(std::move(pending));
+ }
+
+ GLuint createAndConsumeTextureCHROMIUM(const GLbyte* mailbox) override {
+ GLuint texture_id = createTexture();
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture =
+ shared_data_->ConsumeTexture(mailbox, last_waited_sync_token_);
+ namespace_->textures.Replace(texture_id, texture);
+ return texture_id;
+ }
+
+ void GetPixels(const gfx::Size& size,
+ ResourceFormat format,
+ uint8_t* pixels) {
+ CheckTextureIsBound(GL_TEXTURE_2D);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
+ ASSERT_EQ(texture->size, size);
+ ASSERT_EQ(texture->format, format);
+ memcpy(pixels, texture->data.get(), TextureSizeBytes(size, format));
+ }
+
+ protected:
+ explicit ResourceProviderContext(ContextSharedData* shared_data)
+ : shared_data_(shared_data) {}
+
+ private:
+ void AllocateTexture(const gfx::Size& size, GLenum format) {
+ CheckTextureIsBound(GL_TEXTURE_2D);
+ ResourceFormat texture_format = RGBA_8888;
+ switch (format) {
+ case GL_RGBA:
+ texture_format = RGBA_8888;
+ break;
+ case GL_BGRA_EXT:
+ texture_format = BGRA_8888;
+ break;
+ }
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ BoundTexture(GL_TEXTURE_2D)->Reallocate(size, texture_format);
+ }
+
+ void SetPixels(int xoffset,
+ int yoffset,
+ int width,
+ int height,
+ const void* pixels) {
+ CheckTextureIsBound(GL_TEXTURE_2D);
+ base::AutoLock lock_for_texture_access(namespace_->lock);
+ scoped_refptr<TestTexture> texture = BoundTexture(GL_TEXTURE_2D);
+ ASSERT_TRUE(texture->data.get());
+ ASSERT_TRUE(xoffset >= 0 && xoffset + width <= texture->size.width());
+ ASSERT_TRUE(yoffset >= 0 && yoffset + height <= texture->size.height());
+ ASSERT_TRUE(pixels);
+ size_t in_pitch = TextureSizeBytes(gfx::Size(width, 1), texture->format);
+ size_t out_pitch =
+ TextureSizeBytes(gfx::Size(texture->size.width(), 1), texture->format);
+ uint8_t* dest = texture->data.get() + yoffset * out_pitch +
+ TextureSizeBytes(gfx::Size(xoffset, 1), texture->format);
+ const uint8_t* src = static_cast<const uint8_t*>(pixels);
+ for (int i = 0; i < height; ++i) {
+ memcpy(dest, src, in_pitch);
+ dest += out_pitch;
+ src += in_pitch;
+ }
+ }
+
+ struct PendingProduceTexture {
+ GLbyte mailbox[GL_MAILBOX_SIZE_CHROMIUM];
+ scoped_refptr<TestTexture> texture;
+ };
+ ContextSharedData* shared_data_;
+ gpu::SyncToken last_waited_sync_token_;
+ std::vector<std::unique_ptr<PendingProduceTexture>> pending_produce_textures_;
+};
+
+class DisplayResourceProviderTest : public testing::TestWithParam<bool> {
+ public:
+ explicit DisplayResourceProviderTest(bool child_needs_sync_token)
+ : use_gpu_(GetParam()),
+ child_needs_sync_token_(child_needs_sync_token),
+ shared_data_(ContextSharedData::Create()) {
+ if (use_gpu_) {
+ auto context3d(ResourceProviderContext::Create(shared_data_.get()));
+ context3d_ = context3d.get();
+ context_provider_ = TestContextProvider::Create(std::move(context3d));
+ context_provider_->UnboundTestContext3d()
+ ->set_support_texture_format_bgra8888(true);
+ context_provider_->BindToCurrentThread();
+
+ auto child_context_owned =
+ ResourceProviderContext::Create(shared_data_.get());
+ child_context_ = child_context_owned.get();
+ child_context_provider_ =
+ TestContextProvider::Create(std::move(child_context_owned));
+ child_context_provider_->UnboundTestContext3d()
+ ->set_support_texture_format_bgra8888(true);
+ child_context_provider_->BindToCurrentThread();
+ gpu_memory_buffer_manager_ =
+ std::make_unique<TestGpuMemoryBufferManager>();
+ } else {
+ shared_bitmap_manager_ = std::make_unique<TestSharedBitmapManager>();
+ }
+
+ resource_provider_ = std::make_unique<DisplayResourceProvider>(
+ context_provider_.get(), shared_bitmap_manager_.get());
+
+ MakeChildResourceProvider();
+ }
+
+ DisplayResourceProviderTest() : DisplayResourceProviderTest(true) {}
+
+ bool use_gpu() const { return use_gpu_; }
+
+ void MakeChildResourceProvider() {
+ child_resource_provider_ = std::make_unique<cc::LayerTreeResourceProvider>(
+ child_context_provider_.get(), child_needs_sync_token_);
+ }
+
+ static ReturnCallback GetReturnCallback(
+ std::vector<ReturnedResource>* array) {
+ return base::BindRepeating(&CollectResources, array);
+ }
+
+ static void SetResourceFilter(DisplayResourceProvider* resource_provider,
+ ResourceId id,
+ GLenum filter) {
+ DisplayResourceProvider::ScopedSamplerGL sampler(resource_provider, id,
+ GL_TEXTURE_2D, filter);
+ }
+
+ ResourceProviderContext* context() { return context3d_; }
+
+ TransferableResource CreateResource(ResourceFormat format) {
+ if (use_gpu()) {
+ unsigned texture = child_context_->createTexture();
+ gpu::Mailbox gpu_mailbox;
+ child_context_->genMailboxCHROMIUM(gpu_mailbox.name);
+ child_context_->produceTextureDirectCHROMIUM(texture, gpu_mailbox.name);
+ gpu::SyncToken sync_token;
+ child_context_->genSyncToken(sync_token.GetData());
+ EXPECT_TRUE(sync_token.HasData());
+
+ TransferableResource gl_resource = TransferableResource::MakeGL(
+ gpu_mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token);
+ gl_resource.format = format;
+ return gl_resource;
+ } else {
+ gfx::Size size(64, 64);
+ SharedBitmapId shared_bitmap_id = CreateAndFillSharedBitmap(
+ shared_bitmap_manager_.get(), size, format, 0);
+
+ return TransferableResource::MakeSoftware(shared_bitmap_id, size, format);
+ }
+ }
+
+ ResourceId MakeGpuResourceAndSendToDisplay(
+ char c,
+ GLuint filter,
+ GLuint target,
+ const gpu::SyncToken& sync_token,
+ DisplayResourceProvider* resource_provider) {
+ ReturnCallback return_callback = base::DoNothing();
+
+ int child = resource_provider->CreateChild(return_callback);
+
+ gpu::Mailbox gpu_mailbox;
+ gpu_mailbox.name[0] = c;
+ gpu_mailbox.name[1] = 0;
+ auto resource = TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR, target,
+ sync_token);
+ resource.id = 11;
+ resource_provider->ReceiveFromChild(child, {resource});
+ auto& map = resource_provider->GetChildToParentMap(child);
+ return map.find(resource.id)->second;
+ }
+
+ protected:
+ const bool use_gpu_;
+ const bool child_needs_sync_token_;
+ const std::unique_ptr<ContextSharedData> shared_data_;
+ ResourceProviderContext* context3d_ = nullptr;
+ ResourceProviderContext* child_context_ = nullptr;
+ scoped_refptr<TestContextProvider> context_provider_;
+ scoped_refptr<TestContextProvider> child_context_provider_;
+ std::unique_ptr<TestGpuMemoryBufferManager> gpu_memory_buffer_manager_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
+ std::unique_ptr<TestSharedBitmapManager> shared_bitmap_manager_;
+};
+
+INSTANTIATE_TEST_CASE_P(DisplayResourceProviderTests,
+ DisplayResourceProviderTest,
+ ::testing::Values(false, true));
+
+TEST_P(DisplayResourceProviderTest, LockForExternalUse) {
+ // TODO(penghuang): consider supporting SW mode.
+ if (!use_gpu())
+ return;
+
+ gpu::SyncToken sync_token1(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x123),
+ 0x42);
+ auto mailbox = gpu::Mailbox::Generate();
+ TransferableResource gl_resource = TransferableResource::MakeGL(
+ mailbox, GL_LINEAR, GL_TEXTURE_2D, sync_token1);
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ gl_resource, SingleReleaseCallback::Create(base::DoNothing()));
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer some resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent({id1}, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(1u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+
+ unsigned parent_id = resource_map[list.front().id];
+
+ DisplayResourceProvider::LockSetForExternalUse lock_set(
+ resource_provider_.get());
+
+ ResourceMetadata metadata = lock_set.LockResource(parent_id);
+ ASSERT_EQ(metadata.mailbox, mailbox);
+ ASSERT_TRUE(metadata.sync_token.HasData());
+
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ // The resource should not be returned due to the external use lock.
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ gpu::SyncToken sync_token2(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x234),
+ 0x456);
+ sync_token2.SetVerifyFlush();
+ lock_set.UnlockResources(sync_token2);
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ // The resource should be returned after the lock is released.
+ EXPECT_EQ(1u, returned_to_child.size());
+ EXPECT_EQ(sync_token2, returned_to_child[0].sync_token);
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ child_resource_provider_->RemoveImportedResource(id1);
+}
+
+TEST_P(DisplayResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
+ if (!use_gpu())
+ return;
+
+ MockReleaseCallback release;
+ TransferableResource tran = CreateResource(RGBA_8888);
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ tran, SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ {
+ // Transfer some resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent(
+ {id1}, &list, child_context_provider_.get());
+ ASSERT_EQ(1u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceId mapped_resource_id = resource_map[list[0].id];
+ resource_provider_->WaitSyncToken(mapped_resource_id);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ mapped_resource_id);
+
+ resource_provider_->DeclareUsedResourcesFromChild(child_id,
+ ResourceIdSet());
+ EXPECT_EQ(0u, returned_to_child.size());
+ }
+
+ EXPECT_EQ(1u, returned_to_child.size());
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+ // No need to wait for the sync token here -- it will be returned to the
+ // client on delete.
+ {
+ EXPECT_CALL(release, Released(_, _));
+ child_resource_provider_->RemoveImportedResource(id1);
+ }
+
+ resource_provider_->DestroyChild(child_id);
+}
+
+class TestFence : public ResourceFence {
+ public:
+ TestFence() = default;
+
+ // ResourceFence implementation.
+ void Set() override {}
+ bool HasPassed() override { return passed; }
+ void Wait() override {}
+
+ bool passed = false;
+
+ private:
+ ~TestFence() override = default;
+};
+
+TEST_P(DisplayResourceProviderTest, ReadLockFenceStopsReturnToChildOrDelete) {
+ if (!use_gpu())
+ return;
+
+ MockReleaseCallback release;
+ TransferableResource tran1 = CreateResource(RGBA_8888);
+ tran1.read_lock_fences_enabled = true;
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ tran1, SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer some resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent({id1}, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(1u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(list[0].read_lock_fences_enabled);
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+
+ scoped_refptr<TestFence> fence(new TestFence);
+ resource_provider_->SetReadLockFence(fence.get());
+ {
+ unsigned parent_id = resource_map[list.front().id];
+ resource_provider_->WaitSyncToken(parent_id);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ parent_id);
+ }
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(0u, returned_to_child.size());
+ fence->passed = true;
+
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(1u, returned_to_child.size());
+
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ EXPECT_CALL(release, Released(_, _));
+ child_resource_provider_->RemoveImportedResource(id1);
+}
+
+TEST_P(DisplayResourceProviderTest, ReadLockFenceDestroyChild) {
+ if (!use_gpu())
+ return;
+
+ MockReleaseCallback release;
+
+ TransferableResource tran1 = CreateResource(RGBA_8888);
+ tran1.read_lock_fences_enabled = true;
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ tran1, SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+
+ TransferableResource tran2 = CreateResource(RGBA_8888);
+ tran2.read_lock_fences_enabled = false;
+ ResourceId id2 = child_resource_provider_->ImportResource(
+ tran2, SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent({id1, id2}, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(2u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+
+ scoped_refptr<TestFence> fence(new TestFence);
+ resource_provider_->SetReadLockFence(fence.get());
+ {
+ for (size_t i = 0; i < list.size(); i++) {
+ unsigned parent_id = resource_map[list[i].id];
+ resource_provider_->WaitSyncToken(parent_id);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ parent_id);
+ }
+ }
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ EXPECT_EQ(2u, resource_provider_->num_resources());
+
+ resource_provider_->DestroyChild(child_id);
+
+ EXPECT_EQ(0u, resource_provider_->num_resources());
+ EXPECT_EQ(2u, returned_to_child.size());
+
+ // id1 should be lost and id2 should not.
+ EXPECT_EQ(returned_to_child[0].lost, returned_to_child[0].id == id1);
+ EXPECT_EQ(returned_to_child[1].lost, returned_to_child[1].id == id1);
+
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ EXPECT_CALL(release, Released(_, _)).Times(2);
+ child_resource_provider_->RemoveImportedResource(id1);
+ child_resource_provider_->RemoveImportedResource(id2);
+}
+
+TEST_P(DisplayResourceProviderTest, ReadLockFenceContextLost) {
+ if (!use_gpu())
+ return;
+
+ TransferableResource tran1 = CreateResource(RGBA_8888);
+ tran1.read_lock_fences_enabled = true;
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ tran1, SingleReleaseCallback::Create(base::DoNothing()));
+
+ TransferableResource tran2 = CreateResource(RGBA_8888);
+ tran2.read_lock_fences_enabled = false;
+ ResourceId id2 = child_resource_provider_->ImportResource(
+ tran2, SingleReleaseCallback::Create(base::DoNothing()));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent({id1, id2}, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(2u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id2));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+
+ scoped_refptr<TestFence> fence(new TestFence);
+ resource_provider_->SetReadLockFence(fence.get());
+ {
+ for (size_t i = 0; i < list.size(); i++) {
+ unsigned parent_id = resource_map[list[i].id];
+ resource_provider_->WaitSyncToken(parent_id);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ parent_id);
+ }
+ }
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ EXPECT_EQ(2u, resource_provider_->num_resources());
+ resource_provider_->DidLoseContextProvider();
+ resource_provider_ = nullptr;
+
+ EXPECT_EQ(2u, returned_to_child.size());
+
+ EXPECT_TRUE(returned_to_child[0].lost);
+ EXPECT_TRUE(returned_to_child[1].lost);
+}
+
+TEST_P(DisplayResourceProviderTest, ReturnResourcesWithoutSyncToken) {
+ if (!use_gpu())
+ return;
+
+ bool need_sync_tokens = false;
+ auto no_token_resource_provider =
+ std::make_unique<cc::LayerTreeResourceProvider>(
+ child_context_provider_.get(), need_sync_tokens);
+
+ GLuint external_texture_id = child_context_->createExternalTexture();
+
+ // A sync point is specified directly and should be used.
+ gpu::Mailbox external_mailbox;
+ child_context_->genMailboxCHROMIUM(external_mailbox.name);
+ child_context_->produceTextureDirectCHROMIUM(external_texture_id,
+ external_mailbox.name);
+ gpu::SyncToken external_sync_token;
+ child_context_->genSyncToken(external_sync_token.GetData());
+ EXPECT_TRUE(external_sync_token.HasData());
+ ResourceId id = no_token_resource_provider->ImportResource(
+ TransferableResource::MakeGL(external_mailbox, GL_LINEAR,
+ GL_TEXTURE_EXTERNAL_OES,
+ external_sync_token),
+ SingleReleaseCallback::Create(base::DoNothing()));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+ resource_provider_->SetChildNeedsSyncTokens(child_id, false);
+ {
+ // Transfer some resources to the parent.
+ std::vector<TransferableResource> list;
+ no_token_resource_provider->PrepareSendToParent(
+ {id}, &list, child_context_provider_.get());
+ ASSERT_EQ(1u, list.size());
+ // A given sync point should be passed through.
+ EXPECT_EQ(external_sync_token, list[0].mailbox_holder.sync_token);
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ ResourceIdSet resource_ids_to_receive;
+ resource_ids_to_receive.insert(id);
+ resource_provider_->DeclareUsedResourcesFromChild(child_id,
+ resource_ids_to_receive);
+ }
+
+ {
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ // Transfer resources back from the parent to the child. Set no resources as
+ // being in use.
+ ResourceIdSet no_resources;
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, no_resources);
+
+ ASSERT_EQ(1u, returned_to_child.size());
+ std::map<ResourceId, gpu::SyncToken> returned_sync_tokens;
+ for (const auto& returned : returned_to_child)
+ returned_sync_tokens[returned.id] = returned.sync_token;
+
+ // Original sync point given should be returned.
+ ASSERT_TRUE(returned_sync_tokens.find(id) != returned_sync_tokens.end());
+ EXPECT_EQ(external_sync_token, returned_sync_tokens[id]);
+ EXPECT_FALSE(returned_to_child[0].lost);
+ no_token_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+ returned_to_child.clear();
+ }
+
+ resource_provider_->DestroyChild(child_id);
+}
+
+// Test that ScopedBatchReturnResources batching works.
+TEST_P(DisplayResourceProviderTest, ScopedBatchReturnResourcesPreventsReturn) {
+ if (!use_gpu())
+ return;
+
+ MockReleaseCallback release;
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer some resources to the parent.
+ std::vector<ResourceId> resource_ids_to_transfer;
+ ResourceId ids[2];
+ for (size_t i = 0; i < base::size(ids); i++) {
+ TransferableResource tran = CreateResource(RGBA_8888);
+ ids[i] = child_resource_provider_->ImportResource(
+ tran, SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+ resource_ids_to_transfer.push_back(ids[i]);
+ }
+
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(2u, list.size());
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(ids[0]));
+ EXPECT_TRUE(child_resource_provider_->InUseByConsumer(ids[1]));
+
+ resource_provider_->ReceiveFromChild(child_id, list);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+
+ std::vector<std::unique_ptr<DisplayResourceProvider::ScopedReadLockGL>>
+ read_locks;
+ for (auto& resource_id : list) {
+ unsigned int mapped_resource_id = resource_map[resource_id.id];
+ resource_provider_->WaitSyncToken(mapped_resource_id);
+ read_locks.push_back(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
+ resource_provider_.get(), mapped_resource_id));
+ }
+
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ std::unique_ptr<DisplayResourceProvider::ScopedBatchReturnResources>
+ returner =
+ std::make_unique<DisplayResourceProvider::ScopedBatchReturnResources>(
+ resource_provider_.get());
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ read_locks.clear();
+ EXPECT_EQ(0u, returned_to_child.size());
+
+ returner.reset();
+ EXPECT_EQ(2u, returned_to_child.size());
+ // All resources in a batch should share a sync token.
+ EXPECT_EQ(returned_to_child[0].sync_token, returned_to_child[1].sync_token);
+
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+ EXPECT_CALL(release, Released(_, _)).Times(2);
+ child_resource_provider_->RemoveImportedResource(ids[0]);
+ child_resource_provider_->RemoveImportedResource(ids[1]);
+}
+
+TEST_P(DisplayResourceProviderTest, LostMailboxInParent) {
+ gpu::Mailbox gpu_mailbox;
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34);
+ auto tran = TransferableResource::MakeGL(gpu_mailbox, GL_LINEAR,
+ GL_TEXTURE_2D, sync_token);
+ tran.id = 11;
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id = resource_provider_->CreateChild(
+ base::BindRepeating(&CollectResources, &returned_to_child));
+
+ // Receive a resource then lose the gpu context.
+ resource_provider_->ReceiveFromChild(child_id, {tran});
+ resource_provider_->DidLoseContextProvider();
+
+ // Transfer resources back from the parent to the child.
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, {});
+ ASSERT_EQ(1u, returned_to_child.size());
+
+ // Losing an output surface only loses hardware resources.
+ EXPECT_EQ(returned_to_child[0].lost, use_gpu());
+}
+
+TEST_P(DisplayResourceProviderTest, ReadSoftwareResources) {
+ if (use_gpu())
+ return;
+
+ gfx::Size size(64, 64);
+ ResourceFormat format = RGBA_8888;
+ const uint32_t kBadBeef = 0xbadbeef;
+ SharedBitmapId shared_bitmap_id = CreateAndFillSharedBitmap(
+ shared_bitmap_manager_.get(), size, format, kBadBeef);
+
+ auto resource =
+ TransferableResource::MakeSoftware(shared_bitmap_id, size, format);
+
+ MockReleaseCallback release;
+ ResourceId resource_id = child_resource_provider_->ImportResource(
+ resource,
+ SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+ EXPECT_NE(0u, resource_id);
+
+ // Transfer resources to the parent.
+ std::vector<TransferableResource> send_to_parent;
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id = resource_provider_->CreateChild(
+ base::BindRepeating(&CollectResources, &returned_to_child));
+ child_resource_provider_->PrepareSendToParent({resource_id}, &send_to_parent,
+ child_context_provider_.get());
+ resource_provider_->ReceiveFromChild(child_id, send_to_parent);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceId mapped_resource_id = resource_map[resource_id];
+
+ {
+ DisplayResourceProvider::ScopedReadLockSoftware lock(
+ resource_provider_.get(), mapped_resource_id);
+ const SkBitmap* sk_bitmap = lock.sk_bitmap();
+ EXPECT_EQ(sk_bitmap->width(), size.width());
+ EXPECT_EQ(sk_bitmap->height(), size.height());
+ EXPECT_EQ(*sk_bitmap->getAddr32(16, 16), kBadBeef);
+ }
+
+ EXPECT_EQ(0u, returned_to_child.size());
+ // Transfer resources back from the parent to the child. Set no resources as
+ // being in use.
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(1u, returned_to_child.size());
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+ EXPECT_CALL(release, Released(_, false));
+ child_resource_provider_->RemoveImportedResource(resource_id);
+}
+
+class TextureStateTrackingContext : public TestWebGraphicsContext3D {
+ public:
+ MOCK_METHOD2(bindTexture, void(GLenum target, GLuint texture));
+ MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
+ MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
+ MOCK_METHOD2(produceTextureDirectCHROMIUM,
+ void(GLuint texture, const GLbyte* mailbox));
+ MOCK_METHOD1(createAndConsumeTextureCHROMIUM,
+ unsigned(const GLbyte* mailbox));
+
+ // Force all textures to be consecutive numbers starting at "1",
+ // so we easily can test for them.
+ GLuint NextTextureId() override {
+ base::AutoLock lock(namespace_->lock);
+ return namespace_->next_texture_id++;
+ }
+
+ void RetireTextureId(GLuint) override {}
+
+ void genSyncToken(GLbyte* sync_token) override {
+ gpu::SyncToken sync_token_data(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x123),
+ next_fence_sync_++);
+ sync_token_data.SetVerifyFlush();
+ memcpy(sync_token, &sync_token_data, sizeof(sync_token_data));
+ }
+
+ GLuint64 GetNextFenceSync() const { return next_fence_sync_; }
+
+ GLuint64 next_fence_sync_ = 1;
+};
+
+class ResourceProviderTestImportedResourceGLFilters {
+ public:
+ static void RunTest(TestSharedBitmapManager* shared_bitmap_manager,
+ bool mailbox_nearest_neighbor,
+ GLenum sampler_filter) {
+ auto context_owned(std::make_unique<TextureStateTrackingContext>());
+ TextureStateTrackingContext* context = context_owned.get();
+ auto context_provider =
+ TestContextProvider::Create(std::move(context_owned));
+ context_provider->BindToCurrentThread();
+
+ auto resource_provider = std::make_unique<DisplayResourceProvider>(
+ context_provider.get(), shared_bitmap_manager);
+
+ auto child_context_owned = std::make_unique<TextureStateTrackingContext>();
+ TextureStateTrackingContext* child_context = child_context_owned.get();
+ auto child_context_provider =
+ TestContextProvider::Create(std::move(child_context_owned));
+ child_context_provider->BindToCurrentThread();
+
+ auto child_resource_provider =
+ std::make_unique<cc::LayerTreeResourceProvider>(
+ child_context_provider.get(),
+ /*delegated_sync_points_required=*/true);
+
+ unsigned texture_id = 1;
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x12),
+ 0x34);
+ const GLuint64 current_fence_sync = child_context->GetNextFenceSync();
+
+ EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0);
+ EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0);
+
+ gpu::Mailbox gpu_mailbox;
+ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
+ GLuint filter = mailbox_nearest_neighbor ? GL_NEAREST : GL_LINEAR;
+ auto resource = TransferableResource::MakeGL(gpu_mailbox, filter,
+ GL_TEXTURE_2D, sync_token);
+
+ MockReleaseCallback release;
+ ResourceId resource_id = child_resource_provider->ImportResource(
+ resource,
+ SingleReleaseCallback::Create(base::BindOnce(
+ &MockReleaseCallback::Released, base::Unretained(&release))));
+ EXPECT_NE(0u, resource_id);
+ EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync());
+
+ testing::Mock::VerifyAndClearExpectations(child_context);
+
+ // Transfer resources to the parent.
+ std::vector<TransferableResource> send_to_parent;
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id = resource_provider->CreateChild(
+ base::BindRepeating(&CollectResources, &returned_to_child));
+ child_resource_provider->PrepareSendToParent({resource_id}, &send_to_parent,
+ child_context_provider.get());
+ resource_provider->ReceiveFromChild(child_id, send_to_parent);
+
+ // In DisplayResourceProvider's namespace, use the mapped resource id.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider->GetChildToParentMap(child_id);
+ ResourceId mapped_resource_id = resource_map[resource_id];
+ {
+ // The verified flush flag will be set by
+ // cc::LayerTreeResourceProvider::PrepareSendToParent. Before checking if
+ // the gpu::SyncToken matches, set this flag first.
+ sync_token.SetVerifyFlush();
+
+ // Mailbox sync point WaitSyncToken before using the texture.
+ EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token)));
+ resource_provider->WaitSyncToken(mapped_resource_id);
+ testing::Mock::VerifyAndClearExpectations(context);
+
+ EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_))
+ .WillOnce(Return(texture_id));
+ EXPECT_CALL(*context, bindTexture(GL_TEXTURE_2D, texture_id));
+
+ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+
+ // The sampler will reset these if |mailbox_nearest_neighbor| does not
+ // match |sampler_filter|.
+ if (mailbox_nearest_neighbor != (sampler_filter == GL_NEAREST)) {
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ sampler_filter));
+ EXPECT_CALL(*context,
+ texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ sampler_filter));
+ }
+
+ DisplayResourceProvider::ScopedSamplerGL lock(
+ resource_provider.get(), mapped_resource_id, sampler_filter);
+ testing::Mock::VerifyAndClearExpectations(context);
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
+
+ // When done with it, a sync point should be inserted, but no produce is
+ // necessary.
+ EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+
+ EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0);
+ EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0);
+ }
+
+ EXPECT_EQ(0u, returned_to_child.size());
+ // Transfer resources back from the parent to the child. Set no resources as
+ // being in use.
+ resource_provider->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(1u, returned_to_child.size());
+ child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+
+ gpu::SyncToken released_sync_token;
+ {
+ EXPECT_CALL(release, Released(_, false))
+ .WillOnce(SaveArg<0>(&released_sync_token));
+ child_resource_provider->RemoveImportedResource(resource_id);
+ }
+ EXPECT_TRUE(released_sync_token.HasData());
+ }
+};
+
+TEST_P(DisplayResourceProviderTest, ReceiveGLTexture2D_LinearToLinear) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ ResourceProviderTestImportedResourceGLFilters::RunTest(
+ shared_bitmap_manager_.get(), false, GL_LINEAR);
+}
+
+TEST_P(DisplayResourceProviderTest, ReceiveGLTexture2D_NearestToNearest) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ ResourceProviderTestImportedResourceGLFilters::RunTest(
+ shared_bitmap_manager_.get(), true, GL_NEAREST);
+}
+
+TEST_P(DisplayResourceProviderTest, ReceiveGLTexture2D_NearestToLinear) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ ResourceProviderTestImportedResourceGLFilters::RunTest(
+ shared_bitmap_manager_.get(), true, GL_LINEAR);
+}
+
+TEST_P(DisplayResourceProviderTest, ReceiveGLTexture2D_LinearToNearest) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ ResourceProviderTestImportedResourceGLFilters::RunTest(
+ shared_bitmap_manager_.get(), false, GL_NEAREST);
+}
+
+TEST_P(DisplayResourceProviderTest, ReceiveGLTextureExternalOES) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ auto context_owned(std::make_unique<TextureStateTrackingContext>());
+ TextureStateTrackingContext* context = context_owned.get();
+ auto context_provider = TestContextProvider::Create(std::move(context_owned));
+ context_provider->BindToCurrentThread();
+
+ auto resource_provider = std::make_unique<DisplayResourceProvider>(
+ context_provider.get(), shared_bitmap_manager_.get());
+
+ auto child_context_owned = std::make_unique<TextureStateTrackingContext>();
+ TextureStateTrackingContext* child_context = child_context_owned.get();
+ auto child_context_provider =
+ TestContextProvider::Create(std::move(child_context_owned));
+ child_context_provider->BindToCurrentThread();
+
+ auto child_resource_provider =
+ std::make_unique<cc::LayerTreeResourceProvider>(
+ child_context_provider.get(),
+ /*delegated_sync_points_required=*/true);
+
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34);
+ const GLuint64 current_fence_sync = child_context->GetNextFenceSync();
+
+ EXPECT_CALL(*child_context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*child_context, waitSyncToken(_)).Times(0);
+ EXPECT_CALL(*child_context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(*child_context, createAndConsumeTextureCHROMIUM(_)).Times(0);
+
+ gpu::Mailbox gpu_mailbox;
+ memcpy(gpu_mailbox.name, "Hello world", strlen("Hello world") + 1);
+ std::unique_ptr<SingleReleaseCallback> callback =
+ SingleReleaseCallback::Create(base::DoNothing());
+
+ auto resource = TransferableResource::MakeGL(
+ gpu_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, sync_token);
+
+ ResourceId resource_id =
+ child_resource_provider->ImportResource(resource, std::move(callback));
+ EXPECT_NE(0u, resource_id);
+ EXPECT_EQ(current_fence_sync, child_context->GetNextFenceSync());
+
+ testing::Mock::VerifyAndClearExpectations(child_context);
+
+ // Transfer resources to the parent.
+ std::vector<TransferableResource> send_to_parent;
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id = resource_provider->CreateChild(
+ base::BindRepeating(&CollectResources, &returned_to_child));
+ child_resource_provider->PrepareSendToParent({resource_id}, &send_to_parent,
+ child_context_provider_.get());
+ resource_provider->ReceiveFromChild(child_id, send_to_parent);
+
+ // Before create DrawQuad in DisplayResourceProvider's namespace, get the
+ // mapped resource id first.
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider->GetChildToParentMap(child_id);
+ ResourceId mapped_resource_id = resource_map[resource_id];
+ {
+ // The verified flush flag will be set by
+ // cc::LayerTreeResourceProvider::PrepareSendToParent. Before checking if
+ // the gpu::SyncToken matches, set this flag first.
+ sync_token.SetVerifyFlush();
+
+ // Mailbox sync point WaitSyncToken before using the texture.
+ EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token)));
+ resource_provider->WaitSyncToken(mapped_resource_id);
+ testing::Mock::VerifyAndClearExpectations(context);
+
+ unsigned texture_id = 1;
+
+ EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_))
+ .WillOnce(Return(texture_id));
+
+ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider.get(),
+ mapped_resource_id);
+ testing::Mock::VerifyAndClearExpectations(context);
+
+ // When done with it, a sync point should be inserted, but no produce is
+ // necessary.
+ EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+
+ EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
+ EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0);
+ testing::Mock::VerifyAndClearExpectations(context);
+ }
+ EXPECT_EQ(0u, returned_to_child.size());
+ // Transfer resources back from the parent to the child. Set no resources as
+ // being in use.
+ resource_provider->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(1u, returned_to_child.size());
+ child_resource_provider->ReceiveReturnsFromParent(returned_to_child);
+
+ child_resource_provider->RemoveImportedResource(resource_id);
+}
+
+TEST_P(DisplayResourceProviderTest, WaitSyncTokenIfNeeded) {
+ // Mailboxing is only supported for GL textures.
+ if (!use_gpu())
+ return;
+
+ auto context_owned = std::make_unique<TextureStateTrackingContext>();
+ TextureStateTrackingContext* context = context_owned.get();
+ auto context_provider = TestContextProvider::Create(std::move(context_owned));
+ context_provider->BindToCurrentThread();
+
+ auto resource_provider = std::make_unique<DisplayResourceProvider>(
+ context_provider.get(), shared_bitmap_manager_.get());
+
+ const GLuint64 current_fence_sync = context->GetNextFenceSync();
+
+ EXPECT_CALL(*context, bindTexture(_, _)).Times(0);
+ EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
+ EXPECT_CALL(*context, produceTextureDirectCHROMIUM(_, _)).Times(0);
+ EXPECT_CALL(*context, createAndConsumeTextureCHROMIUM(_)).Times(0);
+
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
+ gpu::CommandBufferId::FromUnsafeValue(0x12), 0x34);
+ ResourceId id_with_sync = MakeGpuResourceAndSendToDisplay(
+ 'a', GL_LINEAR, GL_TEXTURE_2D, sync_token, resource_provider.get());
+ ResourceId id_without_sync = MakeGpuResourceAndSendToDisplay(
+ 'a', GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(), resource_provider.get());
+
+ EXPECT_EQ(current_fence_sync, context->GetNextFenceSync());
+
+ // First call to WaitSyncToken should call WaitSyncToken, but only if a
+ // SyncToken was present.
+ {
+ EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))).Times(1);
+ resource_provider->WaitSyncToken(id_with_sync);
+ EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
+ resource_provider->WaitSyncToken(id_without_sync);
+ }
+
+ {
+ // Subsequent calls to WaitSyncToken shouldn't call WaitSyncToken.
+ EXPECT_CALL(*context, waitSyncToken(_)).Times(0);
+ resource_provider->WaitSyncToken(id_with_sync);
+ resource_provider->WaitSyncToken(id_without_sync);
+ }
+}
+
+#if defined(OS_ANDROID)
+TEST_P(DisplayResourceProviderTest, OverlayPromotionHint) {
+ if (!use_gpu())
+ return;
+
+ GLuint external_texture_id = child_context_->createExternalTexture();
+
+ gpu::Mailbox external_mailbox;
+ child_context_->genMailboxCHROMIUM(external_mailbox.name);
+ child_context_->produceTextureDirectCHROMIUM(external_texture_id,
+ external_mailbox.name);
+ gpu::SyncToken external_sync_token;
+ child_context_->genSyncToken(external_sync_token.GetData());
+ EXPECT_TRUE(external_sync_token.HasData());
+
+ TransferableResource id1_transfer = TransferableResource::MakeGLOverlay(
+ external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
+ gfx::Size(1, 1), true);
+ id1_transfer.wants_promotion_hint = true;
+ id1_transfer.is_backed_by_surface_texture = true;
+ ResourceId id1 = child_resource_provider_->ImportResource(
+ id1_transfer, SingleReleaseCallback::Create(base::DoNothing()));
+
+ TransferableResource id2_transfer = TransferableResource::MakeGLOverlay(
+ external_mailbox, GL_LINEAR, GL_TEXTURE_EXTERNAL_OES, external_sync_token,
+ gfx::Size(1, 1), true);
+ id2_transfer.wants_promotion_hint = false;
+ id2_transfer.is_backed_by_surface_texture = false;
+ ResourceId id2 = child_resource_provider_->ImportResource(
+ id2_transfer, SingleReleaseCallback::Create(base::DoNothing()));
+
+ std::vector<ReturnedResource> returned_to_child;
+ int child_id =
+ resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+
+ // Transfer some resources to the parent.
+ std::vector<TransferableResource> list;
+ child_resource_provider_->PrepareSendToParent({id1, id2}, &list,
+ child_context_provider_.get());
+ ASSERT_EQ(2u, list.size());
+ resource_provider_->ReceiveFromChild(child_id, list);
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ resource_provider_->GetChildToParentMap(child_id);
+ ResourceId mapped_id1 = resource_map[list[0].id];
+ ResourceId mapped_id2 = resource_map[list[1].id];
+
+ // The promotion hints should not be recorded until after we wait. This is
+ // because we can't notify them until they're synchronized, and we choose to
+ // ignore unwaited resources rather than send them a "no" hint. If they end
+ // up in the request set before we wait, then the attempt to notify them wil;
+ // DCHECK when we try to lock them for reading in SendPromotionHints.
+ EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
+ {
+ resource_provider_->WaitSyncToken(mapped_id1);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ mapped_id1);
+ }
+ EXPECT_EQ(1u, resource_provider_->CountPromotionHintRequestsForTesting());
+
+ EXPECT_EQ(list[0].mailbox_holder.sync_token,
+ context3d_->last_waited_sync_token());
+ ResourceIdSet resource_ids_to_receive;
+ resource_ids_to_receive.insert(id1);
+ resource_ids_to_receive.insert(id2);
+ resource_provider_->DeclareUsedResourcesFromChild(child_id,
+ resource_ids_to_receive);
+
+ EXPECT_EQ(2u, resource_provider_->num_resources());
+
+ EXPECT_NE(0u, mapped_id1);
+ EXPECT_NE(0u, mapped_id2);
+
+ // Make sure that the request for a promotion hint was noticed.
+ EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id1));
+ EXPECT_TRUE(resource_provider_->IsBackedBySurfaceTexture(mapped_id1));
+ EXPECT_TRUE(resource_provider_->WantsPromotionHintForTesting(mapped_id1));
+
+ EXPECT_TRUE(resource_provider_->IsOverlayCandidate(mapped_id2));
+ EXPECT_FALSE(resource_provider_->IsBackedBySurfaceTexture(mapped_id2));
+ EXPECT_FALSE(resource_provider_->WantsPromotionHintForTesting(mapped_id2));
+
+ // ResourceProvider maintains a set of promotion hint requests that should be
+ // cleared when resources are deleted.
+ resource_provider_->DeclareUsedResourcesFromChild(child_id, ResourceIdSet());
+ EXPECT_EQ(2u, returned_to_child.size());
+ child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+ EXPECT_EQ(0u, resource_provider_->CountPromotionHintRequestsForTesting());
+
+ resource_provider_->DestroyChild(child_id);
+}
+#endif
+
+} // namespace
+} // namespace viz
diff --git a/chromium/components/viz/service/display/display_unittest.cc b/chromium/components/viz/service/display/display_unittest.cc
index fa0e2f93a52..696bdb03231 100644
--- a/chromium/components/viz/service/display/display_unittest.cc
+++ b/chromium/components/viz/service/display/display_unittest.cc
@@ -30,8 +30,8 @@
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/fake_output_surface.h"
#include "components/viz/test/mock_compositor_frame_sink_client.h"
+#include "components/viz/test/test_gles2_interface.h"
#include "components/viz/test/test_shared_bitmap_manager.h"
-#include "components/viz/test/test_web_graphics_context_3d.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -107,21 +107,40 @@ class DisplayTest : public testing::Test {
~DisplayTest() override {}
- void SetUpDisplay(const RendererSettings& settings,
- std::unique_ptr<TestWebGraphicsContext3D> context) {
- begin_frame_source_.reset(new StubBeginFrameSource);
+ void SetUpSoftwareDisplay(const RendererSettings& settings) {
+ std::unique_ptr<FakeOutputSurface> output_surface;
+ auto device = std::make_unique<TestSoftwareOutputDevice>();
+ software_output_device_ = device.get();
+ output_surface = FakeOutputSurface::CreateSoftware(std::move(device));
+ output_surface_ = output_surface.get();
+ CreateDisplaySchedulerAndDisplay(settings, kArbitraryFrameSinkId,
+ std::move(output_surface));
+ }
+
+ void SetUpGpuDisplay(const RendererSettings& settings,
+ std::unique_ptr<TestGLES2Interface> context = nullptr) {
std::unique_ptr<FakeOutputSurface> output_surface;
+ scoped_refptr<TestContextProvider> provider;
if (context) {
- auto provider = TestContextProvider::Create(std::move(context));
- provider->BindToCurrentThread();
- output_surface = FakeOutputSurface::Create3d(std::move(provider));
+ provider = TestContextProvider::Create(std::move(context));
+
} else {
- auto device = std::make_unique<TestSoftwareOutputDevice>();
- software_output_device_ = device.get();
- output_surface = FakeOutputSurface::CreateSoftware(std::move(device));
+ provider = TestContextProvider::Create();
}
+ provider->BindToCurrentThread();
+ output_surface = FakeOutputSurface::Create3d(std::move(provider));
output_surface_ = output_surface.get();
+
+ CreateDisplaySchedulerAndDisplay(settings, kArbitraryFrameSinkId,
+ std::move(output_surface));
+ }
+
+ void CreateDisplaySchedulerAndDisplay(
+ const RendererSettings& settings,
+ const FrameSinkId& frame_sink_id,
+ std::unique_ptr<OutputSurface> output_surface) {
+ begin_frame_source_.reset(new StubBeginFrameSource);
auto scheduler = std::make_unique<TestDisplayScheduler>(
begin_frame_source_.get(), task_runner_.get());
scheduler_ = scheduler.get();
@@ -187,6 +206,8 @@ class StubDisplayClient : public DisplayClient {
void DisplayDidDrawAndSwap() override {}
void DisplayDidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) override{};
+ void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) override {}
};
void CopyCallback(bool* called, std::unique_ptr<CopyOutputResult> result) {
@@ -198,7 +219,7 @@ TEST_F(DisplayTest, DisplayDamaged) {
RendererSettings settings;
settings.partial_swap_enabled = true;
settings.finish_rendering_on_resize = true;
- SetUpDisplay(settings, nullptr);
+ SetUpSoftwareDisplay(settings);
gfx::ColorSpace color_space_1 = gfx::ColorSpace::CreateXYZD50();
gfx::ColorSpace color_space_2 = gfx::ColorSpace::CreateSCRGBLinear();
@@ -462,7 +483,7 @@ TEST_F(DisplayTest, DisplayDamaged) {
void DisplayTest::LatencyInfoCapTest(bool over_capacity) {
RendererSettings settings;
settings.finish_rendering_on_resize = true;
- SetUpDisplay(settings, nullptr);
+ SetUpSoftwareDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -530,9 +551,9 @@ TEST_F(DisplayTest, OverLatencyInfoCap) {
LatencyInfoCapTest(true);
}
-class MockedContext : public TestWebGraphicsContext3D {
+class MockedGLES2Interface : public TestGLES2Interface {
public:
- MOCK_METHOD0(shallowFinishCHROMIUM, void());
+ MOCK_METHOD0(ShallowFinishCHROMIUM, void());
};
TEST_F(DisplayTest, Finish) {
@@ -543,11 +564,11 @@ TEST_F(DisplayTest, Finish) {
settings.partial_swap_enabled = true;
settings.finish_rendering_on_resize = true;
- auto context = std::make_unique<MockedContext>();
- MockedContext* context_ptr = context.get();
- EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
+ auto gl = std::make_unique<MockedGLES2Interface>();
+ MockedGLES2Interface* gl_ptr = gl.get();
+ EXPECT_CALL(*gl_ptr, ShallowFinishCHROMIUM()).Times(0);
- SetUpDisplay(settings, std::move(context));
+ SetUpGpuDisplay(settings, std::move(gl));
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -570,19 +591,19 @@ TEST_F(DisplayTest, Finish) {
display_->DrawAndSwap();
// First resize and draw shouldn't finish.
- testing::Mock::VerifyAndClearExpectations(context_ptr);
+ testing::Mock::VerifyAndClearExpectations(gl_ptr);
- EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
+ EXPECT_CALL(*gl_ptr, ShallowFinishCHROMIUM());
display_->Resize(gfx::Size(150, 150));
- testing::Mock::VerifyAndClearExpectations(context_ptr);
+ testing::Mock::VerifyAndClearExpectations(gl_ptr);
// Another resize without a swap doesn't need to finish.
- EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
+ EXPECT_CALL(*gl_ptr, ShallowFinishCHROMIUM()).Times(0);
display_->SetLocalSurfaceId(local_surface_id2, 1.f);
display_->Resize(gfx::Size(200, 200));
- testing::Mock::VerifyAndClearExpectations(context_ptr);
+ testing::Mock::VerifyAndClearExpectations(gl_ptr);
- EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM()).Times(0);
+ EXPECT_CALL(*gl_ptr, ShallowFinishCHROMIUM()).Times(0);
{
RenderPassList pass_list;
auto pass = RenderPass::Create();
@@ -596,11 +617,11 @@ TEST_F(DisplayTest, Finish) {
display_->DrawAndSwap();
- testing::Mock::VerifyAndClearExpectations(context_ptr);
+ testing::Mock::VerifyAndClearExpectations(gl_ptr);
- EXPECT_CALL(*context_ptr, shallowFinishCHROMIUM());
+ EXPECT_CALL(*gl_ptr, ShallowFinishCHROMIUM());
display_->Resize(gfx::Size(250, 250));
- testing::Mock::VerifyAndClearExpectations(context_ptr);
+ testing::Mock::VerifyAndClearExpectations(gl_ptr);
TearDownDisplay();
}
@@ -617,7 +638,7 @@ class CountLossDisplayClient : public StubDisplayClient {
};
TEST_F(DisplayTest, ContextLossInformsClient) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
CountLossDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -639,7 +660,7 @@ TEST_F(DisplayTest, CompositorFrameDamagesCorrectDisplay) {
LocalSurfaceId local_surface_id(id_allocator_.GenerateId());
// Set up first display.
- SetUpDisplay(settings, nullptr);
+ SetUpSoftwareDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
display_->SetLocalSurfaceId(local_surface_id, 1.f);
@@ -690,7 +711,7 @@ TEST_F(DisplayTest, CompositorFrameDamagesCorrectDisplay) {
// Check if draw occlusion does not remove any DrawQuads when no quad is being
// covered completely.
TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -911,7 +932,7 @@ TEST_F(DisplayTest, DrawOcclusionWithNonCoveringDrawQuad) {
TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1042,7 +1063,7 @@ TEST_F(DisplayTest, CompositorFrameWithOverlapDrawQuad) {
// skip_rect size, such that DrawQuads that are smaller than the |skip_rect|
// are drawn on the screen regardless is shown or not.
TEST_F(DisplayTest, DrawOcclusionWithSkipRect) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1166,7 +1187,7 @@ TEST_F(DisplayTest, DrawOcclusionWithSkipRect) {
// skip_rect size, such that DrawQuads that are smaller than the |skip_rect|
// cannot occlude other quads behind it.
TEST_F(DisplayTest, OcclusionIgnoringSkipRect) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1228,7 +1249,7 @@ TEST_F(DisplayTest, OcclusionIgnoringSkipRect) {
TEST_F(DisplayTest, CompositorFrameWithTransformer) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1499,7 +1520,7 @@ TEST_F(DisplayTest, CompositorFrameWithTransformer) {
// Check if draw occlusion works with transform at epsilon scale.
TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1611,7 +1632,7 @@ TEST_F(DisplayTest, CompositorFrameWithEpsilonScaleTransform) {
// Check if draw occlusion works with transform at negative scale.
TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1736,7 +1757,7 @@ TEST_F(DisplayTest, CompositorFrameWithNegativeScaleTransform) {
TEST_F(DisplayTest, CompositorFrameWithRotation) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1865,7 +1886,7 @@ TEST_F(DisplayTest, CompositorFrameWithRotation) {
TEST_F(DisplayTest, CompositorFrameWithPerspective) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -1941,7 +1962,7 @@ TEST_F(DisplayTest, CompositorFrameWithPerspective) {
TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2008,7 +2029,7 @@ TEST_F(DisplayTest, CompositorFrameWithOpacityChange) {
TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2076,7 +2097,7 @@ TEST_F(DisplayTest, CompositorFrameWithOpaquenessChange) {
TEST_F(DisplayTest, CompositorFrameZTranslate) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2131,7 +2152,7 @@ TEST_F(DisplayTest, CompositorFrameZTranslate) {
TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2252,7 +2273,7 @@ TEST_F(DisplayTest, CompositorFrameWithTranslateTransformer) {
TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2380,7 +2401,7 @@ TEST_F(DisplayTest, CompositorFrameWithCombinedSharedQuadState) {
TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2454,7 +2475,7 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleRenderPass) {
}
TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2524,7 +2545,7 @@ TEST_F(DisplayTest, CompositorFrameWithCoveredRenderPass) {
TEST_F(DisplayTest, CompositorFrameWithClip) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2641,7 +2662,7 @@ TEST_F(DisplayTest, CompositorFrameWithClip) {
TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2689,7 +2710,7 @@ TEST_F(DisplayTest, CompositorFrameWithCopyRequest) {
TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -2869,7 +2890,7 @@ TEST_F(DisplayTest, CompositorFrameWithRenderPass) {
TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -3046,7 +3067,7 @@ TEST_F(DisplayTest, CompositorFrameWithMultipleDrawQuadInSharedQuadState) {
TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
RendererSettings settings;
settings.kMinimumDrawOcclusionSize.set_width(0);
- SetUpDisplay(settings, TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -3149,7 +3170,7 @@ TEST_F(DisplayTest, CompositorFrameWithNonInvertibleTransform) {
// Check if draw occlusion works with very large DrawQuad. crbug.com/824528.
TEST_F(DisplayTest, DrawOcclusionWithLargeDrawQuad) {
- SetUpDisplay(RendererSettings(), TestWebGraphicsContext3D::Create());
+ SetUpGpuDisplay(RendererSettings());
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
@@ -3194,7 +3215,7 @@ TEST_F(DisplayTest, CompositorFrameWithPresentationToken) {
const LocalSurfaceId local_surface_id(id_allocator_.GenerateId());
// Set up first display.
- SetUpDisplay(settings, nullptr);
+ SetUpSoftwareDisplay(settings);
StubDisplayClient client;
display_->Initialize(&client, manager_.surface_manager());
display_->SetLocalSurfaceId(local_surface_id, 1.f);
diff --git a/chromium/components/viz/service/display/gl_renderer.cc b/chromium/components/viz/service/display/gl_renderer.cc
index 0393c487f08..afda183f41e 100644
--- a/chromium/components/viz/service/display/gl_renderer.cc
+++ b/chromium/components/viz/service/display/gl_renderer.cc
@@ -58,7 +58,6 @@
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "media/base/media_switches.h"
-#include "skia/ext/texture_handle.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorFilter.h"
@@ -222,10 +221,8 @@ struct GLRenderer::DrawRenderPassDrawQuadParams {
bool use_aa = false;
- // Some filters affect pixels outside the original contents bounds. This
- // requires translation of the source when texturing, as well as a change in
- // the bounds of the destination.
- gfx::Point src_offset;
+ // Some filters affect pixels outside the original contents bounds, in which
+ // case ApplyImageFilter will modify this rect.
gfx::RectF dst_rect;
// A Skia image that should be sampled from instead of the original
@@ -233,25 +230,11 @@ struct GLRenderer::DrawRenderPassDrawQuadParams {
sk_sp<SkImage> filter_image;
// The original contents, bound for sampling.
- std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL>
+ std::unique_ptr<DisplayResourceProvider::ScopedSamplerGL>
bypass_quad_resource_lock;
// A mask to be applied when drawing the RPDQ.
- std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL>
- mask_resource_lock;
-
- // Original background texture.
- uint32_t background_texture = 0;
-
- // Backdrop bounding box.
- gfx::Rect background_rect;
-
- // Filtered background texture.
- sk_sp<SkImage> background_image;
- GLuint background_image_id = 0;
-
- // Whether the original background texture is needed for the mask.
- bool mask_for_background = false;
+ std::unique_ptr<DisplayResourceProvider::ScopedSamplerGL> mask_resource_lock;
// Whether a color matrix needs to be applied by the shaders when drawing
// the RPDQ.
@@ -266,6 +249,17 @@ struct GLRenderer::DrawRenderPassDrawQuadParams {
// The color space of the texture bound for sampling (from filter_image or
// bypass_quad_resource_lock, depending on the path taken).
gfx::ColorSpace contents_and_bypass_color_space;
+
+ // Background filters block.
+ // Original background texture.
+ uint32_t background_texture = 0;
+ // Backdrop bounding box.
+ gfx::Rect background_rect;
+ // Filtered background texture.
+ sk_sp<SkImage> background_image;
+ GLuint background_image_id = 0;
+ // Whether the original background texture is needed for the mask.
+ bool mask_for_background = false;
};
class GLRenderer::ScopedUseGrContext {
@@ -307,7 +301,7 @@ class GLRenderer::ScopedUseGrContext {
GLRenderer::GLRenderer(
const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
scoped_refptr<base::SingleThreadTaskRunner> current_task_runner)
: DirectRenderer(settings, output_surface, resource_provider),
shared_geometry_quad_(QuadVertexRect()),
@@ -452,8 +446,7 @@ void GLRenderer::BeginDrawingFrame() {
read_lock_fence = sync_queries_.StartNewFrame();
} else {
read_lock_fence =
- base::MakeRefCounted<cc::DisplayResourceProvider::SynchronousFence>(
- gl_);
+ base::MakeRefCounted<DisplayResourceProvider::SynchronousFence>(gl_);
}
resource_provider_->SetReadLockFence(read_lock_fence.get());
@@ -1028,6 +1021,21 @@ bool GLRenderer::InitializeRPDQParameters(
return true;
}
+// Get a GL texture id from an SkImage. An optional origin pointer can be
+// passed in which will be filled out with the origin for the texture
+// backing the SkImage.
+static GLuint GetGLTextureIDFromSkImage(const SkImage* image,
+ GrSurfaceOrigin* origin = nullptr) {
+ GrBackendTexture backend_texture = image->getBackendTexture(true, origin);
+ if (!backend_texture.isValid()) {
+ return 0;
+ }
+ GrGLTextureInfo info;
+ bool result = backend_texture.getGLTextureInfo(&info);
+ DCHECK(result);
+ return info.fID;
+}
+
void GLRenderer::UpdateRPDQShadersForBlending(
DrawRenderPassDrawQuadParams* params) {
const RenderPassDrawQuad* quad = params->quad;
@@ -1067,10 +1075,8 @@ void GLRenderer::UpdateRPDQShadersForBlending(
params->background_rect, unclipped_rect);
if (params->background_image) {
params->background_image_id =
- skia::GrBackendObjectToGrGLTextureInfo(
- params->background_image->getTextureHandle(true))
- ->fID;
- DCHECK(params->background_image_id);
+ GetGLTextureIDFromSkImage(params->background_image.get());
+ DCHECK(params->background_image_id || IsContextLost());
}
}
}
@@ -1169,7 +1175,7 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters(
src_image, src_rect, params->dst_rect, quad->filters_scale,
std::move(filter), &offset, &subset, quad->filters_origin);
} else {
- cc::DisplayResourceProvider::ScopedReadLockGL
+ DisplayResourceProvider::ScopedReadLockGL
prefilter_bypass_quad_texture_lock(
resource_provider_, params->bypass_quad_texture.resource_id);
params->contents_and_bypass_color_space =
@@ -1189,8 +1195,7 @@ bool GLRenderer::UpdateRPDQWithSkiaFilters(
params->dst_rect =
gfx::RectF(src_rect.x() + offset.fX, src_rect.y() + offset.fY,
subset.width(), subset.height());
- params->src_offset.SetPoint(subset.x(), subset.y());
- gfx::RectF tex_rect = gfx::RectF(gfx::PointF(params->src_offset),
+ gfx::RectF tex_rect = gfx::RectF(gfx::PointF(subset.x(), subset.y()),
params->dst_rect.size());
params->tex_coord_rect = tex_rect;
}
@@ -1203,7 +1208,7 @@ void GLRenderer::UpdateRPDQTexturesForSampling(
DrawRenderPassDrawQuadParams* params) {
if (params->quad->mask_resource_id()) {
params->mask_resource_lock.reset(
- new cc::DisplayResourceProvider::ScopedSamplerGL(
+ new DisplayResourceProvider::ScopedSamplerGL(
resource_provider_, params->quad->mask_resource_id(), GL_TEXTURE1,
GL_LINEAR));
}
@@ -1211,10 +1216,8 @@ void GLRenderer::UpdateRPDQTexturesForSampling(
if (params->filter_image) {
GrSurfaceOrigin origin;
GLuint filter_image_id =
- skia::GrBackendObjectToGrGLTextureInfo(
- params->filter_image->getTextureHandle(true, &origin))
- ->fID;
- DCHECK(filter_image_id);
+ GetGLTextureIDFromSkImage(params->filter_image.get(), &origin);
+ DCHECK(filter_image_id || IsContextLost());
DCHECK_EQ(GL_TEXTURE0, GetActiveTextureUnit(gl_));
gl_->BindTexture(GL_TEXTURE_2D, filter_image_id);
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -1229,7 +1232,7 @@ void GLRenderer::UpdateRPDQTexturesForSampling(
params->source_needs_flip = params->flip_texture;
} else {
params->bypass_quad_resource_lock =
- std::make_unique<cc::DisplayResourceProvider::ScopedSamplerGL>(
+ std::make_unique<DisplayResourceProvider::ScopedSamplerGL>(
resource_provider_, params->bypass_quad_texture.resource_id,
GL_LINEAR);
DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D),
@@ -1383,8 +1386,8 @@ void GLRenderer::UpdateRPDQUniforms(DrawRenderPassDrawQuadParams* params) {
gl_->Uniform4f(current_program_->backdrop_rect_location(),
params->background_rect.x(), params->background_rect.y(),
- params->background_rect.width(),
- params->background_rect.height());
+ 1.0f / params->background_rect.width(),
+ 1.0f / params->background_rect.height());
// Either |background_image_id| or |background_texture| will be the
// |backdrop_location| in the shader.
@@ -1862,7 +1865,7 @@ void GLRenderer::DrawContentQuadAA(const ContentDrawQuadBase* quad,
float edge[24];
SetupQuadForClippingAndAntialiasing(device_transform, quad, &aa_quad,
clip_region, &local_quad, edge);
- cc::DisplayResourceProvider::ScopedSamplerGL quad_resource_lock(
+ DisplayResourceProvider::ScopedSamplerGL quad_resource_lock(
resource_provider_, resource_id,
quad->nearest_neighbor ? GL_NEAREST : GL_LINEAR);
SamplerType sampler =
@@ -1932,7 +1935,7 @@ void GLRenderer::DrawContentQuadNoAA(const ContentDrawQuadBase* quad,
? GL_LINEAR
: GL_NEAREST;
- cc::DisplayResourceProvider::ScopedSamplerGL quad_resource_lock(
+ DisplayResourceProvider::ScopedSamplerGL quad_resource_lock(
resource_provider_, resource_id, filter);
SamplerType sampler =
SamplerTypeFromTextureTarget(quad_resource_lock.target());
@@ -2054,40 +2057,48 @@ void GLRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad,
? UV_TEXTURE_MODE_UV
: UV_TEXTURE_MODE_U_V;
- // TODO(ccameron): There are currently three sources of the color space: the
- // resource, quad->color_space, and quad->video_color_space. Remove two of
- // them.
- gfx::ColorSpace src_color_space = quad->video_color_space;
- gfx::ColorSpace dst_color_space =
- current_frame()->current_render_pass->color_space;
- cc::DisplayResourceProvider::ScopedSamplerGL y_plane_lock(
+ DisplayResourceProvider::ScopedSamplerGL y_plane_lock(
resource_provider_, quad->y_plane_resource_id(), GL_TEXTURE1, GL_LINEAR);
- cc::DisplayResourceProvider::ScopedSamplerGL u_plane_lock(
+ DisplayResourceProvider::ScopedSamplerGL u_plane_lock(
resource_provider_, quad->u_plane_resource_id(), GL_TEXTURE2, GL_LINEAR);
DCHECK_EQ(y_plane_lock.target(), u_plane_lock.target());
DCHECK_EQ(y_plane_lock.color_space(), u_plane_lock.color_space());
- // TODO(jbauman): Use base::Optional when available.
- std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL> v_plane_lock;
+ // TODO(ccameron): There are currently three sources of the color space: the
+ // resource, quad->color_space, and quad->video_color_space. Remove two of
+ // them.
+ gfx::ColorSpace src_color_space = quad->video_color_space;
// Invalid or unspecified color spaces should be treated as REC709.
if (!src_color_space.IsValid())
src_color_space = gfx::ColorSpace::CreateREC709();
else
DCHECK_EQ(src_color_space, y_plane_lock.color_space());
-
// The source color space should never be RGB.
DCHECK_NE(src_color_space, src_color_space.GetAsFullRangeRGB());
+ gfx::ColorSpace dst_color_space =
+ current_frame()->current_render_pass->color_space;
+ // Force sRGB output on Windows for overlay candidate video quads to match
+ // DirectComposition behavior in case these switch between overlays and
+ // compositing. See https://crbug.com/811118 for details.
+ if (supports_dc_layers_ &&
+ resource_provider_->IsOverlayCandidate(quad->y_plane_resource_id())) {
+ DCHECK(resource_provider_->IsOverlayCandidate(quad->u_plane_resource_id()));
+ dst_color_space = gfx::ColorSpace::CreateSRGB();
+ }
+
+ // TODO(jbauman): Use base::Optional when available.
+ std::unique_ptr<DisplayResourceProvider::ScopedSamplerGL> v_plane_lock;
if (uv_texture_mode == UV_TEXTURE_MODE_U_V) {
- v_plane_lock.reset(new cc::DisplayResourceProvider::ScopedSamplerGL(
+ v_plane_lock.reset(new DisplayResourceProvider::ScopedSamplerGL(
resource_provider_, quad->v_plane_resource_id(), GL_TEXTURE3,
GL_LINEAR));
DCHECK_EQ(y_plane_lock.target(), v_plane_lock->target());
DCHECK_EQ(y_plane_lock.color_space(), v_plane_lock->color_space());
}
- std::unique_ptr<cc::DisplayResourceProvider::ScopedSamplerGL> a_plane_lock;
+ std::unique_ptr<DisplayResourceProvider::ScopedSamplerGL> a_plane_lock;
if (alpha_texture_mode == YUV_HAS_ALPHA_TEXTURE) {
- a_plane_lock.reset(new cc::DisplayResourceProvider::ScopedSamplerGL(
+ a_plane_lock.reset(new DisplayResourceProvider::ScopedSamplerGL(
resource_provider_, quad->a_plane_resource_id(), GL_TEXTURE4,
GL_LINEAR));
DCHECK_EQ(y_plane_lock.target(), a_plane_lock->target());
@@ -2210,8 +2221,8 @@ void GLRenderer::DrawStreamVideoQuad(const StreamVideoDrawQuad* quad,
gl_, &highp_threshold_cache_, settings_->highp_threshold_min,
quad->shared_quad_state->visible_quad_layer_rect.bottom_right());
- cc::DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_,
- quad->resource_id());
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_,
+ quad->resource_id());
SetUseProgram(ProgramKey::VideoStream(tex_coord_precision),
lock.color_space(),
@@ -2262,7 +2273,7 @@ void GLRenderer::FlushTextureQuadCache(BoundGeometry flush_binding) {
SetBlendEnabled(draw_cache_.needs_blending);
// Assume the current active textures is 0.
- cc::DisplayResourceProvider::ScopedSamplerGL locked_quad(
+ DisplayResourceProvider::ScopedSamplerGL locked_quad(
resource_provider_, draw_cache_.resource_id,
draw_cache_.nearest_neighbor ? GL_NEAREST : GL_LINEAR);
@@ -2353,8 +2364,8 @@ void GLRenderer::EnqueueTextureQuad(const TextureDrawQuad* quad,
gl_, &highp_threshold_cache_, settings_->highp_threshold_min,
quad->shared_quad_state->visible_quad_layer_rect.bottom_right());
- cc::DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_,
- quad->resource_id());
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_,
+ quad->resource_id());
const SamplerType sampler = SamplerTypeFromTextureTarget(lock.target());
bool need_tex_clamp_rect = !quad->resource_size_in_pixels().IsEmpty() &&
@@ -2659,7 +2670,8 @@ void GLRenderer::DrawQuadGeometryWithAA(const DrawQuad* quad,
CenteredRect(tile_rect));
}
-void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
+void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) {
DCHECK(visible_);
TRACE_EVENT0("viz", "GLRenderer::SwapBuffers");
@@ -2670,6 +2682,7 @@ void GLRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
OutputSurfaceFrame output_frame;
output_frame.latency_info = std::move(latency_info);
output_frame.size = surface_size;
+ output_frame.need_presentation_feedback = need_presentation_feedback;
if (use_swap_with_bounds_) {
output_frame.content_bounds = std::move(swap_content_bounds_);
} else if (use_partial_swap_) {
@@ -2752,7 +2765,7 @@ void GLRenderer::SwapBuffersComplete() {
// that once a swap buffer has completed we can remove the oldest buffers
// from the queue, but only once we've swapped another frame afterward.
if (swapping_overlay_resources_.size() > 1) {
- cc::DisplayResourceProvider::ScopedBatchReturnResources returner(
+ DisplayResourceProvider::ScopedBatchReturnResources returner(
resource_provider_);
swapping_overlay_resources_.pop_front();
}
@@ -2770,7 +2783,7 @@ void GLRenderer::SwapBuffersComplete() {
void GLRenderer::DidReceiveTextureInUseResponses(
const gpu::TextureInUseResponses& responses) {
DCHECK(settings_->release_overlay_resources_after_gpu_query);
- cc::DisplayResourceProvider::ScopedBatchReturnResources returner(
+ DisplayResourceProvider::ScopedBatchReturnResources returner(
resource_provider_);
for (const gpu::TextureInUseResponse& response : responses) {
if (response.in_use)
@@ -3085,7 +3098,7 @@ void GLRenderer::ScheduleCALayers() {
unsigned texture_id = 0;
if (contents_resource_id) {
pending_overlay_resources_.push_back(
- std::make_unique<cc::DisplayResourceProvider::ScopedReadLockGL>(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
resource_provider_, contents_resource_id));
texture_id = pending_overlay_resources_.back()->texture_id();
}
@@ -3137,7 +3150,7 @@ void GLRenderer::ScheduleDCLayers() {
for (const auto& contents_resource_id : dc_layer_overlay.resources) {
if (contents_resource_id) {
pending_overlay_resources_.push_back(
- std::make_unique<cc::DisplayResourceProvider::ScopedReadLockGL>(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
resource_provider_, contents_resource_id));
texture_ids[i] = pending_overlay_resources_.back()->texture_id();
ids_to_send = i + 1;
@@ -3178,7 +3191,7 @@ void GLRenderer::ScheduleDCLayers() {
gl_->ScheduleDCLayerCHROMIUM(ids_to_send, texture_ids, contents_rect,
dc_layer_overlay.background_color,
dc_layer_overlay.edge_aa_mask, bounds_rect,
- filter);
+ filter, dc_layer_overlay.is_protected_video);
}
}
@@ -3186,7 +3199,7 @@ void GLRenderer::ScheduleOverlays() {
if (current_frame()->overlay_list.empty())
return;
- cc::OverlayCandidateList& overlays = current_frame()->overlay_list;
+ OverlayCandidateList& overlays = current_frame()->overlay_list;
for (const auto& overlay_candidate : overlays) {
unsigned texture_id = 0;
if (overlay_candidate.use_output_surface_for_resource) {
@@ -3194,7 +3207,7 @@ void GLRenderer::ScheduleOverlays() {
DCHECK(texture_id || IsContextLost());
} else {
pending_overlay_resources_.push_back(
- std::make_unique<cc::DisplayResourceProvider::ScopedReadLockGL>(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockGL>(
resource_provider_, overlay_candidate.resource_id));
texture_id = pending_overlay_resources_.back()->texture_id();
}
@@ -3202,7 +3215,8 @@ void GLRenderer::ScheduleOverlays() {
context_support_->ScheduleOverlayPlane(
overlay_candidate.plane_z_order, overlay_candidate.transform,
texture_id, ToNearestRect(overlay_candidate.display_rect),
- overlay_candidate.uv_rect, !overlay_candidate.is_opaque);
+ overlay_candidate.uv_rect, !overlay_candidate.is_opaque,
+ overlay_candidate.gpu_fence_id);
}
}
@@ -3614,8 +3628,7 @@ ResourceFormat GLRenderer::BackbufferFormat() const {
DCHECK(caps.color_buffer_half_float_rgba);
return RGBA_F16;
}
- return PlatformColor::BestSupportedTextureFormat(
- caps.texture_format_bgra8888);
+ return PlatformColor::BestSupportedTextureFormat(caps);
}
void GLRenderer::AllocateRenderPassResourceIfNeeded(
diff --git a/chromium/components/viz/service/display/gl_renderer.h b/chromium/components/viz/service/display/gl_renderer.h
index 180052af412..1cd981c9d71 100644
--- a/chromium/components/viz/service/display/gl_renderer.h
+++ b/chromium/components/viz/service/display/gl_renderer.h
@@ -33,12 +33,6 @@ namespace base {
class SingleThreadTaskRunner;
}
-namespace cc {
-class GLRendererShaderTest;
-class OutputSurface;
-class StreamVideoDrawQuad;
-} // namespace cc
-
namespace gpu {
namespace gles2 {
class GLES2Interface;
@@ -48,8 +42,11 @@ class GLES2Interface;
namespace viz {
class DynamicGeometryBinding;
+class GLRendererShaderTest;
+class OutputSurface;
class ScopedRenderPassTexture;
class StaticGeometryBinding;
+class StreamVideoDrawQuad;
class TextureDrawQuad;
// Class that handles drawing of composited render layers using GL.
@@ -59,13 +56,14 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
GLRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
scoped_refptr<base::SingleThreadTaskRunner> current_task_runner);
~GLRenderer() override;
bool use_swap_with_bounds() const { return use_swap_with_bounds_; }
- void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) override;
+ void SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) override;
void SwapBuffersComplete() override;
void DidReceiveTextureInUseResponses(
@@ -154,7 +152,7 @@ class VIZ_SERVICE_EXPORT GLRenderer : public DirectRenderer {
friend class GLRendererTest;
using OverlayResourceLock =
- std::unique_ptr<cc::DisplayResourceProvider::ScopedReadLockGL>;
+ std::unique_ptr<DisplayResourceProvider::ScopedReadLockGL>;
using OverlayResourceLockList = std::vector<OverlayResourceLock>;
// If a RenderPass is used as an overlay, we render the RenderPass with any
diff --git a/chromium/components/viz/service/display/gl_renderer_copier.cc b/chromium/components/viz/service/display/gl_renderer_copier.cc
index 478b2cb9950..f116895077d 100644
--- a/chromium/components/viz/service/display/gl_renderer_copier.cc
+++ b/chromium/components/viz/service/display/gl_renderer_copier.cc
@@ -215,10 +215,10 @@ GLuint GLRendererCopier::RenderResultTexture(
// return it as the result texture. The request must not include scaling nor
// a texture mailbox to use for delivering results. The texture format must
// also be GL_RGBA, as described by CopyOutputResult::Format::RGBA_TEXTURE.
- const int purpose = (!request.is_scaled() && flipped_source &&
- !request.has_mailbox() && internal_format == GL_RGBA)
- ? CacheEntry::kResultTexture
- : CacheEntry::kFramebufferCopyTexture;
+ const int purpose =
+ (!request.is_scaled() && flipped_source && internal_format == GL_RGBA)
+ ? CacheEntry::kResultTexture
+ : CacheEntry::kFramebufferCopyTexture;
TakeCachedObjectsOrCreate(SourceOf(request), purpose, 1, &source_texture);
gl->BindTexture(GL_TEXTURE_2D, source_texture);
gl->CopyTexImage2D(GL_TEXTURE_2D, 0, internal_format, sampling_rect.x(),
@@ -230,21 +230,9 @@ GLuint GLRendererCopier::RenderResultTexture(
sampling_rect.set_origin(gfx::Point());
}
- // Determine the result texture: If the copy request provided a valid one, use
- // it instead of one owned by GLRendererCopier.
GLuint result_texture = 0;
- if (request.has_mailbox()) {
- if (!request.mailbox().IsZero()) {
- if (request.sync_token().HasData())
- gl->WaitSyncTokenCHROMIUM(request.sync_token().GetConstData());
- result_texture =
- gl->CreateAndConsumeTextureCHROMIUM(request.mailbox().name);
- }
- }
- if (result_texture == 0) {
- TakeCachedObjectsOrCreate(SourceOf(request), CacheEntry::kResultTexture, 1,
- &result_texture);
- }
+ TakeCachedObjectsOrCreate(SourceOf(request), CacheEntry::kResultTexture, 1,
+ &result_texture);
gl->BindTexture(GL_TEXTURE_2D, result_texture);
gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, result_rect.width(),
result_rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
@@ -266,11 +254,12 @@ GLuint GLRendererCopier::RenderResultTexture(
CacheScalerOrDelete(SourceOf(request), std::move(scaler));
} else {
DCHECK_SIZE_EQ(sampling_rect.size(), result_rect.size());
+ const bool flip_output = !flipped_source;
gl->CopySubTextureCHROMIUM(
source_texture, 0 /* source_level */, GL_TEXTURE_2D, result_texture,
0 /* dest_level */, 0 /* xoffset */, 0 /* yoffset */, sampling_rect.x(),
sampling_rect.y(), sampling_rect.width(), sampling_rect.height(),
- !flipped_source, false, false);
+ flip_output, false, false);
}
// If |source_texture| was a copy, maybe cache it for future requests.
@@ -305,6 +294,80 @@ void GLRendererCopier::StartReadbackFromTexture(
namespace {
+class GLPixelBufferRGBAResult : public CopyOutputResult {
+ public:
+ GLPixelBufferRGBAResult(const gfx::Rect& result_rect,
+ scoped_refptr<ContextProvider> context_provider,
+ GLuint transfer_buffer,
+ GLenum readback_format)
+ : CopyOutputResult(CopyOutputResult::Format::RGBA_BITMAP, result_rect),
+ context_provider_(std::move(context_provider)),
+ transfer_buffer_(transfer_buffer),
+ readback_format_(readback_format) {}
+
+ ~GLPixelBufferRGBAResult() final {
+ if (transfer_buffer_)
+ context_provider_->ContextGL()->DeleteBuffers(1, &transfer_buffer_);
+ }
+
+ bool ReadRGBAPlane(uint8_t* dest, int stride) const final {
+ // No need to read from GPU memory if a cached bitmap already exists.
+ if (rect().IsEmpty() || cached_bitmap()->readyToDraw())
+ return CopyOutputResult::ReadRGBAPlane(dest, stride);
+ auto* const gl = context_provider_->ContextGL();
+ gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_);
+ const uint8_t* pixels = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
+ GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
+ if (pixels) {
+ const SkColorType src_format = (readback_format_ == GL_BGRA_EXT)
+ ? kBGRA_8888_SkColorType
+ : kRGBA_8888_SkColorType;
+ const int src_bytes_per_row = size().width() * kRGBABytesPerPixel;
+ const SkImageInfo src_row_image_info =
+ SkImageInfo::Make(size().width(), 1, src_format, kPremul_SkAlphaType);
+ const SkImageInfo dest_row_image_info =
+ SkImageInfo::MakeN32Premul(size().width(), 1);
+
+ for (int y = 0; y < size().height(); ++y) {
+ const int flipped_y = (size().height() - y - 1);
+ const uint8_t* const src_row = pixels + flipped_y * src_bytes_per_row;
+ void* const dest_row = dest + y * stride;
+ SkPixmap src_pixmap(src_row_image_info, src_row, src_bytes_per_row);
+ SkPixmap dest_pixmap(dest_row_image_info, dest_row, stride);
+ src_pixmap.readPixels(dest_pixmap);
+ }
+ gl->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
+ }
+ gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
+ return !!pixels;
+ }
+
+ const SkBitmap& AsSkBitmap() const final {
+ if (rect().IsEmpty())
+ return *cached_bitmap(); // Return "null" bitmap for empty result.
+
+ if (cached_bitmap()->readyToDraw())
+ return *cached_bitmap();
+
+ SkBitmap result_bitmap;
+ result_bitmap.allocPixels(
+ SkImageInfo::MakeN32Premul(size().width(), size().height()));
+ ReadRGBAPlane(static_cast<uint8_t*>(result_bitmap.getPixels()),
+ result_bitmap.rowBytes());
+ *cached_bitmap() = result_bitmap;
+ // Now that we have a cached bitmap, no need to read from GPU memory
+ // anymore.
+ context_provider_->ContextGL()->DeleteBuffers(1, &transfer_buffer_);
+ transfer_buffer_ = 0;
+ return *cached_bitmap();
+ }
+
+ private:
+ const scoped_refptr<ContextProvider> context_provider_;
+ mutable GLuint transfer_buffer_;
+ GLenum readback_format_;
+};
+
// Manages the execution of one asynchronous framebuffer readback and contains
// all the relevant state needed to complete a copy request. The constructor
// initiates the operation, and then at some later point either: 1) the Finish()
@@ -357,7 +420,8 @@ class ReadPixelsWorkflow {
~ReadPixelsWorkflow() {
auto* const gl = context_provider_->ContextGL();
gl->DeleteQueriesEXT(1, &query_);
- gl->DeleteBuffers(1, &transfer_buffer_);
+ if (transfer_buffer_)
+ gl->DeleteBuffers(1, &transfer_buffer_);
}
GLuint query() const { return query_; }
@@ -365,42 +429,15 @@ class ReadPixelsWorkflow {
// Callback for the asynchronous glReadPixels(). The pixels are read from the
// transfer buffer, and a CopyOutputResult is sent to the requestor.
void Finish() {
- auto* const gl = context_provider_->ContextGL();
-
- gl->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, transfer_buffer_);
- const uint8_t* pixels = static_cast<uint8_t*>(gl->MapBufferCHROMIUM(
- GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, GL_READ_ONLY));
- if (!pixels) {
- // CopyOutputRequest will auto-send an empty result when its destructor
- // is run from ~ReadPixelsWorkflow().
- return;
- }
-
- // Create the result bitmap, making sure to flip the image in the Y
- // dimension.
- //
- // TODO(crbug/758057): Plumb-through color space into the output bitmap.
- SkBitmap result_bitmap;
- const int bytes_per_row = result_rect_.width() * kRGBABytesPerPixel;
- result_bitmap.allocPixels(
- SkImageInfo::Make(result_rect_.width(), result_rect_.height(),
- (readback_format_ == GL_BGRA_EXT)
- ? kBGRA_8888_SkColorType
- : kRGBA_8888_SkColorType,
- kPremul_SkAlphaType),
- bytes_per_row);
- for (int y = 0; y < result_rect_.height(); ++y) {
- const int flipped_y = (result_rect_.height() - y - 1);
- const uint8_t* const src_row = pixels + flipped_y * bytes_per_row;
- void* const dest_row = result_bitmap.getAddr(0, y);
- memcpy(dest_row, src_row, bytes_per_row);
+ auto result = std::make_unique<GLPixelBufferRGBAResult>(
+ result_rect_, context_provider_, transfer_buffer_, readback_format_);
+ transfer_buffer_ = 0; // Ownerhip was transferred to the result.
+ if (!copy_request_->SendsResultsInCurrentSequence()) {
+ // Force readback into a SkBitmap now, because after PostTask we don't
+ // have access to |context_provider_|.
+ result->AsSkBitmap();
}
- gl->UnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
-
- copy_request_->SendResult(std::make_unique<CopyOutputSkBitmapResult>(
- result_rect_, result_bitmap));
-
- // |transfer_buffer_| and |query_| will be deleted soon by the destructor.
+ copy_request_->SendResult(std::move(result));
}
private:
@@ -444,34 +481,18 @@ void GLRendererCopier::SendTextureResult(
// within its own GL context will be using the texture at a point in time
// after the texture has been rendered (via GLRendererCopier's GL context).
gpu::Mailbox mailbox;
- if (request->has_mailbox()) {
- mailbox = request->mailbox();
- } else {
- gl->GenMailboxCHROMIUM(mailbox.name);
- gl->ProduceTextureDirectCHROMIUM(result_texture, mailbox.name);
- }
+ gl->GenMailboxCHROMIUM(mailbox.name);
+ gl->ProduceTextureDirectCHROMIUM(result_texture, mailbox.name);
gpu::SyncToken sync_token;
gl->GenSyncTokenCHROMIUM(sync_token.GetData());
- // Create a |release_callback| appropriate to the situation: If the
- // |result_texture| was provided in the mailbox of the copy request,
- // create a no-op release callback because the requestor owns the texture.
- // Otherwise, create a callback that deletes what was created in this GL
- // context.
- std::unique_ptr<SingleReleaseCallback> release_callback;
- if (request->has_mailbox()) {
- gl->DeleteTextures(1, &result_texture);
- // TODO(crbug/754872): This non-null release callback wart is going away
- // soon, as copy requestors won't need pool/manage textures anymore.
- release_callback = SingleReleaseCallback::Create(base::DoNothing());
- } else {
- // Note: There's no need to try to pool/re-use the result texture from here,
- // since only clients that are trying to re-invent video capture would see
- // any significant performance benefit. Instead, such clients should use the
- // video capture services provided by VIZ.
- release_callback =
- texture_deleter_->GetReleaseCallback(context_provider_, result_texture);
- }
+ // Create a callback that deletes what was created in this GL context.
+ // Note: There's no need to try to pool/re-use the result texture from here,
+ // since only clients that are trying to re-invent video capture would see any
+ // significant performance benefit. Instead, such clients should use the video
+ // capture services provided by VIZ.
+ auto release_callback =
+ texture_deleter_->GetReleaseCallback(context_provider_, result_texture);
request->SendResult(std::make_unique<CopyOutputTextureResult>(
result_rect, mailbox, sync_token, color_space,
@@ -825,9 +846,10 @@ GLRendererCopier::TakeCachedScalerOrCreate(const CopyOutputRequest& for_request,
const GLHelper::ScalerQuality quality = is_downscale_in_both_dimensions
? GLHelper::SCALER_QUALITY_GOOD
: GLHelper::SCALER_QUALITY_BEST;
+ const bool flip_output = !flipped_source;
return helper_.CreateScaler(quality, for_request.scale_from(),
- for_request.scale_to(), flipped_source, false,
- false);
+ for_request.scale_to(), flipped_source,
+ flip_output, false);
}
void GLRendererCopier::CacheScalerOrDelete(
diff --git a/chromium/components/viz/service/display/gl_renderer_copier.h b/chromium/components/viz/service/display/gl_renderer_copier.h
index 7470b09cc91..5f60ffcddb1 100644
--- a/chromium/components/viz/service/display/gl_renderer_copier.h
+++ b/chromium/components/viz/service/display/gl_renderer_copier.h
@@ -183,6 +183,8 @@ class VIZ_SERVICE_EXPORT GLRendererCopier {
const GLuint* names);
// Returns a cached scaler for the given request, or creates one on-demand.
+ // The scaler can be configured for source textures that may or may not be
+ // Y-flipped, but its results will always be Y-flipped.
std::unique_ptr<GLHelper::ScalerInterface> TakeCachedScalerOrCreate(
const CopyOutputRequest& for_request,
bool flipped_source);
diff --git a/chromium/components/viz/service/display/gl_renderer_unittest.cc b/chromium/components/viz/service/display/gl_renderer_unittest.cc
index 241284a5ccc..1913ad59553 100644
--- a/chromium/components/viz/service/display/gl_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/gl_renderer_unittest.cc
@@ -12,11 +12,12 @@
#include <vector>
#include "base/location.h"
+#include "base/single_thread_task_runner.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
-#include "cc/resources/resource_provider.h"
+#include "cc/resources/layer_tree_resource_provider.h"
#include "cc/test/fake_impl_task_runner_provider.h"
#include "cc/test/fake_layer_tree_host_impl.h"
#include "cc/test/fake_output_surface_client.h"
@@ -28,7 +29,9 @@
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/transferable_resource.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "components/viz/test/fake_output_surface.h"
@@ -462,13 +465,13 @@ class FakeRendererGL : public GLRenderer {
public:
FakeRendererGL(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+ DisplayResourceProvider* resource_provider)
: GLRenderer(settings, output_surface, resource_provider, nullptr) {}
FakeRendererGL(
const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
scoped_refptr<base::SingleThreadTaskRunner> current_task_runner)
: GLRenderer(settings,
output_surface,
@@ -504,13 +507,15 @@ class GLRendererWithDefaultHarnessTest : public GLRendererTest {
renderer_->SetVisible(true);
}
- void SwapBuffers() { renderer_->SwapBuffers(std::vector<ui::LatencyInfo>()); }
+ void SwapBuffers() {
+ renderer_->SwapBuffers(std::vector<ui::LatencyInfo>(), false);
+ }
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
};
@@ -538,7 +543,7 @@ class GLRendererShaderTest : public GLRendererTest {
child_context_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_context_provider_.get(), shared_bitmap_manager_.get());
+ child_context_provider_.get());
}
void TestRenderPassProgram(TexCoordPrecision precision,
@@ -628,7 +633,7 @@ class GLRendererShaderTest : public GLRendererTest {
cc::FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
scoped_refptr<TestContextProvider> child_context_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
@@ -651,38 +656,45 @@ TEST_F(GLRendererWithDefaultHarnessTest, ExternalStencil) {
EXPECT_TRUE(renderer_->stencil_enabled());
}
-class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
+class ForbidSynchronousCallGLES2Interface : public TestGLES2Interface {
public:
- ForbidSynchronousCallContext() {}
+ ForbidSynchronousCallGLES2Interface() = default;
- void getAttachedShaders(GLuint program,
+ void GetAttachedShaders(GLuint program,
GLsizei max_count,
GLsizei* count,
GLuint* shaders) override {
ADD_FAILURE();
}
- GLint getAttribLocation(GLuint program, const GLchar* name) override {
+
+ GLint GetAttribLocation(GLuint program, const GLchar* name) override {
ADD_FAILURE();
return 0;
}
- void getBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); }
- void getBufferParameteriv(GLenum target,
+
+ void GetBooleanv(GLenum pname, GLboolean* value) override { ADD_FAILURE(); }
+
+ void GetBufferParameteriv(GLenum target,
GLenum pname,
GLint* value) override {
ADD_FAILURE();
}
- GLenum getError() override {
+
+ GLenum GetError() override {
ADD_FAILURE();
return GL_NO_ERROR;
}
- void getFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); }
- void getFramebufferAttachmentParameteriv(GLenum target,
+
+ void GetFloatv(GLenum pname, GLfloat* value) override { ADD_FAILURE(); }
+
+ void GetFramebufferAttachmentParameteriv(GLenum target,
GLenum attachment,
GLenum pname,
GLint* value) override {
ADD_FAILURE();
}
- void getIntegerv(GLenum pname, GLint* value) override {
+
+ void GetIntegerv(GLenum pname, GLint* value) override {
if (pname == GL_MAX_TEXTURE_SIZE) {
// MAX_TEXTURE_SIZE is cached client side, so it's OK to query.
*value = 1024;
@@ -693,64 +705,66 @@ class ForbidSynchronousCallContext : public TestWebGraphicsContext3D {
// We allow querying the shader compilation and program link status in debug
// mode, but not release.
- void getProgramiv(GLuint program, GLenum pname, GLint* value) override {
-#ifndef NDEBUG
- *value = 1;
-#else
+ void GetProgramiv(GLuint program, GLenum pname, GLint* value) override {
ADD_FAILURE();
-#endif
}
- void getShaderiv(GLuint shader, GLenum pname, GLint* value) override {
-#ifndef NDEBUG
- *value = 1;
-#else
+ void GetShaderiv(GLuint shader, GLenum pname, GLint* value) override {
ADD_FAILURE();
-#endif
}
- void getRenderbufferParameteriv(GLenum target,
+ void GetRenderbufferParameteriv(GLenum target,
GLenum pname,
GLint* value) override {
ADD_FAILURE();
}
- void getShaderPrecisionFormat(GLenum shadertype,
+ void GetShaderPrecisionFormat(GLenum shadertype,
GLenum precisiontype,
GLint* range,
GLint* precision) override {
ADD_FAILURE();
}
- void getTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override {
+
+ void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* value) override {
ADD_FAILURE();
}
- void getTexParameteriv(GLenum target, GLenum pname, GLint* value) override {
+
+ void GetTexParameteriv(GLenum target, GLenum pname, GLint* value) override {
ADD_FAILURE();
}
- void getUniformfv(GLuint program, GLint location, GLfloat* value) override {
+
+ void GetUniformfv(GLuint program, GLint location, GLfloat* value) override {
ADD_FAILURE();
}
- void getUniformiv(GLuint program, GLint location, GLint* value) override {
+
+ void GetUniformiv(GLuint program, GLint location, GLint* value) override {
ADD_FAILURE();
}
- GLint getUniformLocation(GLuint program, const GLchar* name) override {
+
+ GLint GetUniformLocation(GLuint program, const GLchar* name) override {
ADD_FAILURE();
return 0;
}
- void getVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override {
+
+ void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* value) override {
ADD_FAILURE();
}
- void getVertexAttribiv(GLuint index, GLenum pname, GLint* value) override {
+
+ void GetVertexAttribiv(GLuint index, GLenum pname, GLint* value) override {
ADD_FAILURE();
}
- GLsizeiptr getVertexAttribOffset(GLuint index, GLenum pname) override {
+
+ void GetVertexAttribPointerv(GLuint index,
+ GLenum pname,
+ void** pointer) override {
ADD_FAILURE();
- return 0;
}
};
+
TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
- auto context = std::make_unique<ForbidSynchronousCallContext>();
- auto provider = TestContextProvider::Create(std::move(context));
+ auto gl_owned = std::make_unique<ForbidSynchronousCallGLES2Interface>();
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -760,7 +774,7 @@ TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -769,24 +783,26 @@ TEST_F(GLRendererTest, InitializationDoesNotMakeSynchronousCalls) {
resource_provider.get());
}
-class LoseContextOnFirstGetContext : public TestWebGraphicsContext3D {
+class LoseContextOnFirstGetGLES2Interface : public TestGLES2Interface {
public:
- LoseContextOnFirstGetContext() {}
+ LoseContextOnFirstGetGLES2Interface() {}
- void getProgramiv(GLuint program, GLenum pname, GLint* value) override {
- context_lost_ = true;
+ void GetProgramiv(GLuint program, GLenum pname, GLint* value) override {
+ LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+ GL_INNOCENT_CONTEXT_RESET_ARB);
*value = 0;
}
- void getShaderiv(GLuint shader, GLenum pname, GLint* value) override {
- context_lost_ = true;
+ void GetShaderiv(GLuint shader, GLenum pname, GLint* value) override {
+ LoseContextCHROMIUM(GL_GUILTY_CONTEXT_RESET_ARB,
+ GL_INNOCENT_CONTEXT_RESET_ARB);
*value = 0;
}
};
TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
- auto context = std::make_unique<LoseContextOnFirstGetContext>();
- auto provider = TestContextProvider::Create(std::move(context));
+ auto gl_owned = std::make_unique<LoseContextOnFirstGetGLES2Interface>();
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -796,7 +812,7 @@ TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -805,22 +821,24 @@ TEST_F(GLRendererTest, InitializationWithQuicklyLostContextDoesNotAssert) {
resource_provider.get());
}
-class ClearCountingContext : public TestWebGraphicsContext3D {
+class ClearCountingGLES2Interface : public TestGLES2Interface {
public:
- ClearCountingContext() { test_capabilities_.discard_framebuffer = true; }
+ ClearCountingGLES2Interface() = default;
- MOCK_METHOD3(discardFramebufferEXT,
+ MOCK_METHOD3(DiscardFramebufferEXT,
void(GLenum target,
GLsizei numAttachments,
const GLenum* attachments));
- MOCK_METHOD1(clear, void(GLbitfield mask));
+ MOCK_METHOD1(Clear, void(GLbitfield mask));
};
TEST_F(GLRendererTest, OpaqueBackground) {
- std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
- ClearCountingContext* context = context_owned.get();
+ auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
+ gl_owned->set_have_discard_framebuffer(true);
- auto provider = TestContextProvider::Create(std::move(context_owned));
+ auto* gl = gl_owned.get();
+
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -830,7 +848,7 @@ TEST_F(GLRendererTest, OpaqueBackground) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -848,23 +866,24 @@ TEST_F(GLRendererTest, OpaqueBackground) {
// On DEBUG builds, render passes with opaque background clear to blue to
// easily see regions that were not drawn on the screen.
- EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
+ EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _))
.With(Args<2, 1>(ElementsAre(GL_COLOR_EXT)))
.Times(1);
#ifdef NDEBUG
- EXPECT_CALL(*context, clear(_)).Times(0);
+ EXPECT_CALL(*gl, Clear(_)).Times(0);
#else
- EXPECT_CALL(*context, clear(_)).Times(1);
+ EXPECT_CALL(*gl, Clear(_)).Times(1);
#endif
DrawFrame(&renderer, viewport_size);
- Mock::VerifyAndClearExpectations(context);
+ Mock::VerifyAndClearExpectations(gl);
}
TEST_F(GLRendererTest, TransparentBackground) {
- std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
- ClearCountingContext* context = context_owned.get();
+ auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
+ auto* gl = gl_owned.get();
+ gl_owned->set_have_discard_framebuffer(true);
- auto provider = TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -874,7 +893,7 @@ TEST_F(GLRendererTest, TransparentBackground) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -890,18 +909,19 @@ TEST_F(GLRendererTest, TransparentBackground) {
gfx::Transform(), cc::FilterOperations());
root_pass->has_transparent_background = true;
- EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
- EXPECT_CALL(*context, clear(_)).Times(1);
+ EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, 1, _)).Times(1);
+ EXPECT_CALL(*gl, Clear(_)).Times(1);
DrawFrame(&renderer, viewport_size);
- Mock::VerifyAndClearExpectations(context);
+ Mock::VerifyAndClearExpectations(gl);
}
TEST_F(GLRendererTest, OffscreenOutputSurface) {
- std::unique_ptr<ClearCountingContext> context_owned(new ClearCountingContext);
- ClearCountingContext* context = context_owned.get();
+ auto gl_owned = std::make_unique<ClearCountingGLES2Interface>();
+ auto* gl = gl_owned.get();
+ gl_owned->set_have_discard_framebuffer(true);
- auto provider = TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -911,7 +931,7 @@ TEST_F(GLRendererTest, OffscreenOutputSurface) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -925,26 +945,25 @@ TEST_F(GLRendererTest, OffscreenOutputSurface) {
cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(viewport_size),
gfx::Transform(), cc::FilterOperations());
- EXPECT_CALL(*context, discardFramebufferEXT(GL_FRAMEBUFFER, _, _))
+ EXPECT_CALL(*gl, DiscardFramebufferEXT(GL_FRAMEBUFFER, _, _))
.With(Args<2, 1>(ElementsAre(GL_COLOR_ATTACHMENT0)))
.Times(1);
- EXPECT_CALL(*context, clear(_)).Times(AnyNumber());
+ EXPECT_CALL(*gl, Clear(_)).Times(AnyNumber());
DrawFrame(&renderer, viewport_size);
- Mock::VerifyAndClearExpectations(context);
+ Mock::VerifyAndClearExpectations(gl);
}
-class TextureStateTrackingContext : public TestWebGraphicsContext3D {
+class TextureStateTrackingGLES2Interface : public TestGLES2Interface {
public:
- TextureStateTrackingContext() : active_texture_(GL_INVALID_ENUM) {
- test_capabilities_.egl_image_external = true;
- }
+ TextureStateTrackingGLES2Interface() : active_texture_(GL_INVALID_ENUM) {}
- MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
- MOCK_METHOD3(texParameteri, void(GLenum target, GLenum pname, GLint param));
- MOCK_METHOD4(drawElements,
- void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
+ MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token));
+ MOCK_METHOD3(TexParameteri, void(GLenum target, GLenum pname, GLint param));
+ MOCK_METHOD4(
+ DrawElements,
+ void(GLenum mode, GLsizei count, GLenum type, const void* indices));
- virtual void activeTexture(GLenum texture) {
+ void ActiveTexture(GLenum texture) override {
EXPECT_NE(texture, active_texture_);
active_texture_ = texture;
}
@@ -956,11 +975,11 @@ class TextureStateTrackingContext : public TestWebGraphicsContext3D {
};
TEST_F(GLRendererTest, ActiveTextureState) {
- std::unique_ptr<TextureStateTrackingContext> context_owned(
- new TextureStateTrackingContext);
- TextureStateTrackingContext* context = context_owned.get();
+ auto gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>();
+ gl_owned->set_have_extension_egl_image(true);
+ auto* gl = gl_owned.get();
- auto provider = TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -970,7 +989,7 @@ TEST_F(GLRendererTest, ActiveTextureState) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -981,32 +1000,31 @@ TEST_F(GLRendererTest, ActiveTextureState) {
renderer.SetVisible(true);
// During initialization we are allowed to set any texture parameters.
- EXPECT_CALL(*context, texParameteri(_, _, _)).Times(AnyNumber());
+ EXPECT_CALL(*gl, TexParameteri(_, _, _)).Times(AnyNumber());
- std::unique_ptr<TextureStateTrackingContext> child_context_owned(
- new TextureStateTrackingContext);
+ auto child_gl_owned = std::make_unique<TextureStateTrackingGLES2Interface>();
auto child_context_provider =
- TestContextProvider::Create(std::move(child_context_owned));
+ TestContextProvider::Create(std::move(child_gl_owned));
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_context_provider.get(), shared_bitmap_manager.get());
+ child_context_provider.get());
RenderPass* root_pass =
cc::AddRenderPass(&render_passes_in_draw_order_, 1, gfx::Rect(100, 100),
gfx::Transform(), cc::FilterOperations());
gpu::SyncToken mailbox_sync_token;
AddOneOfEveryQuadTypeInDisplayResourceProvider(
- root_pass, resource_provider.get(), child_resource_provider.get(), 0,
- &mailbox_sync_token);
+ root_pass, resource_provider.get(), child_resource_provider.get(),
+ child_context_provider.get(), 0, &mailbox_sync_token);
EXPECT_EQ(12u, resource_provider->num_resources());
renderer.DecideRenderPassAllocationsForFrame(render_passes_in_draw_order_);
// Set up expected texture filter state transitions that match the quads
// created in AppendOneOfEveryQuadType().
- Mock::VerifyAndClearExpectations(context);
+ Mock::VerifyAndClearExpectations(gl);
{
InSequence sequence;
// The verified flush flag will be set by
@@ -1018,43 +1036,45 @@ TEST_F(GLRendererTest, ActiveTextureState) {
// (with mailbox), resource2, resource3, resource4, resource9, resource10,
// resource11, resource12. resource8 has its own mailbox mailbox_sync_token.
// The rest resources share a common default sync token.
- EXPECT_CALL(*context, waitSyncToken(_)).Times(2);
- EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(mailbox_sync_token)))
+ EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(2);
+ EXPECT_CALL(*gl,
+ WaitSyncTokenCHROMIUM(MatchesSyncToken(mailbox_sync_token)))
.Times(1);
- EXPECT_CALL(*context, waitSyncToken(_)).Times(7);
+ EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(_)).Times(7);
// yuv_quad is drawn with the default linear filter.
- EXPECT_CALL(*context, drawElements(_, _, _, _));
+ EXPECT_CALL(*gl, DrawElements(_, _, _, _));
// tile_quad is drawn with GL_NEAREST because it is not transformed or
// scaled.
- EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
- GL_NEAREST));
- EXPECT_CALL(*context, texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
- GL_NEAREST));
+ EXPECT_CALL(
+ *gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
+ EXPECT_CALL(
+ *gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
// The remaining quads also use GL_LINEAR because nearest neighbor
// filtering is currently only used with tile quads.
- EXPECT_CALL(*context, drawElements(_, _, _, _)).Times(8);
+ EXPECT_CALL(*gl, DrawElements(_, _, _, _)).Times(8);
}
gfx::Size viewport_size(100, 100);
DrawFrame(&renderer, viewport_size);
- Mock::VerifyAndClearExpectations(context);
+ Mock::VerifyAndClearExpectations(gl);
}
-class NoClearRootRenderPassMockContext : public TestWebGraphicsContext3D {
+class NoClearRootRenderPassMockGLES2Interface : public TestGLES2Interface {
public:
- MOCK_METHOD1(clear, void(GLbitfield mask));
- MOCK_METHOD4(drawElements,
- void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
+ MOCK_METHOD1(Clear, void(GLbitfield mask));
+ MOCK_METHOD4(
+ DrawElements,
+ void(GLenum mode, GLsizei count, GLenum type, const void* indices));
};
TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
- std::unique_ptr<NoClearRootRenderPassMockContext> mock_context_owned(
- new NoClearRootRenderPassMockContext);
- NoClearRootRenderPassMockContext* mock_context = mock_context_owned.get();
+ auto mock_gl_owned =
+ std::make_unique<NoClearRootRenderPassMockGLES2Interface>();
+ NoClearRootRenderPassMockGLES2Interface* mock_gl = mock_gl_owned.get();
- auto provider = TestContextProvider::Create(std::move(mock_context_owned));
+ auto provider = TestContextProvider::Create(std::move(mock_gl_owned));
provider->BindToCurrentThread();
cc::FakeOutputSurfaceClient output_surface_client;
@@ -1064,7 +1084,7 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1099,17 +1119,15 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
#endif
// First render pass is not the root one, clearing should happen.
- EXPECT_CALL(*mock_context, clear(clear_bits)).Times(AtLeast(1));
+ EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(AtLeast(1));
Expectation first_render_pass =
- EXPECT_CALL(*mock_context, drawElements(_, _, _, _)).Times(1);
+ EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _)).Times(1);
// The second render pass is the root one, clearing should be prevented.
- EXPECT_CALL(*mock_context, clear(clear_bits))
- .Times(0)
- .After(first_render_pass);
+ EXPECT_CALL(*mock_gl, Clear(clear_bits)).Times(0).After(first_render_pass);
- EXPECT_CALL(*mock_context, drawElements(_, _, _, _))
+ EXPECT_CALL(*mock_gl, DrawElements(_, _, _, _))
.Times(AnyNumber())
.After(first_render_pass);
@@ -1118,7 +1136,7 @@ TEST_F(GLRendererTest, ShouldClearRootRenderPass) {
// In multiple render passes all but the root pass should clear the
// framebuffer.
- Mock::VerifyAndClearExpectations(&mock_context);
+ Mock::VerifyAndClearExpectations(&mock_gl);
}
class ScissorTestOnClearCheckingGLES2Interface : public TestGLES2Interface {
@@ -1154,7 +1172,7 @@ TEST_F(GLRendererTest, ScissorTestWhenClearing) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1198,11 +1216,6 @@ class DiscardCheckingGLES2Interface : public TestGLES2Interface {
public:
DiscardCheckingGLES2Interface() = default;
- void InitializeTestContext(TestWebGraphicsContext3D* context) override {
- context->set_have_post_sub_buffer(true);
- context->set_have_discard_framebuffer(true);
- }
-
void DiscardFramebufferEXT(GLenum target,
GLsizei numAttachments,
const GLenum* attachments) override {
@@ -1218,6 +1231,9 @@ class DiscardCheckingGLES2Interface : public TestGLES2Interface {
TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
auto gl_owned = std::make_unique<DiscardCheckingGLES2Interface>();
+ gl_owned->set_have_post_sub_buffer(true);
+ gl_owned->set_have_discard_framebuffer(true);
+
auto* gl = gl_owned.get();
auto provider = TestContextProvider::Create(std::move(gl_owned));
@@ -1229,7 +1245,7 @@ TEST_F(GLRendererTest, NoDiscardOnPartialUpdates) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1429,7 +1445,7 @@ TEST_F(GLRendererTest, NoResourceLeak) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1457,10 +1473,6 @@ TEST_F(GLRendererTest, NoResourceLeak) {
class DrawElementsGLES2Interface : public TestGLES2Interface {
public:
- void InitializeTestContext(TestWebGraphicsContext3D* context) override {
- context->set_have_post_sub_buffer(true);
- }
-
MOCK_METHOD4(
DrawElements,
void(GLenum mode, GLsizei count, GLenum type, const void* indices));
@@ -1470,6 +1482,7 @@ class GLRendererSkipTest : public GLRendererTest {
protected:
GLRendererSkipTest() {
auto gl_owned = std::make_unique<StrictMock<DrawElementsGLES2Interface>>();
+ gl_owned->set_have_post_sub_buffer(true);
gl_ = gl_owned.get();
auto provider = TestContextProvider::Create(std::move(gl_owned));
@@ -1494,7 +1507,7 @@ class GLRendererSkipTest : public GLRendererTest {
cc::FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
};
@@ -1567,7 +1580,7 @@ TEST_F(GLRendererTest, DrawFramePreservesFramebuffer) {
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager =
std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), shared_bitmap_manager.get());
@@ -1611,15 +1624,16 @@ TEST_F(GLRendererShaderTest, DrawRenderPassQuadShaderPermutations) {
int root_pass_id = 1;
RenderPass* root_pass;
- ResourceId mask = child_resource_provider_->CreateGpuTextureResource(
- gfx::Size(20, 12), ResourceTextureHint::kDefault,
- child_resource_provider_->best_texture_format(), gfx::ColorSpace());
- child_resource_provider_->AllocateForTesting(mask);
+ auto transfer_resource = TransferableResource::MakeGL(
+ gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken());
+ ResourceId mask = child_resource_provider_->ImportResource(
+ transfer_resource, SingleReleaseCallback::Create(base::DoNothing()));
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({mask}, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(),
+ child_context_provider_.get());
ResourceId mapped_mask = resource_map[mask];
SkScalar matrix[20];
@@ -1867,28 +1881,34 @@ TEST_F(GLRendererShaderTest, DrawSolidColorShader) {
TestSolidColorProgramAA();
}
-class OutputSurfaceMockContext : public TestWebGraphicsContext3D {
+class OutputSurfaceMockGLES2Interface : public TestGLES2Interface {
public:
- OutputSurfaceMockContext() { test_capabilities_.post_sub_buffer = true; }
+ OutputSurfaceMockGLES2Interface() = default;
// Specifically override methods even if they are unused (used in conjunction
// with StrictMock). We need to make sure that GLRenderer does not issue
// framebuffer-related GLuint calls directly. Instead these are supposed to go
// through the OutputSurface abstraction.
- MOCK_METHOD2(bindFramebuffer, void(GLenum target, GLuint framebuffer));
- MOCK_METHOD3(reshapeWithScaleFactor,
- void(int width, int height, float scale_factor));
- MOCK_METHOD4(drawElements,
- void(GLenum mode, GLsizei count, GLenum type, GLintptr offset));
+ MOCK_METHOD2(BindFramebuffer, void(GLenum target, GLuint framebuffer));
+ MOCK_METHOD5(ResizeCHROMIUM,
+ void(GLuint width,
+ GLuint height,
+ float device_scale,
+ GLenum color_space,
+ GLboolean has_alpha));
+ MOCK_METHOD4(
+ DrawElements,
+ void(GLenum mode, GLsizei count, GLenum type, const void* indices));
};
class MockOutputSurface : public OutputSurface {
public:
explicit MockOutputSurface(scoped_refptr<ContextProvider> provider)
: OutputSurface(std::move(provider)) {}
- virtual ~MockOutputSurface() {}
+ ~MockOutputSurface() override {}
void BindToClient(OutputSurfaceClient*) override {}
+ unsigned UpdateGpuFence() override { return 0; }
MOCK_METHOD0(EnsureBackbuffer, void());
MOCK_METHOD0(DiscardBackbuffer, void());
@@ -1908,7 +1928,6 @@ class MockOutputSurface : public OutputSurface {
MOCK_CONST_METHOD0(IsDisplayedAsOverlayPlane, bool());
MOCK_CONST_METHOD0(GetOverlayTextureId, unsigned());
MOCK_CONST_METHOD0(GetOverlayBufferFormat, gfx::BufferFormat());
- MOCK_CONST_METHOD0(SurfaceIsSuspendForRecycle, bool());
MOCK_CONST_METHOD0(HasExternalStencilTest, bool());
MOCK_METHOD0(ApplyExternalStencil, void());
};
@@ -1916,9 +1935,10 @@ class MockOutputSurface : public OutputSurface {
class MockOutputSurfaceTest : public GLRendererTest {
protected:
void SetUp() override {
- auto context = std::make_unique<StrictMock<OutputSurfaceMockContext>>();
- context_ = context.get();
- auto provider = TestContextProvider::Create(std::move(context));
+ auto gl = std::make_unique<StrictMock<OutputSurfaceMockGLES2Interface>>();
+ gl->set_have_post_sub_buffer(true);
+ gl_ = gl.get();
+ auto provider = TestContextProvider::Create(std::move(gl));
provider->BindToCurrentThread();
output_surface_ =
std::make_unique<StrictMock<MockOutputSurface>>(std::move(provider));
@@ -1941,7 +1961,9 @@ class MockOutputSurfaceTest : public GLRendererTest {
Mock::VerifyAndClearExpectations(output_surface_.get());
}
- void SwapBuffers() { renderer_->SwapBuffers(std::vector<ui::LatencyInfo>()); }
+ void SwapBuffers() {
+ renderer_->SwapBuffers(std::vector<ui::LatencyInfo>(), false);
+ }
void DrawFrame(float device_scale_factor,
const gfx::Size& viewport_size,
@@ -1961,7 +1983,7 @@ class MockOutputSurfaceTest : public GLRendererTest {
EXPECT_CALL(*output_surface_, BindFramebuffer()).Times(1);
- EXPECT_CALL(*context_, drawElements(_, _, _, _)).Times(1);
+ EXPECT_CALL(*gl_, DrawElements(_, _, _, _)).Times(1);
renderer_->DecideRenderPassAllocationsForFrame(
render_passes_in_draw_order_);
@@ -1971,10 +1993,10 @@ class MockOutputSurfaceTest : public GLRendererTest {
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
- OutputSurfaceMockContext* context_ = nullptr;
+ OutputSurfaceMockGLES2Interface* gl_ = nullptr;
std::unique_ptr<StrictMock<MockOutputSurface>> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<FakeRendererGL> renderer_;
};
@@ -1999,9 +2021,9 @@ class TestOverlayProcessor : public OverlayProcessor {
MOCK_METHOD5(Attempt,
bool(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidates,
+ OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds));
};
@@ -2019,7 +2041,7 @@ class TestOverlayProcessor : public OverlayProcessor {
// to be traditionally composited. Candidates with |overlay_handled| set to
// true must also have their |display_rect| converted to integer
// coordinates if necessary.
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
};
explicit TestOverlayProcessor(OutputSurface* surface)
@@ -2056,7 +2078,7 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_context_provider.get(), shared_bitmap_manager.get());
+ child_context_provider.get());
auto transfer_resource = TransferableResource::MakeGLOverlay(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
@@ -2071,14 +2093,15 @@ TEST_F(GLRendererTest, DontOverlayWithCopyRequests) {
base::Bind(&CollectResources, &returned_to_child));
// Transfer resource to the parent.
- cc::ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ std::vector<ResourceId> resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource_id);
std::vector<TransferableResource> list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
+ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list,
+ child_context_provider.get());
parent_resource_provider->ReceiveFromChild(child_id, list);
// In DisplayResourceProvider's namespace, use the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
parent_resource_provider->GetChildToParentMap(child_id);
ResourceId parent_resource_id = resource_map[list[0].id];
@@ -2188,9 +2211,9 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
bool AllowCALayerOverlays() override { return false; }
bool AllowDCLayerOverlays() override { return false; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
ASSERT_EQ(1U, surfaces->size());
- cc::OverlayCandidate& candidate = surfaces->back();
+ OverlayCandidate& candidate = surfaces->back();
candidate.overlay_handled = true;
}
};
@@ -2206,27 +2229,28 @@ class SingleOverlayOnTopProcessor : public OverlayProcessor {
SingleOverlayValidator validator_;
};
-class WaitSyncTokenCountingContext : public TestWebGraphicsContext3D {
+class WaitSyncTokenCountingGLES2Interface : public TestGLES2Interface {
public:
- MOCK_METHOD1(waitSyncToken, void(const GLbyte* sync_token));
+ MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte* sync_token));
};
class MockOverlayScheduler {
public:
- MOCK_METHOD5(Schedule,
+ MOCK_METHOD7(Schedule,
void(int plane_z_order,
gfx::OverlayTransform plane_transform,
unsigned overlay_texture_id,
const gfx::Rect& display_bounds,
- const gfx::RectF& uv_rect));
+ const gfx::RectF& uv_rect,
+ bool enable_blend,
+ unsigned gpu_fence_id));
};
TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
- std::unique_ptr<WaitSyncTokenCountingContext> context_owned(
- new WaitSyncTokenCountingContext);
- WaitSyncTokenCountingContext* context = context_owned.get();
+ auto gl_owned = std::make_unique<WaitSyncTokenCountingGLES2Interface>();
+ WaitSyncTokenCountingGLES2Interface* gl = gl_owned.get();
- auto provider = TestContextProvider::Create(std::move(context_owned));
+ auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
MockOverlayScheduler overlay_scheduler;
@@ -2248,7 +2272,7 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_context_provider.get(), shared_bitmap_manager.get());
+ child_context_provider.get());
gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
gpu::CommandBufferId::FromUnsafeValue(0x123), 29);
@@ -2265,14 +2289,15 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
base::Bind(&CollectResources, &returned_to_child));
// Transfer resource to the parent.
- cc::ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ std::vector<ResourceId> resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource_id);
std::vector<TransferableResource> list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
+ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list,
+ child_context_provider.get());
parent_resource_provider->ReceiveFromChild(child_id, list);
// In DisplayResourceProvider's namespace, use the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
parent_resource_provider->GetChildToParentMap(child_id);
ResourceId parent_resource_id = resource_map[list[0].id];
@@ -2321,12 +2346,13 @@ TEST_F(GLRendererTest, OverlaySyncTokensAreProcessed) {
// Verify that overlay_quad actually gets turned into an overlay, and even
// though it's not drawn, that its sync point is waited on.
- EXPECT_CALL(*context, waitSyncToken(MatchesSyncToken(sync_token))).Times(1);
+ EXPECT_CALL(*gl, WaitSyncTokenCHROMIUM(MatchesSyncToken(sync_token)))
+ .Times(1);
EXPECT_CALL(
overlay_scheduler,
Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, gfx::Rect(viewport_size),
- BoundingRect(uv_top_left, uv_bottom_right)))
+ BoundingRect(uv_top_left, uv_bottom_right), _, _))
.Times(1);
DrawFrame(&renderer, viewport_size);
@@ -2358,7 +2384,7 @@ TEST_F(GLRendererTest, OutputColorMatrixTest) {
FakeOutputSurface::Create3d(std::move(provider)));
cc::FakeOutputSurfaceClient output_surface_client;
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
RendererSettings settings;
@@ -2434,16 +2460,17 @@ class GenerateMipmapMockGLESInterface : public TestGLES2Interface {
TEST_F(GLRendererTest, GenerateMipmap) {
// Initialize the mock GL interface, the output surface and the renderer.
auto gl_owned = std::make_unique<GenerateMipmapMockGLESInterface>();
+ gl_owned->set_support_texture_npot(true);
+
auto* gl = gl_owned.get();
auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
- provider->TestContext3d()->set_support_texture_npot(true);
std::unique_ptr<FakeOutputSurface> output_surface(
FakeOutputSurface::Create3d(std::move(provider)));
cc::FakeOutputSurfaceClient output_surface_client;
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
RendererSettings settings;
@@ -2480,28 +2507,21 @@ TEST_F(GLRendererTest, GenerateMipmap) {
class PartialSwapMockGLES2Interface : public TestGLES2Interface {
public:
- explicit PartialSwapMockGLES2Interface(bool support_dc_layers)
- : support_dc_layers_(support_dc_layers) {}
-
- void InitializeTestContext(TestWebGraphicsContext3D* context) override {
- context->set_have_post_sub_buffer(true);
- context->set_enable_dc_layers(support_dc_layers_);
- }
+ PartialSwapMockGLES2Interface() = default;
MOCK_METHOD1(Enable, void(GLenum cap));
MOCK_METHOD1(Disable, void(GLenum cap));
MOCK_METHOD4(Scissor, void(GLint x, GLint y, GLsizei width, GLsizei height));
MOCK_METHOD1(SetEnableDCLayersCHROMIUM, void(GLboolean enable));
-
- private:
- bool support_dc_layers_;
};
class GLRendererPartialSwapTest : public GLRendererTest {
protected:
void RunTest(bool partial_swap, bool set_draw_rectangle) {
- auto gl_owned =
- std::make_unique<PartialSwapMockGLES2Interface>(set_draw_rectangle);
+ auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>();
+ gl_owned->set_have_post_sub_buffer(true);
+ gl_owned->set_enable_dc_layers(set_draw_rectangle);
+
auto* gl = gl_owned.get();
auto provider = TestContextProvider::Create(std::move(gl_owned));
@@ -2512,7 +2532,7 @@ class GLRendererPartialSwapTest : public GLRendererTest {
FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
@@ -2606,7 +2626,7 @@ class DCLayerValidator : public OverlayCandidateValidator {
void GetStrategies(OverlayProcessor::StrategyList* strategies) override {}
bool AllowCALayerOverlays() override { return false; }
bool AllowDCLayerOverlays() override { return true; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
};
// Test that SetEnableDCLayersCHROMIUM is properly called when enabling
@@ -2614,7 +2634,9 @@ class DCLayerValidator : public OverlayCandidateValidator {
TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kDirectCompositionUnderlays);
- auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>(true);
+ auto gl_owned = std::make_unique<PartialSwapMockGLES2Interface>();
+ gl_owned->set_have_post_sub_buffer(true);
+ gl_owned->set_enable_dc_layers(true);
auto* gl = gl_owned.get();
auto provider = TestContextProvider::Create(std::move(gl_owned));
@@ -2633,7 +2655,7 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
child_context_provider->BindToCurrentThread();
auto child_resource_provider =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_context_provider.get(), nullptr);
+ child_context_provider.get());
auto transfer_resource = TransferableResource::MakeGLOverlay(
gpu::Mailbox::Generate(), GL_LINEAR, GL_TEXTURE_2D, gpu::SyncToken(),
@@ -2648,13 +2670,14 @@ TEST_F(GLRendererTest, DCLayerOverlaySwitch) {
base::Bind(&CollectResources, &returned_to_child));
// Transfer resource to the parent.
- cc::ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ std::vector<ResourceId> resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource_id);
std::vector<TransferableResource> list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
+ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list,
+ child_context_provider.get());
parent_resource_provider->ReceiveFromChild(child_id, list);
// In DisplayResourceProvider's namespace, use the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
parent_resource_provider->GetChildToParentMap(child_id);
ResourceId parent_resource_id = resource_map[list[0].id];
@@ -2740,8 +2763,8 @@ class GLRendererWithMockContextTest : public ::testing::Test {
void SetUp() override {
auto context_support = std::make_unique<MockContextSupport>();
context_support_ptr_ = context_support.get();
- auto context_provider = TestContextProvider::Create(
- TestWebGraphicsContext3D::Create(), std::move(context_support));
+ auto context_provider =
+ TestContextProvider::Create(std::move(context_support));
ASSERT_EQ(context_provider->BindToCurrentThread(),
gpu::ContextResult::kSuccess);
output_surface_ = FakeOutputSurface::Create3d(std::move(context_provider));
@@ -2758,7 +2781,7 @@ class GLRendererWithMockContextTest : public ::testing::Test {
cc::FakeOutputSurfaceClient output_surface_client_;
MockContextSupport* context_support_ptr_;
std::unique_ptr<OutputSurface> output_surface_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<GLRenderer> renderer_;
};
@@ -2773,13 +2796,6 @@ TEST_F(GLRendererWithMockContextTest,
Mock::VerifyAndClearExpectations(context_support_ptr_);
}
-class SwapWithBoundsMockGLES2Interface : public TestGLES2Interface {
- public:
- void InitializeTestContext(TestWebGraphicsContext3D* context) override {
- context->set_have_swap_buffers_with_bounds(true);
- }
-};
-
class ContentBoundsOverlayProcessor : public OverlayProcessor {
public:
class Strategy : public OverlayProcessor::Strategy {
@@ -2789,9 +2805,9 @@ class ContentBoundsOverlayProcessor : public OverlayProcessor {
~Strategy() override = default;
bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidates,
+ OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds) override {
content_bounds->insert(content_bounds->end(), content_bounds_.begin(),
content_bounds_.end());
@@ -2820,7 +2836,8 @@ class ContentBoundsOverlayProcessor : public OverlayProcessor {
class GLRendererSwapWithBoundsTest : public GLRendererTest {
protected:
void RunTest(const std::vector<gfx::Rect>& content_bounds) {
- auto gl_owned = std::make_unique<SwapWithBoundsMockGLES2Interface>();
+ auto gl_owned = std::make_unique<TestGLES2Interface>();
+ gl_owned->set_have_swap_buffers_with_bounds(true);
auto provider = TestContextProvider::Create(std::move(gl_owned));
provider->BindToCurrentThread();
@@ -2830,7 +2847,7 @@ class GLRendererSwapWithBoundsTest : public GLRendererTest {
FakeOutputSurface::Create3d(std::move(provider)));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
@@ -2857,7 +2874,7 @@ class GLRendererSwapWithBoundsTest : public GLRendererTest {
renderer.DecideRenderPassAllocationsForFrame(
render_passes_in_draw_order_);
DrawFrame(&renderer, viewport_size);
- renderer.SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer.SwapBuffers(std::vector<ui::LatencyInfo>(), false);
std::vector<gfx::Rect> expected_content_bounds;
EXPECT_EQ(content_bounds,
@@ -2883,7 +2900,7 @@ class CALayerValidator : public OverlayCandidateValidator {
void GetStrategies(OverlayProcessor::StrategyList* strategies) override {}
bool AllowCALayerOverlays() override { return true; }
bool AllowDCLayerOverlays() override { return false; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
};
class MockCALayerGLES2Interface : public TestGLES2Interface {
@@ -2903,16 +2920,6 @@ class MockCALayerGLES2Interface : public TestGLES2Interface {
GLuint filter));
MOCK_METHOD2(ScheduleCALayerInUseQueryCHROMIUM,
void(GLsizei count, const GLuint* textures));
-
- void InitializeTestContext(TestWebGraphicsContext3D* context) override {
- // Support image storage for GpuMemoryBuffers, needed for
- // CALayers/IOSurfaces backed by textures.
- context->set_support_texture_storage_image(true);
-
- // Allow the renderer to make an empty SwapBuffers - skipping even the
- // root RenderPass.
- context->set_have_commit_overlay_planes(true);
- }
};
class CALayerGLRendererTest : public GLRendererTest {
@@ -2920,6 +2927,13 @@ class CALayerGLRendererTest : public GLRendererTest {
void SetUp() override {
// A mock GLES2Interface that can watch CALayer stuff happen.
auto gles2_interface = std::make_unique<MockCALayerGLES2Interface>();
+ // Support image storage for GpuMemoryBuffers, needed for
+ // CALayers/IOSurfaces backed by textures.
+ gles2_interface->set_support_texture_storage_image(true);
+ // Allow the renderer to make an empty SwapBuffers - skipping even the
+ // root RenderPass.
+ gles2_interface->set_have_commit_overlay_planes(true);
+
gl_ = gles2_interface.get();
auto provider = TestContextProvider::Create(std::move(gles2_interface));
@@ -2967,7 +2981,7 @@ class CALayerGLRendererTest : public GLRendererTest {
MockCALayerGLES2Interface* gl_;
CALayerValidator validator_;
std::unique_ptr<FakeOutputSurface> output_surface_;
- std::unique_ptr<cc::DisplayResourceProvider> display_resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> display_resource_provider_;
std::unique_ptr<RendererSettings> settings_;
std::unique_ptr<FakeRendererGL> renderer_;
};
@@ -3011,7 +3025,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysWithAllQuadsPromoted) {
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// The damage was eliminated when everything was promoted to CALayers.
ASSERT_TRUE(output_surface().last_sent_frame()->sub_buffer_rect);
@@ -3049,7 +3063,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysWithAllQuadsPromoted) {
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
@@ -3098,7 +3112,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// ScheduleCALayerCHROMIUM happened and used a non-0 texture.
EXPECT_NE(saved_texture_id, 0u);
@@ -3151,7 +3165,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// There are now 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
@@ -3201,7 +3215,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReusesTextureWithDifferentSizes) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
@@ -3250,7 +3264,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// ScheduleCALayerCHROMIUM happened and used a non-0 texture.
EXPECT_NE(saved_texture_id, 0u);
@@ -3301,7 +3315,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// There are now 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
@@ -3349,7 +3363,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysDontReuseTooBigTexture) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseAfterNoSwapBuffers) {
@@ -3435,7 +3449,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseAfterNoSwapBuffers) {
Mock::VerifyAndClearExpectations(&gl());
// SwapBuffers() *does* happen this time.
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// There are 2 textures to check if they are free.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(2, _));
@@ -3480,7 +3494,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseAfterNoSwapBuffers) {
}
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
@@ -3524,7 +3538,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
}));
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// ScheduleCALayerCHROMIUM happened and used a non-0 texture.
EXPECT_NE(sent_texture_ids[i], 0u);
@@ -3598,7 +3612,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysReuseManyIfReturnedSlowly) {
}));
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// All sent textures will be checked to verify if they are free yet. There's
// also 1 outstanding texture to check for that wasn't returned yet from the
@@ -3649,7 +3663,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
}));
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// ScheduleCALayerCHROMIUM happened and used a non-0 texture.
EXPECT_NE(sent_texture_ids[i], 0u);
@@ -3689,7 +3703,7 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
EXPECT_CALL(gl(), ScheduleCALayerCHROMIUM(_, _, _, _, _, _));
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
// There's just 1 outstanding RenderPass texture to query for.
EXPECT_CALL(gl(), ScheduleCALayerInUseQueryCHROMIUM(1, _));
@@ -3735,14 +3749,14 @@ TEST_F(CALayerGLRendererTest, CALayerOverlaysCachedTexturesAreFreed) {
}));
DrawFrame(&renderer(), viewport_size);
Mock::VerifyAndClearExpectations(&gl());
- renderer().SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer().SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
class FramebufferWatchingGLRenderer : public FakeRendererGL {
public:
FramebufferWatchingGLRenderer(RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+ DisplayResourceProvider* resource_provider)
: FakeRendererGL(settings, output_surface, resource_provider) {}
void BindFramebufferToOutputSurface() override {
@@ -3780,7 +3794,7 @@ TEST_F(GLRendererTest, UndamagedRenderPassStillDrawnWhenNoPartialSwap) {
auto output_surface = FakeOutputSurface::Create3d(std::move(provider));
output_surface->BindToClient(&output_surface_client);
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
output_surface->context_provider(), nullptr);
diff --git a/chromium/components/viz/service/display/output_surface.cc b/chromium/components/viz/service/display/output_surface.cc
index 87cdf3118b7..f563afc1deb 100644
--- a/chromium/components/viz/service/display/output_surface.cc
+++ b/chromium/components/viz/service/display/output_surface.cc
@@ -16,6 +16,7 @@
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/vulkan/buildflags.h"
#include "ui/gfx/swap_result.h"
namespace viz {
@@ -31,72 +32,35 @@ OutputSurface::OutputSurface(
DCHECK(software_device_);
}
+#if BUILDFLAG(ENABLE_VULKAN)
OutputSurface::OutputSurface(
scoped_refptr<VulkanContextProvider> vulkan_context_provider)
: vulkan_context_provider_(std::move(vulkan_context_provider)) {
DCHECK(vulkan_context_provider_);
}
+#endif
OutputSurface::~OutputSurface() = default;
-OutputSurface::LatencyInfoCache::SwapInfo::SwapInfo(
- uint64_t id,
- std::vector<ui::LatencyInfo> info)
- : swap_id(id), latency_info(std::move(info)) {}
-
-OutputSurface::LatencyInfoCache::SwapInfo::SwapInfo(SwapInfo&& src) = default;
-
-OutputSurface::LatencyInfoCache::SwapInfo&
-OutputSurface::LatencyInfoCache::SwapInfo::operator=(SwapInfo&& src) = default;
-
-OutputSurface::LatencyInfoCache::SwapInfo::~SwapInfo() = default;
-
-OutputSurface::LatencyInfoCache::LatencyInfoCache(Client* client)
- : client_(client) {
- DCHECK(client);
-}
-
-OutputSurface::LatencyInfoCache::~LatencyInfoCache() = default;
-
-bool OutputSurface::LatencyInfoCache::WillSwap(
- std::vector<ui::LatencyInfo> latency_info) {
- bool snapshot_requested = false;
- for (const auto& latency : latency_info) {
- if (latency.FindLatency(ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT,
- nullptr)) {
- snapshot_requested = true;
- break;
- }
- }
-
- // Don't grow unbounded in case of error.
- while (swap_infos_.size() >= kCacheCountMax) {
- client_->LatencyInfoCompleted(swap_infos_.front().latency_info);
- swap_infos_.pop_front();
+void OutputSurface::UpdateLatencyInfoOnSwap(
+ const gfx::SwapResponse& response,
+ std::vector<ui::LatencyInfo>* latency_info) {
+ for (auto& latency : *latency_info) {
+ latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, response.swap_start, 1);
+ latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
+ response.swap_end, 1);
}
- swap_infos_.emplace_back(swap_id_++, std::move(latency_info));
-
- return snapshot_requested;
}
-void OutputSurface::LatencyInfoCache::OnSwapBuffersCompleted(
- const gfx::SwapResponse& response) {
- auto it = std::find_if(
- swap_infos_.begin(), swap_infos_.end(),
- [&](const SwapInfo& si) { return si.swap_id == response.swap_id; });
-
- if (it != swap_infos_.end()) {
- for (auto& latency : it->latency_info) {
- latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, response.swap_start,
- 1);
- latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- response.swap_end, 1);
- }
- client_->LatencyInfoCompleted(it->latency_info);
- swap_infos_.erase(it);
+bool OutputSurface::LatencyInfoHasSnapshotRequest(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ for (const auto& latency : latency_info) {
+ if (latency.Snapshots().size())
+ return true;
}
+ return false;
}
} // namespace viz
diff --git a/chromium/components/viz/service/display/output_surface.h b/chromium/components/viz/service/display/output_surface.h
index 26d0e6394c2..9eaef93529a 100644
--- a/chromium/components/viz/service/display/output_surface.h
+++ b/chromium/components/viz/service/display/output_surface.h
@@ -12,17 +12,20 @@
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/service/display/overlay_candidate_validator.h"
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
#include "gpu/vulkan/buildflags.h"
-#include "gpu/vulkan/vulkan_surface.h"
#include "ui/gfx/color_space.h"
#include "ui/latency/latency_info.h"
+#if BUILDFLAG(ENABLE_VULKAN)
+#include "components/viz/common/gpu/vulkan_context_provider.h"
+#include "gpu/vulkan/vulkan_surface.h"
+#endif
+
namespace gfx {
class ColorSpace;
class Size;
@@ -57,9 +60,11 @@ class VIZ_SERVICE_EXPORT OutputSurface {
explicit OutputSurface(scoped_refptr<ContextProvider> context_provider);
// Constructor for software compositing.
explicit OutputSurface(std::unique_ptr<SoftwareOutputDevice> software_device);
+#if BUILDFLAG(ENABLE_VULKAN)
// Constructor for Vulkan-based compositing.
explicit OutputSurface(
scoped_refptr<VulkanContextProvider> vulkan_context_provider);
+#endif
virtual ~OutputSurface();
@@ -70,9 +75,11 @@ class VIZ_SERVICE_EXPORT OutputSurface {
// In the event of a lost context, the entire output surface should be
// recreated.
ContextProvider* context_provider() const { return context_provider_.get(); }
+#if BUILDFLAG(ENABLE_VULKAN)
VulkanContextProvider* vulkan_context_provider() const {
return vulkan_context_provider_.get();
}
+#endif
SoftwareOutputDevice* software_device() const {
return software_device_.get();
}
@@ -108,9 +115,6 @@ class VIZ_SERVICE_EXPORT OutputSurface {
// Get the format for the main image's overlay.
virtual gfx::BufferFormat GetOverlayBufferFormat() const = 0;
- // If this returns true, then the surface will not attempt to draw.
- virtual bool SurfaceIsSuspendForRecycle() const = 0;
-
virtual void Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
@@ -134,54 +138,30 @@ class VIZ_SERVICE_EXPORT OutputSurface {
virtual gpu::VulkanSurface* GetVulkanSurface() = 0;
#endif
- // A helper class for implementations of OutputSurface that want to cache
- // LatencyInfos that can be updated when we get the corresponding
- // gfx::SwapResponse.
- class VIZ_SERVICE_EXPORT LatencyInfoCache {
- public:
- class Client {
- public:
- virtual ~Client() = default;
- virtual void LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) = 0;
- };
-
- explicit LatencyInfoCache(Client* client);
- ~LatencyInfoCache();
-
- // Returns true if there's a snapshot request.
- bool WillSwap(std::vector<ui::LatencyInfo> latency_info);
- void OnSwapBuffersCompleted(const gfx::SwapResponse& response);
-
- private:
- struct SwapInfo {
- SwapInfo(uint64_t id, std::vector<ui::LatencyInfo> info);
- SwapInfo(SwapInfo&& src);
- SwapInfo& operator=(SwapInfo&& src);
- ~SwapInfo();
- uint64_t swap_id;
- std::vector<ui::LatencyInfo> latency_info;
- DISALLOW_COPY_AND_ASSIGN(SwapInfo);
- };
-
- Client* client_ = nullptr;
-
- // Incremented in sync with the ImageTransportSurface's swap_id_.
- uint64_t swap_id_ = 0;
- base::circular_deque<SwapInfo> swap_infos_;
-
- // We only expect a couple swap acks outstanding, but there are cases where
- // we will get timestamps for swaps from several frames ago when using
- // platform extensions like eglGetFrameTimestampsANDROID.
- static constexpr size_t kCacheCountMax = 10;
-
- DISALLOW_COPY_AND_ASSIGN(LatencyInfoCache);
- };
+ // Updates the GpuFence associated with this surface. The id of a newly
+ // created GpuFence is returned, or if an error occurs, or fences are not
+ // supported, the special id of 0 (meaning "no fence") is returned. In all
+ // cases, any previously associated fence is destroyed. The returned fence id
+ // corresponds to the GL id used by the CHROMIUM_gpu_fence GL extension and
+ // can be passed directly to any related extension functions.
+ virtual unsigned UpdateGpuFence() = 0;
+
+ // Returns true if any of the LatencyInfos provided contains a snapshot
+ // request.
+ static bool LatencyInfoHasSnapshotRequest(
+ const std::vector<ui::LatencyInfo>& latency_info);
+
+ // Updates timing info on the provided LatencyInfo when swap completes.
+ static void UpdateLatencyInfoOnSwap(
+ const gfx::SwapResponse& response,
+ std::vector<ui::LatencyInfo>* latency_info);
protected:
struct OutputSurface::Capabilities capabilities_;
scoped_refptr<ContextProvider> context_provider_;
+#if BUILDFLAG(ENABLE_VULKAN)
scoped_refptr<VulkanContextProvider> vulkan_context_provider_;
+#endif
std::unique_ptr<SoftwareOutputDevice> software_device_;
private:
diff --git a/chromium/components/viz/service/display/output_surface_client.h b/chromium/components/viz/service/display/output_surface_client.h
index 58c086544c7..e802952c92d 100644
--- a/chromium/components/viz/service/display/output_surface_client.h
+++ b/chromium/components/viz/service/display/output_surface_client.h
@@ -13,6 +13,7 @@
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/texture_in_use_response.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/latency/latency_info.h"
namespace gfx {
struct CALayerParams;
@@ -25,7 +26,7 @@ class VIZ_SERVICE_EXPORT OutputSurfaceClient {
public:
// A notification that the swap of the backbuffer to the hardware is complete
// and is now visible to the user.
- virtual void DidReceiveSwapBuffersAck(uint64_t swap_id) = 0;
+ virtual void DidReceiveSwapBuffersAck() = 0;
// For surfaceless/ozone implementations to create damage for the next frame.
virtual void SetNeedsRedrawRect(const gfx::Rect& damage_rect) = 0;
@@ -38,12 +39,14 @@ class VIZ_SERVICE_EXPORT OutputSurfaceClient {
virtual void DidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) = 0;
- // A notification that the presentation feedback for a CompositorFrame with
- // given |swap_id|. See |gfx::PresentationFeedback| for detail.
+ // See |gfx::PresentationFeedback| for detail.
virtual void DidReceivePresentationFeedback(
- uint64_t swap_id,
const gfx::PresentationFeedback& feedback) {}
+ // Call after a swap occurs with all LatencyInfo aggregated up to that point.
+ virtual void DidFinishLatencyInfo(
+ const std::vector<ui::LatencyInfo>& latency_info) = 0;
+
protected:
virtual ~OutputSurfaceClient() {}
};
diff --git a/chromium/components/viz/service/display/output_surface_frame.h b/chromium/components/viz/service/display/output_surface_frame.h
index 6a09dfa06da..b3f20cedc66 100644
--- a/chromium/components/viz/service/display/output_surface_frame.h
+++ b/chromium/components/viz/service/display/output_surface_frame.h
@@ -34,6 +34,7 @@ class VIZ_SERVICE_EXPORT OutputSurfaceFrame {
// Optional content area for SwapWithBounds. Rectangles may overlap.
std::vector<gfx::Rect> content_bounds;
std::vector<ui::LatencyInfo> latency_info;
+ bool need_presentation_feedback = false;
private:
DISALLOW_COPY_AND_ASSIGN(OutputSurfaceFrame);
diff --git a/chromium/components/viz/service/display/overlay_candidate.cc b/chromium/components/viz/service/display/overlay_candidate.cc
new file mode 100644
index 00000000000..2cac5568008
--- /dev/null
+++ b/chromium/components/viz/service/display/overlay_candidate.cc
@@ -0,0 +1,397 @@
+// Copyright 2014 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 "components/viz/service/display/overlay_candidate.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "cc/base/math_util.h"
+#include "components/viz/common/quads/solid_color_draw_quad.h"
+#include "components/viz/common/quads/stream_video_draw_quad.h"
+#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/service/display/display_resource_provider.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/vector3d_f.h"
+
+namespace viz {
+
+namespace {
+// Tolerance for considering axis vector elements to be zero.
+const SkMScalar kEpsilon = std::numeric_limits<float>::epsilon();
+
+const gfx::BufferFormat kOverlayFormats[] = {
+ gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::RGBA_8888,
+ gfx::BufferFormat::BGRX_8888, gfx::BufferFormat::BGRA_8888,
+ gfx::BufferFormat::BGR_565, gfx::BufferFormat::YUV_420_BIPLANAR};
+
+enum Axis { NONE, AXIS_POS_X, AXIS_NEG_X, AXIS_POS_Y, AXIS_NEG_Y };
+
+Axis VectorToAxis(const gfx::Vector3dF& vec) {
+ if (std::abs(vec.z()) > kEpsilon)
+ return NONE;
+ const bool x_zero = (std::abs(vec.x()) <= kEpsilon);
+ const bool y_zero = (std::abs(vec.y()) <= kEpsilon);
+ if (x_zero && !y_zero)
+ return (vec.y() > 0) ? AXIS_POS_Y : AXIS_NEG_Y;
+ else if (y_zero && !x_zero)
+ return (vec.x() > 0) ? AXIS_POS_X : AXIS_NEG_X;
+ else
+ return NONE;
+}
+
+gfx::OverlayTransform GetOverlayTransform(const gfx::Transform& quad_transform,
+ bool y_flipped) {
+ if (!quad_transform.Preserves2dAxisAlignment()) {
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+
+ gfx::Vector3dF x_axis = cc::MathUtil::GetXAxis(quad_transform);
+ gfx::Vector3dF y_axis = cc::MathUtil::GetYAxis(quad_transform);
+ if (y_flipped) {
+ y_axis.Scale(-1);
+ }
+
+ Axis x_to = VectorToAxis(x_axis);
+ Axis y_to = VectorToAxis(y_axis);
+
+ if (x_to == AXIS_POS_X && y_to == AXIS_POS_Y)
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ else if (x_to == AXIS_NEG_X && y_to == AXIS_POS_Y)
+ return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+ else if (x_to == AXIS_POS_X && y_to == AXIS_NEG_Y)
+ return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ else if (x_to == AXIS_NEG_Y && y_to == AXIS_POS_X)
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ else if (x_to == AXIS_NEG_X && y_to == AXIS_NEG_Y)
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ else if (x_to == AXIS_POS_Y && y_to == AXIS_NEG_X)
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ else
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+}
+
+// Apply transform |delta| to |in| and return the resulting transform,
+// or OVERLAY_TRANSFORM_INVALID.
+gfx::OverlayTransform ComposeTransforms(gfx::OverlayTransform delta,
+ gfx::OverlayTransform in) {
+ // There are 8 different possible transforms. We can characterize these
+ // by looking at where the origin moves and the direction the horizontal goes.
+ // (TL=top-left, BR=bottom-right, H=horizontal, V=vertical).
+ // NONE: TL, H
+ // FLIP_VERTICAL: BL, H
+ // FLIP_HORIZONTAL: TR, H
+ // ROTATE_90: TR, V
+ // ROTATE_180: BR, H
+ // ROTATE_270: BL, V
+ // Missing transforms: TL, V & BR, V
+ // Basic combinations:
+ // Flip X & Y -> Rotate 180 (TL,H -> TR,H -> BR,H or TL,H -> BL,H -> BR,H)
+ // Flip X or Y + Rotate 180 -> other flip (eg, TL,H -> TR,H -> BL,H)
+ // Rotate + Rotate simply adds values.
+ // Rotate 90/270 + flip is invalid because we can only have verticals with
+ // the origin in TR or BL.
+ if (delta == gfx::OVERLAY_TRANSFORM_NONE)
+ return in;
+ switch (in) {
+ case gfx::OVERLAY_TRANSFORM_NONE:
+ return delta;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
+ return gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
+ return gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_270;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ switch (delta) {
+ case gfx::OVERLAY_TRANSFORM_ROTATE_90:
+ return gfx::OVERLAY_TRANSFORM_NONE;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_180:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_90;
+ case gfx::OVERLAY_TRANSFORM_ROTATE_270:
+ return gfx::OVERLAY_TRANSFORM_ROTATE_180;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+ break;
+ default:
+ return gfx::OVERLAY_TRANSFORM_INVALID;
+ }
+}
+
+} // namespace
+
+OverlayCandidate::OverlayCandidate()
+ : transform(gfx::OVERLAY_TRANSFORM_NONE),
+ format(gfx::BufferFormat::RGBA_8888),
+ uv_rect(0.f, 0.f, 1.f, 1.f),
+ is_clipped(false),
+ is_opaque(false),
+ use_output_surface_for_resource(false),
+ resource_id(0),
+#if defined(OS_ANDROID)
+ is_backed_by_surface_texture(false),
+ is_promotable_hint(false),
+#endif
+ plane_z_order(0),
+ is_unoccluded(false),
+ overlay_handled(false),
+ gpu_fence_id(0) {
+}
+
+OverlayCandidate::OverlayCandidate(const OverlayCandidate& other) = default;
+
+OverlayCandidate::~OverlayCandidate() = default;
+
+// static
+bool OverlayCandidate::FromDrawQuad(DisplayResourceProvider* resource_provider,
+ const SkMatrix44& output_color_matrix,
+ const DrawQuad* quad,
+ OverlayCandidate* candidate) {
+ // It is currently not possible to set a color conversion matrix on an HW
+ // overlay plane.
+ // TODO(https://crbug.com/792757): Remove this check once the bug is resolved.
+ if (!output_color_matrix.isIdentity())
+ return false;
+
+ // We don't support an opacity value different than one for an overlay plane.
+ if (quad->shared_quad_state->opacity != 1.f)
+ return false;
+ // We support only kSrc (no blending) and kSrcOver (blending with premul).
+ if (!(quad->shared_quad_state->blend_mode == SkBlendMode::kSrc ||
+ quad->shared_quad_state->blend_mode == SkBlendMode::kSrcOver))
+ return false;
+
+ switch (quad->material) {
+ case DrawQuad::TEXTURE_CONTENT:
+ return FromTextureQuad(resource_provider,
+ TextureDrawQuad::MaterialCast(quad), candidate);
+ case DrawQuad::TILED_CONTENT:
+ return FromTileQuad(resource_provider, TileDrawQuad::MaterialCast(quad),
+ candidate);
+ case DrawQuad::STREAM_VIDEO_CONTENT:
+ return FromStreamVideoQuad(resource_provider,
+ StreamVideoDrawQuad::MaterialCast(quad),
+ candidate);
+ default:
+ break;
+ }
+
+ return false;
+}
+
+// static
+bool OverlayCandidate::IsInvisibleQuad(const DrawQuad* quad) {
+ float opacity = quad->shared_quad_state->opacity;
+ if (opacity < std::numeric_limits<float>::epsilon())
+ return true;
+ if (quad->material == DrawQuad::SOLID_COLOR) {
+ SkColor color = SolidColorDrawQuad::MaterialCast(quad)->color;
+ float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity;
+ return quad->ShouldDrawWithBlending() &&
+ alpha < std::numeric_limits<float>::epsilon();
+ }
+ return false;
+}
+
+// static
+bool OverlayCandidate::IsOccluded(const OverlayCandidate& candidate,
+ QuadList::ConstIterator quad_list_begin,
+ QuadList::ConstIterator quad_list_end) {
+ // Check that no visible quad overlaps the candidate.
+ for (auto overlap_iter = quad_list_begin; overlap_iter != quad_list_end;
+ ++overlap_iter) {
+ gfx::RectF overlap_rect = cc::MathUtil::MapClippedRect(
+ overlap_iter->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(overlap_iter->rect));
+ if (candidate.display_rect.Intersects(overlap_rect) &&
+ !OverlayCandidate::IsInvisibleQuad(*overlap_iter))
+ return true;
+ }
+ return false;
+}
+
+// static
+bool OverlayCandidate::FromDrawQuadResource(
+ DisplayResourceProvider* resource_provider,
+ const DrawQuad* quad,
+ ResourceId resource_id,
+ bool y_flipped,
+ OverlayCandidate* candidate) {
+ if (!resource_provider->IsOverlayCandidate(resource_id))
+ return false;
+
+ candidate->format = resource_provider->GetBufferFormat(resource_id);
+ if (std::find(std::begin(kOverlayFormats), std::end(kOverlayFormats),
+ candidate->format) == std::end(kOverlayFormats))
+ return false;
+
+ gfx::OverlayTransform overlay_transform = GetOverlayTransform(
+ quad->shared_quad_state->quad_to_target_transform, y_flipped);
+ if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
+ return false;
+
+ auto& transform = quad->shared_quad_state->quad_to_target_transform;
+ candidate->display_rect = gfx::RectF(quad->rect);
+ transform.TransformRect(&candidate->display_rect);
+
+ candidate->clip_rect = quad->shared_quad_state->clip_rect;
+ candidate->is_clipped = quad->shared_quad_state->is_clipped;
+ candidate->is_opaque = !quad->ShouldDrawWithBlending();
+
+ candidate->resource_id = resource_id;
+ candidate->transform = overlay_transform;
+
+ return true;
+}
+
+// static
+bool OverlayCandidate::FromTextureQuad(
+ DisplayResourceProvider* resource_provider,
+ const TextureDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (quad->background_color != SK_ColorTRANSPARENT)
+ return false;
+ if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(),
+ quad->y_flipped, candidate)) {
+ return false;
+ }
+ candidate->resource_size_in_pixels = quad->resource_size_in_pixels();
+ candidate->uv_rect = BoundingRect(quad->uv_top_left, quad->uv_bottom_right);
+ return true;
+}
+
+// static
+bool OverlayCandidate::FromTileQuad(DisplayResourceProvider* resource_provider,
+ const TileDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), false,
+ candidate)) {
+ return false;
+ }
+ candidate->resource_size_in_pixels = quad->texture_size;
+ candidate->uv_rect = quad->tex_coord_rect;
+ return true;
+}
+
+// static
+bool OverlayCandidate::FromStreamVideoQuad(
+ DisplayResourceProvider* resource_provider,
+ const StreamVideoDrawQuad* quad,
+ OverlayCandidate* candidate) {
+ if (!FromDrawQuadResource(resource_provider, quad, quad->resource_id(), false,
+ candidate)) {
+ return false;
+ }
+ if (!quad->matrix.IsScaleOrTranslation()) {
+ // We cannot handle anything other than scaling & translation for texture
+ // coordinates yet.
+ return false;
+ }
+ candidate->resource_id = quad->resource_id();
+ candidate->resource_size_in_pixels = quad->resource_size_in_pixels();
+#if defined(OS_ANDROID)
+ candidate->is_backed_by_surface_texture =
+ resource_provider->IsBackedBySurfaceTexture(quad->resource_id());
+#endif
+
+ gfx::Point3F uv0 = gfx::Point3F(0, 0, 0);
+ gfx::Point3F uv1 = gfx::Point3F(1, 1, 0);
+ quad->matrix.TransformPoint(&uv0);
+ quad->matrix.TransformPoint(&uv1);
+ gfx::Vector3dF delta = uv1 - uv0;
+ if (delta.x() < 0) {
+ candidate->transform = ComposeTransforms(
+ gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL, candidate->transform);
+ float x0 = uv0.x();
+ uv0.set_x(uv1.x());
+ uv1.set_x(x0);
+ delta.set_x(-delta.x());
+ }
+
+ if (delta.y() < 0) {
+ // In this situation, uv0y < uv1y. Since we overlay inverted, a request
+ // to invert the source texture means we can just output the texture
+ // normally and it will be correct.
+ candidate->uv_rect = gfx::RectF(uv0.x(), uv1.y(), delta.x(), -delta.y());
+ } else {
+ candidate->transform = ComposeTransforms(
+ gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL, candidate->transform);
+ candidate->uv_rect = gfx::RectF(uv0.x(), uv0.y(), delta.x(), delta.y());
+ }
+ return true;
+}
+
+OverlayCandidateList::OverlayCandidateList() = default;
+
+OverlayCandidateList::OverlayCandidateList(const OverlayCandidateList& other) =
+ default;
+
+OverlayCandidateList::OverlayCandidateList(OverlayCandidateList&& other) =
+ default;
+
+OverlayCandidateList::~OverlayCandidateList() = default;
+
+OverlayCandidateList& OverlayCandidateList::operator=(
+ const OverlayCandidateList& other) = default;
+
+OverlayCandidateList& OverlayCandidateList::operator=(
+ OverlayCandidateList&& other) = default;
+
+void OverlayCandidateList::AddPromotionHint(const OverlayCandidate& candidate) {
+ promotion_hint_info_map_[candidate.resource_id] = candidate.display_rect;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_candidate.h b/chromium/components/viz/service/display/overlay_candidate.h
new file mode 100644
index 00000000000..27217c69892
--- /dev/null
+++ b/chromium/components/viz/service/display/overlay_candidate.h
@@ -0,0 +1,144 @@
+// Copyright 2014 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 COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_H_
+
+#include <map>
+#include <vector>
+
+#include "build/build_config.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/common/resources/resource_id.h"
+#include "components/viz/service/viz_service_export.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/overlay_transform.h"
+#include "ui/gfx/transform.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace viz {
+class DisplayResourceProvider;
+class StreamVideoDrawQuad;
+class TextureDrawQuad;
+class TileDrawQuad;
+
+class VIZ_SERVICE_EXPORT OverlayCandidate {
+ public:
+ // Returns true and fills in |candidate| if |draw_quad| is of a known quad
+ // type and contains an overlayable resource.
+ static bool FromDrawQuad(DisplayResourceProvider* resource_provider,
+ const SkMatrix44& output_color_matrix,
+ const DrawQuad* quad,
+ OverlayCandidate* candidate);
+ // Returns true if |quad| will not block quads underneath from becoming
+ // an overlay.
+ static bool IsInvisibleQuad(const DrawQuad* quad);
+
+ // Returns true if any any of the quads in the list given by |quad_list_begin|
+ // and |quad_list_end| are visible and on top of |candidate|.
+ static bool IsOccluded(const OverlayCandidate& candidate,
+ QuadList::ConstIterator quad_list_begin,
+ QuadList::ConstIterator quad_list_end);
+
+ OverlayCandidate();
+ OverlayCandidate(const OverlayCandidate& other);
+ ~OverlayCandidate();
+
+ // Transformation to apply to layer during composition.
+ gfx::OverlayTransform transform;
+ // Format of the buffer to scanout.
+ gfx::BufferFormat format;
+ // Size of the resource, in pixels.
+ gfx::Size resource_size_in_pixels;
+ // Rect on the display to position the overlay to. Implementer must convert
+ // to integer coordinates if setting |overlay_handled| to true.
+ gfx::RectF display_rect;
+ // Crop within the buffer to be placed inside |display_rect|.
+ gfx::RectF uv_rect;
+ // Clip rect in the target content space after composition.
+ gfx::Rect clip_rect;
+ // If the quad is clipped after composition.
+ bool is_clipped;
+ // If the quad doesn't require blending.
+ bool is_opaque;
+ // True if the texture for this overlay should be the same one used by the
+ // output surface's main overlay.
+ bool use_output_surface_for_resource;
+ // Texture resource to present in an overlay.
+ unsigned resource_id;
+
+#if defined(OS_ANDROID)
+ // For candidates from StreamVideoDrawQuads, this records whether the quad is
+ // marked as being backed by a SurfaceTexture or not. If so, it's not really
+ // promotable to an overlay.
+ bool is_backed_by_surface_texture;
+
+ // Filled in by the OverlayCandidateValidator to indicate whether this is a
+ // promotable candidate or not.
+ bool is_promotable_hint;
+#endif
+
+ // Stacking order of the overlay plane relative to the main surface,
+ // which is 0. Signed to allow for "underlays".
+ int plane_z_order;
+ // True if the overlay does not have any visible quads on top of it. Set by
+ // the strategy so the OverlayProcessor can consider subtracting damage caused
+ // by underlay quads.
+ bool is_unoccluded;
+
+ // To be modified by the implementer if this candidate can go into
+ // an overlay.
+ bool overlay_handled;
+
+ // Gpu fence to wait for before overlay is ready for display.
+ unsigned gpu_fence_id;
+
+ private:
+ static bool FromDrawQuadResource(DisplayResourceProvider* resource_provider,
+ const DrawQuad* quad,
+ ResourceId resource_id,
+ bool y_flipped,
+ OverlayCandidate* candidate);
+ static bool FromTextureQuad(DisplayResourceProvider* resource_provider,
+ const TextureDrawQuad* quad,
+ OverlayCandidate* candidate);
+ static bool FromTileQuad(DisplayResourceProvider* resource_provider,
+ const TileDrawQuad* quad,
+ OverlayCandidate* candidate);
+ static bool FromStreamVideoQuad(DisplayResourceProvider* resource_provider,
+ const StreamVideoDrawQuad* quad,
+ OverlayCandidate* candidate);
+};
+
+class VIZ_SERVICE_EXPORT OverlayCandidateList
+ : public std::vector<OverlayCandidate> {
+ public:
+ OverlayCandidateList();
+ OverlayCandidateList(const OverlayCandidateList&);
+ OverlayCandidateList(OverlayCandidateList&&);
+ ~OverlayCandidateList();
+
+ OverlayCandidateList& operator=(const OverlayCandidateList&);
+ OverlayCandidateList& operator=(OverlayCandidateList&&);
+
+ // [id] == candidate's |display_rect| for all promotable resources.
+ using PromotionHintInfoMap = std::map<ResourceId, gfx::RectF>;
+
+ // For android, this provides a set of resources that could be promoted to
+ // overlay, if one backs them with a SurfaceView.
+ PromotionHintInfoMap promotion_hint_info_map_;
+
+ // Helper to insert |candidate| into |promotion_hint_info_|.
+ void AddPromotionHint(const OverlayCandidate& candidate);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_OVERLAY_CANDIDATE_H_
diff --git a/chromium/components/viz/service/display/overlay_candidate_validator.h b/chromium/components/viz/service/display/overlay_candidate_validator.h
index d053dbe8a73..8407cb9a36e 100644
--- a/chromium/components/viz/service/display/overlay_candidate_validator.h
+++ b/chromium/components/viz/service/display/overlay_candidate_validator.h
@@ -7,7 +7,7 @@
#include <vector>
-#include "cc/output/overlay_candidate.h"
+#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/display/overlay_processor.h"
#include "components/viz/service/viz_service_export.h"
@@ -33,7 +33,7 @@ class VIZ_SERVICE_EXPORT OverlayCandidateValidator {
// to be traditionally composited. Candidates with |overlay_handled| set to
// true must also have their |display_rect| converted to integer
// coordinates if necessary.
- virtual void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) = 0;
+ virtual void CheckOverlaySupport(OverlayCandidateList* surfaces) = 0;
virtual ~OverlayCandidateValidator() {}
};
diff --git a/chromium/components/viz/service/display/overlay_processor.cc b/chromium/components/viz/service/display/overlay_processor.cc
index 002e0535d9e..f43a211444a 100644
--- a/chromium/components/viz/service/display/overlay_processor.cc
+++ b/chromium/components/viz/service/display/overlay_processor.cc
@@ -4,16 +4,19 @@
#include "components/viz/service/display/overlay_processor.h"
+#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "cc/resources/display_resource_provider.h"
#include "components/viz/service/display/dc_layer_overlay.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/overlay_strategy_single_on_top.h"
#include "components/viz/service/display/overlay_strategy_underlay.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/transform.h"
+namespace viz {
+
namespace {
#if defined(OS_ANDROID)
@@ -21,9 +24,8 @@ namespace {
// before returning from ProcessForOverlays.
class SendPromotionHintsBeforeReturning {
public:
- SendPromotionHintsBeforeReturning(
- cc::DisplayResourceProvider* resource_provider,
- cc::OverlayCandidateList* candidates)
+ SendPromotionHintsBeforeReturning(DisplayResourceProvider* resource_provider,
+ OverlayCandidateList* candidates)
: resource_provider_(resource_provider), candidates_(candidates) {}
~SendPromotionHintsBeforeReturning() {
resource_provider_->SendPromotionHints(
@@ -31,8 +33,8 @@ class SendPromotionHintsBeforeReturning {
}
private:
- cc::DisplayResourceProvider* resource_provider_;
- cc::OverlayCandidateList* candidates_;
+ DisplayResourceProvider* resource_provider_;
+ OverlayCandidateList* candidates_;
DISALLOW_COPY_AND_ASSIGN(SendPromotionHintsBeforeReturning);
};
@@ -40,7 +42,9 @@ class SendPromotionHintsBeforeReturning {
} // namespace
-namespace viz {
+OverlayProcessor::StrategyType OverlayProcessor::Strategy::GetUMAEnum() const {
+ return StrategyType::kUnknown;
+}
OverlayProcessor::OverlayProcessor(OutputSurface* surface)
: surface_(surface) {}
@@ -62,11 +66,11 @@ gfx::Rect OverlayProcessor::GetAndResetOverlayDamage() {
}
bool OverlayProcessor::ProcessForCALayers(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* overlay_candidates,
+ OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
gfx::Rect* damage_rect) {
OverlayCandidateValidator* overlay_validator =
@@ -90,11 +94,11 @@ bool OverlayProcessor::ProcessForCALayers(
}
bool OverlayProcessor::ProcessForDCLayers(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPassList* render_passes,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* overlay_candidates,
+ OverlayCandidateList* overlay_candidates,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect) {
OverlayCandidateValidator* overlay_validator =
@@ -111,12 +115,12 @@ bool OverlayProcessor::ProcessForDCLayers(
}
void OverlayProcessor::ProcessForOverlays(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPassList* render_passes,
const SkMatrix44& output_color_matrix,
const OverlayProcessor::FilterOperationsMap& render_pass_filters,
const OverlayProcessor::FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* candidates,
+ OverlayCandidateList* candidates,
CALayerOverlayList* ca_layer_overlays,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect,
@@ -158,16 +162,23 @@ void OverlayProcessor::ProcessForOverlays(
}
// Only if that fails, attempt hardware overlay strategies.
+ Strategy* successful_strategy = nullptr;
for (const auto& strategy : strategies_) {
if (!strategy->Attempt(output_color_matrix, resource_provider,
render_passes->back().get(), candidates,
content_bounds)) {
continue;
}
-
+ successful_strategy = strategy.get();
UpdateDamageRect(candidates, previous_frame_underlay_rect, damage_rect);
break;
}
+
+ UMA_HISTOGRAM_ENUMERATION("Viz.DisplayCompositor.OverlayStrategy",
+ successful_strategy
+ ? successful_strategy->GetUMAEnum()
+ : StrategyType::kNoStrategyUsed);
+
TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("viz.debug.overlay_planes"),
"Scheduled overlay planes", candidates->size());
}
@@ -181,12 +192,12 @@ void OverlayProcessor::ProcessForOverlays(
// previous frame. This only handles the common case of a single underlay quad
// for fullscreen video.
void OverlayProcessor::UpdateDamageRect(
- cc::OverlayCandidateList* candidates,
+ OverlayCandidateList* candidates,
const gfx::Rect& previous_frame_underlay_rect,
gfx::Rect* damage_rect) {
gfx::Rect output_surface_overlay_damage_rect;
gfx::Rect this_frame_underlay_rect;
- for (const cc::OverlayCandidate& overlay : *candidates) {
+ for (const OverlayCandidate& overlay : *candidates) {
if (overlay.plane_z_order >= 0) {
const gfx::Rect overlay_display_rect =
ToEnclosedRect(overlay.display_rect);
diff --git a/chromium/components/viz/service/display/overlay_processor.h b/chromium/components/viz/service/display/overlay_processor.h
index 3822f52fed4..a8ee4b71e95 100644
--- a/chromium/components/viz/service/display/overlay_processor.h
+++ b/chromium/components/viz/service/display/overlay_processor.h
@@ -9,10 +9,10 @@
#include "base/containers/flat_map.h"
#include "base/macros.h"
-#include "cc/output/overlay_candidate.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/service/display/ca_layer_overlay.h"
#include "components/viz/service/display/dc_layer_overlay.h"
+#include "components/viz/service/display/overlay_candidate.h"
#include "components/viz/service/viz_service_export.h"
namespace cc {
@@ -24,6 +24,18 @@ class OutputSurface;
class VIZ_SERVICE_EXPORT OverlayProcessor {
public:
+ // Enum used for UMA histogram. These enum values must not be changed or
+ // reused.
+ enum class StrategyType {
+ kUnknown = 0,
+ kNoStrategyUsed = 1,
+ kFullscreen = 2,
+ kSingleOnTop = 3,
+ kUnderlay = 4,
+ kUnderlayCast = 5,
+ kMaxValue = kUnderlayCast,
+ };
+
class VIZ_SERVICE_EXPORT Strategy {
public:
virtual ~Strategy() {}
@@ -32,10 +44,12 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
// and adds any additional passes necessary to represent overlays to
// |render_passes|.
virtual bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidates,
+ OverlayCandidateList* candidates,
std::vector<gfx::Rect>* content_bounds) = 0;
+
+ virtual StrategyType GetUMAEnum() const;
};
using StrategyList = std::vector<std::unique_ptr<Strategy>>;
@@ -52,12 +66,12 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
// Attempt to replace quads from the specified root render pass with overlays
// or CALayers. This must be called every frame.
void ProcessForOverlays(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPassList* render_passes,
const SkMatrix44& output_color_matrix,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* overlay_candidates,
+ OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect,
@@ -71,23 +85,23 @@ class VIZ_SERVICE_EXPORT OverlayProcessor {
private:
bool ProcessForCALayers(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* overlay_candidates,
+ OverlayCandidateList* overlay_candidates,
CALayerOverlayList* ca_layer_overlays,
gfx::Rect* damage_rect);
bool ProcessForDCLayers(
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPassList* render_passes,
const FilterOperationsMap& render_pass_filters,
const FilterOperationsMap& render_pass_background_filters,
- cc::OverlayCandidateList* overlay_candidates,
+ OverlayCandidateList* overlay_candidates,
DCLayerOverlayList* dc_layer_overlays,
gfx::Rect* damage_rect);
// Update |damage_rect| by removing damage casued by |candidates|.
- void UpdateDamageRect(cc::OverlayCandidateList* candidates,
+ void UpdateDamageRect(OverlayCandidateList* candidates,
const gfx::Rect& previous_frame_underlay_rect,
gfx::Rect* damage_rect);
diff --git a/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc b/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
index d7bd9f61428..aa5e125acca 100644
--- a/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_fullscreen.cc
@@ -22,15 +22,15 @@ OverlayStrategyFullscreen::~OverlayStrategyFullscreen() {}
bool OverlayStrategyFullscreen::Attempt(
const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
QuadList* quad_list = &render_pass->quad_list;
// First quad of quad_list is the top most quad.
auto front = quad_list->begin();
while (front != quad_list->end()) {
- if (!cc::OverlayCandidate::IsInvisibleQuad(*front))
+ if (!OverlayCandidate::IsInvisibleQuad(*front))
break;
++front;
}
@@ -42,22 +42,20 @@ bool OverlayStrategyFullscreen::Attempt(
if (quad->ShouldDrawWithBlending())
return false;
- cc::OverlayCandidate candidate;
- if (!cc::OverlayCandidate::FromDrawQuad(
- resource_provider, output_color_matrix, quad, &candidate)) {
+ OverlayCandidate candidate;
+ if (!OverlayCandidate::FromDrawQuad(resource_provider, output_color_matrix,
+ quad, &candidate)) {
return false;
}
if (!candidate.display_rect.origin().IsOrigin() ||
gfx::ToRoundedSize(candidate.display_rect.size()) !=
- render_pass->output_rect.size() ||
- render_pass->output_rect.size() != candidate.resource_size_in_pixels) {
+ render_pass->output_rect.size()) {
return false;
}
candidate.is_opaque = true;
candidate.plane_z_order = 0;
- candidate.overlay_handled = true;
- cc::OverlayCandidateList new_candidate_list;
+ OverlayCandidateList new_candidate_list;
new_candidate_list.push_back(candidate);
capability_checker_->CheckOverlaySupport(&new_candidate_list);
if (!new_candidate_list.front().overlay_handled)
@@ -69,4 +67,8 @@ bool OverlayStrategyFullscreen::Attempt(
return true;
}
+OverlayProcessor::StrategyType OverlayStrategyFullscreen::GetUMAEnum() const {
+ return OverlayProcessor::StrategyType::kFullscreen;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_strategy_fullscreen.h b/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
index 1ce04efa6bb..62bf1232d32 100644
--- a/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
+++ b/chromium/components/viz/service/display/overlay_strategy_fullscreen.h
@@ -23,11 +23,13 @@ class VIZ_SERVICE_EXPORT OverlayStrategyFullscreen
~OverlayStrategyFullscreen() override;
bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
+ OverlayProcessor::StrategyType GetUMAEnum() const override;
+
private:
OverlayCandidateValidator* capability_checker_; // Weak.
diff --git a/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc b/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
index 8888d6b4d95..573f48207f9 100644
--- a/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_single_on_top.cc
@@ -20,19 +20,19 @@ OverlayStrategySingleOnTop::~OverlayStrategySingleOnTop() {}
bool OverlayStrategySingleOnTop::Attempt(
const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
QuadList* quad_list = &render_pass->quad_list;
// Build a list of candidates with the associated quad.
- cc::OverlayCandidate best_candidate;
+ OverlayCandidate best_candidate;
auto best_quad_it = quad_list->end();
for (auto it = quad_list->begin(); it != quad_list->end(); ++it) {
- cc::OverlayCandidate candidate;
- if (cc::OverlayCandidate::FromDrawQuad(
- resource_provider, output_color_matrix, *it, &candidate) &&
- !cc::OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) {
+ OverlayCandidate candidate;
+ if (OverlayCandidate::FromDrawQuad(resource_provider, output_color_matrix,
+ *it, &candidate) &&
+ !OverlayCandidate::IsOccluded(candidate, quad_list->cbegin(), it)) {
if (candidate.display_rect.size().GetArea() >
best_candidate.display_rect.size().GetArea()) {
best_candidate = candidate;
@@ -51,18 +51,18 @@ bool OverlayStrategySingleOnTop::Attempt(
bool OverlayStrategySingleOnTop::TryOverlay(
QuadList* quad_list,
- cc::OverlayCandidateList* candidate_list,
- const cc::OverlayCandidate& candidate,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
QuadList::Iterator candidate_iterator) {
// Add the overlay.
- cc::OverlayCandidateList new_candidate_list = *candidate_list;
+ OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(candidate);
new_candidate_list.back().plane_z_order = 1;
// Check for support.
capability_checker_->CheckOverlaySupport(&new_candidate_list);
- const cc::OverlayCandidate& overlay_candidate = new_candidate_list.back();
+ const OverlayCandidate& overlay_candidate = new_candidate_list.back();
// If the candidate can be handled by an overlay, create a pass for it.
if (overlay_candidate.overlay_handled) {
quad_list->EraseAndInvalidateAllPointers(candidate_iterator);
@@ -73,4 +73,8 @@ bool OverlayStrategySingleOnTop::TryOverlay(
return false;
}
+OverlayProcessor::StrategyType OverlayStrategySingleOnTop::GetUMAEnum() const {
+ return OverlayProcessor::StrategyType::kSingleOnTop;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_strategy_single_on_top.h b/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
index 0a50ffa5bd0..9a9c07d4d95 100644
--- a/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
+++ b/chromium/components/viz/service/display/overlay_strategy_single_on_top.h
@@ -21,15 +21,17 @@ class VIZ_SERVICE_EXPORT OverlayStrategySingleOnTop
~OverlayStrategySingleOnTop() override;
bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
+ OverlayProcessor::StrategyType GetUMAEnum() const override;
+
private:
bool TryOverlay(QuadList* quad_list,
- cc::OverlayCandidateList* candidate_list,
- const cc::OverlayCandidate& candidate,
+ OverlayCandidateList* candidate_list,
+ const OverlayCandidate& candidate,
QuadList::Iterator candidate_iterator);
OverlayCandidateValidator* capability_checker_; // Weak.
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay.cc b/chromium/components/viz/service/display/overlay_strategy_underlay.cc
index 0460321e86d..846ad14eaba 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay.cc
@@ -4,6 +4,7 @@
#include "components/viz/service/display/overlay_strategy_underlay.h"
+#include "build/build_config.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/service/display/overlay_candidate_validator.h"
@@ -11,8 +12,9 @@
namespace viz {
OverlayStrategyUnderlay::OverlayStrategyUnderlay(
- OverlayCandidateValidator* capability_checker)
- : capability_checker_(capability_checker) {
+ OverlayCandidateValidator* capability_checker,
+ OpaqueMode opaque_mode)
+ : capability_checker_(capability_checker), opaque_mode_(opaque_mode) {
DCHECK(capability_checker);
}
@@ -20,22 +22,25 @@ OverlayStrategyUnderlay::~OverlayStrategyUnderlay() {}
bool OverlayStrategyUnderlay::Attempt(
const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
QuadList& quad_list = render_pass->quad_list;
for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
- cc::OverlayCandidate candidate;
- if (!cc::OverlayCandidate::FromDrawQuad(
- resource_provider, output_color_matrix, *it, &candidate)) {
+ OverlayCandidate candidate;
+ if (!OverlayCandidate::FromDrawQuad(resource_provider, output_color_matrix,
+ *it, &candidate) ||
+ (opaque_mode_ == OpaqueMode::RequireOpaqueCandidates &&
+ !candidate.is_opaque)) {
continue;
}
// Add the overlay.
- cc::OverlayCandidateList new_candidate_list = *candidate_list;
+ OverlayCandidateList new_candidate_list = *candidate_list;
new_candidate_list.push_back(candidate);
new_candidate_list.back().plane_z_order = -1;
+ new_candidate_list.front().is_opaque = false;
// Check for support.
capability_checker_->CheckOverlaySupport(&new_candidate_list);
@@ -44,7 +49,7 @@ bool OverlayStrategyUnderlay::Attempt(
// need to switch out the video quad with a black transparent one.
if (new_candidate_list.back().overlay_handled) {
new_candidate_list.back().is_unoccluded =
- !cc::OverlayCandidate::IsOccluded(candidate, quad_list.cbegin(), it);
+ !OverlayCandidate::IsOccluded(candidate, quad_list.cbegin(), it);
quad_list.ReplaceExistingQuadWithOpaqueTransparentSolidColor(it);
candidate_list->swap(new_candidate_list);
@@ -66,4 +71,8 @@ bool OverlayStrategyUnderlay::Attempt(
return false;
}
+OverlayProcessor::StrategyType OverlayStrategyUnderlay::GetUMAEnum() const {
+ return OverlayProcessor::StrategyType::kUnderlay;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay.h b/chromium/components/viz/service/display/overlay_strategy_underlay.h
index 45371779d29..7dce1364b79 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay.h
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay.h
@@ -21,18 +21,32 @@ class OverlayCandidateValidator;
class VIZ_SERVICE_EXPORT OverlayStrategyUnderlay
: public OverlayProcessor::Strategy {
public:
- explicit OverlayStrategyUnderlay(
- OverlayCandidateValidator* capability_checker);
+ enum class OpaqueMode {
+ // Require candidates to be |is_opaque|.
+ RequireOpaqueCandidates,
+
+ // Allow non-|is_opaque| candidates to be promoted.
+ AllowTransparentCandidates,
+ };
+
+ // If |allow_nonopaque_overlays| is true, then we don't require that the
+ // the candidate is_opaque.
+ OverlayStrategyUnderlay(
+ OverlayCandidateValidator* capability_checker,
+ OpaqueMode opaque_mode = OpaqueMode::RequireOpaqueCandidates);
~OverlayStrategyUnderlay() override;
bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
+ OverlayProcessor::StrategyType GetUMAEnum() const override;
+
private:
OverlayCandidateValidator* capability_checker_; // Weak.
+ OpaqueMode opaque_mode_;
DISALLOW_COPY_AND_ASSIGN(OverlayStrategyUnderlay);
};
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
index cc7ba761d87..b585b1c9f2e 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -26,15 +26,15 @@ OverlayStrategyUnderlayCast::~OverlayStrategyUnderlayCast() {}
bool OverlayStrategyUnderlayCast::Attempt(
const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) {
QuadList& quad_list = render_pass->quad_list;
bool found_underlay = false;
gfx::Rect content_rect;
for (const auto* quad : base::Reversed(quad_list)) {
- if (cc::OverlayCandidate::IsInvisibleQuad(quad))
+ if (OverlayCandidate::IsInvisibleQuad(quad))
continue;
const auto& transform = quad->shared_quad_state->quad_to_target_transform;
@@ -43,8 +43,8 @@ bool OverlayStrategyUnderlayCast::Attempt(
bool is_underlay = false;
if (!found_underlay) {
- cc::OverlayCandidate candidate;
- is_underlay = cc::OverlayCandidate::FromDrawQuad(
+ OverlayCandidate candidate;
+ is_underlay = OverlayCandidate::FromDrawQuad(
resource_provider, output_color_matrix, quad, &candidate);
found_underlay = is_underlay;
}
@@ -63,9 +63,17 @@ bool OverlayStrategyUnderlayCast::Attempt(
}
if (found_underlay) {
+ // If the primary plane shows up in the candidates list make sure it isn't
+ // opaque otherwise the video underlay won't be visible.
+ if (!candidate_list->empty()) {
+ DCHECK_EQ(1u, candidate_list->size());
+ DCHECK(candidate_list->front().use_output_surface_for_resource);
+ candidate_list->front().is_opaque = false;
+ }
+
for (auto it = quad_list.begin(); it != quad_list.end(); ++it) {
- cc::OverlayCandidate candidate;
- if (!cc::OverlayCandidate::FromDrawQuad(
+ OverlayCandidate candidate;
+ if (!OverlayCandidate::FromDrawQuad(
resource_provider, output_color_matrix, *it, &candidate)) {
continue;
}
@@ -89,6 +97,10 @@ bool OverlayStrategyUnderlayCast::Attempt(
return found_underlay;
}
+OverlayProcessor::StrategyType OverlayStrategyUnderlayCast::GetUMAEnum() const {
+ return OverlayProcessor::StrategyType::kUnderlayCast;
+}
+
// static
void OverlayStrategyUnderlayCast::SetOverlayCompositedCallback(
const OverlayCompositedCallback& cb) {
diff --git a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
index 0ea20e6c4f1..ea73e340b5d 100644
--- a/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
+++ b/chromium/components/viz/service/display/overlay_strategy_underlay_cast.h
@@ -24,9 +24,9 @@ class VIZ_SERVICE_EXPORT OverlayStrategyUnderlayCast
~OverlayStrategyUnderlayCast() override;
bool Attempt(const SkMatrix44& output_color_matrix,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
RenderPass* render_pass,
- cc::OverlayCandidateList* candidate_list,
+ OverlayCandidateList* candidate_list,
std::vector<gfx::Rect>* content_bounds) override;
// Callback that's made whenever an overlay quad is processed in the
@@ -36,6 +36,8 @@ class VIZ_SERVICE_EXPORT OverlayStrategyUnderlayCast
base::RepeatingCallback<void(const gfx::RectF&, gfx::OverlayTransform)>;
static void SetOverlayCompositedCallback(const OverlayCompositedCallback& cb);
+ OverlayProcessor::StrategyType GetUMAEnum() const override;
+
private:
DISALLOW_COPY_AND_ASSIGN(OverlayStrategyUnderlayCast);
};
diff --git a/chromium/components/viz/service/display/overlay_unittest.cc b/chromium/components/viz/service/display/overlay_unittest.cc
index 5cb75117474..119841fc713 100644
--- a/chromium/components/viz/service/display/overlay_unittest.cc
+++ b/chromium/components/viz/service/display/overlay_unittest.cc
@@ -9,7 +9,6 @@
#include "base/containers/flat_map.h"
#include "base/test/scoped_feature_list.h"
-#include "cc/resources/display_resource_provider.h"
#include "cc/resources/layer_tree_resource_provider.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
@@ -22,6 +21,7 @@
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "components/viz/service/display/ca_layer_overlay.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/gl_renderer.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_client.h"
@@ -72,7 +72,9 @@ class FullscreenOverlayValidator : public OverlayCandidateValidator {
}
bool AllowCALayerOverlays() override { return false; }
bool AllowDCLayerOverlays() override { return false; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
+ surfaces->back().overlay_handled = true;
+ }
};
class SingleOverlayValidator : public OverlayCandidateValidator {
@@ -86,13 +88,13 @@ class SingleOverlayValidator : public OverlayCandidateValidator {
bool AllowCALayerOverlays() override { return false; }
bool AllowDCLayerOverlays() override { return false; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {
// We may have 1 or 2 surfaces depending on whether this ran through the
// full renderer and picked up the output surface, or not.
ASSERT_LE(1U, surfaces->size());
ASSERT_GE(2U, surfaces->size());
- cc::OverlayCandidate& candidate = surfaces->back();
+ OverlayCandidate& candidate = surfaces->back();
EXPECT_TRUE(!candidate.use_output_surface_for_resource);
for (const auto& r : expected_rects_) {
const float kAbsoluteError = 0.01f;
@@ -129,7 +131,7 @@ class CALayerValidator : public OverlayCandidateValidator {
void GetStrategies(OverlayProcessor::StrategyList* strategies) override {}
bool AllowCALayerOverlays() override { return true; }
bool AllowDCLayerOverlays() override { return false; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
};
class DCLayerValidator : public OverlayCandidateValidator {
@@ -137,7 +139,7 @@ class DCLayerValidator : public OverlayCandidateValidator {
void GetStrategies(OverlayProcessor::StrategyList* strategies) override {}
bool AllowCALayerOverlays() override { return false; }
bool AllowDCLayerOverlays() override { return true; }
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override {}
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override {}
};
class SingleOnTopOverlayValidator : public SingleOverlayValidator {
@@ -154,6 +156,14 @@ class UnderlayOverlayValidator : public SingleOverlayValidator {
}
};
+class TransparentUnderlayOverlayValidator : public SingleOverlayValidator {
+ public:
+ void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
+ strategies->push_back(std::make_unique<OverlayStrategyUnderlay>(
+ this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates));
+ }
+};
+
class UnderlayCastOverlayValidator : public SingleOverlayValidator {
public:
void GetStrategies(OverlayProcessor::StrategyList* strategies) override {
@@ -211,7 +221,7 @@ class OverlayOutputSurface : public OutputSurface {
gfx::BufferFormat GetOverlayBufferFormat() const override {
return gfx::BufferFormat::RGBX_8888;
}
- bool SurfaceIsSuspendForRecycle() const override { return false; }
+ unsigned UpdateGpuFence() override { return 0; }
void set_is_displayed_as_overlay_plane(bool value) {
is_displayed_as_overlay_plane_ = value;
@@ -272,8 +282,9 @@ static ResourceId CreateResourceInLayerTree(
}
ResourceId CreateResource(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const gfx::Size& size,
bool is_overlay_candidate) {
ResourceId resource_id = CreateResourceInLayerTree(
@@ -283,14 +294,15 @@ ResourceId CreateResource(
base::BindRepeating([](const std::vector<ReturnedResource>&) {}));
// Transfer resource to the parent.
- cc::ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ std::vector<ResourceId> resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource_id);
std::vector<TransferableResource> list;
- child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list);
+ child_resource_provider->PrepareSendToParent(resource_ids_to_transfer, &list,
+ child_context_provider);
parent_resource_provider->ReceiveFromChild(child_id, list);
// In DisplayResourceProvider's namespace, use the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
parent_resource_provider->GetChildToParentMap(child_id);
return resource_map[list[0].id];
}
@@ -307,8 +319,9 @@ SolidColorDrawQuad* CreateSolidColorQuadAt(
}
TextureDrawQuad* CreateCandidateQuadAt(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Rect& rect) {
@@ -319,9 +332,9 @@ TextureDrawQuad* CreateCandidateQuadAt(
float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
gfx::Size resource_size_in_pixels = rect.size();
bool is_overlay_candidate = true;
- ResourceId resource_id =
- CreateResource(parent_resource_provider, child_resource_provider,
- resource_size_in_pixels, is_overlay_candidate);
+ ResourceId resource_id = CreateResource(
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ resource_size_in_pixels, is_overlay_candidate);
auto* overlay_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
overlay_quad->SetNew(shared_quad_state, rect, rect, needs_blending,
@@ -334,8 +347,9 @@ TextureDrawQuad* CreateCandidateQuadAt(
}
TextureDrawQuad* CreateTransparentCandidateQuadAt(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Rect& rect) {
@@ -346,9 +360,9 @@ TextureDrawQuad* CreateTransparentCandidateQuadAt(
float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
gfx::Size resource_size_in_pixels = rect.size();
bool is_overlay_candidate = true;
- ResourceId resource_id =
- CreateResource(parent_resource_provider, child_resource_provider,
- resource_size_in_pixels, is_overlay_candidate);
+ ResourceId resource_id = CreateResource(
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ resource_size_in_pixels, is_overlay_candidate);
auto* overlay_quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
overlay_quad->SetNew(shared_quad_state, rect, rect, needs_blending,
@@ -361,8 +375,9 @@ TextureDrawQuad* CreateTransparentCandidateQuadAt(
}
StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Rect& rect,
@@ -370,9 +385,9 @@ StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
bool needs_blending = false;
gfx::Size resource_size_in_pixels = rect.size();
bool is_overlay_candidate = true;
- ResourceId resource_id =
- CreateResource(parent_resource_provider, child_resource_provider,
- resource_size_in_pixels, is_overlay_candidate);
+ ResourceId resource_id = CreateResource(
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ resource_size_in_pixels, is_overlay_candidate);
auto* overlay_quad =
render_pass->CreateAndAppendDrawQuad<StreamVideoDrawQuad>();
@@ -383,29 +398,32 @@ StreamVideoDrawQuad* CreateCandidateVideoQuadAt(
}
TextureDrawQuad* CreateFullscreenCandidateQuad(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass) {
- return CreateCandidateQuadAt(parent_resource_provider,
- child_resource_provider, shared_quad_state,
- render_pass, render_pass->output_rect);
+ return CreateCandidateQuadAt(
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ shared_quad_state, render_pass, render_pass->output_rect);
}
StreamVideoDrawQuad* CreateFullscreenCandidateVideoQuad(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Transform& transform) {
return CreateCandidateVideoQuadAt(
- parent_resource_provider, child_resource_provider, shared_quad_state,
- render_pass, render_pass->output_rect, transform);
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ shared_quad_state, render_pass, render_pass->output_rect, transform);
}
YUVVideoDrawQuad* CreateFullscreenCandidateYUVVideoQuad(
- cc::DisplayResourceProvider* parent_resource_provider,
+ DisplayResourceProvider* parent_resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass) {
bool needs_blending = false;
@@ -413,9 +431,9 @@ YUVVideoDrawQuad* CreateFullscreenCandidateYUVVideoQuad(
gfx::Rect rect = render_pass->output_rect;
gfx::Size resource_size_in_pixels = rect.size();
bool is_overlay_candidate = true;
- ResourceId resource_id =
- CreateResource(parent_resource_provider, child_resource_provider,
- resource_size_in_pixels, is_overlay_candidate);
+ ResourceId resource_id = CreateResource(
+ parent_resource_provider, child_resource_provider, child_context_provider,
+ resource_size_in_pixels, is_overlay_candidate);
auto* overlay_quad = render_pass->CreateAndAppendDrawQuad<YUVVideoDrawQuad>();
overlay_quad->SetNew(shared_quad_state, rect, rect, needs_blending,
@@ -427,7 +445,7 @@ YUVVideoDrawQuad* CreateFullscreenCandidateYUVVideoQuad(
return overlay_quad;
}
-void CreateOpaqueQuadAt(cc::ResourceProvider* resource_provider,
+void CreateOpaqueQuadAt(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Rect& rect) {
@@ -435,7 +453,7 @@ void CreateOpaqueQuadAt(cc::ResourceProvider* resource_provider,
color_quad->SetNew(shared_quad_state, rect, rect, SK_ColorBLACK, false);
}
-void CreateOpaqueQuadAt(cc::ResourceProvider* resource_provider,
+void CreateOpaqueQuadAt(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass,
const gfx::Rect& rect,
@@ -445,7 +463,7 @@ void CreateOpaqueQuadAt(cc::ResourceProvider* resource_provider,
color_quad->SetNew(shared_quad_state, rect, rect, color, false);
}
-void CreateFullscreenOpaqueQuad(cc::ResourceProvider* resource_provider,
+void CreateFullscreenOpaqueQuad(DisplayResourceProvider* resource_provider,
const SharedQuadState* shared_quad_state,
RenderPass* render_pass) {
CreateOpaqueQuadAt(resource_provider, shared_quad_state, render_pass,
@@ -514,7 +532,7 @@ class OverlayTest : public testing::Test {
child_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_provider_.get(), shared_bitmap_manager_.get());
+ child_provider_.get());
overlay_processor_ =
std::make_unique<OverlayProcessor>(output_surface_.get());
@@ -525,7 +543,7 @@ class OverlayTest : public testing::Test {
std::unique_ptr<OutputSurfaceType> output_surface_;
cc::FakeOutputSurfaceClient client_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
scoped_refptr<TestContextProvider> child_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
std::unique_ptr<OverlayProcessor> overlay_processor_;
@@ -536,6 +554,8 @@ class OverlayTest : public testing::Test {
using FullscreenOverlayTest = OverlayTest<FullscreenOverlayValidator>;
using SingleOverlayOnTopTest = OverlayTest<SingleOnTopOverlayValidator>;
using UnderlayTest = OverlayTest<UnderlayOverlayValidator>;
+using TransparentUnderlayTest =
+ OverlayTest<TransparentUnderlayOverlayValidator>;
using UnderlayCastTest = OverlayTest<UnderlayCastOverlayValidator>;
using CALayerOverlayTest = OverlayTest<CALayerValidator>;
@@ -557,7 +577,7 @@ TEST(OverlayTest, OverlaysProcessorHasStrategy) {
output_surface.SetOverlayCandidateValidator(new SingleOverlayValidator);
auto shared_bitmap_manager = std::make_unique<TestSharedBitmapManager>();
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider =
+ std::unique_ptr<DisplayResourceProvider> resource_provider =
cc::FakeResourceProvider::CreateDisplayResourceProvider(
provider.get(), shared_bitmap_manager.get());
@@ -572,7 +592,7 @@ TEST_F(FullscreenOverlayTest, SuccessfulOverlay) {
gfx::Rect output_rect = pass->output_rect;
TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
unsigned original_resource_id = original_quad->resource_id();
// Add something behind it.
@@ -580,7 +600,7 @@ TEST_F(FullscreenOverlayTest, SuccessfulOverlay) {
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -608,14 +628,14 @@ TEST_F(FullscreenOverlayTest, FailOnOutputColorMatrix) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
// Add something behind it.
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -638,10 +658,11 @@ TEST_F(FullscreenOverlayTest, AlphaFail) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateTransparentCandidateQuadAt(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), pass.get()->output_rect);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ pass.get()->output_rect);
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -659,15 +680,15 @@ TEST_F(FullscreenOverlayTest, AlphaFail) {
EXPECT_EQ(0U, candidate_list.size());
}
-TEST_F(FullscreenOverlayTest, ResourceSizeInPixelsFail) {
+TEST_F(FullscreenOverlayTest, SuccessfulResourceSizeInPixels) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
original_quad->set_resource_size_in_pixels(gfx::Size(64, 64));
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -678,10 +699,10 @@ TEST_F(FullscreenOverlayTest, ResourceSizeInPixelsFail) {
resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
render_pass_filters, render_pass_background_filters, &candidate_list,
nullptr, nullptr, &damage_rect_, &content_bounds_);
- ASSERT_EQ(0U, candidate_list.size());
+ ASSERT_EQ(1U, candidate_list.size());
- // Check that the quad is not gone.
- EXPECT_EQ(1U, main_pass->quad_list.size());
+ // Check that the quad is gone.
+ EXPECT_EQ(0U, main_pass->quad_list.size());
}
TEST_F(FullscreenOverlayTest, OnTopFail) {
@@ -694,10 +715,10 @@ TEST_F(FullscreenOverlayTest, OnTopFail) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -718,12 +739,13 @@ TEST_F(FullscreenOverlayTest, NotCoveringFullscreenFail) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
gfx::Rect inset_rect = pass->output_rect;
inset_rect.Inset(0, 1, 0, 1);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), inset_rect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ inset_rect);
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -752,10 +774,10 @@ TEST_F(FullscreenOverlayTest, RemoveFullscreenQuadFromQuadList) {
shared_state->opacity = 1.f;
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -777,7 +799,7 @@ TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
TextureDrawQuad* original_quad = CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
unsigned original_resource_id = original_quad->resource_id();
// Add something behind it.
@@ -787,7 +809,7 @@ TEST_F(SingleOverlayOnTopTest, SuccessfulOverlay) {
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -815,9 +837,10 @@ TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
// Add a small quad.
const auto kSmallCandidateRect = gfx::Rect(0, 0, 16, 16);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kSmallCandidateRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kSmallCandidateRect);
output_surface_->GetOverlayCandidateValidator()->AddExpectedRect(
gfx::RectF(kSmallCandidateRect));
@@ -825,7 +848,8 @@ TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) {
const auto kBigCandidateRect = gfx::Rect(20, 20, 32, 32);
TextureDrawQuad* quad_big = CreateCandidateQuadAt(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kBigCandidateRect);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kBigCandidateRect);
output_surface_->GetOverlayCandidateValidator()->AddExpectedRect(
gfx::RectF(kBigCandidateRect));
@@ -836,7 +860,7 @@ TEST_F(SingleOverlayOnTopTest, PrioritizeBiggerOne) {
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -860,7 +884,7 @@ TEST_F(SingleOverlayOnTopTest, DamageRect) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
damage_rect_ = kOverlayRect;
// Add something behind it.
@@ -870,10 +894,10 @@ TEST_F(SingleOverlayOnTopTest, DamageRect) {
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
// Primary plane.
- cc::OverlayCandidate output_surface_plane;
+ OverlayCandidate output_surface_plane;
output_surface_plane.display_rect = gfx::RectF(kOverlayRect);
output_surface_plane.use_output_surface_for_resource = true;
output_surface_plane.overlay_handled = true;
@@ -903,7 +927,7 @@ TEST_F(SingleOverlayOnTopTest, NoCandidates) {
RenderPassList original_pass_list;
RenderPass::CopyAll(pass_list, &original_pass_list);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
overlay_processor_->ProcessForOverlays(
@@ -924,7 +948,7 @@ TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -932,7 +956,7 @@ TEST_F(SingleOverlayOnTopTest, OccludedCandidates) {
RenderPassList original_pass_list;
RenderPass::CopyAll(pass_list, &original_pass_list);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
overlay_processor_->ProcessForOverlays(
@@ -949,7 +973,7 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
// Add something behind it.
CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -958,7 +982,7 @@ TEST_F(SingleOverlayOnTopTest, MultipleRenderPasses) {
pass->shared_quad_state_list.back(), pass.get());
// Check for potential candidates.
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -974,10 +998,10 @@ TEST_F(SingleOverlayOnTopTest, AcceptBlending) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
TextureDrawQuad* quad = CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
quad->needs_blending = true;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = quad->rect;
@@ -998,10 +1022,10 @@ TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
TextureDrawQuad* quad = CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
quad->background_color = SK_ColorBLACK;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1017,10 +1041,10 @@ TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->blend_mode = SkBlendMode::kScreen;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1036,10 +1060,10 @@ TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->opacity = 0.5f;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1055,11 +1079,11 @@ TEST_F(SingleOverlayOnTopTest, RejectNonAxisAlignedTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutXAxis(45.f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1075,11 +1099,11 @@ TEST_F(SingleOverlayOnTopTest, AllowClipped) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = kOverlayClipRect;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1097,11 +1121,11 @@ TEST_F(UnderlayTest, AllowVerticalFlip) {
rect.Offset(0, -rect.height());
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f,
-1.0f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1121,12 +1145,12 @@ TEST_F(UnderlayTest, AllowHorizontalFlip) {
rect.Offset(-rect.width(), 0);
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(-1.0f,
2.0f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1145,11 +1169,11 @@ TEST_F(SingleOverlayOnTopTest, AllowPositiveScaleTransform) {
rect.set_width(rect.width() / 2);
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(2.0f,
1.0f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1166,12 +1190,12 @@ TEST_F(SingleOverlayOnTopTest, AcceptMirrorYTransform) {
rect.Offset(0, -rect.height());
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()->quad_to_target_transform.Scale(1.f,
-1.f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1188,12 +1212,12 @@ TEST_F(UnderlayTest, Allow90DegreeRotation) {
rect.Offset(0, -rect.height());
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(90.f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1211,12 +1235,12 @@ TEST_F(UnderlayTest, Allow180DegreeRotation) {
rect.Offset(-rect.width(), -rect.height());
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(180.f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1234,12 +1258,12 @@ TEST_F(UnderlayTest, Allow270DegreeRotation) {
rect.Offset(-rect.width(), 0);
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), rect);
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(270.f);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1252,6 +1276,84 @@ TEST_F(UnderlayTest, Allow270DegreeRotation) {
EXPECT_EQ(gfx::OVERLAY_TRANSFORM_ROTATE_270, candidate_list.back().transform);
}
+TEST_F(UnderlayTest, AllowsOpaqueCandidates) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get())
+ ->needs_blending = false;
+ pass->shared_quad_state_list.front()->opacity = 1.0;
+
+ OverlayCandidateList candidate_list;
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+ ASSERT_EQ(1U, candidate_list.size());
+}
+
+TEST_F(UnderlayTest, DisallowsTransparentCandidates) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get())
+ ->needs_blending = true;
+
+ OverlayCandidateList candidate_list;
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+ ASSERT_EQ(0U, candidate_list.size());
+}
+
+TEST_F(TransparentUnderlayTest, AllowsOpaqueCandidates) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get())
+ ->needs_blending = false;
+ pass->shared_quad_state_list.front()->opacity = 1.0;
+
+ OverlayCandidateList candidate_list;
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+ ASSERT_EQ(1U, candidate_list.size());
+}
+
+TEST_F(TransparentUnderlayTest, AllowsTransparentCandidates) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ CreateFullscreenCandidateQuad(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get())
+ ->needs_blending = true;
+
+ OverlayCandidateList candidate_list;
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+ ASSERT_EQ(1U, candidate_list.size());
+}
+
TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
output_surface_->GetOverlayCandidateValidator()->AddExpectedRect(
gfx::RectF(kOverlayBottomRightRect));
@@ -1260,11 +1362,12 @@ TEST_F(SingleOverlayOnTopTest, AllowNotTopIfNotOccluded) {
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1288,10 +1391,10 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentOnTop) {
shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->opacity = 1.f;
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(), shared_state,
- pass.get(), kOverlayBottomRightRect);
+ child_resource_provider_.get(), child_provider_.get(),
+ shared_state, pass.get(), kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1311,11 +1414,12 @@ TEST_F(SingleOverlayOnTopTest, AllowTransparentColorOnTop) {
CreateSolidColorQuadAt(pass->shared_quad_state_list.back(),
SK_ColorTRANSPARENT, pass.get(),
kOverlayBottomRightRect);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1336,10 +1440,10 @@ TEST_F(SingleOverlayOnTopTest, RejectOpaqueColorOnTop) {
shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->opacity = 1.f;
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(), shared_state,
- pass.get(), kOverlayBottomRightRect);
+ child_resource_provider_.get(), child_provider_.get(),
+ shared_state, pass.get(), kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1358,10 +1462,10 @@ TEST_F(SingleOverlayOnTopTest, RejectTransparentColorOnTopWithoutBlending) {
kOverlayBottomRightRect)
->needs_blending = false;
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(), shared_state,
- pass.get(), kOverlayBottomRightRect);
+ child_resource_provider_.get(), child_provider_.get(),
+ shared_state, pass.get(), kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1377,9 +1481,10 @@ TEST_F(SingleOverlayOnTopTest, RejectVideoSwapTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kSwapTransform);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kSwapTransform);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1395,9 +1500,10 @@ TEST_F(UnderlayTest, AllowVideoXMirrorTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kXMirrorTransform);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kXMirrorTransform);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1413,9 +1519,10 @@ TEST_F(UnderlayTest, AllowVideoBothMirrorTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kBothMirrorTransform);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kBothMirrorTransform);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1431,9 +1538,10 @@ TEST_F(UnderlayTest, AllowVideoNormalTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kNormalTransform);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kNormalTransform);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1449,9 +1557,10 @@ TEST_F(SingleOverlayOnTopTest, AllowVideoYMirrorTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kYMirrorTransform);
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get(),
+ kYMirrorTransform);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1470,11 +1579,12 @@ TEST_F(UnderlayTest, OverlayLayerUnderMainLayer) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1499,12 +1609,12 @@ TEST_F(UnderlayTest, AllowOnTop) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->CreateAndAppendSharedQuadState()->opacity = 0.5f;
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1529,11 +1639,11 @@ TEST_F(UnderlayTest, InitialUnderlayDamageNotSubtracted) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
damage_rect_ = kOverlayRect;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1553,7 +1663,7 @@ TEST_F(UnderlayTest, DamageSubtractedForConsecutiveIdenticalUnderlays) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
damage_rect_ = kOverlayRect;
@@ -1561,7 +1671,7 @@ TEST_F(UnderlayTest, DamageSubtractedForConsecutiveIdenticalUnderlays) {
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1587,13 +1697,14 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonIdenticalConsecutiveUnderlays) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), overlay_rects[i]);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ overlay_rects[i]);
damage_rect_ = overlay_rects[i];
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1618,7 +1729,8 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonConsecutiveIdenticalUnderlays) {
if (has_fullscreen_candidate[i]) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(),
+ pass.get());
}
damage_rect_ = kOverlayRect;
@@ -1627,7 +1739,7 @@ TEST_F(UnderlayTest, DamageNotSubtractedForNonConsecutiveIdenticalUnderlays) {
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1649,11 +1761,11 @@ TEST_F(UnderlayTest, DamageNotSubtractedWhenQuadsAboveOverlap) {
pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
damage_rect_ = kOverlayRect;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1678,13 +1790,13 @@ TEST_F(UnderlayTest, DamageSubtractedWhenQuadsAboveDontOverlap) {
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
CreateCandidateQuadAt(resource_provider_.get(),
- child_resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayBottomRightRect);
damage_rect_ = kOverlayBottomRightRect;
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1698,6 +1810,37 @@ TEST_F(UnderlayTest, DamageSubtractedWhenQuadsAboveDontOverlap) {
EXPECT_TRUE(damage_rect_.IsEmpty());
}
+TEST_F(UnderlayTest, PrimaryPlaneOverlayIsTransparentWithUnderlay) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ gfx::Rect output_rect = pass->output_rect;
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ output_rect, SK_ColorWHITE);
+
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
+
+ OverlayCandidateList candidate_list;
+ OverlayCandidate candidate;
+ candidate.use_output_surface_for_resource = true;
+ candidate.is_opaque = true;
+ candidate_list.push_back(candidate);
+
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+
+ EXPECT_EQ(2U, candidate_list.size());
+ ASSERT_EQ(false, candidate_list[0].is_opaque);
+}
+
TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
@@ -1705,7 +1848,7 @@ TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1719,11 +1862,12 @@ TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
TEST_F(UnderlayCastTest, FullScreenOverlayContentBounds) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1745,9 +1889,10 @@ TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) {
const gfx::Rect kTopRight(128, 0, 128, 128);
std::unique_ptr<RenderPass> pass = CreateRenderPass();
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(), kLeftSide,
SK_ColorBLACK);
@@ -1755,7 +1900,7 @@ TEST_F(UnderlayCastTest, BlackOutsideOverlayContentBounds) {
pass->shared_quad_state_list.back(), pass.get(), kTopRight,
SK_ColorBLACK);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1774,11 +1919,12 @@ TEST_F(UnderlayCastTest, OverlayOccludedContentBounds) {
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayTopLeftRect);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1800,11 +1946,12 @@ TEST_F(UnderlayCastTest, OverlayOccludedUnionContentBounds) {
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
kOverlayBottomRightRect);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1829,14 +1976,15 @@ TEST_F(UnderlayCastTest, RoundOverlayContentBounds) {
transform.Translate(0.5f, 0.5f);
std::unique_ptr<RenderPass> pass = CreateRenderPassWithTransform(transform);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), overlay_rect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ overlay_rect);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(0, 0, 10, 10), SK_ColorWHITE);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1862,14 +2010,15 @@ TEST_F(UnderlayCastTest, RoundContentBounds) {
transform.Translate(0.5f, 0.5f);
std::unique_ptr<RenderPass> pass = CreateRenderPassWithTransform(transform);
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), overlay_rect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ overlay_rect);
CreateOpaqueQuadAt(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get(),
gfx::Rect(0, 0, 255, 255), SK_ColorWHITE);
- cc::OverlayCandidateList candidate_list;
+ OverlayCandidateList candidate_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1883,10 +2032,41 @@ TEST_F(UnderlayCastTest, RoundContentBounds) {
EXPECT_EQ(kOverlayRect, content_bounds_[0]);
}
-cc::OverlayCandidateList BackbufferOverlayList(
- const RenderPass* root_render_pass) {
- cc::OverlayCandidateList list;
- cc::OverlayCandidate output_surface_plane;
+TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsTransparentWithUnderlay) {
+ std::unique_ptr<RenderPass> pass = CreateRenderPass();
+ gfx::Rect output_rect = pass->output_rect;
+ CreateOpaqueQuadAt(resource_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ output_rect, SK_ColorWHITE);
+
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayRect);
+
+ OverlayCandidateList candidate_list;
+ OverlayCandidate candidate;
+ candidate.use_output_surface_for_resource = true;
+ candidate.is_opaque = true;
+ candidate_list.push_back(candidate);
+
+ OverlayProcessor::FilterOperationsMap render_pass_filters;
+ OverlayProcessor::FilterOperationsMap render_pass_background_filters;
+ RenderPassList pass_list;
+ pass_list.push_back(std::move(pass));
+ overlay_processor_->ProcessForOverlays(
+ resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+ render_pass_filters, render_pass_background_filters, &candidate_list,
+ nullptr, nullptr, &damage_rect_, &content_bounds_);
+
+ ASSERT_EQ(false, candidate_list[0].is_opaque);
+ EXPECT_EQ(1U, content_bounds_.size());
+ EXPECT_EQ(output_rect, content_bounds_[0]);
+}
+
+OverlayCandidateList BackbufferOverlayList(const RenderPass* root_render_pass) {
+ OverlayCandidateList list;
+ OverlayCandidate output_surface_plane;
output_surface_plane.display_rect = gfx::RectF(root_render_pass->output_rect);
output_surface_plane.use_output_surface_for_resource = true;
output_surface_plane.overlay_handled = true;
@@ -1898,13 +2078,13 @@ TEST_F(CALayerOverlayTest, AllowNonAxisAlignedTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(45.f);
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- cc::OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1923,12 +2103,12 @@ TEST_F(CALayerOverlayTest, ThreeDTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutXAxis(45.f);
CALayerOverlayList ca_layer_list;
- cc::OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1950,13 +2130,13 @@ TEST_F(CALayerOverlayTest, AllowContainingClip) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = kOverlayRect;
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- cc::OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -1975,13 +2155,13 @@ TEST_F(CALayerOverlayTest, NontrivialClip) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->is_clipped = true;
pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(64, 64, 128, 128);
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- cc::OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -2003,12 +2183,12 @@ TEST_F(CALayerOverlayTest, SkipTransparent) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->opacity = 0;
gfx::Rect damage_rect;
CALayerOverlayList ca_layer_list;
- cc::OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
+ OverlayCandidateList overlay_list(BackbufferOverlayList(pass.get()));
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -2043,13 +2223,13 @@ TEST_P(DCLayerOverlayTest, AllowNonAxisAlignedTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(45.f);
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2074,14 +2254,14 @@ TEST_P(DCLayerOverlayTest, AllowRequiredNonAxisAlignedTransform) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
YUVVideoDrawQuad* yuv_quad = CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
yuv_quad->require_overlay = true;
pass->shared_quad_state_list.back()
->quad_to_target_transform.RotateAboutZAxis(45.f);
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2109,11 +2289,11 @@ TEST_P(DCLayerOverlayTest, Occluded) {
gfx::Rect(0, 2, 100, 100), SK_ColorWHITE);
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2138,11 +2318,11 @@ TEST_P(DCLayerOverlayTest, Occluded) {
gfx::Rect(2, 2, 100, 100), SK_ColorWHITE);
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2168,11 +2348,11 @@ TEST_P(DCLayerOverlayTest, DamageRect) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2204,7 +2384,8 @@ TEST_P(DCLayerOverlayTest, MultiplePassDamageRect) {
pass1->id = child_pass_id;
YUVVideoDrawQuad* yuv_quad = CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass1->shared_quad_state_list.back(), pass1.get());
+ child_provider_.get(), pass1->shared_quad_state_list.back(),
+ pass1.get());
yuv_quad->require_overlay = true;
pass1->damage_rect = gfx::Rect();
pass1->transform_to_root_target.Translate(0, 100);
@@ -2226,7 +2407,7 @@ TEST_P(DCLayerOverlayTest, MultiplePassDamageRect) {
gfx::Rect damage_rect;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect();
@@ -2281,15 +2462,15 @@ TEST_P(DCLayerOverlayTest, ClipRect) {
pass->shared_quad_state_list.back()->clip_rect = gfx::Rect(0, 3, 100, 100);
SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
shared_state->opacity = 1.f;
- CreateFullscreenCandidateYUVVideoQuad(resource_provider_.get(),
- child_resource_provider_.get(),
- shared_state, pass.get());
+ CreateFullscreenCandidateYUVVideoQuad(
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_provider_.get(), shared_state, pass.get());
shared_state->is_clipped = true;
// Clipped rect shouldn't be overlapped by clipped opaque quad rect.
shared_state->clip_rect = gfx::Rect(0, 0, 100, 3);
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
RenderPassList pass_list;
@@ -2322,11 +2503,11 @@ TEST_P(DCLayerOverlayTest, TransparentOnTop) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
CreateFullscreenCandidateYUVVideoQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
pass->shared_quad_state_list.back()->opacity = 0.5f;
DCLayerOverlayList dc_layer_list;
- cc::OverlayCandidateList overlay_list;
+ OverlayCandidateList overlay_list;
OverlayProcessor::FilterOperationsMap render_pass_filters;
OverlayProcessor::FilterOperationsMap render_pass_background_filters;
damage_rect_ = gfx::Rect(1, 1, 10, 10);
@@ -2350,7 +2531,7 @@ class OverlayInfoRendererGL : public GLRenderer {
public:
OverlayInfoRendererGL(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+ DisplayResourceProvider* resource_provider)
: GLRenderer(settings, output_surface, resource_provider, nullptr),
expect_overlays_(false) {}
@@ -2385,12 +2566,14 @@ class OverlayInfoRendererGL : public GLRenderer {
class MockOverlayScheduler {
public:
- MOCK_METHOD5(Schedule,
+ MOCK_METHOD7(Schedule,
void(int plane_z_order,
gfx::OverlayTransform plane_transform,
unsigned overlay_texture_id,
const gfx::Rect& display_bounds,
- const gfx::RectF& uv_rect));
+ const gfx::RectF& uv_rect,
+ bool enable_blend,
+ unsigned gpu_fence_id));
};
class GLRendererWithOverlaysTest : public testing::Test {
@@ -2413,7 +2596,7 @@ class GLRendererWithOverlaysTest : public testing::Test {
child_provider_->BindToCurrentThread();
child_resource_provider_ =
cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- child_provider_.get(), nullptr);
+ child_provider_.get());
}
void Init(bool use_validator) {
@@ -2430,16 +2613,16 @@ class GLRendererWithOverlaysTest : public testing::Test {
renderer_->DrawFrame(pass_list, 1.f, viewport_size);
}
void SwapBuffers() {
- renderer_->SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer_->SwapBuffers(std::vector<ui::LatencyInfo>(), false);
renderer_->SwapBuffersComplete();
}
void SwapBuffersWithoutComplete() {
- renderer_->SwapBuffers(std::vector<ui::LatencyInfo>());
+ renderer_->SwapBuffers(std::vector<ui::LatencyInfo>(), false);
}
void SwapBuffersComplete() { renderer_->SwapBuffersComplete(); }
void ReturnResourceInUseQuery(ResourceId id) {
- cc::DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
- id);
+ DisplayResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+ id);
gpu::TextureInUseResponse response;
response.texture = lock.texture_id();
response.in_use = false;
@@ -2451,7 +2634,7 @@ class GLRendererWithOverlaysTest : public testing::Test {
RendererSettings settings_;
cc::FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<OutputSurfaceType> output_surface_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<OverlayInfoRendererGL> renderer_;
scoped_refptr<TestContextProvider> provider_;
scoped_refptr<TestContextProvider> child_provider_;
@@ -2468,9 +2651,10 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
std::unique_ptr<RenderPass> pass = CreateRenderPass();
- CreateCandidateQuadAt(
- resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get(), kOverlayBottomRightRect);
+ CreateCandidateQuadAt(resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get(),
+ pass->shared_quad_state_list.back(), pass.get(),
+ kOverlayBottomRightRect);
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -2484,11 +2668,12 @@ TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2);
EXPECT_CALL(scheduler_,
Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _,
- gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1)))
+ gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1), _, _))
.Times(1);
- EXPECT_CALL(scheduler_, Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _,
- kOverlayBottomRightRect,
- BoundingRect(kUVTopLeft, kUVBottomRight)))
+ EXPECT_CALL(
+ scheduler_,
+ Schedule(1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayBottomRightRect,
+ BoundingRect(kUVTopLeft, kUVBottomRight), _, _))
.Times(1);
DrawFrame(&pass_list, kDisplaySize);
EXPECT_EQ(1U, output_surface_->bind_framebuffer_count());
@@ -2513,7 +2698,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadInUnderlay) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -2523,11 +2708,11 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadInUnderlay) {
EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
EXPECT_CALL(scheduler_,
Schedule(0, gfx::OVERLAY_TRANSFORM_NONE, _,
- gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1)))
+ gfx::Rect(kDisplaySize), gfx::RectF(0, 0, 1, 1), _, _))
.Times(1);
EXPECT_CALL(scheduler_,
Schedule(-1, gfx::OVERLAY_TRANSFORM_NONE, _, kOverlayRect,
- BoundingRect(kUVTopLeft, kUVBottomRight)))
+ BoundingRect(kUVTopLeft, kUVBottomRight), _, _))
.Times(1);
DrawFrame(&pass_list, kDisplaySize);
EXPECT_EQ(1U, output_surface_->bind_framebuffer_count());
@@ -2547,7 +2732,7 @@ TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
@@ -2560,7 +2745,7 @@ TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
// Should not see the primary surface's overlay.
output_surface_->set_is_displayed_as_overlay_plane(false);
EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(0);
DrawFrame(&pass_list, kDisplaySize);
EXPECT_EQ(1U, output_surface_->bind_framebuffer_count());
SwapBuffers();
@@ -2580,7 +2765,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenPartialSwapEnabled) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenOpaqueQuad(resource_provider_.get(),
@@ -2591,7 +2776,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenPartialSwapEnabled) {
output_surface_->set_is_displayed_as_overlay_plane(true);
EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(0);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
DrawFrame(&pass_list, kDisplaySize);
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
SwapBuffers();
@@ -2610,7 +2795,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenEmptySwapAllowed) {
CreateFullscreenCandidateQuad(
resource_provider_.get(), child_resource_provider_.get(),
- pass->shared_quad_state_list.back(), pass.get());
+ child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
CreateFullscreenOpaqueQuad(resource_provider_.get(),
pass->shared_quad_state_list.back(), pass.get());
@@ -2622,7 +2807,7 @@ TEST_F(GLRendererWithOverlaysTest, OccludedQuadNotDrawnWhenEmptySwapAllowed) {
output_surface_->set_is_displayed_as_overlay_plane(true);
EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(0);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
DrawFrame(&pass_list, kDisplaySize);
EXPECT_EQ(0U, output_surface_->bind_framebuffer_count());
SwapBuffers();
@@ -2643,10 +2828,10 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
child_resource_provider_.get(), gfx::Size(32, 32), true);
// Return the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
- SendResourceAndGetChildToParentMap({resource1, resource2, resource3},
- resource_provider_.get(),
- child_resource_provider_.get());
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ SendResourceAndGetChildToParentMap(
+ {resource1, resource2, resource3}, resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get());
ResourceId mapped_resource1 = resource_map[resource1];
ResourceId mapped_resource2 = resource_map[resource2];
@@ -2660,7 +2845,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
frame1.render_passes_in_draw_order = &pass_list;
frame1.overlay_list.resize(2);
frame1.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay1 = frame1.overlay_list.back();
+ OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = mapped_resource1;
overlay1.plane_z_order = 1;
@@ -2668,7 +2853,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
frame2.render_passes_in_draw_order = &pass_list;
frame2.overlay_list.resize(2);
frame2.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay2 = frame2.overlay_list.back();
+ OverlayCandidate& overlay2 = frame2.overlay_list.back();
overlay2.resource_id = mapped_resource2;
overlay2.plane_z_order = 1;
@@ -2676,11 +2861,11 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
frame3.render_passes_in_draw_order = &pass_list;
frame3.overlay_list.resize(2);
frame3.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay3 = frame3.overlay_list.back();
+ OverlayCandidate& overlay3 = frame3.overlay_list.back();
overlay3.resource_id = mapped_resource3;
overlay3.plane_z_order = 1;
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame1);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2704,7 +2889,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
EXPECT_FALSE(resource_provider_->InUse(mapped_resource2));
EXPECT_FALSE(resource_provider_->InUse(mapped_resource3));
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame2);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2720,7 +2905,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
EXPECT_TRUE(resource_provider_->InUse(mapped_resource2));
EXPECT_FALSE(resource_provider_->InUse(mapped_resource3));
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame3);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2738,7 +2923,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
EXPECT_FALSE(resource_provider_->InUse(mapped_resource2));
EXPECT_TRUE(resource_provider_->InUse(mapped_resource3));
// No overlays, release the resource.
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(0);
DirectRenderer::DrawingFrame frame_no_overlays;
frame_no_overlays.render_passes_in_draw_order = &pass_list;
renderer_->set_expect_overlays(false);
@@ -2761,7 +2946,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
// Use the same buffer twice.
renderer_->set_expect_overlays(true);
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame1);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2779,7 +2964,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
EXPECT_FALSE(resource_provider_->InUse(mapped_resource2));
EXPECT_FALSE(resource_provider_->InUse(mapped_resource3));
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame1);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2797,7 +2982,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedWithDelay) {
EXPECT_FALSE(resource_provider_->InUse(mapped_resource2));
EXPECT_FALSE(resource_provider_->InUse(mapped_resource3));
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(0);
renderer_->set_expect_overlays(false);
renderer_->SetCurrentFrame(frame_no_overlays);
renderer_->BeginDrawingFrame();
@@ -2832,10 +3017,10 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
child_resource_provider_.get(), gfx::Size(32, 32), true);
// Return the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
- SendResourceAndGetChildToParentMap({resource1, resource2, resource3},
- resource_provider_.get(),
- child_resource_provider_.get());
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ SendResourceAndGetChildToParentMap(
+ {resource1, resource2, resource3}, resource_provider_.get(),
+ child_resource_provider_.get(), child_provider_.get());
ResourceId mapped_resource1 = resource_map[resource1];
ResourceId mapped_resource2 = resource_map[resource2];
ResourceId mapped_resource3 = resource_map[resource3];
@@ -2848,7 +3033,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
frame1.render_passes_in_draw_order = &pass_list;
frame1.overlay_list.resize(2);
frame1.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay1 = frame1.overlay_list.back();
+ OverlayCandidate& overlay1 = frame1.overlay_list.back();
overlay1.resource_id = mapped_resource1;
overlay1.plane_z_order = 1;
@@ -2856,7 +3041,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
frame2.render_passes_in_draw_order = &pass_list;
frame2.overlay_list.resize(2);
frame2.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay2 = frame2.overlay_list.back();
+ OverlayCandidate& overlay2 = frame2.overlay_list.back();
overlay2.resource_id = mapped_resource2;
overlay2.plane_z_order = 1;
@@ -2864,12 +3049,12 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
frame3.render_passes_in_draw_order = &pass_list;
frame3.overlay_list.resize(2);
frame3.overlay_list.front().use_output_surface_for_resource = true;
- cc::OverlayCandidate& overlay3 = frame3.overlay_list.back();
+ OverlayCandidate& overlay3 = frame3.overlay_list.back();
overlay3.resource_id = mapped_resource3;
overlay3.plane_z_order = 1;
// First frame, with no swap completion.
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame1);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2879,7 +3064,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
Mock::VerifyAndClearExpectations(&scheduler_);
// Second frame, with no swap completion.
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame2);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2892,7 +3077,7 @@ TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturnedAfterGpuQuery) {
// Third frame, still with no swap completion (where the resources would
// otherwise have been released).
- EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(2);
+ EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _, _, _)).Times(2);
renderer_->SetCurrentFrame(frame3);
renderer_->BeginDrawingFrame();
renderer_->FinishDrawingFrame();
@@ -2958,7 +3143,7 @@ class CALayerOverlayRPDQTest : public CALayerOverlayTest {
OverlayProcessor::FilterOperationsMap render_pass_filters_;
OverlayProcessor::FilterOperationsMap render_pass_background_filters_;
CALayerOverlayList ca_layer_list_;
- cc::OverlayCandidateList overlay_list_;
+ OverlayCandidateList overlay_list_;
};
TEST_F(CALayerOverlayRPDQTest, RenderPassDrawQuadNoFilters) {
diff --git a/chromium/components/viz/service/display/renderer_pixeltest.cc b/chromium/components/viz/service/display/renderer_pixeltest.cc
index f939419f0f2..5a4c00d3e26 100644
--- a/chromium/components/viz/service/display/renderer_pixeltest.cc
+++ b/chromium/components/viz/service/display/renderer_pixeltest.cc
@@ -8,7 +8,6 @@
#include <tuple>
#include "base/memory/aligned_memory.h"
-#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "cc/base/math_util.h"
#include "cc/paint/paint_flags.h"
@@ -21,8 +20,11 @@
#include "cc/test/render_pass_test_utils.h"
#include "cc/test/resource_provider_test_utils.h"
#include "cc/test/test_in_process_context_provider.h"
+#include "components/viz/common/gpu/texture_allocation.h"
#include "components/viz/common/quads/picture_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
+#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/gl_renderer.h"
#include "components/viz/test/test_shared_bitmap_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -46,6 +48,72 @@ namespace viz {
namespace {
#if !defined(OS_ANDROID)
+std::unique_ptr<base::SharedMemory> AllocateAndRegisterSharedBitmapMemory(
+ const SharedBitmapId& id,
+ const gfx::Size& size,
+ SharedBitmapManager* shared_bitmap_manager) {
+ std::unique_ptr<base::SharedMemory> shm =
+ bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888);
+ shared_bitmap_manager->ChildAllocatedSharedBitmap(
+ bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size,
+ RGBA_8888),
+ id);
+ return shm;
+}
+
+void DeleteTexture(scoped_refptr<ContextProvider> context_provider,
+ GLuint texture,
+ const gpu::SyncToken& sync_token,
+ bool is_lost) {
+ DCHECK(context_provider);
+ gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
+ DCHECK(gl);
+ gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
+ gl->DeleteTextures(1, &texture);
+}
+
+ResourceId CreateGpuResource(scoped_refptr<ContextProvider> context_provider,
+ cc::LayerTreeResourceProvider* resource_provider,
+ const gfx::Size& size,
+ ResourceFormat format,
+ gfx::ColorSpace color_space,
+ const void* pixels = nullptr) {
+ DCHECK(context_provider);
+ gpu::gles2::GLES2Interface* gl = context_provider->ContextGL();
+ DCHECK(gl);
+ const gpu::Capabilities& caps = context_provider->ContextCapabilities();
+ auto allocation = TextureAllocation::MakeTextureId(
+ gl, caps, format,
+ /*use_gpu_memory_buffer_resources=*/false,
+ /*for_framebuffer_attachment=*/false);
+ if (pixels) {
+ TextureAllocation::UploadStorage(gl, caps, format, size, allocation,
+ color_space, pixels);
+ } else {
+ TextureAllocation::AllocateStorage(gl, caps, format, size, allocation,
+ color_space);
+ }
+ gpu::Mailbox mailbox;
+ gl->GenMailboxCHROMIUM(mailbox.name);
+ gl->ProduceTextureDirectCHROMIUM(allocation.texture_id, mailbox.name);
+ gpu::SyncToken sync_token;
+ gl->GenSyncTokenCHROMIUM(sync_token.GetData());
+ TransferableResource gl_resource = TransferableResource::MakeGL(
+ mailbox, GL_LINEAR, allocation.texture_target, sync_token);
+ gl_resource.size = size;
+ gl_resource.format = format;
+ // We didn't allocate a GpuMemoryBuffer, but we want to set buffer_format for
+ // consistency with other callsites.
+ // TODO(piman): See if we can remove TransferableResource::buffer_format
+ // altogether, it looks redundant with format. crbug.com/836488
+ gl_resource.buffer_format = BufferFormat(format);
+ gl_resource.color_space = std::move(color_space);
+ auto release_callback = SingleReleaseCallback::Create(base::BindOnce(
+ &DeleteTexture, std::move(context_provider), allocation.texture_id));
+ return resource_provider->ImportResource(gl_resource,
+ std::move(release_callback));
+}
+
std::unique_ptr<RenderPass> CreateTestRootRenderPass(int id,
const gfx::Rect& rect) {
std::unique_ptr<RenderPass> pass = RenderPass::Create();
@@ -128,8 +196,10 @@ void CreateTestTwoColoredTextureDrawQuad(
SkColor background_color,
bool premultiplied_alpha,
const SharedQuadState* shared_state,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ SharedBitmapManager* shared_bitmap_manager,
+ scoped_refptr<ContextProvider> child_context_provider,
RenderPass* render_pass) {
SkPMColor pixel_color = premultiplied_alpha
? SkPreMultiplyColor(texel_color)
@@ -153,20 +223,28 @@ void CreateTestTwoColoredTextureDrawQuad(
ResourceId resource;
if (gpu_resource) {
- resource = child_resource_provider->CreateGpuTextureResource(
- rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- gfx::ColorSpace());
+ resource = CreateGpuResource(std::move(child_context_provider),
+ child_resource_provider, rect.size(),
+ RGBA_8888, gfx::ColorSpace(), &pixels.front());
} else {
- resource = child_resource_provider->CreateBitmapResource(
- rect.size(), gfx::ColorSpace(), RGBA_8888);
+ SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
+ std::unique_ptr<base::SharedMemory> shm =
+ AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(),
+ shared_bitmap_manager);
+ resource = child_resource_provider->ImportResource(
+ TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
+ RGBA_8888),
+ SingleReleaseCallback::Create(base::DoNothing()));
+
+ for (int i = 0; i < rect.size().GetArea(); ++i)
+ static_cast<uint32_t*>(shm->memory())[i] = pixels[i];
}
- child_resource_provider->CopyToResource(
- resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size());
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource}, resource_provider,
- child_resource_provider);
+ child_resource_provider,
+ child_context_provider.get());
ResourceId mapped_resource = resource_map[resource];
bool needs_blending = true;
@@ -190,8 +268,10 @@ void CreateTestTextureDrawQuad(
SkColor background_color,
bool premultiplied_alpha,
const SharedQuadState* shared_state,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ SharedBitmapManager* shared_bitmap_manager,
+ scoped_refptr<ContextProvider> child_context_provider,
RenderPass* render_pass) {
SkPMColor pixel_color = premultiplied_alpha
? SkPreMultiplyColor(texel_color)
@@ -204,20 +284,28 @@ void CreateTestTextureDrawQuad(
ResourceId resource;
if (gpu_resource) {
- resource = child_resource_provider->CreateGpuTextureResource(
- rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- gfx::ColorSpace());
+ resource = CreateGpuResource(std::move(child_context_provider),
+ child_resource_provider, rect.size(),
+ RGBA_8888, gfx::ColorSpace(), &pixels.front());
} else {
- resource = child_resource_provider->CreateBitmapResource(
- rect.size(), gfx::ColorSpace(), RGBA_8888);
+ SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
+ std::unique_ptr<base::SharedMemory> shm =
+ AllocateAndRegisterSharedBitmapMemory(shared_bitmap_id, rect.size(),
+ shared_bitmap_manager);
+ resource = child_resource_provider->ImportResource(
+ TransferableResource::MakeSoftware(shared_bitmap_id, rect.size(),
+ RGBA_8888),
+ SingleReleaseCallback::Create(base::DoNothing()));
+
+ for (int i = 0; i < rect.size().GetArea(); ++i)
+ static_cast<uint32_t*>(shm->memory())[i] = pixels[i];
}
- child_resource_provider->CopyToResource(
- resource, reinterpret_cast<uint8_t*>(&pixels.front()), rect.size());
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource}, resource_provider,
- child_resource_provider);
+ child_resource_provider,
+ child_context_provider.get());
ResourceId mapped_resource = resource_map[resource];
bool needs_blending = true;
@@ -239,14 +327,17 @@ void CreateTestTextureDrawQuad(
SkColor background_color,
bool premultiplied_alpha,
const SharedQuadState* shared_state,
- cc::DisplayResourceProvider* resource_provider,
+ DisplayResourceProvider* resource_provider,
cc::LayerTreeResourceProvider* child_resource_provider,
+ SharedBitmapManager* shared_bitmap_manager,
+ scoped_refptr<ContextProvider> child_context_provider,
RenderPass* render_pass) {
float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
CreateTestTextureDrawQuad(gpu_resource, rect, texel_color, vertex_opacity,
background_color, premultiplied_alpha, shared_state,
resource_provider, child_resource_provider,
- render_pass);
+ shared_bitmap_manager,
+ std::move(child_context_provider), render_pass);
}
void CreateTestYUVVideoDrawQuad_FromVideoFrame(
@@ -258,8 +349,9 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
cc::VideoResourceUpdater* video_resource_updater,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
const bool with_alpha = (video_frame->format() == media::PIXEL_FORMAT_I420A);
gfx::ColorSpace video_color_space = video_frame->ColorSpace();
@@ -303,16 +395,17 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
resources.release_callbacks[media::VideoFrame::kAPlane])));
}
- cc::ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+ std::vector<ResourceId> resource_ids_to_transfer;
resource_ids_to_transfer.push_back(resource_y);
resource_ids_to_transfer.push_back(resource_u);
resource_ids_to_transfer.push_back(resource_v);
if (with_alpha)
resource_ids_to_transfer.push_back(resource_a);
// Transfer resources to the parent, and get the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap(
- resource_ids_to_transfer, resource_provider, child_resource_provider);
+ resource_ids_to_transfer, resource_provider, child_resource_provider,
+ child_context_provider);
ResourceId mapped_resource_y = resource_map[resource_y];
ResourceId mapped_resource_u = resource_map[resource_u];
@@ -351,7 +444,7 @@ void CreateTestYUVVideoDrawQuad_FromVideoFrame(
}
ResourceFormat yuv_highbit_resource_format =
- child_resource_provider->YuvResourceFormat(bits_per_channel);
+ video_resource_updater->YuvResourceFormat(bits_per_channel);
float multiplier = 1.0;
@@ -375,8 +468,9 @@ void CreateTestY16TextureDrawQuad_FromVideoFrame(
cc::VideoResourceUpdater* video_resource_updater,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
cc::VideoFrameExternalResources resources =
video_resource_updater->CreateExternalResourcesFromVideoFrame(
video_frame);
@@ -390,9 +484,10 @@ void CreateTestY16TextureDrawQuad_FromVideoFrame(
SingleReleaseCallback::Create(std::move(resources.release_callbacks[0])));
// Transfer resources to the parent, and get the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource_y}, resource_provider,
- child_resource_provider);
+ child_resource_provider,
+ child_context_provider);
ResourceId mapped_resource_y = resource_map[resource_y];
auto* quad = render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
@@ -458,8 +553,9 @@ void CreateTestYUVVideoDrawQuad_Striped(
cc::VideoResourceUpdater* video_resource_updater,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
format, rect.size(), rect, rect.size(), base::TimeDelta());
@@ -497,7 +593,7 @@ void CreateTestYUVVideoDrawQuad_Striped(
CreateTestYUVVideoDrawQuad_FromVideoFrame(
shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
video_resource_updater, rect, visible_rect, resource_provider,
- child_resource_provider);
+ child_resource_provider, child_context_provider);
}
// Creates a video frame of size background_size filled with yuv_background,
@@ -521,8 +617,9 @@ void CreateTestYUVVideoDrawQuad_TwoColor(
uint8_t v_foreground,
RenderPass* render_pass,
cc::VideoResourceUpdater* video_resource_updater,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
const gfx::Rect rect(background_size);
scoped_refptr<media::VideoFrame> video_frame =
@@ -566,7 +663,7 @@ void CreateTestYUVVideoDrawQuad_TwoColor(
CreateTestYUVVideoDrawQuad_FromVideoFrame(
shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
video_resource_updater, rect, visible_rect, resource_provider,
- child_resource_provider);
+ child_resource_provider, child_context_provider);
}
void CreateTestYUVVideoDrawQuad_Solid(
@@ -582,8 +679,9 @@ void CreateTestYUVVideoDrawQuad_Solid(
cc::VideoResourceUpdater* video_resource_updater,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
scoped_refptr<media::VideoFrame> video_frame = media::VideoFrame::CreateFrame(
format, rect.size(), rect, rect.size(), base::TimeDelta());
video_frame->metadata()->SetInteger(media::VideoFrameMetadata::COLOR_SPACE,
@@ -605,7 +703,7 @@ void CreateTestYUVVideoDrawQuad_Solid(
CreateTestYUVVideoDrawQuad_FromVideoFrame(
shared_state, video_frame, alpha_value, tex_coord_rect, render_pass,
video_resource_updater, rect, visible_rect, resource_provider,
- child_resource_provider);
+ child_resource_provider, child_context_provider);
}
void CreateTestYUVVideoDrawQuad_NV12(
@@ -617,10 +715,12 @@ void CreateTestYUVVideoDrawQuad_NV12(
uint8_t u,
uint8_t v,
RenderPass* render_pass,
+ cc::VideoResourceUpdater* video_resource_updater,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ scoped_refptr<ContextProvider> child_context_provider) {
gfx::ColorSpace gfx_color_space = gfx::ColorSpace::CreateREC601();
if (video_frame_color_space == media::COLOR_SPACE_JPEG) {
gfx_color_space = gfx::ColorSpace::CreateJpeg();
@@ -631,29 +731,26 @@ void CreateTestYUVVideoDrawQuad_NV12(
const gfx::Size uv_tex_size = media::VideoFrame::PlaneSize(
media::PIXEL_FORMAT_NV12, media::VideoFrame::kUVPlane, rect.size());
- ResourceId resource_y = child_resource_provider->CreateGpuTextureResource(
- rect.size(), ResourceTextureHint::kDefault,
- child_resource_provider->YuvResourceFormat(8), gfx_color_space);
- ResourceId resource_u = child_resource_provider->CreateGpuTextureResource(
- uv_tex_size, ResourceTextureHint::kDefault, RGBA_8888, gfx_color_space);
- ResourceId resource_v = resource_u;
- ResourceId resource_a = 0;
-
std::vector<uint8_t> y_pixels(ya_tex_size.GetArea(), y);
- child_resource_provider->CopyToResource(resource_y, y_pixels.data(),
- ya_tex_size);
+ ResourceId resource_y = CreateGpuResource(
+ child_context_provider, child_resource_provider, ya_tex_size,
+ video_resource_updater->YuvResourceFormat(8), gfx_color_space,
+ y_pixels.data());
// U goes in the R component and V goes in the G component.
uint32_t rgba_pixel = (u << 24) | (v << 16);
std::vector<uint32_t> uv_pixels(uv_tex_size.GetArea(), rgba_pixel);
- child_resource_provider->CopyToResource(
- resource_u, reinterpret_cast<uint8_t*>(uv_pixels.data()), uv_tex_size);
+ ResourceId resource_u = CreateGpuResource(
+ child_context_provider, child_resource_provider, uv_tex_size, RGBA_8888,
+ gfx_color_space, uv_pixels.data());
+ ResourceId resource_v = resource_u;
+ ResourceId resource_a = 0;
// Transfer resources to the parent, and get the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
- SendResourceAndGetChildToParentMap({resource_y, resource_u, resource_v},
- resource_provider,
- child_resource_provider);
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ SendResourceAndGetChildToParentMap(
+ {resource_y, resource_u, resource_v}, resource_provider,
+ child_resource_provider, child_context_provider.get());
ResourceId mapped_resource_y = resource_map[resource_y];
ResourceId mapped_resource_u = resource_map[resource_u];
@@ -686,8 +783,9 @@ void CreateTestY16TextureDrawQuad_TwoColor(
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
const gfx::Rect& foreground_rect,
- cc::DisplayResourceProvider* resource_provider,
- cc::LayerTreeResourceProvider* child_resource_provider) {
+ DisplayResourceProvider* resource_provider,
+ cc::LayerTreeResourceProvider* child_resource_provider,
+ ContextProvider* child_context_provider) {
std::unique_ptr<unsigned char, base::AlignedFreeDeleter> memory(
static_cast<unsigned char*>(
base::AlignedAlloc(rect.size().GetArea() * 2,
@@ -730,7 +828,7 @@ void CreateTestY16TextureDrawQuad_TwoColor(
CreateTestY16TextureDrawQuad_FromVideoFrame(
shared_state, video_frame, tex_coord_rect, render_pass,
video_resource_updater, rect, visible_rect, resource_provider,
- child_resource_provider);
+ child_resource_provider, child_context_provider);
}
using RendererTypes =
@@ -783,6 +881,13 @@ bool FuzzyForSoftwareOnlyPixelComparator<SoftwareRenderer>::Compare(
}
template <>
+bool FuzzyForSoftwareOnlyPixelComparator<SkiaRenderer>::Compare(
+ const SkBitmap& actual_bmp,
+ const SkBitmap& expected_bmp) const {
+ return fuzzy_.Compare(actual_bmp, expected_bmp);
+}
+
+template <>
bool FuzzyForSoftwareOnlyPixelComparator<
cc::SoftwareRendererWithExpandedViewport>::
Compare(const SkBitmap& actual_bmp, const SkBitmap& expected_bmp) const {
@@ -861,13 +966,14 @@ TYPED_TEST(RendererPixelTest, PremultipliedTextureWithoutBackground) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- CreateTestTextureDrawQuad(this->use_gpu(),
- gfx::Rect(this->device_viewport_size_),
- SkColorSetARGB(128, 0, 255, 0), // Texel color.
- SK_ColorTRANSPARENT, // Background color.
- true, // Premultiplied alpha.
- shared_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), pass.get());
+ CreateTestTextureDrawQuad(
+ this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+ SkColorSetARGB(128, 0, 255, 0), // Texel color.
+ SK_ColorTRANSPARENT, // Background color.
+ true, // Premultiplied alpha.
+ shared_state, this->resource_provider_.get(),
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, pass.get());
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
@@ -890,13 +996,14 @@ TYPED_TEST(RendererPixelTest, PremultipliedTextureWithBackground) {
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
texture_quad_state->opacity = 0.8f;
- CreateTestTextureDrawQuad(this->use_gpu(),
- gfx::Rect(this->device_viewport_size_),
- SkColorSetARGB(204, 120, 255, 120), // Texel color.
- SK_ColorGREEN, // Background color.
- true, // Premultiplied alpha.
- texture_quad_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), pass.get());
+ CreateTestTextureDrawQuad(
+ this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+ SkColorSetARGB(204, 120, 255, 120), // Texel color.
+ SK_ColorGREEN, // Background color.
+ true, // Premultiplied alpha.
+ texture_quad_state, this->resource_provider_.get(),
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, pass.get());
SharedQuadState* color_quad_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -1022,14 +1129,15 @@ TEST_F(GLRendererPixelTest,
texture_quad_state->opacity = 0.8f;
float vertex_opacity[4] = {1.f, 1.f, 0.f, 0.f};
- CreateTestTextureDrawQuad(this->use_gpu(),
- gfx::Rect(this->device_viewport_size_),
- SkColorSetARGB(204, 120, 255, 120), // Texel color.
- vertex_opacity,
- SK_ColorGREEN, // Background color.
- true, // Premultiplied alpha.
- texture_quad_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), pass.get());
+ CreateTestTextureDrawQuad(
+ this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+ SkColorSetARGB(204, 120, 255, 120), // Texel color.
+ vertex_opacity,
+ SK_ColorGREEN, // Background color.
+ true, // Premultiplied alpha.
+ texture_quad_state, this->resource_provider_.get(),
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, pass.get());
SharedQuadState* color_quad_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -1109,12 +1217,6 @@ class IntersectingQuadPixelTest : public RendererPixelTest<TypeParam> {
RenderPassList pass_list_;
};
-// TODO(weiliangc): Move these tests to normal RendererPixelTest as they pass
-// with SkiaRenderer. Failed test list recorded in crbug.com/821176.
-template <typename TypeParam>
-class IntersectingQuadNonSkiaPixelTest
- : public IntersectingQuadPixelTest<TypeParam> {};
-
template <typename TypeParam>
class IntersectingQuadGLPixelTest
: public IntersectingQuadPixelTest<TypeParam> {
@@ -1123,15 +1225,17 @@ class IntersectingQuadGLPixelTest
IntersectingQuadPixelTest<TypeParam>::SetUp();
constexpr bool kUseStreamVideoDrawQuad = false;
constexpr bool kUseGpuMemoryBufferResources = false;
+ constexpr bool kUseR16Texture = false;
+ constexpr int kMaxResourceSize = 10000;
video_resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
this->child_context_provider_.get(), nullptr,
this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
- kUseGpuMemoryBufferResources);
+ kUseGpuMemoryBufferResources, kUseR16Texture, kMaxResourceSize);
video_resource_updater2_ = std::make_unique<cc::VideoResourceUpdater>(
this->child_context_provider_.get(), nullptr,
this->child_resource_provider_.get(), kUseStreamVideoDrawQuad,
- kUseGpuMemoryBufferResources);
+ kUseGpuMemoryBufferResources, kUseR16Texture, kMaxResourceSize);
}
protected:
@@ -1150,7 +1254,6 @@ using GLRendererTypes =
::testing::Types<GLRenderer, cc::GLRendererWithExpandedViewport>;
TYPED_TEST_CASE(IntersectingQuadPixelTest, RendererTypes);
-TYPED_TEST_CASE(IntersectingQuadNonSkiaPixelTest, NonSkiaRendererTypes);
TYPED_TEST_CASE(IntersectingQuadGLPixelTest, GLRendererTypes);
TYPED_TEST_CASE(IntersectingQuadSoftwareTest, SoftwareRendererTypes);
@@ -1170,6 +1273,11 @@ TYPED_TEST(IntersectingQuadPixelTest, SolidColorQuads) {
FILE_PATH_LITERAL("intersecting_blue_green.png"));
}
+static inline SkColor GetSkiaOrGLColor(const SkColor& color) {
+ return SkColorSetARGB(SkColorGetA(color), SkColorGetB(color),
+ SkColorGetG(color), SkColorGetR(color));
+}
+
template <typename TypeParam>
SkColor GetColor(const SkColor& color) {
return color;
@@ -1177,28 +1285,35 @@ SkColor GetColor(const SkColor& color) {
template <>
SkColor GetColor<GLRenderer>(const SkColor& color) {
- return SkColorSetARGB(SkColorGetA(color), SkColorGetB(color),
- SkColorGetG(color), SkColorGetR(color));
+ return GetSkiaOrGLColor(color);
}
+
+template <>
+SkColor GetColor<SkiaRenderer>(const SkColor& color) {
+ return GetSkiaOrGLColor(color);
+}
+
template <>
SkColor GetColor<cc::GLRendererWithExpandedViewport>(const SkColor& color) {
- return GetColor<GLRenderer>(color);
+ return GetSkiaOrGLColor(color);
}
-TYPED_TEST(IntersectingQuadNonSkiaPixelTest, TexturedQuads) {
+TYPED_TEST(IntersectingQuadPixelTest, TexturedQuads) {
this->SetupQuadStateAndRenderPass();
CreateTestTwoColoredTextureDrawQuad(
this->use_gpu(), this->quad_rect_,
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
true, this->front_quad_state_, this->resource_provider_.get(),
- this->child_resource_provider_.get(), this->render_pass_.get());
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, this->render_pass_.get());
CreateTestTwoColoredTextureDrawQuad(
this->use_gpu(), this->quad_rect_,
GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
true, this->back_quad_state_, this->resource_provider_.get(),
- this->child_resource_provider_.get(), this->render_pass_.get());
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, this->render_pass_.get());
SCOPED_TRACE("IntersectingTexturedQuads");
this->AppendBackgroundAndRunTest(
@@ -1261,7 +1376,7 @@ TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
FILE_PATH_LITERAL("intersecting_blue_green_squares.png"));
}
-TYPED_TEST(IntersectingQuadNonSkiaPixelTest, RenderPassQuads) {
+TYPED_TEST(IntersectingQuadPixelTest, RenderPassQuads) {
this->SetupQuadStateAndRenderPass();
int child_pass_id1 = 2;
int child_pass_id2 = 3;
@@ -1278,13 +1393,15 @@ TYPED_TEST(IntersectingQuadNonSkiaPixelTest, RenderPassQuads) {
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)),
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 255)), SK_ColorTRANSPARENT,
true, child1_quad_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), child_pass1.get());
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, child_pass1.get());
CreateTestTwoColoredTextureDrawQuad(
this->use_gpu(), this->quad_rect_,
GetColor<TypeParam>(SkColorSetARGB(255, 0, 255, 0)),
GetColor<TypeParam>(SkColorSetARGB(255, 0, 0, 0)), SK_ColorTRANSPARENT,
true, child2_quad_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), child_pass2.get());
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, child_pass2.get());
CreateTestRenderPassDrawQuad(this->front_quad_state_, this->quad_rect_,
child_pass_id1, this->render_pass_.get());
@@ -1312,14 +1429,16 @@ TYPED_TEST(IntersectingQuadGLPixelTest, YUVVideoQuads) {
media::COLOR_SPACE_JPEG, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f),
this->quad_rect_.size(), this->quad_rect_, 0, 128, 128, inner_rect, 29,
255, 107, this->render_pass_.get(), this->video_resource_updater_.get(),
- this->resource_provider_.get(), this->child_resource_provider_.get());
+ this->resource_provider_.get(), this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
CreateTestYUVVideoDrawQuad_TwoColor(
this->back_quad_state_, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_JPEG,
false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), this->quad_rect_.size(),
this->quad_rect_, 149, 43, 21, inner_rect, 0, 128, 128,
this->render_pass_.get(), this->video_resource_updater2_.get(),
- this->resource_provider_.get(), this->child_resource_provider_.get());
+ this->resource_provider_.get(), this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
SCOPED_TRACE("IntersectingVideoQuads");
this->AppendBackgroundAndRunTest(
@@ -1339,13 +1458,15 @@ TYPED_TEST(IntersectingQuadGLPixelTest, Y16VideoQuads) {
this->front_quad_state_, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 18, 0,
this->render_pass_.get(), this->video_resource_updater_.get(),
this->quad_rect_, this->quad_rect_, inner_rect,
- this->resource_provider_.get(), this->child_resource_provider_.get());
+ this->resource_provider_.get(), this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
CreateTestY16TextureDrawQuad_TwoColor(
this->back_quad_state_, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 0, 182,
this->render_pass_.get(), this->video_resource_updater2_.get(),
this->quad_rect_, this->quad_rect_, inner_rect,
- this->resource_provider_.get(), this->child_resource_provider_.get());
+ this->resource_provider_.get(), this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
SCOPED_TRACE("IntersectingVideoQuads");
this->AppendBackgroundAndRunTest(
@@ -1363,13 +1484,14 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithoutBackground) {
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- CreateTestTextureDrawQuad(this->use_gpu(),
- gfx::Rect(this->device_viewport_size_),
- SkColorSetARGB(128, 0, 255, 0), // Texel color.
- SK_ColorTRANSPARENT, // Background color.
- false, // Premultiplied alpha.
- shared_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), pass.get());
+ CreateTestTextureDrawQuad(
+ this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+ SkColorSetARGB(128, 0, 255, 0), // Texel color.
+ SK_ColorTRANSPARENT, // Background color.
+ false, // Premultiplied alpha.
+ shared_state, this->resource_provider_.get(),
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, pass.get());
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
@@ -1393,13 +1515,14 @@ TEST_F(GLRendererPixelTest, NonPremultipliedTextureWithBackground) {
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
texture_quad_state->opacity = 0.8f;
- CreateTestTextureDrawQuad(this->use_gpu(),
- gfx::Rect(this->device_viewport_size_),
- SkColorSetARGB(204, 120, 255, 120), // Texel color.
- SK_ColorGREEN, // Background color.
- false, // Premultiplied alpha.
- texture_quad_state, this->resource_provider_.get(),
- this->child_resource_provider_.get(), pass.get());
+ CreateTestTextureDrawQuad(
+ this->use_gpu(), gfx::Rect(this->device_viewport_size_),
+ SkColorSetARGB(204, 120, 255, 120), // Texel color.
+ SK_ColorGREEN, // Background color.
+ false, // Premultiplied alpha.
+ texture_quad_state, this->resource_provider_.get(),
+ this->child_resource_provider_.get(), this->shared_bitmap_manager_.get(),
+ this->child_context_provider_, pass.get());
SharedQuadState* color_quad_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
@@ -1449,7 +1572,8 @@ class VideoGLRendererPixelTest : public cc::GLRendererPixelTest {
shared_state, format, color_space, false, tex_coord_rect,
background_size, gfx::Rect(background_size), 128, 128, 128, green_rect,
149, 43, 21, pass.get(), video_resource_updater_.get(),
- resource_provider_.get(), child_resource_provider_.get());
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_context_provider_.get());
pass_list->push_back(std::move(pass));
}
@@ -1457,9 +1581,12 @@ class VideoGLRendererPixelTest : public cc::GLRendererPixelTest {
GLRendererPixelTest::SetUp();
constexpr bool kUseStreamVideoDrawQuad = false;
constexpr bool kUseGpuMemoryBufferResources = false;
+ constexpr bool kUseR16Texture = false;
+ constexpr int kMaxResourceSize = 10000;
video_resource_updater_ = std::make_unique<cc::VideoResourceUpdater>(
child_context_provider_.get(), nullptr, child_resource_provider_.get(),
- kUseStreamVideoDrawQuad, kUseGpuMemoryBufferResources);
+ kUseStreamVideoDrawQuad, kUseGpuMemoryBufferResources, kUseR16Texture,
+ kMaxResourceSize);
}
std::unique_ptr<cc::VideoResourceUpdater> video_resource_updater_;
@@ -1487,7 +1614,7 @@ TEST_P(VideoGLRendererPixelHiLoTest, SimpleYUVRect) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1515,7 +1642,8 @@ TEST_P(VideoGLRendererPixelHiLoTest, ClippedYUVRect) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
false, IsHighbit(), gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
video_resource_updater_.get(), draw_rect, viewport,
- resource_provider_.get(), child_resource_provider_.get());
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1541,7 +1669,7 @@ TEST_F(VideoGLRendererPixelHiLoTest, OffsetYUVRect) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
false, false, gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f), pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1568,7 +1696,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVRectBlack) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_SD_REC601,
false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1597,7 +1725,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRect) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_JPEG, false,
gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1619,8 +1747,9 @@ TEST_F(VideoGLRendererPixelTest, SimpleNV12JRect) {
// YUV of (149,43,21) should be green (0,255,0) in RGB.
CreateTestYUVVideoDrawQuad_NV12(
shared_state, media::COLOR_SPACE_JPEG, gfx::ColorSpace::CreateJpeg(),
- gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(), rect, rect,
- resource_provider_.get(), child_resource_provider_.get());
+ gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 149, 43, 21, pass.get(),
+ video_resource_updater_.get(), rect, rect, resource_provider_.get(),
+ child_resource_provider_.get(), child_context_provider_);
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1668,7 +1797,7 @@ TEST_F(VideoGLRendererPixelTest, SimpleYUVJRectGrey) {
shared_state, media::PIXEL_FORMAT_I420, media::COLOR_SPACE_JPEG, false,
gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 15, 128, 128, pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1694,7 +1823,7 @@ TEST_F(VideoGLRendererPixelHiLoTest, SimpleYUVARect) {
shared_state, media::PIXEL_FORMAT_I420A, media::COLOR_SPACE_SD_REC601,
false, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
@@ -1723,7 +1852,7 @@ TEST_F(VideoGLRendererPixelTest, FullyTransparentYUVARect) {
shared_state, media::PIXEL_FORMAT_I420A, media::COLOR_SPACE_SD_REC601,
true, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), pass.get(),
video_resource_updater_.get(), rect, rect, resource_provider_.get(),
- child_resource_provider_.get());
+ child_resource_provider_.get(), child_context_provider_.get());
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
@@ -1749,7 +1878,8 @@ TEST_F(VideoGLRendererPixelTest, TwoColorY16Rect) {
CreateTestY16TextureDrawQuad_TwoColor(
shared_state, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f), 68, 123, pass.get(),
video_resource_updater_.get(), rect, rect, upper_rect,
- resource_provider_.get(), child_resource_provider_.get());
+ resource_provider_.get(), child_resource_provider_.get(),
+ child_context_provider_.get());
RenderPassList pass_list;
pass_list.push_back(std::move(pass));
@@ -1760,7 +1890,7 @@ TEST_F(VideoGLRendererPixelTest, TwoColorY16Rect) {
cc::FuzzyPixelOffByOneComparator(true)));
}
-TYPED_TEST(NonSkiaRendererPixelTest, FastPassColorFilterAlpha) {
+TYPED_TEST(RendererPixelTest, FastPassColorFilterAlpha) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -1838,7 +1968,7 @@ TYPED_TEST(NonSkiaRendererPixelTest, FastPassColorFilterAlpha) {
FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
}
-TYPED_TEST(NonSkiaRendererPixelTest, FastPassSaturateFilter) {
+TYPED_TEST(RendererPixelTest, FastPassSaturateFilter) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -1898,7 +2028,7 @@ TYPED_TEST(NonSkiaRendererPixelTest, FastPassSaturateFilter) {
FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
}
-TYPED_TEST(NonSkiaRendererPixelTest, FastPassFilterChain) {
+TYPED_TEST(RendererPixelTest, FastPassFilterChain) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -1960,7 +2090,7 @@ TYPED_TEST(NonSkiaRendererPixelTest, FastPassFilterChain) {
FuzzyForSoftwareOnlyPixelComparator<TypeParam>(false)));
}
-TYPED_TEST(NonSkiaRendererPixelTest, FastPassColorFilterAlphaTranslation) {
+TYPED_TEST(RendererPixelTest, FastPassColorFilterAlphaTranslation) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -2142,7 +2272,7 @@ TYPED_TEST(RendererPixelTest, EnlargedRenderPassTextureWithAntiAliasing) {
// This tests the case where we have a RenderPass with a mask, but the quad
// for the masked surface does not include the full surface texture.
-TYPED_TEST(NonSkiaRendererPixelTest, RenderPassAndMaskWithPartialQuad) {
+TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -2186,23 +2316,20 @@ TYPED_TEST(NonSkiaRendererPixelTest, RenderPassAndMaskWithPartialQuad) {
ResourceId mask_resource_id;
if (this->use_gpu()) {
- mask_resource_id = this->child_resource_provider_->CreateGpuTextureResource(
- mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- gfx::ColorSpace());
+ mask_resource_id = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ mask_rect.size(), RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
} else {
- mask_resource_id = this->child_resource_provider_->CreateBitmapResource(
- mask_rect.size(), gfx::ColorSpace(), RGBA_8888);
+ mask_resource_id =
+ this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
}
- this->child_resource_provider_->CopyToResource(
- mask_resource_id, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
- mask_rect.size());
-
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({mask_resource_id},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
// This RenderPassDrawQuad does not include the full |viewport_rect|
@@ -2241,7 +2368,7 @@ TYPED_TEST(NonSkiaRendererPixelTest, RenderPassAndMaskWithPartialQuad) {
// This tests the case where we have a RenderPass with a mask, but the quad
// for the masked surface does not include the full surface texture.
-TYPED_TEST(NonSkiaRendererPixelTest, RenderPassAndMaskWithPartialQuad2) {
+TYPED_TEST(RendererPixelTest, RenderPassAndMaskWithPartialQuad2) {
gfx::Rect viewport_rect(this->device_viewport_size_);
int root_pass_id = 1;
@@ -2285,23 +2412,20 @@ TYPED_TEST(NonSkiaRendererPixelTest, RenderPassAndMaskWithPartialQuad2) {
ResourceId mask_resource_id;
if (this->use_gpu()) {
- mask_resource_id = this->child_resource_provider_->CreateGpuTextureResource(
- mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- gfx::ColorSpace());
+ mask_resource_id = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ mask_rect.size(), RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
} else {
- mask_resource_id = this->child_resource_provider_->CreateBitmapResource(
- mask_rect.size(), gfx::ColorSpace(), RGBA_8888);
+ mask_resource_id =
+ this->AllocateAndFillSoftwareResource(mask_rect.size(), bitmap);
}
- this->child_resource_provider_->CopyToResource(
- mask_resource_id, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
- mask_rect.size());
-
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({mask_resource_id},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_mask_resource_id = resource_map[mask_resource_id];
// This RenderPassDrawQuad does not include the full |viewport_rect|
@@ -2440,16 +2564,14 @@ class RendererPixelTestWithBackgroundFilter
gfx::Rect filter_pass_layer_rect_;
};
+// The software renderer does not support background filters yet.
using BackgroundFilterRendererTypes =
- ::testing::Types<GLRenderer, SoftwareRenderer>;
+ ::testing::Types<GLRenderer, SkiaRenderer>;
+
TYPED_TEST_CASE(RendererPixelTestWithBackgroundFilter,
BackgroundFilterRendererTypes);
-using GLRendererPixelTestWithBackgroundFilter =
- RendererPixelTestWithBackgroundFilter<GLRenderer>;
-
-// TODO(skaslev): The software renderer does not support filters yet.
-TEST_F(GLRendererPixelTestWithBackgroundFilter, InvertFilter) {
+TYPED_TEST(RendererPixelTestWithBackgroundFilter, InvertFilter) {
this->background_filters_.Append(
cc::FilterOperation::CreateInvertFilter(1.f));
@@ -2771,21 +2893,19 @@ TEST_F(GLRendererPixelTest, TileDrawQuadForceAntiAliasingOff) {
gfx::Size tile_size(32, 32);
ResourceId resource;
if (this->use_gpu()) {
- resource = this->child_resource_provider_->CreateGpuTextureResource(
- tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+ resource = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ tile_size, RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
} else {
- resource = this->child_resource_provider_->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
+ resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
}
- this->child_resource_provider_->CopyToResource(
- resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
-
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
int id = 1;
@@ -3207,19 +3327,18 @@ TYPED_TEST(NonSkiaRendererPixelTest, TileDrawQuadNearestNeighbor) {
gfx::Size tile_size(2, 2);
ResourceId resource;
if (this->use_gpu()) {
- resource = this->child_resource_provider_->CreateGpuTextureResource(
- tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+ resource = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ tile_size, RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
} else {
- resource = this->child_resource_provider_->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
+ resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
}
- this->child_resource_provider_->CopyToResource(
- resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
int id = 1;
@@ -3262,17 +3381,15 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadNearestNeighbor) {
draw_point_color(&canvas, 1, 1, SK_ColorGREEN);
gfx::Size tile_size(2, 2);
- ResourceId resource = this->child_resource_provider_->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
-
- this->child_resource_provider_->CopyToResource(
- resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
+ ResourceId resource =
+ this->AllocateAndFillSoftwareResource(tile_size, bitmap);
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
int id = 1;
@@ -3317,17 +3434,15 @@ TYPED_TEST(SoftwareRendererPixelTest, TextureDrawQuadLinear) {
}
gfx::Size tile_size(2, 2);
- ResourceId resource = this->child_resource_provider_->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
-
- this->child_resource_provider_->CopyToResource(
- resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
+ ResourceId resource =
+ this->AllocateAndFillSoftwareResource(tile_size, bitmap);
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
int id = 1;
@@ -3666,20 +3781,16 @@ TEST_F(GLRendererPixelTest, TextureQuadBatching) {
inset_rect.Inset(6, 6, 4, 4);
}
- ResourceId resource =
- this->child_resource_provider_->CreateGpuTextureResource(
- mask_rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- gfx::ColorSpace());
-
- this->child_resource_provider_->CopyToResource(
- resource, reinterpret_cast<uint8_t*>(bitmap.getPixels()),
- mask_rect.size());
+ ResourceId resource = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ mask_rect.size(), RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
// Arbitrary dividing lengths to divide up the resource into 16 quads.
@@ -3748,19 +3859,18 @@ TEST_F(GLRendererPixelTest, TileQuadClamping) {
ResourceId resource;
if (this->use_gpu()) {
- resource = this->child_resource_provider_->CreateGpuTextureResource(
- tile_size, ResourceTextureHint::kDefault, RGBA_8888, gfx::ColorSpace());
+ resource = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ tile_size, RGBA_8888, gfx::ColorSpace(), bitmap.getPixels());
} else {
- resource = this->child_resource_provider_->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
+ resource = this->AllocateAndFillSoftwareResource(tile_size, bitmap);
}
- this->child_resource_provider_->CopyToResource(
- resource, static_cast<uint8_t*>(bitmap.getPixels()), tile_size);
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource},
this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
int id = 1;
@@ -3847,7 +3957,7 @@ TEST_F(GLRendererPixelTestWithOverdrawFeedback, TranslucentRectangles) {
cc::ExactPixelComparator(true)));
}
-using ColorSpacePair = std::tuple<gfx::ColorSpace, gfx::ColorSpace>;
+using ColorSpacePair = std::tuple<gfx::ColorSpace, gfx::ColorSpace, bool>;
class ColorTransformPixelTest
: public GLRendererPixelTest,
@@ -3857,7 +3967,7 @@ class ColorTransformPixelTest
// Note that this size of 17 is not random -- it is chosen to match the
// size of LUTs that are created. If we did not match the LUT size exactly,
// then the error for LUT based transforms is much larger.
- device_viewport_size_ = gfx::Size(17, 4);
+ device_viewport_size_ = gfx::Size(17, 5);
src_color_space_ = std::get<0>(GetParam());
dst_color_space_ = std::get<1>(GetParam());
if (!src_color_space_.IsValid()) {
@@ -3868,9 +3978,11 @@ class ColorTransformPixelTest
dst_color_space_ =
gfx::ICCProfileForTestingNoAnalyticTrFn().GetColorSpace();
}
+ premultiplied_alpha_ = std::get<2>(GetParam());
}
gfx::ColorSpace src_color_space_;
gfx::ColorSpace dst_color_space_;
+ bool premultiplied_alpha_ = false;
};
TEST_P(ColorTransformPixelTest, Basic) {
@@ -3883,15 +3995,25 @@ TEST_P(ColorTransformPixelTest, Basic) {
// Row 1: Gradient of green from 0 to 255
// Row 2: Gradient of blue from 0 to 255
// Row 3: Gradient of grey from 0 to 255
+ // Row 4: Gradient of alpha from 0 to 255 with mixed colors.
for (int x = 0; x < rect.width(); ++x) {
- int v = (x * 255) / (rect.width() - 1);
+ int gradient_value = (x * 255) / (rect.width() - 1);
for (int y = 0; y < rect.height(); ++y) {
- for (int c = 0; c < 3; ++c) {
- if (y == c || y == rect.height() - 1) {
- input_colors[c + 4 * (x + rect.width() * y)] = v;
+ uint8_t* pixel = &input_colors[4 * (x + rect.width() * y)];
+ pixel[3] = 255;
+ if (y < 3) {
+ pixel[y] = gradient_value;
+ } else if (y == 3) {
+ pixel[0] = pixel[1] = pixel[2] = gradient_value;
+ } else {
+ if (premultiplied_alpha_) {
+ pixel[x % 3] = gradient_value;
+ pixel[3] = gradient_value;
+ } else {
+ pixel[x % 3] = 0xFF;
+ pixel[3] = gradient_value;
}
}
- input_colors[3 + 4 * (x + rect.width() * y)] = 255;
}
}
@@ -3915,30 +4037,30 @@ TEST_P(ColorTransformPixelTest, Basic) {
color.set_y(std::min(std::max(0.f, color.y()), 1.f));
color.set_z(std::min(std::max(0.f, color.z()), 1.f));
expected_output_colors[i] =
- SkColorSetARGBInline(255, static_cast<size_t>(255.f * color.x() + 0.5f),
- static_cast<size_t>(255.f * color.y() + 0.5f),
- static_cast<size_t>(255.f * color.z() + 0.5f));
+ SkColorSetARGB(255, static_cast<size_t>(255.f * color.x() + 0.5f),
+ static_cast<size_t>(255.f * color.y() + 0.5f),
+ static_cast<size_t>(255.f * color.z() + 0.5f));
}
int id = 1;
std::unique_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
pass->color_space = dst_color_space_;
+ // Append a quad to execute the transform.
{
SharedQuadState* shared_state =
CreateTestSharedQuadState(gfx::Transform(), rect, pass.get());
- ResourceId resource = child_resource_provider_->CreateGpuTextureResource(
- rect.size(), ResourceTextureHint::kDefault, RGBA_8888,
- src_color_space_);
- this->child_resource_provider_->CopyToResource(
- resource, input_colors.data(), rect.size());
+ ResourceId resource = CreateGpuResource(
+ this->child_context_provider_, this->child_resource_provider_.get(),
+ rect.size(), RGBA_8888, src_color_space_, input_colors.data());
// Return the mapped resource id.
- cc::ResourceProvider::ResourceIdMap resource_map =
- SendResourceAndGetChildToParentMap(
- {resource}, this->resource_provider_.get(),
- this->child_resource_provider_.get());
+ std::unordered_map<ResourceId, ResourceId> resource_map =
+ SendResourceAndGetChildToParentMap({resource},
+ this->resource_provider_.get(),
+ this->child_resource_provider_.get(),
+ this->child_context_provider_.get());
ResourceId mapped_resource = resource_map[resource];
bool needs_blending = true;
@@ -3946,17 +4068,16 @@ TEST_P(ColorTransformPixelTest, Basic) {
const gfx::PointF uv_bottom_right(1.0f, 1.0f);
const bool flipped = false;
const bool nearest_neighbor = false;
- const bool premultiplied_alpha = false;
auto* quad = pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
quad->SetNew(shared_state, rect, rect, needs_blending, mapped_resource,
- premultiplied_alpha, uv_top_left, uv_bottom_right,
+ premultiplied_alpha_, uv_top_left, uv_bottom_right,
SK_ColorBLACK, vertex_opacity, flipped, nearest_neighbor,
false);
auto* color_quad = pass->CreateAndAppendDrawQuad<SolidColorDrawQuad>();
- color_quad->SetNew(shared_state, rect, rect, SK_ColorWHITE, false);
+ color_quad->SetNew(shared_state, rect, rect, SK_ColorBLACK, false);
}
RenderPassList pass_list;
@@ -4033,17 +4154,23 @@ gfx::ColorSpace intermediate_color_spaces[] = {
gfx::ColorSpace(PrimaryID::XYZ_D50, TransferID::IEC61966_2_1_HDR),
};
+bool color_space_premul_values[] = {
+ true, false,
+};
+
INSTANTIATE_TEST_CASE_P(
FromColorSpace,
ColorTransformPixelTest,
testing::Combine(testing::ValuesIn(src_color_spaces),
- testing::ValuesIn(intermediate_color_spaces)));
+ testing::ValuesIn(intermediate_color_spaces),
+ testing::ValuesIn(color_space_premul_values)));
INSTANTIATE_TEST_CASE_P(
ToColorSpace,
ColorTransformPixelTest,
testing::Combine(testing::ValuesIn(intermediate_color_spaces),
- testing::ValuesIn(dst_color_spaces)));
+ testing::ValuesIn(dst_color_spaces),
+ testing::ValuesIn(color_space_premul_values)));
#endif // !defined(OS_ANDROID)
diff --git a/chromium/components/viz/service/display/scoped_render_pass_texture.h b/chromium/components/viz/service/display/scoped_render_pass_texture.h
index b3a79e2067d..5700c68745e 100644
--- a/chromium/components/viz/service/display/scoped_render_pass_texture.h
+++ b/chromium/components/viz/service/display/scoped_render_pass_texture.h
@@ -7,7 +7,6 @@
#include "base/macros.h"
#include "components/viz/common/resources/resource_format.h"
-#include "components/viz/common/resources/resource_texture_hint.h"
#include "components/viz/service/viz_service_export.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/gfx/color_space.h"
diff --git a/chromium/components/viz/service/display/shader.cc b/chromium/components/viz/service/display/shader.cc
index e7a927d140e..62bab35ad8b 100644
--- a/chromium/components/viz/service/display/shader.cc
+++ b/chromium/components/viz/service/display/shader.cc
@@ -11,6 +11,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/strings/char_traits.h"
#include "base/strings/stringprintf.h"
#include "components/viz/service/display/static_geometry_binding.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -18,29 +19,18 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
-constexpr bool ConstexprEqual(const char* a, const char* b, size_t length) {
- for (size_t i = 0; i < length; i++) {
- if (a[i] != b[i])
- return false;
- }
- return true;
-}
-
constexpr base::StringPiece StripLambda(base::StringPiece shader) {
- // Must contain at least "[]() {}" and trailing null (included in size).
- // TODO(jbroman): Simplify this once we're in a post-C++17 world, where
- // starts_with and ends_with can easily be made constexpr.
- DCHECK(shader.size() >= 7); // NOLINT
- DCHECK(ConstexprEqual(shader.data(), "[]() {", 6));
+ // Must contain at least "[]() {}".
+ DCHECK(shader.starts_with("[]() {"));
+ DCHECK(shader.ends_with("}"));
shader.remove_prefix(6);
- DCHECK(shader[shader.size() - 1] == '}'); // NOLINT
shader.remove_suffix(1);
return shader;
}
// Shaders are passed in with lambda syntax, which tricks clang-format into
// handling them correctly. StripLambda removes this.
-#define SHADER0(Src) StripLambda(base::StringPiece(#Src, sizeof(#Src) - 1))
+#define SHADER0(Src) StripLambda(#Src)
#define HDR(x) \
do { \
@@ -535,11 +525,7 @@ void FragmentShader::Init(GLES2Interface* context,
}
void FragmentShader::SetBlendModeFunctions(std::string* shader_string) const {
- if (shader_string->find("ApplyBlendMode") == std::string::npos)
- return;
-
if (!has_blend_mode()) {
- shader_string->insert(0, "#define ApplyBlendMode(X, Y) (X)\n");
return;
}
@@ -549,48 +535,39 @@ void FragmentShader::SetBlendModeFunctions(std::string* shader_string) const {
uniform TexCoordPrecision vec4 backdropRect;
});
- base::StringPiece mixFunction;
+ base::StringPiece function_apply_blend_mode;
if (mask_for_background_) {
- static constexpr base::StringPiece kMixFunctionWithMask = SHADER0([]() {
- vec4 MixBackdrop(TexCoordPrecision vec2 bgTexCoord, float mask) {
+ static constexpr base::StringPiece kFunctionApplyBlendMode = SHADER0([]() {
+ vec4 ApplyBlendMode(vec4 src, float mask) {
+ TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
+ bgTexCoord *= backdropRect.zw;
vec4 backdrop = texture2D(s_backdropTexture, bgTexCoord);
vec4 original_backdrop =
texture2D(s_originalBackdropTexture, bgTexCoord);
- return mix(original_backdrop, backdrop, mask);
+ vec4 dst = mix(original_backdrop, backdrop, mask);
+ return Blend(src, dst);
}
});
- mixFunction = kMixFunctionWithMask;
+ function_apply_blend_mode = kFunctionApplyBlendMode;
} else {
- static constexpr base::StringPiece kMixFunctionWithoutMask = SHADER0([]() {
- vec4 MixBackdrop(TexCoordPrecision vec2 bgTexCoord, float mask) {
- return texture2D(s_backdropTexture, bgTexCoord);
+ static constexpr base::StringPiece kFunctionApplyBlendMode = SHADER0([]() {
+ vec4 ApplyBlendMode(vec4 src) {
+ TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
+ bgTexCoord *= backdropRect.zw;
+ vec4 dst = texture2D(s_backdropTexture, bgTexCoord);
+ return Blend(src, dst);
}
});
- mixFunction = kMixFunctionWithoutMask;
+ function_apply_blend_mode = kFunctionApplyBlendMode;
}
- static constexpr base::StringPiece kFunctionApplyBlendMode = SHADER0([]() {
- vec4 GetBackdropColor(float mask) {
- TexCoordPrecision vec2 bgTexCoord = gl_FragCoord.xy - backdropRect.xy;
- bgTexCoord.x /= backdropRect.z;
- bgTexCoord.y /= backdropRect.w;
- return MixBackdrop(bgTexCoord, mask);
- }
-
- vec4 ApplyBlendMode(vec4 src, float mask) {
- vec4 dst = GetBackdropColor(mask);
- return Blend(src, dst);
- }
- });
-
std::string shader;
shader.reserve(shader_string->size() + 1024);
shader += "precision mediump float;";
AppendHelperFunctions(&shader);
AppendBlendFunction(&shader);
kUniforms.AppendToString(&shader);
- mixFunction.AppendToString(&shader);
- kFunctionApplyBlendMode.AppendToString(&shader);
+ function_apply_blend_mode.AppendToString(&shader);
shader += *shader_string;
*shader_string = std::move(shader);
}
@@ -1015,12 +992,6 @@ std::string FragmentShader::GetShaderSource() const {
SRC("float aa = clamp(gl_FragCoord.w * min(d2.x, d2.y), 0.0, 1.0);");
}
- // Premultiply by alpha.
- if (premultiply_alpha_mode_ == NON_PREMULTIPLIED_ALPHA) {
- SRC("// Premultiply alpha");
- SRC("texColor.rgb *= texColor.a;");
- }
-
// Apply background texture.
if (has_background_color_) {
HDR("uniform vec4 background_color;");
@@ -1087,10 +1058,16 @@ std::string FragmentShader::GetShaderSource() const {
SRC("gl_FragColor = vec4(texColor.rgb, 1.0);");
break;
case FRAG_COLOR_MODE_APPLY_BLEND_MODE:
- if (mask_mode_ != NO_MASK)
- SRC("gl_FragColor = ApplyBlendMode(texColor, maskColor.w);");
- else
- SRC("gl_FragColor = ApplyBlendMode(texColor, 0.0);");
+ if (!has_blend_mode()) {
+ SRC("gl_FragColor = texColor;");
+ } else if (mask_mode_ != NO_MASK) {
+ if (mask_for_background_)
+ SRC("gl_FragColor = ApplyBlendMode(texColor, maskColor.w);");
+ else
+ SRC("gl_FragColor = ApplyBlendMode(texColor);");
+ } else {
+ SRC("gl_FragColor = ApplyBlendMode(texColor);");
+ }
break;
}
source += "}\n";
diff --git a/chromium/components/viz/service/display/shader_unittest.cc b/chromium/components/viz/service/display/shader_unittest.cc
index c05da251fe5..6990cbf14de 100644
--- a/chromium/components/viz/service/display/shader_unittest.cc
+++ b/chromium/components/viz/service/display/shader_unittest.cc
@@ -4,8 +4,8 @@
#include "components/viz/service/display/shader.h"
+#include "components/viz/test/test_context_provider.h"
#include "components/viz/test/test_gles2_interface.h"
-#include "components/viz/test/test_web_graphics_context_3d.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/size.h"
@@ -13,12 +13,11 @@
namespace viz {
TEST(ShaderTest, HighpThresholds) {
- // The test context always uses a mediump precision of 10 bits which
+ // The test gl always uses a mediump precision of 10 bits which
// corresponds to a native highp threshold of 2^10 = 1024
- std::unique_ptr<TestWebGraphicsContext3D> test_context =
- TestWebGraphicsContext3D::Create();
- TestGLES2Interface test_gl;
- test_gl.set_test_context(test_context.get());
+ scoped_refptr<TestContextProvider> provider = TestContextProvider::Create();
+ provider->BindToCurrentThread();
+ gpu::gles2::GLES2Interface* test_gl = provider->ContextGL();
int threshold_cache = 0;
int threshold_min;
@@ -29,30 +28,30 @@ TEST(ShaderTest, HighpThresholds) {
threshold_min = 0;
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
closePoint));
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
smallSize));
EXPECT_EQ(TEX_COORD_PRECISION_HIGH,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
farPoint));
EXPECT_EQ(TEX_COORD_PRECISION_HIGH,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
bigSize));
threshold_min = 3000;
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
closePoint));
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
smallSize));
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
farPoint));
EXPECT_EQ(TEX_COORD_PRECISION_MEDIUM,
- TexCoordPrecisionRequired(&test_gl, &threshold_cache, threshold_min,
+ TexCoordPrecisionRequired(test_gl, &threshold_cache, threshold_min,
bigSize));
}
diff --git a/chromium/components/viz/service/display/skia_output_surface.cc b/chromium/components/viz/service/display/skia_output_surface.cc
new file mode 100644
index 00000000000..abc0a6cdc1c
--- /dev/null
+++ b/chromium/components/viz/service/display/skia_output_surface.cc
@@ -0,0 +1,15 @@
+// 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 "components/viz/service/display/skia_output_surface.h"
+
+namespace viz {
+
+SkiaOutputSurface::SkiaOutputSurface(
+ scoped_refptr<ContextProvider> context_provider)
+ : OutputSurface(std::move(context_provider)) {}
+
+SkiaOutputSurface::~SkiaOutputSurface() = default;
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display/skia_output_surface.h b/chromium/components/viz/service/display/skia_output_surface.h
new file mode 100644
index 00000000000..a93bfc26d66
--- /dev/null
+++ b/chromium/components/viz/service/display/skia_output_surface.h
@@ -0,0 +1,98 @@
+// 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.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
+
+#include "components/viz/common/resources/resource_format.h"
+#include "components/viz/service/display/output_surface.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+
+class SkCanvas;
+class SkImage;
+
+namespace viz {
+
+struct ResourceMetadata;
+
+// This class extends the OutputSurface for SkiaRenderer needs. In future, the
+// SkiaRenderer will be the only renderer. When other renderers are removed,
+// we will replace OutputSurface with SkiaOutputSurface, and remove all
+// OutputSurface's methods which are not useful for SkiaRenderer.
+class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface {
+ public:
+ explicit SkiaOutputSurface(scoped_refptr<ContextProvider> context_provider);
+ ~SkiaOutputSurface() override;
+
+ // Get a SkCanvas for the current frame. The SkiaRenderer will use this
+ // SkCanvas to draw quads. This class retains the ownership of the SkCanvas,
+ // And this SkCanvas may become invalid, when the frame is swapped out.
+ virtual SkCanvas* GetSkCanvasForCurrentFrame() = 0;
+
+ // Make a promise SkImage from the given |metadata|. The SkiaRenderer can use
+ // the image with SkCanvas returned by |GetSkCanvasForCurrentFrame|, but Skia
+ // will not read the content of the resource until the sync token in the
+ // |metadata| is satisfied. The SwapBuffers should take care of this by
+ // scheduling a GPU task with all resource sync tokens recorded by
+ // MakePromiseSkImage for the current frame.
+ virtual sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) = 0;
+
+ // Make a promise SkImage from the given |metadata| and the |yuv_color_space|.
+ // For YUV format, three resource metadatas should be provided. metadatas[0]
+ // contains pixels from y panel, metadatas[1] contains pixels from u panel,
+ // metadatas[2] contains pixels from v panel.
+ // For NV12 format, two resource metadatas should be provided. metadatas[0]
+ // contains pixels from y panel, metadatas[1] contains pixels from u and v
+ // panels.
+ virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
+ std::vector<ResourceMetadata> metadatas,
+ SkYUVColorSpace yuv_color_space) = 0;
+
+ // Swaps the current backbuffer to the screen and return a sync token which
+ // can be waited on in a command buffer to ensure the frame is completed. This
+ // token is released when the GPU ops from drawing the frame have been seen
+ // and processed by the GPU main.
+ // TODO(penghuang): replace OutputSurface::SwapBuffers with this method when
+ // SkiaRenderer and DDL are used everywhere.
+ virtual gpu::SyncToken SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
+
+ // Begin painting a render pass. This method will create a
+ // SkDeferredDisplayListRecorder and return a SkCanvas of it. The SkiaRenderer
+ // will use this SkCanvas to paint the render pass.
+ // Note: BeginPaintRenderPass cannot be called without finishing the prior
+ // paint render pass.
+ virtual SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
+ const gfx::Size& size,
+ ResourceFormat format,
+ bool mipmap) = 0;
+
+ // Finish painting a render pass. It should be paired with
+ // BeginPaintRenderPass. This method will schedule a GPU task to play the DDL
+ // back on GPU thread on a cached SkSurface. This method returns a sync token
+ // which can be waited on in a command buffer to ensure the paint operation is
+ // completed. This token is released when the GPU ops from painting the render
+ // pass have been seen and processed by the GPU main.
+ virtual gpu::SyncToken FinishPaintRenderPass() = 0;
+
+ // Make a promise SkImage from a render pass id. The render pass has been
+ // painted with BeginPaintRenderPass and FinishPaintRenderPass. The format
+ // and mipmap must match arguments used for BeginPaintRenderPass() to paint
+ // this render pass.
+ virtual sk_sp<SkImage> MakePromiseSkImageFromRenderPass(
+ const RenderPassId& id,
+ const gfx::Size& size,
+ ResourceFormat format,
+ bool mipmap) = 0;
+
+ // Remove cached resources generated by BeginPaintRenderPass and
+ // FinishPaintRenderPass.
+ virtual void RemoveRenderPassResource(std::vector<RenderPassId> ids) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurface);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_OUTPUT_SURFACE_H_
diff --git a/chromium/components/viz/service/display/skia_renderer.cc b/chromium/components/viz/service/display/skia_renderer.cc
index 452b0146409..783fb7f778e 100644
--- a/chromium/components/viz/service/display/skia_renderer.cc
+++ b/chromium/components/viz/service/display/skia_renderer.cc
@@ -17,13 +17,16 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/common/quads/yuv_video_draw_quad.h"
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/resource_fence.h"
#include "components/viz/common/resources/resource_format_utils.h"
+#include "components/viz/common/resources/resource_metadata.h"
#include "components/viz/common/skia_helper.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/renderer_utils.h"
+#include "components/viz/service/display/skia_output_surface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "skia/ext/opacity_filter_canvas.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -34,32 +37,20 @@
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkOverdrawColorFilter.h"
+#include "third_party/skia/include/effects/SkShaderMaskFilter.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
-#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
-#if BUILDFLAG(ENABLE_VULKAN)
-#include "components/viz/common/gpu/vulkan_in_process_context_provider.h"
-#include "gpu/vulkan/vulkan_device_queue.h"
-#include "gpu/vulkan/vulkan_implementation.h"
-#include "gpu/vulkan/vulkan_surface.h"
-#include "gpu/vulkan/vulkan_swap_chain.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-#include "third_party/skia/include/gpu/vk/GrVkBackendContext.h"
-#include "third_party/skia/include/gpu/vk/GrVkTypes.h"
-#endif
-
namespace viz {
// Parameters needed to draw a RenderPassDrawQuad.
struct SkiaRenderer::DrawRenderPassDrawQuadParams {
// The "in" parameters that will be used when apply filters.
const cc::FilterOperations* filters = nullptr;
- const cc::FilterOperations* background_filters = nullptr;
- // The "out" parameters that will be returned for future use.
+ // The "out" parameters returned by filters.
// A Skia image that should be sampled from instead of the original
// contents.
sk_sp<SkImage> filter_image;
@@ -68,32 +59,141 @@ struct SkiaRenderer::DrawRenderPassDrawQuadParams {
gfx::RectF tex_coord_rect;
};
+namespace {
+
+bool IsTextureResource(DisplayResourceProvider* resource_provider,
+ ResourceId resource_id) {
+ return resource_provider->GetResourceType(resource_id) ==
+ ResourceType::kTexture;
+}
+
+} // namespace
+
+// Scoped helper class for building SkImage from resource id.
+class SkiaRenderer::ScopedSkImageBuilder {
+ public:
+ ScopedSkImageBuilder(SkiaRenderer* skia_renderer, ResourceId resource_id);
+ ~ScopedSkImageBuilder() = default;
+
+ const SkImage* sk_image() const { return sk_image_; }
+
+ private:
+ std::unique_ptr<DisplayResourceProvider::ScopedReadLockSkImage> lock_;
+ const SkImage* sk_image_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedSkImageBuilder);
+};
+
+SkiaRenderer::ScopedSkImageBuilder::ScopedSkImageBuilder(
+ SkiaRenderer* skia_renderer,
+ ResourceId resource_id) {
+ auto* resource_provider = skia_renderer->resource_provider_;
+ if (!skia_renderer->skia_output_surface_ ||
+ skia_renderer->non_root_surface_ ||
+ !IsTextureResource(resource_provider, resource_id)) {
+ // TODO(penghuang): remove this code when DDL is used everywhere.
+ lock_ = std::make_unique<DisplayResourceProvider::ScopedReadLockSkImage>(
+ resource_provider, resource_id);
+ sk_image_ = lock_->sk_image();
+ } else {
+ // Look up the image from promise_images_by resource_id and return the
+ // reference. If the resource_id doesn't exist, this statement will
+ // allocate it and return reference of it, and the reference will be used
+ // to store the new created image later.
+ auto& image = skia_renderer->promise_images_[resource_id];
+ if (!image) {
+ auto metadata =
+ skia_renderer->lock_set_for_external_use_.LockResource(resource_id);
+ DCHECK(!metadata.mailbox.IsZero());
+ image = skia_renderer->skia_output_surface_->MakePromiseSkImage(
+ std::move(metadata));
+ DCHECK(image);
+ }
+ sk_image_ = image.get();
+ }
+}
+
+class SkiaRenderer::ScopedYUVSkImageBuilder {
+ public:
+ ScopedYUVSkImageBuilder(SkiaRenderer* skia_renderer,
+ const YUVVideoDrawQuad* quad) {
+ DCHECK(skia_renderer->skia_output_surface_);
+ DCHECK(IsTextureResource(skia_renderer->resource_provider_,
+ quad->y_plane_resource_id()));
+ DCHECK(IsTextureResource(skia_renderer->resource_provider_,
+ quad->u_plane_resource_id()));
+ DCHECK(IsTextureResource(skia_renderer->resource_provider_,
+ quad->v_plane_resource_id()));
+ DCHECK(quad->a_plane_resource_id() == kInvalidResourceId ||
+ IsTextureResource(skia_renderer->resource_provider_,
+ quad->a_plane_resource_id()));
+
+ YUVIds ids(quad->y_plane_resource_id(), quad->u_plane_resource_id(),
+ quad->v_plane_resource_id(), quad->a_plane_resource_id());
+ auto& image = skia_renderer->yuv_promise_images_[std::move(ids)];
+
+ if (!image) {
+ auto yuv_color_space = kRec601_SkYUVColorSpace;
+ quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space);
+
+ std::vector<ResourceMetadata> metadatas;
+ bool is_yuv = quad->u_plane_resource_id() != quad->v_plane_resource_id();
+ metadatas.reserve(is_yuv ? 3 : 2);
+ auto y_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
+ quad->y_plane_resource_id());
+ metadatas.push_back(std::move(y_metadata));
+ auto u_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
+ quad->u_plane_resource_id());
+ metadatas.push_back(std::move(u_metadata));
+ if (is_yuv) {
+ auto v_metadata =
+ skia_renderer->lock_set_for_external_use_.LockResource(
+ quad->v_plane_resource_id());
+ metadatas.push_back(std::move(v_metadata));
+ }
+
+ if (quad->a_plane_resource_id() != kInvalidResourceId) {
+ // TODO(penghuang): Handle alpha channel when Skia supports YUVA format.
+ NOTIMPLEMENTED();
+ }
+
+ image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
+ std::move(metadatas), yuv_color_space);
+ DCHECK(image);
+ }
+ sk_image_ = image.get();
+ }
+
+ ~ScopedYUVSkImageBuilder() = default;
+
+ const SkImage* sk_image() const { return sk_image_; }
+
+ private:
+ std::unique_ptr<DisplayResourceProvider::ScopedReadLockSkImage> lock_;
+ SkImage* sk_image_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedYUVSkImageBuilder);
+};
+
SkiaRenderer::SkiaRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
- : DirectRenderer(settings, output_surface, resource_provider) {
-#if BUILDFLAG(ENABLE_VULKAN)
- use_swap_with_bounds_ = false;
-#else
+ DisplayResourceProvider* resource_provider,
+ SkiaOutputSurface* skia_output_surface)
+ : DirectRenderer(settings, output_surface, resource_provider),
+ skia_output_surface_(skia_output_surface),
+ lock_set_for_external_use_(resource_provider) {
const auto& context_caps =
output_surface_->context_provider()->ContextCapabilities();
use_swap_with_bounds_ = context_caps.swap_buffers_with_bounds;
- if (context_caps.sync_query)
+ if (context_caps.sync_query) {
sync_queries_ = base::Optional<SyncQueryCollection>(
- output_surface->context_provider()->ContextGL());
-#endif
+ output_surface_->context_provider()->ContextGL());
+ }
}
-SkiaRenderer::~SkiaRenderer() {
-#if BUILDFLAG(ENABLE_VULKAN)
- return;
-#endif
-}
+SkiaRenderer::~SkiaRenderer() = default;
bool SkiaRenderer::CanPartialSwap() {
-#if BUILDFLAG(ENABLE_VULKAN)
- return false;
-#endif
if (use_swap_with_bounds_)
return false;
auto* context_provider = output_surface_->context_provider();
@@ -102,29 +202,28 @@ bool SkiaRenderer::CanPartialSwap() {
void SkiaRenderer::BeginDrawingFrame() {
TRACE_EVENT0("viz", "SkiaRenderer::BeginDrawingFrame");
-#if BUILDFLAG(ENABLE_VULKAN)
- return;
-#else
// Copied from GLRenderer.
scoped_refptr<ResourceFence> read_lock_fence;
if (sync_queries_) {
read_lock_fence = sync_queries_->StartNewFrame();
} else {
read_lock_fence =
- base::MakeRefCounted<cc::DisplayResourceProvider::SynchronousFence>(
+ base::MakeRefCounted<DisplayResourceProvider::SynchronousFence>(
output_surface_->context_provider()->ContextGL());
}
resource_provider_->SetReadLockFence(read_lock_fence.get());
- // Insert WaitSyncTokenCHROMIUM on quad resources prior to drawing the frame,
- // so that drawing can proceed without GL context switching interruptions.
- for (const auto& pass : *current_frame()->render_passes_in_draw_order) {
- for (auto* quad : pass->quad_list) {
- for (ResourceId resource_id : quad->resources)
- resource_provider_->WaitSyncToken(resource_id);
+ if (!skia_output_surface_) {
+ // Insert WaitSyncTokenCHROMIUM on quad resources prior to drawing the
+ // frame, so that drawing can proceed without GL context switching
+ // interruptions.
+ for (const auto& pass : *current_frame()->render_passes_in_draw_order) {
+ for (auto* quad : pass->quad_list) {
+ for (ResourceId resource_id : quad->resources)
+ resource_provider_->WaitSyncToken(resource_id);
+ }
}
}
-#endif
}
void SkiaRenderer::FinishDrawingFrame() {
@@ -154,12 +253,14 @@ void SkiaRenderer::FinishDrawingFrame() {
swap_content_bounds_ = current_frame()->root_content_bounds;
}
-void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
+void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) {
DCHECK(visible_);
TRACE_EVENT0("cc,benchmark", "SkiaRenderer::SwapBuffers");
OutputSurfaceFrame output_frame;
output_frame.latency_info = std::move(latency_info);
output_frame.size = surface_size_for_swap_buffers();
+ output_frame.need_presentation_feedback = need_presentation_feedback;
if (use_swap_with_bounds_) {
output_frame.content_bounds = std::move(swap_content_bounds_);
} else if (use_partial_swap_) {
@@ -168,7 +269,17 @@ void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
} else if (swap_buffer_rect_.IsEmpty() && allow_empty_swap_) {
output_frame.sub_buffer_rect = swap_buffer_rect_;
}
- output_surface_->SwapBuffers(std::move(output_frame));
+
+ if (skia_output_surface_) {
+ auto sync_token =
+ skia_output_surface_->SkiaSwapBuffers(std::move(output_frame));
+ promise_images_.clear();
+ yuv_promise_images_.clear();
+ lock_set_for_external_use_.UnlockResources(sync_token);
+ } else {
+ // TODO(penghuang): remove it when SkiaRenderer and SkDDL are always used.
+ output_surface_->SwapBuffers(std::move(output_frame));
+ }
swap_buffer_rect_ = gfx::Rect();
}
@@ -195,36 +306,16 @@ void SkiaRenderer::BindFramebufferToOutputSurface() {
SkSurfaceProps surface_props =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
-#if BUILDFLAG(ENABLE_VULKAN)
- gpu::VulkanSurface* vulkan_surface = output_surface_->GetVulkanSurface();
- gpu::VulkanSwapChain* swap_chain = vulkan_surface->GetSwapChain();
- VkImage image = swap_chain->GetCurrentImage(swap_chain->current_image());
-
- GrVkImageInfo info_;
- info_.fImage = image;
- info_.fAlloc = {VK_NULL_HANDLE, 0, 0, 0};
- info_.fImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
- info_.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- info_.fFormat = VK_FORMAT_B8G8R8A8_UNORM;
- info_.fLevelCount = 1;
-
- GrBackendRenderTarget render_target(
- current_frame()->device_viewport_size.width(),
- current_frame()->device_viewport_size.height(), 0, 0, info_);
-
- GrContext* gr_context =
- output_surface_->vulkan_context_provider()->GetGrContext();
- root_surface_ = SkSurface::MakeFromBackendRenderTarget(
- gr_context, render_target, kTopLeft_GrSurfaceOrigin,
- kBGRA_8888_SkColorType, nullptr, &surface_props);
-#else
// TODO(weiliangc): Set up correct can_use_lcd_text for SkSurfaceProps flags.
// How to setup is in ResourceProvider. (http://crbug.com/644851)
GrContext* gr_context = output_surface_->context_provider()->GrContext();
- if (!root_canvas_ || root_canvas_->getGrContext() != gr_context ||
- gfx::SkISizeToSize(root_canvas_->getBaseLayerSize()) !=
- current_frame()->device_viewport_size) {
+ if (skia_output_surface_) {
+ root_canvas_ = skia_output_surface_->GetSkCanvasForCurrentFrame();
+ DCHECK(root_canvas_);
+ } else if (!root_canvas_ || root_canvas_->getGrContext() != gr_context ||
+ gfx::SkISizeToSize(root_canvas_->getBaseLayerSize()) !=
+ current_frame()->device_viewport_size) {
// Either no SkSurface setup yet, or new GrContext, need to create new
// surface.
GrGLFramebufferInfo framebuffer_info;
@@ -237,13 +328,12 @@ void SkiaRenderer::BindFramebufferToOutputSurface() {
root_surface_ = SkSurface::MakeFromBackendRenderTarget(
gr_context, render_target, kBottomLeft_GrSurfaceOrigin,
kRGB_888x_SkColorType, nullptr, &surface_props);
+ root_canvas_ = root_surface_->getCanvas();
}
-#endif
- root_canvas_ = root_surface_->getCanvas();
if (settings_->show_overdraw_feedback) {
- const gfx::Size size(root_surface_->width(), root_surface_->height());
- overdraw_surface_ = root_surface_->makeSurface(
+ const auto& size = current_frame()->device_viewport_size;
+ overdraw_surface_ = root_canvas_->makeSurface(
SkImageInfo::MakeA8(size.width(), size.height()));
nway_canvas_ = std::make_unique<SkNWayCanvas>(size.width(), size.height());
overdraw_canvas_ =
@@ -264,9 +354,16 @@ void SkiaRenderer::BindFramebufferToTexture(const RenderPassId render_pass_id) {
// This function is called after AllocateRenderPassResourceIfNeeded, so there
// should be backing ready.
RenderPassBacking& backing = iter->second;
- non_root_surface_ = backing.render_pass_surface;
- current_canvas_ = non_root_surface_->getCanvas();
- current_surface_ = non_root_surface_.get();
+ if (skia_output_surface_) {
+ non_root_surface_ = nullptr;
+ current_canvas_ = skia_output_surface_->BeginPaintRenderPass(
+ render_pass_id, backing.size, backing.format, backing.mipmap);
+ } else {
+ non_root_surface_ = backing.render_pass_surface;
+ current_surface_ = non_root_surface_.get();
+ current_canvas_ = non_root_surface_->getCanvas();
+ }
+ is_drawing_render_pass_ = true;
}
void SkiaRenderer::SetScissorTestRect(const gfx::Rect& scissor_rect) {
@@ -420,8 +517,15 @@ void SkiaRenderer::DoDrawQuad(const DrawQuad* quad,
// reaching a direct renderer.
NOTREACHED();
break;
- case DrawQuad::INVALID:
case DrawQuad::YUV_VIDEO_CONTENT:
+ if (skia_output_surface_) {
+ DrawYUVVideoQuad(YUVVideoDrawQuad::MaterialCast(quad));
+ } else {
+ DrawUnsupportedQuad(quad);
+ NOTIMPLEMENTED();
+ }
+ break;
+ case DrawQuad::INVALID:
case DrawQuad::STREAM_VIDEO_CONTENT:
DrawUnsupportedQuad(quad);
NOTREACHED();
@@ -509,10 +613,8 @@ void SkiaRenderer::DrawSolidColorQuad(const SolidColorDrawQuad* quad) {
}
void SkiaRenderer::DrawTextureQuad(const TextureDrawQuad* quad) {
- // TODO(skaslev): Add support for non-premultiplied alpha.
- cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
- quad->resource_id());
- const SkImage* image = lock.sk_image();
+ ScopedSkImageBuilder builder(this, quad->resource_id());
+ const SkImage* image = builder.sk_image();
if (!image)
return;
gfx::RectF uv_rect = gfx::ScaleRect(
@@ -551,9 +653,9 @@ void SkiaRenderer::DrawTileQuad(const TileDrawQuad* quad) {
// |resource_provider_| can be NULL in resourceless software draws, which
// should never produce tile quads in the first place.
DCHECK(resource_provider_);
- cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
- quad->resource_id());
- if (!lock.sk_image())
+ ScopedSkImageBuilder builder(this, quad->resource_id());
+ const SkImage* image = builder.sk_image();
+ if (!image)
return;
gfx::RectF visible_tex_coord_rect = cc::MathUtil::ScaleRectProportional(
quad->tex_coord_rect, gfx::RectF(quad->rect),
@@ -564,7 +666,27 @@ void SkiaRenderer::DrawTileQuad(const TileDrawQuad* quad) {
SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect);
current_paint_.setFilterQuality(
quad->nearest_neighbor ? kNone_SkFilterQuality : kLow_SkFilterQuality);
- current_canvas_->drawImageRect(lock.sk_image(), uv_rect,
+ current_canvas_->drawImageRect(image, uv_rect,
+ gfx::RectFToSkRect(visible_quad_vertex_rect),
+ &current_paint_);
+}
+
+void SkiaRenderer::DrawYUVVideoQuad(const YUVVideoDrawQuad* quad) {
+ DCHECK(resource_provider_);
+ ScopedYUVSkImageBuilder builder(this, quad);
+ const SkImage* image = builder.sk_image();
+ if (!image)
+ return;
+ gfx::RectF visible_tex_coord_rect = cc::MathUtil::ScaleRectProportional(
+ quad->ya_tex_coord_rect, gfx::RectF(quad->rect),
+ gfx::RectF(quad->visible_rect));
+ gfx::RectF visible_quad_vertex_rect = cc::MathUtil::ScaleRectProportional(
+ QuadVertexRect(), gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect));
+
+ SkRect uv_rect = gfx::RectFToSkRect(visible_tex_coord_rect);
+ // TODO(penghuang): figure out how to set correct filter quality.
+ current_paint_.setFilterQuality(kLow_SkFilterQuality);
+ current_canvas_->drawImageRect(image, uv_rect,
gfx::RectFToSkRect(visible_quad_vertex_rect),
&current_paint_);
}
@@ -582,10 +704,8 @@ bool SkiaRenderer::CalculateRPDQParams(sk_sp<SkImage> content,
// should be backing ready.
RenderPassBacking& content_texture = iter->second;
DCHECK(!params->filters->IsEmpty());
- gfx::Size size(content_texture.render_pass_surface->width(),
- content_texture.render_pass_surface->height());
auto paint_filter = cc::RenderSurfaceFilters::BuildImageFilter(
- *params->filters, gfx::SizeF(size));
+ *params->filters, gfx::SizeF(content_texture.size));
auto filter = paint_filter ? paint_filter->cached_sk_filter_ : nullptr;
// Apply filters to the content texture.
@@ -641,17 +761,20 @@ void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
DCHECK(render_pass_backings_.end() != iter);
// This function is called after AllocateRenderPassResourceIfNeeded, so there
// should be backing ready.
- RenderPassBacking& content_texture = iter->second;
+ RenderPassBacking& backing = iter->second;
// TODO(weiliangc): GL Renderer has optimization that when Render Pass has a
// single quad inside we would draw that directly. We could add similar
// optimization here by using the quad's SkImage.
sk_sp<SkImage> content =
- content_texture.render_pass_surface->makeImageSnapshot();
+ skia_output_surface_
+ ? skia_output_surface_->MakePromiseSkImageFromRenderPass(
+ quad->render_pass_id, backing.size, backing.format,
+ backing.mipmap)
+ : backing.render_pass_surface->makeImageSnapshot();
DrawRenderPassDrawQuadParams params;
params.filters = FiltersForPass(quad->render_pass_id);
- params.background_filters = BackgroundFiltersForPass(quad->render_pass_id);
bool can_draw = CalculateRPDQParams(content, quad, &params);
if (!can_draw)
@@ -670,8 +793,6 @@ void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
QuadVertexRect(), gfx::RectF(quad->rect),
gfx::RectF(quad->visible_rect)));
}
- current_canvas_->drawImageRect(content, content_rect, dest_visible_rect,
- &current_paint_);
SkRect dest_rect = gfx::RectFToSkRect(QuadVertexRect());
@@ -680,20 +801,42 @@ void SkiaRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
SkMatrix::kFill_ScaleToFit);
sk_sp<SkShader> shader;
- shader = content->makeShader(SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode, &content_mat);
+ shader = content->makeShader(&content_mat);
- // TODO(weiliangc): Implement mask. (https://crbug.com/644851)
if (quad->mask_resource_id()) {
- NOTIMPLEMENTED();
+ ScopedSkImageBuilder builder(this, quad->mask_resource_id());
+ const SkImage* image = builder.sk_image();
+ if (!image)
+ return;
+
+ // Scale normalized uv rect into absolute texel coordinates.
+ SkRect mask_rect = gfx::RectFToSkRect(
+ gfx::ScaleRect(quad->mask_uv_rect, quad->mask_texture_size.width(),
+ quad->mask_texture_size.height()));
+
+ SkMatrix mask_mat;
+ mask_mat.setRectToRect(mask_rect, dest_rect, SkMatrix::kFill_ScaleToFit);
+ current_paint_.setMaskFilter(
+ SkShaderMaskFilter::Make((image->makeShader(&mask_mat))));
+ current_paint_.setShader(std::move(shader));
+ current_canvas_->drawRect(dest_visible_rect, current_paint_);
+ return;
}
- // TODO(weiliangc): If we have a background filter shader, render its
- // results first. (https://crbug.com/644851)
- if (ShouldApplyBackgroundFilters(quad, params.background_filters)) {
+ // If we have a background filter shader, render its results first.
+ sk_sp<SkShader> background_filter_shader =
+ GetBackgroundFilterShader(quad, SkShader::kClamp_TileMode);
+ if (background_filter_shader) {
+ SkPaint paint;
+ paint.setShader(std::move(background_filter_shader));
+ paint.setMaskFilter(current_paint_.refMaskFilter());
+ current_canvas_->drawRect(dest_visible_rect, paint);
current_paint_.setShader(std::move(shader));
current_canvas_->drawRect(dest_visible_rect, current_paint_);
+ return;
}
+ current_canvas_->drawImageRect(content, content_rect, dest_visible_rect,
+ &current_paint_);
}
void SkiaRenderer::DrawUnsupportedQuad(const DrawQuad* quad) {
@@ -714,6 +857,12 @@ void SkiaRenderer::CopyDrawnRenderPass(
// TODO(weiliangc): Make copy request work. (crbug.com/644851)
TRACE_EVENT0("viz", "SkiaRenderer::CopyDrawnRenderPass");
+ if (skia_output_surface_) {
+ // TODO(penghuang): Support it with SkDDL.
+ NOTIMPLEMENTED();
+ return;
+ }
+
gfx::Rect copy_rect = current_frame()->current_render_pass->output_rect;
if (request->has_area())
copy_rect.Intersect(request->area());
@@ -752,7 +901,17 @@ void SkiaRenderer::DidChangeVisibility() {
}
void SkiaRenderer::FinishDrawingQuadList() {
- current_canvas_->flush();
+ if (skia_output_surface_) {
+ if (is_drawing_render_pass_) {
+ gpu::SyncToken sync_token = skia_output_surface_->FinishPaintRenderPass();
+ promise_images_.clear();
+ yuv_promise_images_.clear();
+ lock_set_for_external_use_.UnlockResources(sync_token);
+ is_drawing_render_pass_ = false;
+ }
+ } else {
+ current_canvas_->flush();
+ }
}
void SkiaRenderer::GenerateMipmap() {
@@ -773,20 +932,17 @@ bool SkiaRenderer::ShouldApplyBackgroundFilters(
return true;
}
-SkBitmap SkiaRenderer::GetBackdropBitmap(const gfx::Rect& bounding_rect) const {
- SkBitmap bitmap;
- bitmap.allocPixels(SkImageInfo::MakeN32Premul(bounding_rect.width(),
- bounding_rect.height()));
- if (!current_canvas_->readPixels(bitmap, bounding_rect.x(),
- bounding_rect.y()))
- bitmap.reset();
- return bitmap;
+sk_sp<SkImage> SkiaRenderer::GetBackdropImage(
+ const gfx::Rect& bounding_rect) const {
+ return root_surface_->makeImageSnapshot()->makeSubset(
+ gfx::RectToSkIRect(bounding_rect));
}
gfx::Rect SkiaRenderer::GetBackdropBoundingBoxForRenderPassQuad(
const RenderPassDrawQuad* quad,
const gfx::Transform& contents_device_transform,
- const cc::FilterOperations* background_filters) const {
+ const cc::FilterOperations* background_filters,
+ gfx::Rect* unclipped_rect) const {
DCHECK(ShouldApplyBackgroundFilters(quad, background_filters));
gfx::Rect backdrop_rect = gfx::ToEnclosingRect(cc::MathUtil::MapClippedRect(
contents_device_transform, QuadVertexRect()));
@@ -795,18 +951,105 @@ gfx::Rect SkiaRenderer::GetBackdropBoundingBoxForRenderPassQuad(
matrix.setScale(quad->filters_scale.x(), quad->filters_scale.y());
backdrop_rect = background_filters->MapRectReverse(backdrop_rect, matrix);
+ *unclipped_rect = backdrop_rect;
backdrop_rect.Intersect(MoveFromDrawToWindowSpace(
current_frame()->current_render_pass->output_rect));
return backdrop_rect;
}
+// If non-null, auto_bounds will be filled with the automatically-computed
+// destination bounds. If null, the output will be the same size as the
+// input image.
+sk_sp<SkImage> SkiaRenderer::ApplyBackgroundFilters(
+ SkImageFilter* filter,
+ const RenderPassDrawQuad* quad,
+ sk_sp<SkImage> src_image,
+ const gfx::Rect& rect) const {
+ if (!filter)
+ return nullptr;
+
+ SkMatrix local_matrix;
+ local_matrix.setTranslate(quad->filters_origin.x(), quad->filters_origin.y());
+ local_matrix.postScale(quad->filters_scale.x(), quad->filters_scale.y());
+
+ SkImageInfo image_info =
+ SkImageInfo::Make(rect.width(), rect.height(), src_image->colorType(),
+ src_image->alphaType(), nullptr);
+
+ GrContext* gr_context = output_surface_->context_provider()->GrContext();
+ // TODO(weiliangc): Set up correct can_use_lcd_text for SkSurfaceProps flags.
+ // How to setup is in ResourceProvider. (http://crbug.com/644851)
+ // LegacyFontHost will get LCD text and skia figures out what type to use.
+ SkSurfaceProps surface_props(0, SkSurfaceProps::kLegacyFontHost_InitType);
+ sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
+ gr_context, SkBudgeted::kNo, image_info, 0, kBottomLeft_GrSurfaceOrigin,
+ &surface_props, false);
+
+ if (!surface) {
+ return nullptr;
+ }
+
+ SkPaint paint;
+ // Treat subnormal float values as zero for performance.
+ cc::ScopedSubnormalFloatDisabler disabler;
+ paint.setImageFilter(filter->makeWithLocalMatrix(local_matrix));
+ surface->getCanvas()->translate(-rect.x(), -rect.y());
+ surface->getCanvas()->drawImage(src_image, rect.x(), rect.y(), &paint);
+
+ return surface->makeImageSnapshot();
+}
+
sk_sp<SkShader> SkiaRenderer::GetBackgroundFilterShader(
const RenderPassDrawQuad* quad,
SkShader::TileMode content_tile_mode) const {
- // TODO(weiliangc): properly implement background filters. (crbug.com/644851)
- NOTIMPLEMENTED();
- return nullptr;
+ const cc::FilterOperations* background_filters =
+ BackgroundFiltersForPass(quad->render_pass_id);
+ if (!ShouldApplyBackgroundFilters(quad, background_filters))
+ return nullptr;
+
+ gfx::Transform quad_rect_matrix;
+ QuadRectTransform(&quad_rect_matrix,
+ quad->shared_quad_state->quad_to_target_transform,
+ gfx::RectF(quad->rect));
+ gfx::Transform contents_device_transform =
+ current_frame()->window_matrix * current_frame()->projection_matrix *
+ quad_rect_matrix;
+ contents_device_transform.FlattenTo2d();
+
+ gfx::Rect unclipped_rect;
+ gfx::Rect backdrop_rect = GetBackdropBoundingBoxForRenderPassQuad(
+ quad, contents_device_transform, background_filters, &unclipped_rect);
+
+ // Figure out the transformations to move it back to pixel space.
+ gfx::Transform contents_device_transform_inverse;
+ if (!contents_device_transform.GetInverse(&contents_device_transform_inverse))
+ return nullptr;
+
+ SkMatrix filter_backdrop_transform =
+ contents_device_transform_inverse.matrix();
+ filter_backdrop_transform.preTranslate(backdrop_rect.x(), backdrop_rect.y());
+
+ // Apply the filter to the backdrop.
+ sk_sp<SkImage> backdrop_image = GetBackdropImage(backdrop_rect);
+
+ gfx::Vector2dF clipping_offset =
+ (unclipped_rect.top_right() - backdrop_rect.top_right()) +
+ (backdrop_rect.bottom_left() - unclipped_rect.bottom_left());
+ sk_sp<SkImageFilter> filter =
+ cc::RenderSurfaceFilters::BuildImageFilter(
+ *background_filters,
+ gfx::SizeF(backdrop_image->width(), backdrop_image->height()),
+ clipping_offset)
+ ->cached_sk_filter_;
+ sk_sp<SkImage> filter_backdrop_image =
+ ApplyBackgroundFilters(filter.get(), quad, backdrop_image, backdrop_rect);
+
+ if (!filter_backdrop_image)
+ return nullptr;
+
+ return filter_backdrop_image->makeShader(content_tile_mode, content_tile_mode,
+ &filter_backdrop_transform);
}
void SkiaRenderer::UpdateRenderPassTextures(
@@ -823,10 +1066,8 @@ void SkiaRenderer::UpdateRenderPassTextures(
const RenderPassRequirements& requirements = render_pass_it->second;
const RenderPassBacking& backing = pair.second;
- SkSurface* backing_surface = pair.second.render_pass_surface.get();
- bool size_appropriate =
- backing_surface->width() >= requirements.size.width() &&
- backing_surface->height() >= requirements.size.height();
+ bool size_appropriate = backing.size.width() >= requirements.size.width() &&
+ backing.size.height() >= requirements.size.height();
bool mipmap_appropriate = !requirements.mipmap || backing.mipmap;
if (!size_appropriate || !mipmap_appropriate)
passes_to_delete.push_back(pair.first);
@@ -838,6 +1079,10 @@ void SkiaRenderer::UpdateRenderPassTextures(
auto it = render_pass_backings_.find(passes_to_delete[i]);
render_pass_backings_.erase(it);
}
+
+ if (skia_output_surface_ && !passes_to_delete.empty()) {
+ skia_output_surface_->RemoveRenderPassResource(std::move(passes_to_delete));
+ }
}
void SkiaRenderer::AllocateRenderPassResourceIfNeeded(
@@ -847,32 +1092,30 @@ void SkiaRenderer::AllocateRenderPassResourceIfNeeded(
if (it != render_pass_backings_.end())
return;
-#if BUILDFLAG(ENABLE_VULKAN)
- GrContext* gr_context =
- output_surface_->vulkan_context_provider()->GetGrContext();
// TODO(penghuang): check supported format correctly.
- bool capability_bgra8888 = true;
-#else
- ContextProvider* context_provider = output_surface_->context_provider();
- bool capability_bgra8888 =
- context_provider->ContextCapabilities().texture_format_bgra8888;
- GrContext* gr_context = context_provider->GrContext();
-#endif
+ gpu::Capabilities caps;
+ caps.texture_format_bgra8888 = true;
+ GrContext* gr_context = nullptr;
+ if (!skia_output_surface_) {
+ ContextProvider* context_provider = output_surface_->context_provider();
+ caps.texture_format_bgra8888 =
+ context_provider->ContextCapabilities().texture_format_bgra8888;
+ gr_context = context_provider->GrContext();
+ }
render_pass_backings_.insert(std::pair<RenderPassId, RenderPassBacking>(
render_pass_id,
- RenderPassBacking(gr_context, requirements.size, requirements.mipmap,
- capability_bgra8888,
+ RenderPassBacking(gr_context, caps, requirements.size,
+ requirements.mipmap,
current_frame()->current_render_pass->color_space)));
}
SkiaRenderer::RenderPassBacking::RenderPassBacking(
GrContext* gr_context,
+ const gpu::Capabilities& caps,
const gfx::Size& size,
bool mipmap,
- bool capability_bgra8888,
const gfx::ColorSpace& color_space)
- : mipmap(mipmap), color_space(color_space) {
- ResourceFormat format;
+ : size(size), mipmap(mipmap), color_space(color_space) {
if (color_space.IsHDR()) {
// If a platform does not support half-float renderbuffers then it should
// not should request HDR rendering.
@@ -880,14 +1123,20 @@ SkiaRenderer::RenderPassBacking::RenderPassBacking(
// DCHECK(caps.color_buffer_half_float_rgba);
format = RGBA_F16;
} else {
- format = PlatformColor::BestSupportedTextureFormat(capability_bgra8888);
+ format = PlatformColor::BestSupportedTextureFormat(caps);
}
- SkColorType color_type = ResourceFormatToClosestSkColorType(format);
+
+ // For DDL, we don't need create teh render_pass_surface here, and we will
+ // create the SkSurface by SkiaOutputSurface on Gpu thread.
+ if (!gr_context)
+ return;
constexpr uint32_t flags = 0;
// LegacyFontHost will get LCD text and skia figures out what type to use.
SkSurfaceProps surface_props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
int msaa_sample_count = 0;
+ SkColorType color_type =
+ ResourceFormatToClosestSkColorType(true /* gpu_compositing*/, format);
SkImageInfo image_info = SkImageInfo::Make(
size.width(), size.height(), color_type, kPremul_SkAlphaType, nullptr);
render_pass_surface = SkSurface::MakeRenderTarget(
@@ -899,15 +1148,20 @@ SkiaRenderer::RenderPassBacking::~RenderPassBacking() {}
SkiaRenderer::RenderPassBacking::RenderPassBacking(
SkiaRenderer::RenderPassBacking&& other)
- : mipmap(other.mipmap), color_space(other.color_space) {
+ : size(other.size),
+ mipmap(other.mipmap),
+ color_space(other.color_space),
+ format(other.format) {
render_pass_surface = other.render_pass_surface;
other.render_pass_surface = nullptr;
}
SkiaRenderer::RenderPassBacking& SkiaRenderer::RenderPassBacking::operator=(
SkiaRenderer::RenderPassBacking&& other) {
+ size = other.size;
mipmap = other.mipmap;
color_space = other.color_space;
+ format = other.format;
render_pass_surface = other.render_pass_surface;
other.render_pass_surface = nullptr;
return *this;
@@ -923,8 +1177,7 @@ gfx::Size SkiaRenderer::GetRenderPassBackingPixelSize(
const RenderPassId& render_pass_id) {
auto it = render_pass_backings_.find(render_pass_id);
DCHECK(it != render_pass_backings_.end());
- SkSurface* texture = it->second.render_pass_surface.get();
- return gfx::Size(texture->width(), texture->height());
+ return it->second.size;
}
} // namespace viz
diff --git a/chromium/components/viz/service/display/skia_renderer.h b/chromium/components/viz/service/display/skia_renderer.h
index 08a8a3de61d..63fdef52ea9 100644
--- a/chromium/components/viz/service/display/skia_renderer.h
+++ b/chromium/components/viz/service/display/skia_renderer.h
@@ -5,37 +5,41 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_SKIA_RENDERER_H_
+#include <tuple>
+
#include "base/macros.h"
#include "cc/cc_export.h"
#include "components/viz/service/display/direct_renderer.h"
#include "components/viz/service/display/sync_query_collection.h"
#include "components/viz/service/viz_service_export.h"
-#include "gpu/vulkan/buildflags.h"
#include "ui/latency/latency_info.h"
class SkNWayCanvas;
-namespace cc {
-class OutputSurface;
-class RenderPassDrawQuad;
-} // namespace cc
+namespace gpu {
+struct Capabilities;
+}
namespace viz {
class DebugBorderDrawQuad;
class PictureDrawQuad;
+class SkiaOutputSurface;
class SolidColorDrawQuad;
class TextureDrawQuad;
class TileDrawQuad;
+class YUVVideoDrawQuad;
class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
public:
+ // TODO(penghuang): Remove skia_output_surface when DDL is used everywhere.
SkiaRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider);
-
+ DisplayResourceProvider* resource_provider,
+ SkiaOutputSurface* skia_output_surface = nullptr);
~SkiaRenderer() override;
- void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) override;
+ void SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) override;
void SetDisablePictureQuadImageFiltering(bool disable) {
disable_picture_quad_image_filtering_ = disable;
@@ -73,6 +77,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
private:
struct DrawRenderPassDrawQuadParams;
+ class ScopedSkImageBuilder;
+ class ScopedYUVSkImageBuilder;
void ClearCanvas(SkColor color);
void ClearFramebuffer();
@@ -84,6 +90,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
void DrawSolidColorQuad(const SolidColorDrawQuad* quad);
void DrawTextureQuad(const TextureDrawQuad* quad);
void DrawTileQuad(const TileDrawQuad* quad);
+ void DrawYUVVideoQuad(const YUVVideoDrawQuad* quad);
void DrawUnsupportedQuad(const DrawQuad* quad);
bool CalculateRPDQParams(sk_sp<SkImage> src_image,
const RenderPassDrawQuad* quad,
@@ -95,8 +102,14 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
gfx::Rect GetBackdropBoundingBoxForRenderPassQuad(
const RenderPassDrawQuad* quad,
const gfx::Transform& contents_device_transform,
- const cc::FilterOperations* background_filters) const;
- SkBitmap GetBackdropBitmap(const gfx::Rect& bounding_rect) const;
+ const cc::FilterOperations* background_filters,
+ gfx::Rect* unclipped_rect) const;
+ sk_sp<SkImage> ApplyBackgroundFilters(SkImageFilter* filter,
+ const RenderPassDrawQuad* quad,
+ sk_sp<SkImage> src_image,
+ const gfx::Rect& rect) const;
+
+ sk_sp<SkImage> GetBackdropImage(const gfx::Rect& bounding_rect) const;
sk_sp<SkShader> GetBackgroundFilterShader(
const RenderPassDrawQuad* quad,
SkShader::TileMode content_tile_mode) const;
@@ -104,12 +117,14 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
// A map from RenderPass id to the texture used to draw the RenderPass from.
struct RenderPassBacking {
sk_sp<SkSurface> render_pass_surface;
+ gfx::Size size;
bool mipmap;
gfx::ColorSpace color_space;
+ ResourceFormat format;
RenderPassBacking(GrContext* gr_context,
+ const gpu::Capabilities& caps,
const gfx::Size& size,
bool mipmap,
- bool capability_bgra8888,
const gfx::ColorSpace& color_space);
~RenderPassBacking();
RenderPassBacking(RenderPassBacking&&);
@@ -117,11 +132,13 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
};
base::flat_map<RenderPassId, RenderPassBacking> render_pass_backings_;
+ SkiaOutputSurface* const skia_output_surface_ = nullptr;
bool disable_picture_quad_image_filtering_ = false;
-
bool is_scissor_enabled_ = false;
+
gfx::Rect scissor_rect_;
+ bool is_drawing_render_pass_ = false;
sk_sp<SkSurface> root_surface_;
sk_sp<SkSurface> non_root_surface_;
sk_sp<SkSurface> overdraw_surface_;
@@ -138,6 +155,22 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
gfx::Rect swap_buffer_rect_;
std::vector<gfx::Rect> swap_content_bounds_;
+ // Lock set for resources that are used for the current frame. All resources
+ // in this set will be unlocked with a sync token when the frame is done in
+ // the compositor thread. And the sync token will be released when the DDL
+ // for the current frame is replayed on the GPU thread.
+ // It is only used with DDL.
+ DisplayResourceProvider::LockSetForExternalUse lock_set_for_external_use_;
+
+ // Promise images created from resources used in the current frame. This map
+ // will be cleared when the frame is done and before all resources in
+ // |lock_set_for_external_use_| are unlocked on the compositor thread.
+ // It is only used with DDL.
+ base::flat_map<ResourceId, sk_sp<SkImage>> promise_images_;
+
+ using YUVIds = std::tuple<ResourceId, ResourceId, ResourceId, ResourceId>;
+ base::flat_map<YUVIds, sk_sp<SkImage>> yuv_promise_images_;
+
DISALLOW_COPY_AND_ASSIGN(SkiaRenderer);
};
diff --git a/chromium/components/viz/service/display/software_output_device.cc b/chromium/components/viz/service/display/software_output_device.cc
index 7f8e8fd8504..6508266d977 100644
--- a/chromium/components/viz/service/display/software_output_device.cc
+++ b/chromium/components/viz/service/display/software_output_device.cc
@@ -5,14 +5,27 @@
#include "components/viz/service/display/software_output_device.h"
#include "base/logging.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/vsync_provider.h"
namespace viz {
-SoftwareOutputDevice::SoftwareOutputDevice() = default;
+SoftwareOutputDevice::SoftwareOutputDevice()
+ : SoftwareOutputDevice(base::SequencedTaskRunnerHandle::Get()) {}
+
+SoftwareOutputDevice::SoftwareOutputDevice(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : task_runner_(std::move(task_runner)) {}
+
SoftwareOutputDevice::~SoftwareOutputDevice() = default;
+void SoftwareOutputDevice::BindToClient(SoftwareOutputDeviceClient* client) {
+ DCHECK(client);
+ DCHECK(!client_);
+ client_ = client;
+}
+
void SoftwareOutputDevice::Resize(const gfx::Size& viewport_pixel_size,
float scale_factor) {
if (viewport_pixel_size_ == viewport_pixel_size)
@@ -36,4 +49,8 @@ gfx::VSyncProvider* SoftwareOutputDevice::GetVSyncProvider() {
return vsync_provider_.get();
}
+void SoftwareOutputDevice::OnSwapBuffers(base::OnceClosure swap_ack_callback) {
+ task_runner_->PostTask(FROM_HERE, std::move(swap_ack_callback));
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display/software_output_device.h b/chromium/components/viz/service/display/software_output_device.h
index 63e233deb7d..ac80d97157e 100644
--- a/chromium/components/viz/service/display/software_output_device.h
+++ b/chromium/components/viz/service/display/software_output_device.h
@@ -7,7 +7,10 @@
#include <memory>
+#include "base/callback.h"
#include "base/macros.h"
+#include "base/sequenced_task_runner.h"
+#include "components/viz/service/display/software_output_device_client.h"
#include "components/viz/service/viz_service_export.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/geometry/rect.h"
@@ -18,17 +21,25 @@ class SkCanvas;
namespace gfx {
class VSyncProvider;
-}
+} // namespace gfx
namespace viz {
+class SoftwareOutputDeviceClient;
+
// This is a "tear-off" class providing software drawing support to
// OutputSurface, such as to a platform-provided window framebuffer.
class VIZ_SERVICE_EXPORT SoftwareOutputDevice {
public:
+ // Uses TaskRunner returned from SequencedTaskRunnerHandle::Get().
SoftwareOutputDevice();
+ explicit SoftwareOutputDevice(
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
virtual ~SoftwareOutputDevice();
+ // This may be called only once, and requires a non-nullptr argument.
+ void BindToClient(SoftwareOutputDeviceClient* client);
+
// Discards any pre-existing backing buffers and allocates memory for a
// software device of |size|. This must be called before the
// |SoftwareOutputDevice| can be used in other ways.
@@ -55,7 +66,15 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDevice {
// hardware vsync. Return null if a provider doesn't exist.
virtual gfx::VSyncProvider* GetVSyncProvider();
+ // Called from OutputSurface::SwapBuffers(). The default implementation will
+ // immediately run |swap_ack_callback| via PostTask. If swap isn't synchronous
+ // this can be overriden so that |swap_ack_callback| is run after swap
+ // completes.
+ virtual void OnSwapBuffers(base::OnceClosure swap_ack_callback);
+
protected:
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+ SoftwareOutputDeviceClient* client_ = nullptr;
gfx::Size viewport_pixel_size_;
gfx::Rect damage_rect_;
sk_sp<SkSurface> surface_;
diff --git a/chromium/components/viz/service/display/software_output_device_client.h b/chromium/components/viz/service/display/software_output_device_client.h
new file mode 100644
index 00000000000..695354d2e08
--- /dev/null
+++ b/chromium/components/viz/service/display/software_output_device_client.h
@@ -0,0 +1,26 @@
+// 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.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_
+
+namespace gfx {
+struct CALayerParams;
+} // namespace gfx
+
+namespace viz {
+
+class SoftwareOutputDeviceClient {
+ public:
+ virtual ~SoftwareOutputDeviceClient() {}
+
+ // Specify the CALayer parameters used to display the content drawn by this
+ // device on macOS.
+ virtual void SoftwareDeviceUpdatedCALayerParams(
+ const gfx::CALayerParams& ca_layer_params) = 0;
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_SOFTWARE_OUTPUT_DEVICE_CLIENT_H_
diff --git a/chromium/components/viz/service/display/software_renderer.cc b/chromium/components/viz/service/display/software_renderer.cc
index a107b5be1f9..bc958f621cc 100644
--- a/chromium/components/viz/service/display/software_renderer.cc
+++ b/chromium/components/viz/service/display/software_renderer.cc
@@ -38,10 +38,9 @@
namespace viz {
-SoftwareRenderer::SoftwareRenderer(
- const RendererSettings* settings,
- OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+SoftwareRenderer::SoftwareRenderer(const RendererSettings* settings,
+ OutputSurface* output_surface,
+ DisplayResourceProvider* resource_provider)
: DirectRenderer(settings, output_surface, resource_provider),
output_device_(output_surface->software_device()) {}
@@ -65,11 +64,13 @@ void SoftwareRenderer::FinishDrawingFrame() {
output_device_->EndPaint();
}
-void SoftwareRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
+void SoftwareRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) {
DCHECK(visible_);
TRACE_EVENT0("viz", "SoftwareRenderer::SwapBuffers");
OutputSurfaceFrame output_frame;
output_frame.latency_info = std::move(latency_info);
+ output_frame.need_presentation_feedback = need_presentation_feedback;
output_surface_->SwapBuffers(std::move(output_frame));
}
@@ -168,16 +169,8 @@ void SoftwareRenderer::PrepareSurfaceForPass(
}
bool SoftwareRenderer::IsSoftwareResource(ResourceId resource_id) const {
- switch (resource_provider_->GetResourceType(resource_id)) {
- case ResourceType::kGpuMemoryBuffer:
- case ResourceType::kTexture:
- return false;
- case ResourceType::kBitmap:
- return true;
- }
-
- LOG(FATAL) << "Invalid resource type.";
- return false;
+ return resource_provider_->GetResourceType(resource_id) ==
+ ResourceType::kBitmap;
}
void SoftwareRenderer::DoDrawQuad(const DrawQuad* quad,
@@ -359,8 +352,8 @@ void SoftwareRenderer::DrawTextureQuad(const TextureDrawQuad* quad) {
}
// TODO(skaslev): Add support for non-premultiplied alpha.
- cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
- quad->resource_id());
+ DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
+ quad->resource_id());
if (!lock.valid())
return;
const SkImage* image = lock.sk_image();
@@ -402,8 +395,8 @@ void SoftwareRenderer::DrawTileQuad(const TileDrawQuad* quad) {
DCHECK(resource_provider_);
DCHECK(IsSoftwareResource(quad->resource_id()));
- cc::DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
- quad->resource_id());
+ DisplayResourceProvider::ScopedReadLockSkImage lock(resource_provider_,
+ quad->resource_id());
if (!lock.valid())
return;
@@ -476,11 +469,10 @@ void SoftwareRenderer::DrawRenderPassQuad(const RenderPassDrawQuad* quad) {
SkShader::kClamp_TileMode, &content_mat);
}
- std::unique_ptr<cc::DisplayResourceProvider::ScopedReadLockSoftware>
- mask_lock;
+ std::unique_ptr<DisplayResourceProvider::ScopedReadLockSoftware> mask_lock;
if (quad->mask_resource_id()) {
mask_lock =
- std::make_unique<cc::DisplayResourceProvider::ScopedReadLockSoftware>(
+ std::make_unique<DisplayResourceProvider::ScopedReadLockSoftware>(
resource_provider_, quad->mask_resource_id());
if (!mask_lock->valid())
diff --git a/chromium/components/viz/service/display/software_renderer.h b/chromium/components/viz/service/display/software_renderer.h
index 3e7d634b077..0b901e7b7ed 100644
--- a/chromium/components/viz/service/display/software_renderer.h
+++ b/chromium/components/viz/service/display/software_renderer.h
@@ -10,13 +10,10 @@
#include "components/viz/service/viz_service_export.h"
#include "ui/latency/latency_info.h"
-namespace cc {
-class OutputSurface;
-class DisplayResourceProvider;
-} // namespace cc
-
namespace viz {
class DebugBorderDrawQuad;
+class DisplayResourceProvider;
+class OutputSurface;
class PictureDrawQuad;
class RenderPassDrawQuad;
class SoftwareOutputDevice;
@@ -28,11 +25,12 @@ class VIZ_SERVICE_EXPORT SoftwareRenderer : public DirectRenderer {
public:
SoftwareRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider);
+ DisplayResourceProvider* resource_provider);
~SoftwareRenderer() override;
- void SwapBuffers(std::vector<ui::LatencyInfo> latency_info) override;
+ void SwapBuffers(std::vector<ui::LatencyInfo> latency_info,
+ bool need_presentation_feedback) override;
void SetDisablePictureQuadImageFiltering(bool disable) {
disable_picture_quad_image_filtering_ = disable;
diff --git a/chromium/components/viz/service/display/software_renderer_unittest.cc b/chromium/components/viz/service/display/software_renderer_unittest.cc
index e14a27766a7..86210a12099 100644
--- a/chromium/components/viz/service/display/software_renderer_unittest.cc
+++ b/chromium/components/viz/service/display/software_renderer_unittest.cc
@@ -7,6 +7,8 @@
#include <stdint.h>
#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/memory/shared_memory.h"
#include "base/run_loop.h"
#include "cc/test/animation_test_common.h"
#include "cc/test/fake_output_surface_client.h"
@@ -20,8 +22,10 @@
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
+#include "components/viz/common/quads/shared_bitmap.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/tile_draw_quad.h"
+#include "components/viz/common/resources/bitmap_allocation.h"
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/test/fake_output_surface.h"
#include "components/viz/test/test_shared_bitmap_manager.h"
@@ -52,11 +56,10 @@ class SoftwareRendererTest : public testing::Test {
renderer_->SetVisible(true);
child_resource_provider_ =
- cc::FakeResourceProvider::CreateLayerTreeResourceProvider(
- nullptr, shared_bitmap_manager_.get());
+ cc::FakeResourceProvider::CreateLayerTreeResourceProvider(nullptr);
}
- cc::DisplayResourceProvider* resource_provider() const {
+ DisplayResourceProvider* resource_provider() const {
return resource_provider_.get();
}
@@ -66,6 +69,26 @@ class SoftwareRendererTest : public testing::Test {
SoftwareRenderer* renderer() const { return renderer_.get(); }
+ ResourceId AllocateAndFillSoftwareResource(const gfx::Size& size,
+ const SkBitmap& source) {
+ std::unique_ptr<base::SharedMemory> shm =
+ bitmap_allocation::AllocateMappedBitmap(size, RGBA_8888);
+ SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
+ source.readPixels(info, shm->memory(), info.minRowBytes(), 0, 0);
+
+ // Registers the SharedBitmapId in the display compositor.
+ SharedBitmapId shared_bitmap_id = SharedBitmap::GenerateId();
+ shared_bitmap_manager_->ChildAllocatedSharedBitmap(
+ bitmap_allocation::DuplicateAndCloseMappedBitmap(shm.get(), size,
+ RGBA_8888),
+ shared_bitmap_id);
+
+ // Makes a resource id that refers to the registered SharedBitmapId.
+ return child_resource_provider_->ImportResource(
+ TransferableResource::MakeSoftware(shared_bitmap_id, size, RGBA_8888),
+ SingleReleaseCallback::Create(base::DoNothing()));
+ }
+
std::unique_ptr<SkBitmap> DrawAndCopyOutput(RenderPassList* list,
float device_scale_factor,
gfx::Size viewport_size) {
@@ -97,7 +120,7 @@ class SoftwareRendererTest : public testing::Test {
cc::FakeOutputSurfaceClient output_surface_client_;
std::unique_ptr<FakeOutputSurface> output_surface_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<cc::LayerTreeResourceProvider> child_resource_provider_;
std::unique_ptr<SoftwareRenderer> renderer_;
};
@@ -156,11 +179,6 @@ TEST_F(SoftwareRendererTest, TileQuad) {
bool needs_blending = false;
InitializeRenderer(std::make_unique<SoftwareOutputDevice>());
- ResourceId resource_yellow = child_resource_provider()->CreateBitmapResource(
- outer_size, gfx::ColorSpace(), RGBA_8888);
- ResourceId resource_cyan = child_resource_provider()->CreateBitmapResource(
- inner_size, gfx::ColorSpace(), RGBA_8888);
-
SkBitmap yellow_tile;
yellow_tile.allocN32Pixels(outer_size.width(), outer_size.height());
yellow_tile.eraseColor(SK_ColorYELLOW);
@@ -169,17 +187,16 @@ TEST_F(SoftwareRendererTest, TileQuad) {
cyan_tile.allocN32Pixels(inner_size.width(), inner_size.height());
cyan_tile.eraseColor(SK_ColorCYAN);
- child_resource_provider()->CopyToResource(
- resource_yellow, static_cast<uint8_t*>(yellow_tile.getPixels()),
- outer_size);
- child_resource_provider()->CopyToResource(
- resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), inner_size);
+ ResourceId resource_yellow =
+ this->AllocateAndFillSoftwareResource(outer_size, yellow_tile);
+ ResourceId resource_cyan =
+ this->AllocateAndFillSoftwareResource(inner_size, cyan_tile);
// Transfer resources to the parent, and get the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource_yellow, resource_cyan},
resource_provider(),
- child_resource_provider());
+ child_resource_provider(), nullptr);
ResourceId mapped_resource_yellow = resource_map[resource_yellow];
ResourceId mapped_resource_cyan = resource_map[resource_cyan];
@@ -228,9 +245,6 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
visible_rect.Inset(1, 2, 3, 4);
InitializeRenderer(std::make_unique<SoftwareOutputDevice>());
- ResourceId resource_cyan = child_resource_provider()->CreateBitmapResource(
- tile_size, gfx::ColorSpace(), RGBA_8888);
-
SkBitmap cyan_tile; // The lowest five rows are yellow.
cyan_tile.allocN32Pixels(tile_size.width(), tile_size.height());
cyan_tile.eraseColor(SK_ColorCYAN);
@@ -238,13 +252,13 @@ TEST_F(SoftwareRendererTest, TileQuadVisibleRect) {
tile_rect.width(), tile_rect.bottom()),
SK_ColorYELLOW);
- child_resource_provider()->CopyToResource(
- resource_cyan, static_cast<uint8_t*>(cyan_tile.getPixels()), tile_size);
+ ResourceId resource_cyan =
+ AllocateAndFillSoftwareResource(tile_size, cyan_tile);
// Transfer resources to the parent, and get the resource map.
- cc::ResourceProvider::ResourceIdMap resource_map =
+ std::unordered_map<ResourceId, ResourceId> resource_map =
SendResourceAndGetChildToParentMap({resource_cyan}, resource_provider(),
- child_resource_provider());
+ child_resource_provider(), nullptr);
ResourceId mapped_resource_cyan = resource_map[resource_cyan];
gfx::Rect root_rect(tile_size);
diff --git a/chromium/components/viz/service/display/surface_aggregator.cc b/chromium/components/viz/service/display/surface_aggregator.cc
index 5c41b6d48b8..c021630d66f 100644
--- a/chromium/components/viz/service/display/surface_aggregator.cc
+++ b/chromium/components/viz/service/display/surface_aggregator.cc
@@ -13,10 +13,10 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/ranges.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/math_util.h"
-#include "cc/resources/display_resource_provider.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/render_pass_draw_quad.h"
@@ -24,6 +24,7 @@
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/surfaces/surface.h"
#include "components/viz/service/surfaces/surface_client.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -34,6 +35,10 @@ namespace {
// Maximum bucket size for the UMA stats.
constexpr int kUmaStatMaxSurfaces = 30;
+// Used for determine when to treat opacity close to 1.f as opaque. The value is
+// chosen to be smaller than 1/255.
+constexpr float kOpacityEpsilon = 0.001f;
+
const char kUmaValidSurface[] =
"Compositing.SurfaceAggregator.SurfaceDrawQuad.ValidSurface";
const char kUmaMissingSurface[] =
@@ -77,7 +82,7 @@ bool CalculateQuadSpaceDamageRect(
} // namespace
SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
- cc::DisplayResourceProvider* provider,
+ DisplayResourceProvider* provider,
bool aggregate_only_damaged)
: manager_(manager),
provider_(provider),
@@ -323,14 +328,15 @@ void SurfaceAggregator::EmitSurfaceContent(
referenced_surfaces_.insert(surface_id);
// TODO(vmpstr): provider check is a hack for unittests that don't set up a
// resource provider.
- cc::ResourceProvider::ResourceIdMap empty_map;
+ std::unordered_map<ResourceId, ResourceId> empty_map;
const auto& child_to_parent_map =
provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
: empty_map;
gfx::Transform combined_transform = scaled_quad_to_target_transform;
combined_transform.ConcatTransform(target_transform);
- bool merge_pass = source_sqs->opacity == 1.f && copy_requests.empty() &&
- combined_transform.Preserves2dAxisAlignment();
+ bool merge_pass =
+ base::IsApproximatelyEqual(source_sqs->opacity, 1.f, kOpacityEpsilon) &&
+ copy_requests.empty() && combined_transform.Preserves2dAxisAlignment();
const RenderPassList& referenced_passes = render_pass_list;
// TODO(fsamuel): Move this to a separate helper function.
@@ -763,7 +769,7 @@ void SurfaceAggregator::CopyPasses(const CompositorFrame& frame,
// TODO(vmpstr): provider check is a hack for unittests that don't set up a
// resource provider.
- cc::ResourceProvider::ResourceIdMap empty_map;
+ std::unordered_map<ResourceId, ResourceId> empty_map;
const auto& child_to_parent_map =
provider_ ? provider_->GetChildToParentMap(ChildIdForSurface(surface))
: empty_map;
@@ -841,11 +847,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
int parent_pass_id,
bool will_draw,
PrewalkResult* result) {
- // This is for debugging a possible use after free.
- // TODO(jbauman): Remove this once we have enough information.
- // http://crbug.com/560181
- base::WeakPtr<SurfaceAggregator> debug_weak_this = weak_factory_.GetWeakPtr();
-
if (referenced_surfaces_.count(surface->surface_id()))
return gfx::Rect();
@@ -864,18 +865,16 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
surface->RefResources(frame.resource_list);
provider_->ReceiveFromChild(child_id, frame.resource_list);
}
- CHECK(debug_weak_this.get());
std::vector<ResourceId> referenced_resources;
size_t reserve_size = frame.resource_list.size();
referenced_resources.reserve(reserve_size);
bool invalid_frame = false;
- cc::ResourceProvider::ResourceIdMap empty_map;
+ std::unordered_map<ResourceId, ResourceId> empty_map;
const auto& child_to_parent_map =
provider_ ? provider_->GetChildToParentMap(child_id) : empty_map;
- CHECK(debug_weak_this.get());
RenderPassId remapped_pass_id =
RemapPassId(frame.render_pass_list.back()->id, surface->surface_id());
if (in_moved_pixel_surface)
@@ -976,14 +975,12 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
if (invalid_frame)
return gfx::Rect();
- CHECK(debug_weak_this.get());
valid_surfaces_.insert(surface->surface_id());
ResourceIdSet resource_set(std::move(referenced_resources),
base::KEEP_FIRST_OF_DUPES);
if (provider_)
provider_->DeclareUsedResourcesFromChild(child_id, resource_set);
- CHECK(debug_weak_this.get());
gfx::Rect damage_rect;
gfx::Rect full_damage;
@@ -1050,8 +1047,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
surface_info.target_to_surface_transform, surface_damage));
}
- CHECK(debug_weak_this.get());
-
if (!damage_rect.IsEmpty()) {
// The following call can cause one or more copy requests to be added to the
// Surface. Therefore, no code before this point should have assumed
@@ -1066,8 +1061,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
if (will_draw)
surface->OnWillBeDrawn();
- CHECK(debug_weak_this.get());
-
for (const auto& surface_id : frame.metadata.referenced_surfaces) {
if (!contained_surfaces_.count(surface_id)) {
result->undrawn_surfaces.insert(surface_id);
@@ -1077,7 +1070,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
}
}
- CHECK(debug_weak_this.get());
for (const auto& render_pass : frame.render_pass_list) {
if (!render_pass->copy_requests.empty()) {
RenderPassId remapped_pass_id =
@@ -1089,8 +1081,6 @@ gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
}
auto it = referenced_surfaces_.find(surface->surface_id());
- // TODO(jbauman): Remove when https://crbug.com/745684 fixed.
- CHECK(referenced_surfaces_.end() != it);
referenced_surfaces_.erase(it);
if (!damage_rect.IsEmpty() && frame.metadata.may_contain_video)
result->may_contain_video = true;
diff --git a/chromium/components/viz/service/display/surface_aggregator.h b/chromium/components/viz/service/display/surface_aggregator.h
index fc2c379e225..14b4bfe907d 100644
--- a/chromium/components/viz/service/display/surface_aggregator.h
+++ b/chromium/components/viz/service/display/surface_aggregator.h
@@ -19,12 +19,9 @@
#include "components/viz/service/viz_service_export.h"
#include "ui/gfx/color_space.h"
-namespace cc {
-class DisplayResourceProvider;
-} // namespace cc
-
namespace viz {
class CompositorFrame;
+class DisplayResourceProvider;
class Surface;
class SurfaceClient;
class SurfaceDrawQuad;
@@ -36,7 +33,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
using FrameSinkIdMap = base::flat_map<FrameSinkId, LocalSurfaceId>;
SurfaceAggregator(SurfaceManager* manager,
- cc::DisplayResourceProvider* provider,
+ DisplayResourceProvider* provider,
bool aggregate_only_damaged);
~SurfaceAggregator();
@@ -202,7 +199,7 @@ class VIZ_SERVICE_EXPORT SurfaceAggregator {
const std::vector<ReturnedResource>& resources);
SurfaceManager* manager_;
- cc::DisplayResourceProvider* provider_;
+ DisplayResourceProvider* provider_;
// Every Surface has its own RenderPass ID namespace. This structure maps
// each source (SurfaceId, RenderPass id) to a unified ID namespace that's
diff --git a/chromium/components/viz/service/display/surface_aggregator_perftest.cc b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
index 9ae9e880f2f..ca2a7834ed1 100644
--- a/chromium/components/viz/service/display/surface_aggregator_perftest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_perftest.cc
@@ -3,13 +3,13 @@
// found in the LICENSE file.
#include "cc/base/lap_timer.h"
-#include "cc/resources/display_resource_provider.h"
#include "cc/test/fake_output_surface_client.h"
#include "cc/test/fake_resource_provider.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/surface_aggregator.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
@@ -150,7 +150,7 @@ class SurfaceAggregatorPerfTest : public testing::Test {
FrameSinkManagerImpl manager_;
scoped_refptr<TestContextProvider> context_provider_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
cc::LapTimer timer_;
};
diff --git a/chromium/components/viz/service/display/surface_aggregator_unittest.cc b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
index d25d5115d4a..23db64eab7b 100644
--- a/chromium/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/chromium/components/viz/service/display/surface_aggregator_unittest.cc
@@ -14,7 +14,6 @@
#include "base/memory/weak_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
-#include "cc/resources/display_resource_provider.h"
#include "cc/test/fake_resource_provider.h"
#include "cc/test/render_pass_test_utils.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -27,6 +26,7 @@
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/shared_bitmap_manager.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "components/viz/service/surfaces/surface.h"
@@ -378,7 +378,7 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
void SetUp() override {
SurfaceAggregatorTest::SetUp();
- root_local_surface_id_ = allocator_.GenerateId();
+ root_local_surface_id_ = allocator_.GetCurrentLocalSurfaceId();
root_surface_ = manager_.surface_manager()->GetSurfaceForId(
SurfaceId(support_->frame_sink_id(), root_local_surface_id_));
}
@@ -533,29 +533,44 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, OpacityCopied) {
SubmitCompositorFrame(embedded_support.get(), embedded_passes,
arraysize(embedded_passes), embedded_local_surface_id,
device_scale_factor);
+ SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
+ {
+ Quad quads[] = {Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(),
+ SK_ColorWHITE, gfx::Rect(5, 5), .5f,
+ gfx::Transform(), false)};
+ Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
- Quad quads[] = {Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(),
- SK_ColorWHITE, gfx::Rect(5, 5), .5f,
- gfx::Transform(), false)};
- Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
+ SubmitCompositorFrame(support_.get(), passes, arraysize(passes),
+ root_local_surface_id_, device_scale_factor);
- SubmitCompositorFrame(support_.get(), passes, arraysize(passes),
- root_local_surface_id_, device_scale_factor);
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(
+ root_surface_id, GetNextDisplayTimeAndIncrement());
- SurfaceId root_surface_id(support_->frame_sink_id(), root_local_surface_id_);
- CompositorFrame aggregated_frame =
- aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement());
+ auto& render_pass_list = aggregated_frame.render_pass_list;
+ EXPECT_EQ(2u, render_pass_list.size());
- auto& render_pass_list = aggregated_frame.render_pass_list;
- ASSERT_EQ(2u, render_pass_list.size());
- auto& shared_quad_state_list = render_pass_list[0]->shared_quad_state_list;
- ASSERT_EQ(2u, shared_quad_state_list.size());
- EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(0)->opacity);
- EXPECT_EQ(1.f, shared_quad_state_list.ElementAt(1)->opacity);
-
- auto& shared_quad_state_list2 = render_pass_list[1]->shared_quad_state_list;
- ASSERT_EQ(1u, shared_quad_state_list2.size());
- EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity);
+ auto& shared_quad_state_list2 = render_pass_list[1]->shared_quad_state_list;
+ ASSERT_EQ(1u, shared_quad_state_list2.size());
+ EXPECT_EQ(.5f, shared_quad_state_list2.ElementAt(0)->opacity);
+ }
+
+ // For the case where opacity is close to 1.f, we treat it as opaque, and not
+ // use a render surface.
+ {
+ Quad quads[] = {Quad::SurfaceQuad(embedded_surface_id, InvalidSurfaceId(),
+ SK_ColorWHITE, gfx::Rect(5, 5), .9999f,
+ gfx::Transform(), false)};
+ Pass passes[] = {Pass(quads, arraysize(quads), SurfaceSize())};
+
+ SubmitCompositorFrame(support_.get(), passes, arraysize(passes),
+ root_local_surface_id_, device_scale_factor);
+
+ CompositorFrame aggregated_frame = aggregator_.Aggregate(
+ root_surface_id, GetNextDisplayTimeAndIncrement());
+
+ auto& render_pass_list = aggregated_frame.render_pass_list;
+ EXPECT_EQ(1u, render_pass_list.size());
+ }
}
// Test that when surface is rotated and we need the render surface to apply the
@@ -2952,7 +2967,7 @@ class SurfaceAggregatorWithResourcesTest : public testing::Test,
protected:
FrameSinkManagerImpl manager_;
std::unique_ptr<SharedBitmapManager> shared_bitmap_manager_;
- std::unique_ptr<cc::DisplayResourceProvider> resource_provider_;
+ std::unique_ptr<DisplayResourceProvider> resource_provider_;
std::unique_ptr<SurfaceAggregator> aggregator_;
};
diff --git a/chromium/components/viz/service/display/vulkan_renderer.cc b/chromium/components/viz/service/display/vulkan_renderer.cc
index 87ede657bd4..1ddd1d36e24 100644
--- a/chromium/components/viz/service/display/vulkan_renderer.cc
+++ b/chromium/components/viz/service/display/vulkan_renderer.cc
@@ -19,7 +19,7 @@ void VulkanRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
VulkanRenderer::VulkanRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider)
+ DisplayResourceProvider* resource_provider)
: DirectRenderer(settings, output_surface, resource_provider) {}
void VulkanRenderer::DidChangeVisibility() {
diff --git a/chromium/components/viz/service/display/vulkan_renderer.h b/chromium/components/viz/service/display/vulkan_renderer.h
index ce07ecce7b7..4e7ff89a7ab 100644
--- a/chromium/components/viz/service/display/vulkan_renderer.h
+++ b/chromium/components/viz/service/display/vulkan_renderer.h
@@ -9,17 +9,15 @@
#include "components/viz/service/viz_service_export.h"
#include "ui/latency/latency_info.h"
-namespace cc {
-class OutputSurface;
-} // namespace cc
-
namespace viz {
+class OutputSurface;
+
class VIZ_SERVICE_EXPORT VulkanRenderer : public DirectRenderer {
public:
VulkanRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
- cc::DisplayResourceProvider* resource_provider);
+ DisplayResourceProvider* resource_provider);
~VulkanRenderer() override;
// Implementation of public DirectRenderer functions.
diff --git a/chromium/components/viz/service/display_embedder/DEPS b/chromium/components/viz/service/display_embedder/DEPS
index 5fc1a52037e..38bf218cf88 100644
--- a/chromium/components/viz/service/display_embedder/DEPS
+++ b/chromium/components/viz/service/display_embedder/DEPS
@@ -2,7 +2,6 @@
include_rules = [
"+cc/base",
- "+cc/ipc",
"+cc/output",
"+cc/resources",
"+cc/scheduler",
@@ -10,18 +9,21 @@ include_rules = [
"+components/viz/service/display/output_surface_frame.h",
"+components/viz/service/display/output_surface.h",
"+components/viz/service/display/overlay_candidate_validator.h",
+ "+components/viz/service/display/skia_output_surface.h",
"+components/viz/service/display/software_output_device.h",
+ "+gpu/config/gpu_feature_info.h",
+ "+components/viz/service/gl/gpu_service_impl.h",
"+gpu/GLES2",
"+gpu/command_buffer/client",
"+gpu/command_buffer/common",
"+gpu/command_buffer/service",
- "+gpu/ipc/client",
- "+gpu/ipc/common",
- "+gpu/ipc/in_process_command_buffer.h",
- "+gpu/ipc/service",
+ "+gpu/ipc",
+ "+gpu/skia_bindings",
"+mojo/public/cpp/bindings",
"+mojo/public/cpp/system",
"+skia",
+ "+third_party/khronos/GLES2/gl2.h",
+ "+third_party/khronos/GLES2/gl2ext.h",
"+third_party/skia",
"+ui/accelerated_widget_mac",
"+ui/display",
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.cc b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.cc
index a91ebec2695..f0af20b4c82 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.cc
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.cc
@@ -20,11 +20,19 @@ CompositorOverlayCandidateValidatorAndroid::
void CompositorOverlayCandidateValidatorAndroid::GetStrategies(
OverlayProcessor::StrategyList* strategies) {
- strategies->push_back(std::make_unique<OverlayStrategyUnderlay>(this));
+ // For Android, we do not have the ability to skip an overlay, since the
+ // texture is already in a SurfaceView. Ideally, we would honor a 'force
+ // overlay' flag that FromDrawQuad would also check.
+ // For now, though, just skip the opacity check. We really have no idea if
+ // the underlying overlay is opaque anyway; the candidate is referring to
+ // a dummy resource that has no relation to what the overlay contains.
+ // https://crbug.com/842931 .
+ strategies->push_back(std::make_unique<OverlayStrategyUnderlay>(
+ this, OverlayStrategyUnderlay::OpaqueMode::AllowTransparentCandidates));
}
void CompositorOverlayCandidateValidatorAndroid::CheckOverlaySupport(
- cc::OverlayCandidateList* candidates) {
+ 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
@@ -32,7 +40,7 @@ void CompositorOverlayCandidateValidatorAndroid::CheckOverlaySupport(
DCHECK_LE(candidates->size(), 1u);
if (!candidates->empty()) {
- cc::OverlayCandidate& candidate = candidates->front();
+ OverlayCandidate& candidate = candidates->front();
// This quad either will be promoted, or would be if it were backed by a
// SurfaceView. Record that it should get a promotion hint.
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h
index df053dce733..2b30937d787 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_android.h
@@ -26,7 +26,7 @@ class VIZ_SERVICE_EXPORT CompositorOverlayCandidateValidatorAndroid
~CompositorOverlayCandidateValidatorAndroid() override;
void GetStrategies(OverlayProcessor::StrategyList* strategies) override;
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
bool AllowCALayerOverlays() override;
bool AllowDCLayerOverlays() override;
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.cc b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.cc
index 07bc790a298..ebe761bab99 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.cc
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.cc
@@ -27,7 +27,7 @@ bool CompositorOverlayCandidateValidatorMac::AllowDCLayerOverlays() {
}
void CompositorOverlayCandidateValidatorMac::CheckOverlaySupport(
- cc::OverlayCandidateList* surfaces) {}
+ OverlayCandidateList* surfaces) {}
void CompositorOverlayCandidateValidatorMac::SetSoftwareMirrorMode(
bool enabled) {
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h
index b2a01c46c19..7d6ad9e5b20 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_mac.h
@@ -23,7 +23,7 @@ class VIZ_SERVICE_EXPORT CompositorOverlayCandidateValidatorMac
void GetStrategies(OverlayProcessor::StrategyList* strategies) override;
bool AllowCALayerOverlays() override;
bool AllowDCLayerOverlays() override;
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
// CompositorOverlayCandidateValidator implementation.
void SetSoftwareMirrorMode(bool enabled) override;
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.cc b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.cc
index 88f74d0f352..e0bdbf80fae 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.cc
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.cc
@@ -29,8 +29,8 @@ std::unique_ptr<OverlayProcessor::Strategy> MakeOverlayStrategy(
} // namespace
// |overlay_candidates| is an object used to answer questions about possible
-// overlays configuarations.
-// |strategies_string| is a comma-separated string containing all the overaly
+// overlays configurations.
+// |strategies_string| is a comma-separated string containing all the overlay
// strategies that should be returned by GetStrategies.
// If |strategies_string| is empty "single-on-top,underlay" will be used as
// default.
@@ -82,7 +82,7 @@ bool CompositorOverlayCandidateValidatorOzone::AllowDCLayerOverlays() {
}
void CompositorOverlayCandidateValidatorOzone::CheckOverlaySupport(
- cc::OverlayCandidateList* surfaces) {
+ OverlayCandidateList* surfaces) {
// SW mirroring copies out of the framebuffer, so we can't remove any
// quads for overlaying, otherwise the output is incorrect.
if (software_mirror_active_) {
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h
index 13fcbc9c039..3c03de00fe8 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_ozone.h
@@ -31,7 +31,7 @@ class VIZ_SERVICE_EXPORT CompositorOverlayCandidateValidatorOzone
void GetStrategies(OverlayProcessor::StrategyList* strategies) override;
bool AllowCALayerOverlays() override;
bool AllowDCLayerOverlays() override;
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
// CompositorOverlayCandidateValidator implementation.
void SetSoftwareMirrorMode(bool enabled) override;
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.cc b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.cc
index 44494ef59c5..28663e891fa 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.cc
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.cc
@@ -18,7 +18,7 @@ void CompositorOverlayCandidateValidatorWin::GetStrategies(
OverlayProcessor::StrategyList* strategies) {}
void CompositorOverlayCandidateValidatorWin::CheckOverlaySupport(
- cc::OverlayCandidateList* candidates) {
+ OverlayCandidateList* candidates) {
NOTIMPLEMENTED();
}
diff --git a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h
index fe25ef93771..2685709a9b6 100644
--- a/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h
+++ b/chromium/components/viz/service/display_embedder/compositor_overlay_candidate_validator_win.h
@@ -20,7 +20,7 @@ class VIZ_SERVICE_EXPORT CompositorOverlayCandidateValidatorWin
~CompositorOverlayCandidateValidatorWin() override;
void GetStrategies(OverlayProcessor::StrategyList* strategies) override;
- void CheckOverlaySupport(cc::OverlayCandidateList* surfaces) override;
+ void CheckOverlaySupport(OverlayCandidateList* surfaces) override;
bool AllowCALayerOverlays() override;
bool AllowDCLayerOverlays() override;
diff --git a/chromium/components/viz/service/display_embedder/display_provider.h b/chromium/components/viz/service/display_embedder/display_provider.h
index eaae5ac0805..12fa6146fef 100644
--- a/chromium/components/viz/service/display_embedder/display_provider.h
+++ b/chromium/components/viz/service/display_embedder/display_provider.h
@@ -8,6 +8,7 @@
#include <memory>
#include "gpu/ipc/common/surface_handle.h"
+#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
namespace viz {
@@ -29,6 +30,7 @@ class DisplayProvider {
const FrameSinkId& frame_sink_id,
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
+ mojom::DisplayClient* display_client,
ExternalBeginFrameControllerImpl* external_begin_frame_controller,
const RendererSettings& renderer_settings,
std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source) = 0;
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface.cc b/chromium/components/viz/service/display_embedder/gl_output_surface.cc
index ef2e3675d25..55fc38aabac 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface.cc
@@ -15,33 +15,34 @@
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "gpu/command_buffer/common/swap_buffers_flags.h"
#include "ui/gl/gl_utils.h"
namespace viz {
GLOutputSurface::GLOutputSurface(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
SyntheticBeginFrameSource* synthetic_begin_frame_source)
: OutputSurface(context_provider),
synthetic_begin_frame_source_(synthetic_begin_frame_source),
- latency_tracker_(true),
- latency_info_cache_(this),
+ use_gpu_fence_(
+ context_provider->ContextCapabilities().chromium_gpu_fence &&
+ context_provider->ContextCapabilities()
+ .use_gpu_fences_for_overlay_planes),
weak_ptr_factory_(this) {
capabilities_.flipped_output_surface =
context_provider->ContextCapabilities().flips_vertically;
capabilities_.supports_stencil =
context_provider->ContextCapabilities().num_stencil_bits > 0;
- context_provider->SetSwapBuffersCompletionCallback(
- base::BindRepeating(&GLOutputSurface::OnGpuSwapBuffersCompleted,
- weak_ptr_factory_.GetWeakPtr()));
context_provider->SetUpdateVSyncParametersCallback(
base::BindRepeating(&GLOutputSurface::OnVSyncParametersUpdated,
weak_ptr_factory_.GetWeakPtr()));
- context_provider->SetPresentationCallback(base::BindRepeating(
- &GLOutputSurface::OnPresentation, weak_ptr_factory_.GetWeakPtr()));
}
-GLOutputSurface::~GLOutputSurface() {}
+GLOutputSurface::~GLOutputSurface() {
+ if (gpu_fence_id_ > 0)
+ context_provider()->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+}
void GLOutputSurface::BindToClient(OutputSurfaceClient* client) {
DCHECK(client);
@@ -86,21 +87,37 @@ void GLOutputSurface::Reshape(const gfx::Size& size,
void GLOutputSurface::SwapBuffers(OutputSurfaceFrame frame) {
DCHECK(context_provider_);
- if (latency_info_cache_.WillSwap(std::move(frame.latency_info)))
+ uint32_t flags = 0;
+ if (synthetic_begin_frame_source_)
+ flags |= gpu::SwapBuffersFlags::kVSyncParams;
+
+ if (LatencyInfoHasSnapshotRequest(frame.latency_info))
context_provider_->ContextSupport()->SetSnapshotRequested();
+ auto swap_callback = base::BindOnce(
+ &GLOutputSurface::OnGpuSwapBuffersCompleted,
+ weak_ptr_factory_.GetWeakPtr(), std::move(frame.latency_info));
+ gpu::ContextSupport::PresentationCallback presentation_callback;
+ if (frame.need_presentation_feedback) {
+ flags |= gpu::SwapBuffersFlags::kPresentationFeedback;
+ presentation_callback = base::BindOnce(&GLOutputSurface::OnPresentation,
+ weak_ptr_factory_.GetWeakPtr());
+ }
+
set_draw_rectangle_for_frame_ = false;
if (frame.sub_buffer_rect) {
context_provider_->ContextSupport()->PartialSwapBuffers(
- *frame.sub_buffer_rect);
+ *frame.sub_buffer_rect, flags, std::move(swap_callback),
+ std::move(presentation_callback));
} else {
- context_provider_->ContextSupport()->Swap();
+ context_provider_->ContextSupport()->Swap(flags, std::move(swap_callback),
+ std::move(presentation_callback));
}
}
uint32_t GLOutputSurface::GetFramebufferCopyTextureFormat() {
// TODO(danakj): What attributes are used for the default framebuffer here?
- // Can it have alpha? InProcessContextProvider doesn't take any
+ // Can it have alpha? VizProcessContextProvider doesn't take any
// attributes.
return GL_RGB;
}
@@ -122,37 +139,28 @@ gfx::BufferFormat GLOutputSurface::GetOverlayBufferFormat() const {
return gfx::BufferFormat::RGBX_8888;
}
-bool GLOutputSurface::SurfaceIsSuspendForRecycle() const {
- return false;
-}
-
bool GLOutputSurface::HasExternalStencilTest() const {
return false;
}
void GLOutputSurface::ApplyExternalStencil() {}
-void GLOutputSurface::DidReceiveSwapBuffersAck(gfx::SwapResult result,
- uint64_t swap_id) {
- client_->DidReceiveSwapBuffersAck(swap_id);
+void GLOutputSurface::DidReceiveSwapBuffersAck(gfx::SwapResult result) {
+ client_->DidReceiveSwapBuffersAck();
}
void GLOutputSurface::OnGpuSwapBuffersCompleted(
+ std::vector<ui::LatencyInfo> latency_info,
const gpu::SwapBuffersCompleteParams& params) {
if (!params.texture_in_use_responses.empty())
client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
if (!params.ca_layer_params.is_empty)
client_->DidReceiveCALayerParams(params.ca_layer_params);
- DidReceiveSwapBuffersAck(params.swap_response.result,
- params.swap_response.swap_id);
- latency_info_cache_.OnSwapBuffersCompleted(params.swap_response);
-}
+ DidReceiveSwapBuffersAck(params.swap_response.result);
-void GLOutputSurface::LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (const auto& latency : latency_info) {
- latency_tracker_.OnGpuSwapBuffersCompleted(latency);
- }
+ UpdateLatencyInfoOnSwap(params.swap_response, &latency_info);
+ latency_tracker_.OnGpuSwapBuffersCompleted(latency_info);
+ client_->DidFinishLatencyInfo(latency_info);
}
void GLOutputSurface::OnVSyncParametersUpdated(base::TimeTicks timebase,
@@ -166,9 +174,8 @@ void GLOutputSurface::OnVSyncParametersUpdated(base::TimeTicks timebase,
}
void GLOutputSurface::OnPresentation(
- uint64_t swap_id,
const gfx::PresentationFeedback& feedback) {
- client_->DidReceivePresentationFeedback(swap_id, feedback);
+ client_->DidReceivePresentationFeedback(feedback);
}
#if BUILDFLAG(ENABLE_VULKAN)
@@ -178,4 +185,16 @@ gpu::VulkanSurface* GLOutputSurface::GetVulkanSurface() {
}
#endif
+unsigned GLOutputSurface::UpdateGpuFence() {
+ if (!use_gpu_fence_)
+ return 0;
+
+ if (gpu_fence_id_ > 0)
+ context_provider()->ContextGL()->DestroyGpuFenceCHROMIUM(gpu_fence_id_);
+
+ gpu_fence_id_ = context_provider()->ContextGL()->CreateGpuFenceCHROMIUM();
+
+ return gpu_fence_id_;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface.h b/chromium/components/viz/service/display_embedder/gl_output_surface.h
index c2e58bb7dca..06f87f581c3 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface.h
@@ -7,8 +7,8 @@
#include <memory>
-#include "components/viz/common/gpu/in_process_context_provider.h"
#include "components/viz/service/display/output_surface.h"
+#include "components/viz/service/display_embedder/viz_process_context_provider.h"
#include "ui/latency/latency_tracker.h"
namespace viz {
@@ -17,10 +17,9 @@ class SyntheticBeginFrameSource;
// An OutputSurface implementation that directly draws and
// swaps to an actual GL surface.
-class GLOutputSurface : public OutputSurface,
- public OutputSurface::LatencyInfoCache::Client {
+class GLOutputSurface : public OutputSurface {
public:
- GLOutputSurface(scoped_refptr<InProcessContextProvider> context_provider,
+ GLOutputSurface(scoped_refptr<VizProcessContextProvider> context_provider,
SyntheticBeginFrameSource* synthetic_begin_frame_source);
~GLOutputSurface() override;
@@ -41,31 +40,26 @@ class GLOutputSurface : public OutputSurface,
bool IsDisplayedAsOverlayPlane() const override;
unsigned GetOverlayTextureId() const override;
gfx::BufferFormat GetOverlayBufferFormat() const override;
- bool SurfaceIsSuspendForRecycle() const override;
bool HasExternalStencilTest() const override;
void ApplyExternalStencil() override;
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
-
- // OutputSurface::LatencyInfoCache::Client implementation.
- void LatencyInfoCompleted(
- const std::vector<ui::LatencyInfo>& latency_info) override;
+ unsigned UpdateGpuFence() override;
protected:
OutputSurfaceClient* client() const { return client_; }
// Called when a swap completion is signaled from ImageTransportSurface.
- virtual void DidReceiveSwapBuffersAck(gfx::SwapResult result,
- uint64_t swap_id);
+ virtual void DidReceiveSwapBuffersAck(gfx::SwapResult result);
private:
// Called when a swap completion is signaled from ImageTransportSurface.
- void OnGpuSwapBuffersCompleted(const gpu::SwapBuffersCompleteParams& params);
+ void OnGpuSwapBuffersCompleted(std::vector<ui::LatencyInfo> latency_info,
+ const gpu::SwapBuffersCompleteParams& params);
void OnVSyncParametersUpdated(base::TimeTicks timebase,
base::TimeDelta interval);
- void OnPresentation(uint64_t swap_id,
- const gfx::PresentationFeedback& feedback);
+ void OnPresentation(const gfx::PresentationFeedback& feedback);
OutputSurfaceClient* client_ = nullptr;
SyntheticBeginFrameSource* const synthetic_begin_frame_source_;
@@ -75,7 +69,8 @@ class GLOutputSurface : public OutputSurface,
// True if the draw rectangle has been set at all since the last resize.
bool has_set_draw_rectangle_since_last_resize_ = false;
gfx::Size size_;
- LatencyInfoCache latency_info_cache_;
+ bool use_gpu_fence_;
+ unsigned gpu_fence_id_ = 0;
base::WeakPtrFactory<GLOutputSurface> weak_ptr_factory_;
};
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
index cf02039d4b4..279daf5f4ff 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.cc
@@ -18,7 +18,7 @@
namespace viz {
GLOutputSurfaceBufferQueue::GLOutputSurfaceBufferQueue(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
@@ -105,8 +105,7 @@ gfx::BufferFormat GLOutputSurfaceBufferQueue::GetOverlayBufferFormat() const {
}
void GLOutputSurfaceBufferQueue::DidReceiveSwapBuffersAck(
- gfx::SwapResult result,
- uint64_t swap_id) {
+ gfx::SwapResult result) {
bool force_swap = false;
if (result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS) {
// Even through the swap failed, this is a fixable error so we can pretend
@@ -117,7 +116,7 @@ void GLOutputSurfaceBufferQueue::DidReceiveSwapBuffersAck(
}
buffer_queue_->PageFlipComplete();
- client()->DidReceiveSwapBuffersAck(swap_id);
+ client()->DidReceiveSwapBuffersAck();
if (force_swap)
client()->SetNeedsRedrawRect(gfx::Rect(swap_size_));
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
index ff22c17ad31..3703297b1c7 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_buffer_queue.h
@@ -10,9 +10,9 @@
#include "base/memory/weak_ptr.h"
#include "components/viz/common/gl_helper.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/gpu/in_process_context_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display_embedder/gl_output_surface.h"
+#include "components/viz/service/display_embedder/viz_process_context_provider.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/swap_result.h"
@@ -34,7 +34,7 @@ class SyntheticBeginFrameSource;
class GLOutputSurfaceBufferQueue : public GLOutputSurface {
public:
GLOutputSurfaceBufferQueue(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
@@ -61,8 +61,7 @@ class GLOutputSurfaceBufferQueue : public GLOutputSurface {
gfx::BufferFormat GetOverlayBufferFormat() const override;
// GLOutputSurface:
- void DidReceiveSwapBuffersAck(gfx::SwapResult result,
- uint64_t swap_id) override;
+ void DidReceiveSwapBuffersAck(gfx::SwapResult result) override;
GLHelper gl_helper_;
std::unique_ptr<BufferQueue> buffer_queue_;
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
index e1a1c23f4dd..cb0fa658934 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.cc
@@ -9,7 +9,7 @@
namespace viz {
GLOutputSurfaceMac::GLOutputSurfaceMac(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
index f26801f584b..5e2e8b20542 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_mac.h
@@ -12,7 +12,7 @@ namespace viz {
class GLOutputSurfaceMac : public GLOutputSurfaceBufferQueue {
public:
- GLOutputSurfaceMac(scoped_refptr<InProcessContextProvider> context_provider,
+ GLOutputSurfaceMac(scoped_refptr<VizProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.cc
index 50deccee3f7..8c42482ba2c 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.cc
@@ -9,7 +9,7 @@
namespace viz {
GLOutputSurfaceOzone::GLOutputSurfaceOzone(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
gpu::SurfaceHandle surface_handle,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.h b/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.h
index 69544d0a23f..47a7cffb50f 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_ozone.h
@@ -11,12 +11,13 @@ namespace viz {
class GLOutputSurfaceOzone : public GLOutputSurfaceBufferQueue {
public:
- GLOutputSurfaceOzone(scoped_refptr<InProcessContextProvider> context_provider,
- gpu::SurfaceHandle surface_handle,
- SyntheticBeginFrameSource* synthetic_begin_frame_source,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- uint32_t target,
- uint32_t internal_format);
+ GLOutputSurfaceOzone(
+ scoped_refptr<VizProcessContextProvider> context_provider,
+ gpu::SurfaceHandle surface_handle,
+ SyntheticBeginFrameSource* synthetic_begin_frame_source,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ uint32_t target,
+ uint32_t internal_format);
~GLOutputSurfaceOzone() override;
private:
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc b/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc
index da3fde6007a..5e79df4b94e 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_win.cc
@@ -9,7 +9,7 @@
namespace viz {
GLOutputSurfaceWin::GLOutputSurfaceWin(
- scoped_refptr<InProcessContextProvider> context_provider,
+ scoped_refptr<VizProcessContextProvider> context_provider,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
bool use_overlays)
: GLOutputSurface(context_provider, synthetic_begin_frame_source) {
diff --git a/chromium/components/viz/service/display_embedder/gl_output_surface_win.h b/chromium/components/viz/service/display_embedder/gl_output_surface_win.h
index c62a7498b47..e71a7b0bd40 100644
--- a/chromium/components/viz/service/display_embedder/gl_output_surface_win.h
+++ b/chromium/components/viz/service/display_embedder/gl_output_surface_win.h
@@ -16,7 +16,7 @@ class CompositorOverlayCandidateValidatorWin;
class GLOutputSurfaceWin : public GLOutputSurface {
public:
- GLOutputSurfaceWin(scoped_refptr<InProcessContextProvider> context_provider,
+ GLOutputSurfaceWin(scoped_refptr<VizProcessContextProvider> context_provider,
SyntheticBeginFrameSource* synthetic_begin_frame_source,
bool use_overlays);
~GLOutputSurfaceWin() override;
diff --git a/chromium/components/viz/service/display_embedder/gpu_display_provider.cc b/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
index 45b178149bf..3da085bc5df 100644
--- a/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
+++ b/chromium/components/viz/service/display_embedder/gpu_display_provider.cc
@@ -7,18 +7,20 @@
#include <utility>
#include "base/command_line.h"
+#include "base/compiler_specific.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cc/base/switches.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
-#include "components/viz/common/gpu/in_process_context_provider.h"
#include "components/viz/service/display/display.h"
#include "components/viz/service/display/display_scheduler.h"
#include "components/viz/service/display_embedder/external_begin_frame_controller_impl.h"
#include "components/viz/service/display_embedder/gl_output_surface.h"
#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
+#include "components/viz/service/display_embedder/skia_output_surface_impl.h"
#include "components/viz/service/display_embedder/software_output_surface.h"
+#include "components/viz/service/display_embedder/viz_process_context_provider.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/service/image_factory.h"
#include "gpu/ipc/common/surface_handle.h"
@@ -64,11 +66,13 @@ namespace viz {
GpuDisplayProvider::GpuDisplayProvider(
uint32_t restart_id,
+ GpuServiceImpl* gpu_service_impl,
scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service,
gpu::GpuChannelManager* gpu_channel_manager,
bool headless,
bool wait_for_all_pipeline_stages_before_draw)
: restart_id_(restart_id),
+ gpu_service_impl_(gpu_service_impl),
gpu_service_(std::move(gpu_service)),
gpu_channel_manager_delegate_(gpu_channel_manager->delegate()),
gpu_memory_buffer_manager_(
@@ -88,6 +92,7 @@ std::unique_ptr<Display> GpuDisplayProvider::CreateDisplay(
const FrameSinkId& frame_sink_id,
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
+ mojom::DisplayClient* display_client,
ExternalBeginFrameControllerImpl* external_begin_frame_controller,
const RendererSettings& renderer_settings,
std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source) {
@@ -103,21 +108,46 @@ std::unique_ptr<Display> GpuDisplayProvider::CreateDisplay(
display_begin_frame_source = synthetic_begin_frame_source.get();
}
+ // TODO(penghuang): Merge two output surfaces into one when GLRenderer and
+ // software compositor is removed.
std::unique_ptr<OutputSurface> output_surface;
+ SkiaOutputSurface* skia_output_surface = nullptr;
if (!gpu_compositing) {
output_surface = std::make_unique<SoftwareOutputSurface>(
- CreateSoftwareOutputDeviceForPlatform(surface_handle), task_runner_);
+ CreateSoftwareOutputDeviceForPlatform(surface_handle, display_client));
+ } else if (renderer_settings.use_skia_renderer &&
+ renderer_settings.use_skia_deferred_display_list) {
+#if defined(OS_MACOSX) || defined(OS_WIN)
+ // TODO(penghuang): Support DDL for all platforms.
+ NOTIMPLEMENTED();
+ // Workaround compile error: private field 'gpu_service_impl_' is not used.
+ ALLOW_UNUSED_LOCAL(gpu_service_impl_);
+#else
+ // Create an offscreen context_provider for SkiaOutputSurfaceImpl, because
+ // SkiaRenderer still needs it to draw RenderPass into a texture.
+ // TODO(penghuang): Remove this context_provider. https://crbug.com/825901
+ auto context_provider = base::MakeRefCounted<VizProcessContextProvider>(
+ gpu_service_, gpu::kNullSurfaceHandle, gpu_memory_buffer_manager_.get(),
+ image_factory_, gpu_channel_manager_delegate_,
+ gpu::SharedMemoryLimits());
+ auto result = context_provider->BindToCurrentThread();
+ CHECK_EQ(result, gpu::ContextResult::kSuccess);
+ output_surface = std::make_unique<SkiaOutputSurfaceImpl>(
+ gpu_service_impl_, surface_handle, std::move(context_provider),
+ synthetic_begin_frame_source.get());
+ skia_output_surface = static_cast<SkiaOutputSurface*>(output_surface.get());
+#endif
} else {
- scoped_refptr<InProcessContextProvider> context_provider;
+ scoped_refptr<VizProcessContextProvider> context_provider;
// Retry creating and binding |context_provider| on transient failures.
gpu::ContextResult context_result = gpu::ContextResult::kTransientFailure;
while (context_result != gpu::ContextResult::kSuccess) {
- context_provider = base::MakeRefCounted<InProcessContextProvider>(
+ context_provider = base::MakeRefCounted<VizProcessContextProvider>(
gpu_service_, surface_handle, gpu_memory_buffer_manager_.get(),
image_factory_, gpu_channel_manager_delegate_,
- gpu::SharedMemoryLimits(), nullptr /* shared_context */);
+ gpu::SharedMemoryLimits());
context_result = context_provider->BindToCurrentThread();
// TODO(crbug.com/819474): Don't crash here, instead fallback to software
@@ -166,34 +196,22 @@ std::unique_ptr<Display> GpuDisplayProvider::CreateDisplay(
return std::make_unique<Display>(
ServerSharedBitmapManager::current(), renderer_settings, frame_sink_id,
- std::move(output_surface), std::move(scheduler), task_runner_);
+ std::move(output_surface), std::move(scheduler), task_runner_,
+ skia_output_surface);
}
std::unique_ptr<SoftwareOutputDevice>
GpuDisplayProvider::CreateSoftwareOutputDeviceForPlatform(
- gpu::SurfaceHandle surface_handle) {
+ gpu::SurfaceHandle surface_handle,
+ mojom::DisplayClient* display_client) {
if (headless_)
return std::make_unique<SoftwareOutputDevice>();
-#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
- gfx::AcceleratedWidget widget = surface_handle;
-#endif
-
#if defined(OS_WIN)
- if (!output_device_backing_)
- output_device_backing_ = std::make_unique<OutputDeviceBacking>();
- return std::make_unique<SoftwareOutputDeviceWin>(output_device_backing_.get(),
- widget);
+ return CreateSoftwareOutputDeviceWinGpu(
+ surface_handle, &output_device_backing_, display_client);
#elif defined(OS_MACOSX)
- // TODO(crbug.com/730660): What do we do to get something we can draw to? Can
- // we use an IO surface? Can we use CA layers and overlays like we do for gpu
- // compositing? See https://crrev.com/c/792295 to no longer have
- // GpuSurfaceTracker. Part of the SoftwareOutputDeviceMac::EndPaint probably
- // needs to move to the browser process, and we need to set up transport of an
- // IO surface to here?
- NOTIMPLEMENTED();
- (void)widget;
- return nullptr;
+ return std::make_unique<SoftwareOutputDeviceMac>(task_runner_);
#elif defined(OS_ANDROID)
// Android does not do software compositing, so we can't get here.
NOTREACHED();
@@ -202,11 +220,11 @@ GpuDisplayProvider::CreateSoftwareOutputDeviceForPlatform(
ui::SurfaceFactoryOzone* factory =
ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone();
std::unique_ptr<ui::SurfaceOzoneCanvas> surface_ozone =
- factory->CreateCanvasForWidget(widget);
+ factory->CreateCanvasForWidget(surface_handle);
CHECK(surface_ozone);
return std::make_unique<SoftwareOutputDeviceOzone>(std::move(surface_ozone));
#elif defined(USE_X11)
- return std::make_unique<SoftwareOutputDeviceX11>(widget);
+ return std::make_unique<SoftwareOutputDeviceX11>(surface_handle);
#endif
}
diff --git a/chromium/components/viz/service/display_embedder/gpu_display_provider.h b/chromium/components/viz/service/display_embedder/gpu_display_provider.h
index 0a4c19bbfa8..f714ee18a64 100644
--- a/chromium/components/viz/service/display_embedder/gpu_display_provider.h
+++ b/chromium/components/viz/service/display_embedder/gpu_display_provider.h
@@ -18,6 +18,10 @@
#include "gpu/ipc/common/surface_handle.h"
#include "gpu/ipc/in_process_command_buffer.h"
+#if defined(OS_WIN)
+#include "components/viz/service/display_embedder/output_device_backing.h"
+#endif
+
namespace gpu {
class GpuChannelManager;
class GpuChannelManagerDelegate;
@@ -27,7 +31,7 @@ class ImageFactory;
namespace viz {
class Display;
class ExternalBeginFrameControllerImpl;
-class OutputDeviceBacking;
+class GpuServiceImpl;
class SoftwareOutputDevice;
// In-process implementation of DisplayProvider.
@@ -35,6 +39,7 @@ class VIZ_SERVICE_EXPORT GpuDisplayProvider : public DisplayProvider {
public:
GpuDisplayProvider(
uint32_t restart_id,
+ GpuServiceImpl* gpu_service_impl,
scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service,
gpu::GpuChannelManager* gpu_channel_manager,
bool headless,
@@ -46,6 +51,7 @@ class VIZ_SERVICE_EXPORT GpuDisplayProvider : public DisplayProvider {
const FrameSinkId& frame_sink_id,
gpu::SurfaceHandle surface_handle,
bool gpu_compositing,
+ mojom::DisplayClient* display_client,
ExternalBeginFrameControllerImpl* external_begin_frame_controller,
const RendererSettings& renderer_settings,
std::unique_ptr<SyntheticBeginFrameSource>* out_begin_frame_source)
@@ -53,9 +59,11 @@ class VIZ_SERVICE_EXPORT GpuDisplayProvider : public DisplayProvider {
private:
std::unique_ptr<SoftwareOutputDevice> CreateSoftwareOutputDeviceForPlatform(
- gpu::SurfaceHandle surface_handle);
+ gpu::SurfaceHandle surface_handle,
+ mojom::DisplayClient* display_client);
const uint32_t restart_id_;
+ GpuServiceImpl* const gpu_service_impl_;
scoped_refptr<gpu::InProcessCommandBuffer::Service> gpu_service_;
gpu::GpuChannelManagerDelegate* const gpu_channel_manager_delegate_;
std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_;
@@ -63,7 +71,7 @@ class VIZ_SERVICE_EXPORT GpuDisplayProvider : public DisplayProvider {
#if defined(OS_WIN)
// Used for software compositing output on Windows.
- std::unique_ptr<OutputDeviceBacking> output_device_backing_;
+ OutputDeviceBacking output_device_backing_;
#endif
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/components/viz/service/display_embedder/output_device_backing.cc b/chromium/components/viz/service/display_embedder/output_device_backing.cc
new file mode 100644
index 00000000000..68e3aca8758
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/output_device_backing.cc
@@ -0,0 +1,102 @@
+// 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 "components/viz/service/display_embedder/output_device_backing.h"
+
+#include <algorithm>
+
+#include "base/debug/alias.h"
+#include "base/memory/shared_memory.h"
+#include "base/stl_util.h"
+#include "components/viz/common/resources/resource_sizes.h"
+
+namespace viz {
+namespace {
+
+// If a window is larger than this in bytes, don't even try to create a backing
+// bitmap for it.
+constexpr size_t kMaxBitmapSizeBytes = 4 * (16384 * 8192);
+
+// Finds the size in bytes to hold |viewport_size| pixels. If |viewport_size| is
+// a valid size this will return true and |out_bytes| will contain the size in
+// bytes. If |viewport_size| is not a valid size then this will return false.
+bool GetViewportSizeInBytes(const gfx::Size& viewport_size, size_t* out_bytes) {
+ size_t bytes;
+ if (!ResourceSizes::MaybeSizeInBytes(viewport_size, RGBA_8888, &bytes))
+ return false;
+ if (bytes > kMaxBitmapSizeBytes)
+ return false;
+ *out_bytes = bytes;
+ return true;
+}
+
+} // namespace
+
+OutputDeviceBacking::OutputDeviceBacking() = default;
+
+OutputDeviceBacking::~OutputDeviceBacking() {
+ DCHECK(clients_.empty());
+}
+
+void OutputDeviceBacking::ClientResized() {
+ // If the max viewport size doesn't change then nothing here changes.
+ if (GetMaxViewportBytes() == created_shm_bytes_)
+ return;
+
+ // Otherwise we need to allocate a new SharedMemory segment and clients
+ // should re-request it.
+ for (auto* client : clients_)
+ client->ReleaseCanvas();
+
+ shm_.reset();
+ created_shm_bytes_ = 0;
+}
+
+void OutputDeviceBacking::RegisterClient(Client* client) {
+ clients_.push_back(client);
+}
+
+void OutputDeviceBacking::UnregisterClient(Client* client) {
+ DCHECK(base::ContainsValue(clients_, client));
+ base::Erase(clients_, client);
+ ClientResized();
+}
+
+base::SharedMemory* OutputDeviceBacking::GetSharedMemory(
+ const gfx::Size& viewport_size) {
+ // If |viewport_size| is empty or too big don't try to allocate SharedMemory.
+ size_t viewport_bytes;
+ if (!GetViewportSizeInBytes(viewport_size, &viewport_bytes))
+ return nullptr;
+
+ // Allocate a new SharedMemory segment that can fit the largest viewport.
+ if (!shm_) {
+ size_t max_viewport_bytes = GetMaxViewportBytes();
+ DCHECK_LE(viewport_bytes, max_viewport_bytes);
+
+ shm_ = std::make_unique<base::SharedMemory>();
+ base::debug::Alias(&max_viewport_bytes);
+ CHECK(shm_->CreateAnonymous(max_viewport_bytes));
+ created_shm_bytes_ = max_viewport_bytes;
+ } else {
+ // Clients must call Resize() for new |viewport_size|.
+ DCHECK_LE(viewport_bytes, created_shm_bytes_);
+ }
+
+ return shm_.get();
+}
+
+size_t OutputDeviceBacking::GetMaxViewportBytes() {
+ // Minimum byte size is 1 because creating a 0-byte-long SharedMemory fails.
+ size_t max_bytes = 1;
+ for (auto* client : clients_) {
+ size_t current_bytes;
+ if (!GetViewportSizeInBytes(client->GetViewportPixelSize(), &current_bytes))
+ continue;
+ max_bytes = std::max(max_bytes, current_bytes);
+ }
+ return max_bytes;
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/output_device_backing.h b/chromium/components/viz/service/display_embedder/output_device_backing.h
new file mode 100644
index 00000000000..b3a9b1cb81c
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/output_device_backing.h
@@ -0,0 +1,65 @@
+// 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.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OUTPUT_DEVICE_BACKING_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OUTPUT_DEVICE_BACKING_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/viz/service/viz_service_export.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace base {
+class SharedMemory;
+}
+
+namespace viz {
+
+// Allocates and owns a SharedMemory backing for multiple SoftwareOutputDevices.
+// The backing will be big enough to hold the largest size returned by a
+// client's GetViewportPixelSize().
+class VIZ_SERVICE_EXPORT OutputDeviceBacking {
+ public:
+ class Client {
+ public:
+ virtual const gfx::Size& GetViewportPixelSize() const = 0;
+ virtual void ReleaseCanvas() = 0;
+
+ protected:
+ virtual ~Client() = default;
+ };
+
+ OutputDeviceBacking();
+ ~OutputDeviceBacking();
+
+ void RegisterClient(Client* client);
+ void UnregisterClient(Client* client);
+
+ // Called when a client has resized. Clients should call Resize() after being
+ // registered when they have a valid size. Will potential invalidate
+ // SharedMemory and call ReleaseCanvas() on clients.
+ void ClientResized();
+
+ // Requests a SharedMemory segment large enough to fit |viewport_size|. Will
+ // return null if |viewport_size| is too large to safely allocate SharedMemory
+ // for.
+ base::SharedMemory* GetSharedMemory(const gfx::Size& viewport_size);
+
+ // Returns the maximum size in bytes needed for the largest viewport from
+ // registered clients.
+ size_t GetMaxViewportBytes();
+
+ private:
+ std::vector<Client*> clients_;
+ std::unique_ptr<base::SharedMemory> shm_;
+ size_t created_shm_bytes_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(OutputDeviceBacking);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_OUTPUT_DEVICE_BACKING_H_
diff --git a/chromium/components/viz/service/display_embedder/output_device_backing_unittest.cc b/chromium/components/viz/service/display_embedder/output_device_backing_unittest.cc
new file mode 100644
index 00000000000..916573333a6
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/output_device_backing_unittest.cc
@@ -0,0 +1,112 @@
+// 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 "components/viz/service/display_embedder/output_device_backing.h"
+
+#include <limits>
+#include <memory>
+
+#include "components/viz/common/resources/resource_sizes.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace viz {
+namespace {
+
+size_t GetViewportSizeInBytes(const gfx::Size& viewport_size) {
+ size_t bytes = std::numeric_limits<size_t>::max();
+ CHECK(ResourceSizes::MaybeSizeInBytes(viewport_size, RGBA_8888, &bytes));
+ return bytes;
+}
+
+// Test implementation with a set viewport size.
+class TestBackingClient : public OutputDeviceBacking::Client {
+ public:
+ TestBackingClient(OutputDeviceBacking* backing,
+ const gfx::Size& viewport_size)
+ : backing_(backing), viewport_size_(viewport_size) {
+ backing_->RegisterClient(this);
+ backing_->ClientResized();
+ backing_->GetSharedMemory(viewport_size_);
+ }
+ ~TestBackingClient() override { backing_->UnregisterClient(this); }
+
+ const gfx::Size& viewport_size() const { return viewport_size_; }
+ bool release_canvas_called() const { return release_canvas_called_; }
+
+ // OutputDeviceBacking::Client implementation.
+ const gfx::Size& GetViewportPixelSize() const override {
+ return viewport_size_;
+ }
+ void ReleaseCanvas() override { release_canvas_called_ = true; }
+
+ private:
+ OutputDeviceBacking* const backing_;
+ gfx::Size viewport_size_;
+ bool release_canvas_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestBackingClient);
+};
+
+} // namespace
+
+// Verify GetMaxViewportBytes() returns the size in bytes of the largest
+// viewport.
+TEST(OutputDeviceBackingTest, GetMaxViewportBytes) {
+ OutputDeviceBacking backing;
+ TestBackingClient client_a(&backing, gfx::Size(1024, 768));
+ TestBackingClient client_b(&backing, gfx::Size(1920, 1080));
+
+ EXPECT_EQ(GetViewportSizeInBytes(client_b.viewport_size()),
+ backing.GetMaxViewportBytes());
+}
+
+// Verify that unregistering a client works as expected.
+TEST(OutputDeviceBackingTest, UnregisterClient) {
+ OutputDeviceBacking backing;
+ auto client_a =
+ std::make_unique<TestBackingClient>(&backing, gfx::Size(1920, 1080));
+ auto client_b =
+ std::make_unique<TestBackingClient>(&backing, gfx::Size(1080, 1920));
+ auto client_c =
+ std::make_unique<TestBackingClient>(&backing, gfx::Size(1024, 768));
+
+ // Unregister one of the clients with the 1920x1080 viewport size.
+ client_a.reset();
+
+ // After removing |client_a| the max viewport didn't change so ReleaseCanvas()
+ // shouldn't be have been called.
+ EXPECT_FALSE(client_b->release_canvas_called());
+ EXPECT_FALSE(client_c->release_canvas_called());
+
+ // Unregister the second client with 1920x1080 viewport.
+ client_b.reset();
+
+ // After removing |client_b| then max viewport did change so ReleaseCanvas()
+ // should have been called.
+ EXPECT_TRUE(client_c->release_canvas_called());
+
+ EXPECT_EQ(GetViewportSizeInBytes(client_c->viewport_size()),
+ backing.GetMaxViewportBytes());
+}
+
+// Verify that a client with a viewport that is too large doesn't allocate
+// SharedMemory.
+TEST(OutputDeviceBackingTest, ViewportSizeBiggerThanMax) {
+ OutputDeviceBacking backing;
+
+ // The viewport is bigger than |kMaxBitmapSizeBytes| and OutputDeviceBacking
+ // won't try to create SharedMemory for it.
+ TestBackingClient client_a(&backing, gfx::Size(16385, 8193));
+ EXPECT_EQ(nullptr, backing.GetSharedMemory(client_a.viewport_size()));
+
+ // This should cause SharedMemory to get allocated.
+ TestBackingClient client_b(&backing, gfx::Size(1024, 768));
+ EXPECT_NE(nullptr, backing.GetSharedMemory(client_b.viewport_size()));
+
+ // Even though SharedMemory was allocated to fit |client_b|, it will be too
+ // small for |client_a| and GetSharedMemory() should still return null.
+ EXPECT_EQ(nullptr, backing.GetSharedMemory(client_a.viewport_size()));
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
index a9745b91c9c..9d84f91109a 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.cc
@@ -23,10 +23,7 @@ namespace viz {
class BitmapData : public base::RefCountedThreadSafe<BitmapData> {
public:
explicit BitmapData(size_t buffer_size) : buffer_size(buffer_size) {}
- // For shm allocated and shared from a client out-of-process.
std::unique_ptr<base::SharedMemory> memory;
- // For memory allocated by the ServerSharedBitmapManager for in-process.
- std::unique_ptr<uint8_t[]> pixels;
size_t buffer_size;
private:
@@ -39,31 +36,23 @@ namespace {
class ServerSharedBitmap : public SharedBitmap {
public:
- ServerSharedBitmap(uint8_t* pixels,
- scoped_refptr<BitmapData> bitmap_data,
- const SharedBitmapId& id,
- ServerSharedBitmapManager* manager)
- : SharedBitmap(pixels, id, 0 /* sequence_number */),
- bitmap_data_(bitmap_data),
- manager_(manager) {}
+ ServerSharedBitmap(scoped_refptr<BitmapData> bitmap_data,
+ const SharedBitmapId& id)
+ : SharedBitmap(static_cast<uint8_t*>(bitmap_data->memory->memory()),
+ id,
+ 0 /* sequence_number */),
+ bitmap_data_(std::move(bitmap_data)) {}
~ServerSharedBitmap() override {
- if (manager_)
- manager_->FreeSharedMemoryFromMap(id());
}
// SharedBitmap implementation.
base::UnguessableToken GetCrossProcessGUID() const override {
- if (!bitmap_data_->memory) {
- // Locally allocated for in-process use.
- return {};
- }
return bitmap_data_->memory->mapped_id();
}
private:
scoped_refptr<BitmapData> bitmap_data_;
- ServerSharedBitmapManager* manager_;
};
} // namespace
@@ -81,26 +70,6 @@ ServerSharedBitmapManager* ServerSharedBitmapManager::current() {
return g_shared_memory_manager.Pointer();
}
-std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::AllocateSharedBitmap(
- const gfx::Size& size,
- ResourceFormat format) {
- DCHECK(IsBitmapFormatSupported(format));
- base::AutoLock lock(lock_);
- size_t bitmap_size;
- if (!ResourceSizes::MaybeSizeInBytes(size, format, &bitmap_size))
- return nullptr;
-
- scoped_refptr<BitmapData> data(new BitmapData(bitmap_size));
- // Bitmaps allocated in server don't need to be shared to other processes, so
- // allocate them with new instead.
- data->pixels = std::unique_ptr<uint8_t[]>(new uint8_t[bitmap_size]);
-
- SharedBitmapId id = SharedBitmap::GenerateId();
- handle_map_[id] = data;
- return std::make_unique<ServerSharedBitmap>(data->pixels.get(), data, id,
- this);
-}
-
std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
const gfx::Size& size,
ResourceFormat format,
@@ -117,16 +86,11 @@ std::unique_ptr<SharedBitmap> ServerSharedBitmapManager::GetSharedBitmapFromId(
bitmap_size > data->buffer_size)
return nullptr;
- if (data->pixels) {
- return std::make_unique<ServerSharedBitmap>(data->pixels.get(), data, id,
- nullptr);
- }
if (!data->memory->memory()) {
return nullptr;
}
- return std::make_unique<ServerSharedBitmap>(
- static_cast<uint8_t*>(data->memory->memory()), data, id, nullptr);
+ return std::make_unique<ServerSharedBitmap>(data, id);
}
bool ServerSharedBitmapManager::ChildAllocatedSharedBitmap(
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
index af9be4360b3..57810735850 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager.h
@@ -36,9 +36,6 @@ class VIZ_SERVICE_EXPORT ServerSharedBitmapManager
static ServerSharedBitmapManager* current();
// SharedBitmapManager implementation.
- std::unique_ptr<SharedBitmap> AllocateSharedBitmap(
- const gfx::Size& size,
- ResourceFormat format) override;
std::unique_ptr<SharedBitmap> GetSharedBitmapFromId(
const gfx::Size& size,
ResourceFormat format,
diff --git a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
index cce61d24a22..b5923739380 100644
--- a/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/server_shared_bitmap_manager_unittest.cc
@@ -5,7 +5,6 @@
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/common/resources/resource_sizes.h"
-#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,12 +35,11 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) {
memset(bitmap->memory(), 0xff, size_in_bytes);
SharedBitmapId id = SharedBitmap::GenerateId();
- SharedBitmapAllocationNotifierImpl notifier(manager());
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, size_in_bytes,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
+ manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> large_bitmap;
large_bitmap =
@@ -81,7 +79,7 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) {
EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
0);
- notifier.DidDeleteSharedBitmap(id);
+ manager()->ChildDeletedSharedBitmap(id);
memset(bitmap->memory(), 0, size_in_bytes);
@@ -91,42 +89,6 @@ TEST_F(ServerSharedBitmapManagerTest, TestCreate) {
shared_bitmap.reset();
}
-TEST_F(ServerSharedBitmapManagerTest, ServiceDestroyed) {
- gfx::Size bitmap_size(1, 1);
- size_t size_in_bytes;
- EXPECT_TRUE(
- ResourceSizes::MaybeSizeInBytes(bitmap_size, RGBA_8888, &size_in_bytes));
- std::unique_ptr<base::SharedMemory> bitmap(new base::SharedMemory());
- bitmap->CreateAndMapAnonymous(size_in_bytes);
- memset(bitmap->memory(), 0xff, size_in_bytes);
- SharedBitmapId id = SharedBitmap::GenerateId();
-
- // This outlives the SharedBitmapAllocationNotifier.
- std::unique_ptr<SharedBitmap> shared_bitmap;
-
- {
- SharedBitmapAllocationNotifierImpl notifier(manager());
- base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
- mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
- handle, size_in_bytes,
- mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
-
- shared_bitmap =
- manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id);
- ASSERT_TRUE(shared_bitmap.get() != nullptr);
-
- EXPECT_EQ(1u, manager()->AllocatedBitmapCount());
- }
- EXPECT_EQ(0u, manager()->AllocatedBitmapCount());
-
- std::unique_ptr<SharedBitmap> shared_bitmap2;
- shared_bitmap2 = manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id);
- EXPECT_FALSE(!!shared_bitmap2);
- EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
- 0);
-}
-
TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) {
gfx::Size bitmap_size(1, 1);
size_t size_in_bytes;
@@ -137,13 +99,11 @@ TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) {
memset(bitmap->memory(), 0xff, size_in_bytes);
SharedBitmapId id = SharedBitmap::GenerateId();
- SharedBitmapAllocationNotifierImpl notifier(manager());
-
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, size_in_bytes,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
+ manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<base::SharedMemory> bitmap2(new base::SharedMemory());
bitmap2->CreateAndMapAnonymous(size_in_bytes);
@@ -153,14 +113,14 @@ TEST_F(ServerSharedBitmapManagerTest, AddDuplicate) {
buffer_handle = mojo::WrapSharedMemoryHandle(
handle2, size_in_bytes,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
+ manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> shared_bitmap;
shared_bitmap = manager()->GetSharedBitmapFromId(bitmap_size, RGBA_8888, id);
ASSERT_TRUE(shared_bitmap.get() != nullptr);
EXPECT_EQ(memcmp(shared_bitmap->pixels(), bitmap->memory(), size_in_bytes),
0);
- notifier.DidDeleteSharedBitmap(id);
+ manager()->ChildDeletedSharedBitmap(id);
}
TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) {
@@ -174,21 +134,19 @@ TEST_F(ServerSharedBitmapManagerTest, SharedMemoryHandle) {
base::UnguessableToken shared_memory_guid = bitmap->handle().GetGUID();
EXPECT_FALSE(shared_memory_guid.is_empty());
- SharedBitmapAllocationNotifierImpl notifier(manager());
-
SharedBitmapId id = SharedBitmap::GenerateId();
base::SharedMemoryHandle handle = bitmap->handle().Duplicate();
mojo::ScopedSharedBufferHandle buffer_handle = mojo::WrapSharedMemoryHandle(
handle, size_in_bytes,
mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
- notifier.ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
+ manager()->ChildAllocatedSharedBitmap(std::move(buffer_handle), id);
std::unique_ptr<SharedBitmap> shared_bitmap;
shared_bitmap =
manager()->GetSharedBitmapFromId(gfx::Size(1, 1), RGBA_8888, id);
EXPECT_EQ(shared_bitmap->GetCrossProcessGUID(), shared_memory_guid);
- notifier.DidDeleteSharedBitmap(id);
+ manager()->ChildDeletedSharedBitmap(id);
}
} // namespace
diff --git a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
deleted file mode 100644
index fa5468d37a3..00000000000
--- a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// 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.
-
-#include "components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h"
-
-#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
-#include "mojo/public/cpp/system/platform_handle.h"
-
-namespace viz {
-
-SharedBitmapAllocationNotifierImpl::SharedBitmapAllocationNotifierImpl(
- ServerSharedBitmapManager* manager)
- : manager_(manager), binding_(this) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-}
-
-SharedBitmapAllocationNotifierImpl::~SharedBitmapAllocationNotifierImpl() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- ChildDied();
-}
-
-void SharedBitmapAllocationNotifierImpl::Bind(
- mojom::SharedBitmapAllocationNotifierRequest request) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (binding_.is_bound()) {
- DLOG(ERROR) << "Only one SharedBitmapAllocationNotifierRequest is "
- << "expected from the renderer.";
- return;
- }
- binding_.Bind(std::move(request));
-}
-
-void SharedBitmapAllocationNotifierImpl::DidAllocateSharedBitmap(
- mojo::ScopedSharedBufferHandle buffer,
- const SharedBitmapId& id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- this->ChildAllocatedSharedBitmap(std::move(buffer), id);
- last_sequence_number_++;
- for (SharedBitmapAllocationObserver& observer : observers_)
- observer.OnSharedBitmapAllocatedByChild(last_sequence_number_);
-}
-
-void SharedBitmapAllocationNotifierImpl::DidDeleteSharedBitmap(
- const SharedBitmapId& id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- manager_->ChildDeletedSharedBitmap(id);
- owned_bitmaps_.erase(id);
-}
-
-void SharedBitmapAllocationNotifierImpl::ChildAllocatedSharedBitmap(
- mojo::ScopedSharedBufferHandle buffer,
- const SharedBitmapId& id) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (manager_->ChildAllocatedSharedBitmap(std::move(buffer), id))
- owned_bitmaps_.insert(id);
-}
-
-void SharedBitmapAllocationNotifierImpl::ChildDied() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- for (const auto& id : owned_bitmaps_)
- manager_->ChildDeletedSharedBitmap(id);
- owned_bitmaps_.clear();
- binding_.Close();
-}
-
-void SharedBitmapAllocationNotifierImpl::AddObserver(
- SharedBitmapAllocationObserver* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- observers_.AddObserver(observer);
-}
-
-void SharedBitmapAllocationNotifierImpl::RemoveObserver(
- SharedBitmapAllocationObserver* observer) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- observers_.RemoveObserver(observer);
-}
-
-} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h b/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
deleted file mode 100644
index 0b4e32ddaf8..00000000000
--- a/chromium/components/viz/service/display_embedder/shared_bitmap_allocation_notifier_impl.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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 COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SHARED_BITMAP_ALLOCATION_NOTIFIER_IMPL_H_
-#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SHARED_BITMAP_ALLOCATION_NOTIFIER_IMPL_H_
-
-#include <unordered_set>
-
-#include "base/observer_list.h"
-#include "base/threading/thread_checker.h"
-#include "components/viz/common/quads/shared_bitmap.h"
-#include "components/viz/service/viz_service_export.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "services/viz/public/interfaces/compositing/shared_bitmap_allocation_notifier.mojom.h"
-
-namespace viz {
-class ServerSharedBitmapManager;
-
-class SharedBitmapAllocationObserver {
- public:
- virtual void OnSharedBitmapAllocatedByChild(uint32_t sequence_number) = 0;
-};
-
-class VIZ_SERVICE_EXPORT SharedBitmapAllocationNotifierImpl
- : public mojom::SharedBitmapAllocationNotifier {
- public:
- explicit SharedBitmapAllocationNotifierImpl(
- ServerSharedBitmapManager* manager);
-
- ~SharedBitmapAllocationNotifierImpl() override;
-
- void AddObserver(SharedBitmapAllocationObserver* observer);
- void RemoveObserver(SharedBitmapAllocationObserver* observer);
-
- void Bind(mojom::SharedBitmapAllocationNotifierRequest request);
-
- // mojom::SharedBitmapAllocationNotifier overrides:
- void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
- const SharedBitmapId& id) override;
- void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
-
- void ChildAllocatedSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
- const SharedBitmapId& id);
-
- void ChildDied();
-
- uint32_t last_sequence_number() const { return last_sequence_number_; }
-
- private:
- THREAD_CHECKER(thread_checker_);
- ServerSharedBitmapManager* const manager_;
- mojo::Binding<mojom::SharedBitmapAllocationNotifier> binding_;
- std::unordered_set<SharedBitmapId, SharedBitmapIdHash> owned_bitmaps_;
- base::ObserverList<SharedBitmapAllocationObserver> observers_;
- uint32_t last_sequence_number_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBitmapAllocationNotifierImpl);
-};
-
-} // namespace viz
-
-#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SHARED_BITMAP_ALLOCATION_NOTIFIER_IMPL_H_
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc
new file mode 100644
index 00000000000..ac7b616b261
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -0,0 +1,516 @@
+// 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 "components/viz/service/display_embedder/skia_output_surface_impl.h"
+
+#include "base/callback_helpers.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "components/viz/common/resources/resource_metadata.h"
+#include "components/viz/service/display/output_surface_client.h"
+#include "components/viz/service/display/output_surface_frame.h"
+#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h"
+#include "components/viz/service/display_embedder/viz_process_context_provider.h"
+#include "components/viz/service/gl/gpu_service_impl.h"
+#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "gpu/command_buffer/service/scheduler.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_gl_api_implementation.h"
+
+namespace viz {
+
+namespace {
+
+template <typename... Args>
+void PostAsyncTask(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ const base::RepeatingCallback<void(Args...)>& callback,
+ Args... args) {
+ task_runner->PostTask(FROM_HERE, base::BindOnce(callback, args...));
+}
+
+template <typename... Args>
+base::RepeatingCallback<void(Args...)> CreateSafeCallback(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ const base::RepeatingCallback<void(Args...)>& callback) {
+ return base::BindRepeating(&PostAsyncTask<Args...>, task_runner, callback);
+}
+
+} // namespace
+
+// A helper class for fullfilling promise image on the GPU thread.
+template <class FullfillContextType>
+class SkiaOutputSurfaceImpl::PromiseTextureHelper {
+ public:
+ using HelperType = PromiseTextureHelper<FullfillContextType>;
+
+ PromiseTextureHelper(base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu,
+ FullfillContextType context)
+ : impl_on_gpu_(impl_on_gpu), context_(std::move(context)) {}
+ ~PromiseTextureHelper() = default;
+
+ static sk_sp<SkImage> MakePromiseSkImage(
+ SkiaOutputSurfaceImpl* impl,
+ SkDeferredDisplayListRecorder* recorder,
+ const GrBackendFormat& backend_format,
+ gfx::Size size,
+ GrMipMapped mip_mapped,
+ GrSurfaceOrigin origin,
+ SkColorType color_type,
+ SkAlphaType alpha_type,
+ sk_sp<SkColorSpace> color_space,
+ FullfillContextType context) {
+ DCHECK_CALLED_ON_VALID_THREAD(impl->thread_checker_);
+ auto helper = std::make_unique<HelperType>(impl->impl_on_gpu_->weak_ptr(),
+ std::move(context));
+ auto image = recorder->makePromiseTexture(
+ backend_format, size.width(), size.height(), mip_mapped, origin,
+ color_type, alpha_type, color_space, HelperType::Fullfill,
+ HelperType::Release, HelperType::Done, helper.get());
+ if (image) {
+ helper->Init(impl);
+ helper.release();
+ }
+ return image;
+ }
+
+ private:
+ void Init(SkiaOutputSurfaceImpl* impl);
+
+ static void Fullfill(void* texture_context,
+ GrBackendTexture* backend_texture) {
+ DCHECK(texture_context);
+ auto* helper = static_cast<HelperType*>(texture_context);
+ // The fullfill is always called by SkiaOutputSurfaceImplOnGpu::SwapBuffers
+ // or SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass, so impl_on_gpu_
+ // should be always valid.
+ DCHECK(helper->impl_on_gpu_);
+ helper->impl_on_gpu_->FullfillPromiseTexture(helper->context_,
+ backend_texture);
+ }
+
+ static void Release(void* texture_context) { DCHECK(texture_context); }
+
+ static void Done(void* texture_context) {
+ DCHECK(texture_context);
+ std::unique_ptr<HelperType> helper(
+ static_cast<HelperType*>(texture_context));
+ }
+
+ base::WeakPtr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
+
+ // The data for calling the fullfill methods in SkiaOutputSurfaceImpl.
+ FullfillContextType context_;
+
+ DISALLOW_COPY_AND_ASSIGN(PromiseTextureHelper);
+};
+
+template <class T>
+void SkiaOutputSurfaceImpl::PromiseTextureHelper<T>::Init(
+ SkiaOutputSurfaceImpl* impl) {}
+
+// For YUVResourceMetadata, we need to record the |context_| pointer in
+// |impl->yuv_resource_metadatas_|, because we have to create SkImage from YUV
+// textures before drawing the ddl to a SKSurface.
+// TODO(penghuang): Remove this hack when Skia supports drawing YUV textures
+// directly.
+template <>
+void SkiaOutputSurfaceImpl::PromiseTextureHelper<YUVResourceMetadata>::Init(
+ SkiaOutputSurfaceImpl* impl) {
+ impl->yuv_resource_metadatas_.push_back(&context_);
+}
+
+SkiaOutputSurfaceImpl::SkiaOutputSurfaceImpl(
+ GpuServiceImpl* gpu_service,
+ gpu::SurfaceHandle surface_handle,
+ scoped_refptr<VizProcessContextProvider> context_provider,
+ SyntheticBeginFrameSource* synthetic_begin_frame_source)
+ : SkiaOutputSurface(context_provider),
+ gpu_service_(gpu_service),
+ surface_handle_(surface_handle),
+ synthetic_begin_frame_source_(synthetic_begin_frame_source),
+ weak_ptr_factory_(this) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ recorder_ = nullptr;
+ // Use GPU scheduler to release impl_on_gpu_ on the GPU thread, so all
+ // scheduled tasks for the impl_on_gpu_ will be executed, before releasing
+ // it. The GPU thread is the main thread of the viz process. It outlives the
+ // compositor thread. We don't need worry about it for now.
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ auto callback =
+ base::BindOnce([](std::unique_ptr<SkiaOutputSurfaceImplOnGpu>) {},
+ std::move(impl_on_gpu_));
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::vector<gpu::SyncToken>()));
+}
+
+void SkiaOutputSurfaceImpl::BindToClient(OutputSurfaceClient* client) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(client);
+ DCHECK(!client_);
+
+ client_ = client;
+ weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
+ client_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
+
+ base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ auto callback = base::BindOnce(&SkiaOutputSurfaceImpl::InitializeOnGpuThread,
+ base::Unretained(this), &event);
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::vector<gpu::SyncToken>()));
+ event.Wait();
+}
+
+void SkiaOutputSurfaceImpl::EnsureBackbuffer() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+
+void SkiaOutputSurfaceImpl::DiscardBackbuffer() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+
+void SkiaOutputSurfaceImpl::BindFramebuffer() {
+ // TODO(penghuang): remove this method when GLRenderer is removed.
+}
+
+void SkiaOutputSurfaceImpl::SetDrawRectangle(const gfx::Rect& draw_rectangle) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+
+void SkiaOutputSurfaceImpl::Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha,
+ bool use_stencil) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ recorder_ = nullptr;
+ SkSurfaceCharacterization* characterization = nullptr;
+ std::unique_ptr<base::WaitableEvent> event;
+ if (characterization_.isValid()) {
+ characterization_ =
+ characterization_.createResized(size.width(), size.height());
+ } else {
+ characterization = &characterization_;
+ // TODO(penghuang): avoid blocking compositor thread.
+ // We don't have a valid surface characterization, so we have to wait
+ // until reshape is finished on Gpu thread.
+ event = std::make_unique<base::WaitableEvent>(
+ base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED);
+ }
+
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ // impl_on_gpu_ is released on the GPU thread by a posted task from
+ // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+ auto callback = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::Reshape,
+ base::Unretained(impl_on_gpu_.get()), size,
+ device_scale_factor, color_space, has_alpha,
+ use_stencil, characterization, event.get());
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::vector<gpu::SyncToken>()));
+
+ if (event)
+ event->Wait();
+ RecreateRecorder();
+}
+
+void SkiaOutputSurfaceImpl::SwapBuffers(OutputSurfaceFrame frame) {
+ NOTREACHED();
+}
+
+uint32_t SkiaOutputSurfaceImpl::GetFramebufferCopyTextureFormat() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ return GL_RGB;
+}
+
+OverlayCandidateValidator* SkiaOutputSurfaceImpl::GetOverlayCandidateValidator()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return nullptr;
+}
+
+bool SkiaOutputSurfaceImpl::IsDisplayedAsOverlayPlane() const {
+ return false;
+}
+
+unsigned SkiaOutputSurfaceImpl::GetOverlayTextureId() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return 0;
+}
+
+gfx::BufferFormat SkiaOutputSurfaceImpl::GetOverlayBufferFormat() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ return gfx::BufferFormat::RGBX_8888;
+}
+
+bool SkiaOutputSurfaceImpl::HasExternalStencilTest() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ return false;
+}
+
+void SkiaOutputSurfaceImpl::ApplyExternalStencil() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+#if BUILDFLAG(ENABLE_VULKAN)
+gpu::VulkanSurface* SkiaOutputSurfaceImpl::GetVulkanSurface() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ return nullptr;
+}
+#endif
+
+unsigned SkiaOutputSurfaceImpl::UpdateGpuFence() {
+ return 0;
+}
+
+SkCanvas* SkiaOutputSurfaceImpl::GetSkCanvasForCurrentFrame() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(recorder_);
+ DCHECK_EQ(current_render_pass_id_, 0u);
+
+ return recorder_->getCanvas();
+}
+
+sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImage(
+ ResourceMetadata metadata) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(recorder_);
+
+ // Convert internal format from GLES2 to platform GL.
+ const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo();
+ metadata.backend_format = GrBackendFormat::MakeGL(
+ gl::GetInternalFormat(version_info,
+ *metadata.backend_format.getGLFormat()),
+ *metadata.backend_format.getGLTarget());
+
+ DCHECK(!metadata.mailbox.IsZero());
+ resource_sync_tokens_.push_back(metadata.sync_token);
+
+ return PromiseTextureHelper<ResourceMetadata>::MakePromiseSkImage(
+ this, recorder_.get(), metadata.backend_format, metadata.size,
+ metadata.mip_mapped, metadata.origin, metadata.color_type,
+ metadata.alpha_type, metadata.color_space, std::move(metadata));
+}
+
+sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromYUV(
+ std::vector<ResourceMetadata> metadatas,
+ SkYUVColorSpace yuv_color_space) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(recorder_);
+
+ DCHECK(metadatas.size() == 2 || metadatas.size() == 3);
+
+ // TODO(penghuang): Create SkImage from YUV textures directly when it is
+ // supported by Skia.
+ YUVResourceMetadata yuv_metadata(std::move(metadatas), yuv_color_space);
+
+ // Convert internal format from GLES2 to platform GL.
+ const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo();
+ auto backend_format = GrBackendFormat::MakeGL(
+ gl::GetInternalFormat(version_info, GL_BGRA8_EXT), GL_TEXTURE_2D);
+
+ return PromiseTextureHelper<YUVResourceMetadata>::MakePromiseSkImage(
+ this, recorder_.get(), backend_format, yuv_metadata.size(),
+ GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType,
+ kPremul_SkAlphaType, nullptr /* color_space */, std::move(yuv_metadata));
+}
+
+gpu::SyncToken SkiaOutputSurfaceImpl::SkiaSwapBuffers(
+ OutputSurfaceFrame frame) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(recorder_);
+
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE,
+ impl_on_gpu_->command_buffer_id(),
+ ++sync_fence_release_);
+ sync_token.SetVerifyFlush();
+
+ auto ddl = recorder_->detach();
+ DCHECK(ddl);
+ RecreateRecorder();
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ // impl_on_gpu_ is released on the GPU thread by a posted task from
+ // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+ auto callback = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::SwapBuffers,
+ base::Unretained(impl_on_gpu_.get()), std::move(frame), std::move(ddl),
+ std::move(yuv_resource_metadatas_), sync_fence_release_);
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::move(resource_sync_tokens_)));
+ return sync_token;
+}
+
+SkCanvas* SkiaOutputSurfaceImpl::BeginPaintRenderPass(
+ const RenderPassId& id,
+ const gfx::Size& surface_size,
+ ResourceFormat format,
+ bool mipmap) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(gpu_service_->gr_context());
+ DCHECK(!current_render_pass_id_);
+ DCHECK(!offscreen_surface_recorder_);
+ DCHECK(resource_sync_tokens_.empty());
+
+ current_render_pass_id_ = id;
+
+ auto gr_context_thread_safe = gpu_service_->gr_context()->threadSafeProxy();
+ constexpr uint32_t flags = 0;
+ // LegacyFontHost will get LCD text and skia figures out what type to use.
+ SkSurfaceProps surface_props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+ int msaa_sample_count = 0;
+ SkColorType color_type =
+ ResourceFormatToClosestSkColorType(true /*gpu_compositing */, format);
+ SkImageInfo image_info =
+ SkImageInfo::Make(surface_size.width(), surface_size.height(), color_type,
+ kPremul_SkAlphaType, nullptr /* color_space */);
+
+ // TODO(penghuang): Figure out how to choose the right size.
+ constexpr size_t kCacheMaxResourceBytes = 90 * 1024 * 1024;
+ const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo();
+ unsigned int texture_storage_format = TextureStorageFormat(format);
+ auto backend_format = GrBackendFormat::MakeGL(
+ gl::GetInternalFormat(version_info, texture_storage_format),
+ GL_TEXTURE_2D);
+ auto characterization = gr_context_thread_safe->createCharacterization(
+ kCacheMaxResourceBytes, image_info, backend_format, msaa_sample_count,
+ kTopLeft_GrSurfaceOrigin, surface_props, mipmap);
+ DCHECK(characterization.isValid());
+ offscreen_surface_recorder_ =
+ std::make_unique<SkDeferredDisplayListRecorder>(characterization);
+ return offscreen_surface_recorder_->getCanvas();
+}
+
+gpu::SyncToken SkiaOutputSurfaceImpl::FinishPaintRenderPass() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(gpu_service_->gr_context());
+ DCHECK(current_render_pass_id_);
+ DCHECK(offscreen_surface_recorder_);
+
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE,
+ impl_on_gpu_->command_buffer_id(),
+ ++sync_fence_release_);
+ sync_token.SetVerifyFlush();
+
+ auto ddl = offscreen_surface_recorder_->detach();
+ offscreen_surface_recorder_ = nullptr;
+ DCHECK(ddl);
+
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ // impl_on_gpu_ is released on the GPU thread by a posted task from
+ // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+ auto callback = base::BindOnce(
+ &SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass,
+ base::Unretained(impl_on_gpu_.get()), current_render_pass_id_,
+ std::move(ddl), std::move(yuv_resource_metadatas_), sync_fence_release_);
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::move(resource_sync_tokens_)));
+ current_render_pass_id_ = 0;
+ return sync_token;
+}
+
+sk_sp<SkImage> SkiaOutputSurfaceImpl::MakePromiseSkImageFromRenderPass(
+ const RenderPassId& id,
+ const gfx::Size& size,
+ ResourceFormat format,
+ bool mipmap) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(recorder_);
+
+ // Convert internal format from GLES2 to platform GL.
+ const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo();
+ unsigned int texture_storage_format = TextureStorageFormat(format);
+ auto backend_format = GrBackendFormat::MakeGL(
+ gl::GetInternalFormat(version_info, texture_storage_format),
+ GL_TEXTURE_2D);
+ SkColorType color_type =
+ ResourceFormatToClosestSkColorType(true /*gpu_compositing */, format);
+ return PromiseTextureHelper<RenderPassId>::MakePromiseSkImage(
+ this, recorder_.get(), backend_format, size,
+ mipmap ? GrMipMapped::kYes : GrMipMapped::kNo, kTopLeft_GrSurfaceOrigin,
+ color_type, kPremul_SkAlphaType, nullptr /* color_space */, id);
+}
+
+void SkiaOutputSurfaceImpl::RemoveRenderPassResource(
+ std::vector<RenderPassId> ids) {
+ DCHECK(!ids.empty());
+ auto sequence_id = gpu_service_->skia_output_surface_sequence_id();
+ // impl_on_gpu_ is released on the GPU thread by a posted task from
+ // SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
+ auto callback =
+ base::BindOnce(&SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource,
+ base::Unretained(impl_on_gpu_.get()), std::move(ids));
+ gpu_service_->scheduler()->ScheduleTask(gpu::Scheduler::Task(
+ sequence_id, std::move(callback), std::vector<gpu::SyncToken>()));
+}
+
+void SkiaOutputSurfaceImpl::InitializeOnGpuThread(base::WaitableEvent* event) {
+ base::ScopedClosureRunner scoped_runner(
+ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event)));
+ auto did_swap_buffer_complete_callback = base::BindRepeating(
+ &SkiaOutputSurfaceImpl::DidSwapBuffersComplete, weak_ptr_);
+ auto buffer_presented_callback =
+ base::BindRepeating(&SkiaOutputSurfaceImpl::BufferPresented, weak_ptr_);
+ impl_on_gpu_ = std::make_unique<SkiaOutputSurfaceImplOnGpu>(
+ gpu_service_, surface_handle_,
+ CreateSafeCallback(client_thread_task_runner_,
+ did_swap_buffer_complete_callback),
+ CreateSafeCallback(client_thread_task_runner_,
+ buffer_presented_callback));
+ capabilities_ = impl_on_gpu_->capabilities();
+}
+
+void SkiaOutputSurfaceImpl::RecreateRecorder() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(characterization_.isValid());
+ recorder_ =
+ std::make_unique<SkDeferredDisplayListRecorder>(characterization_);
+ // TODO(penghuang): remove the unnecessary getCanvas() call, when the
+ // recorder crash is fixed in skia.
+ recorder_->getCanvas();
+}
+
+void SkiaOutputSurfaceImpl::DidSwapBuffersComplete(
+ gpu::SwapBuffersCompleteParams params) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(client_);
+
+ if (!params.texture_in_use_responses.empty())
+ client_->DidReceiveTextureInUseResponses(params.texture_in_use_responses);
+ if (!params.ca_layer_params.is_empty)
+ client_->DidReceiveCALayerParams(params.ca_layer_params);
+ client_->DidReceiveSwapBuffersAck();
+}
+
+void SkiaOutputSurfaceImpl::BufferPresented(
+ const gfx::PresentationFeedback& feedback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(client_);
+ client_->DidReceivePresentationFeedback(feedback);
+ if (synthetic_begin_frame_source_ &&
+ feedback.flags & gfx::PresentationFeedback::kVSync) {
+ // TODO(brianderson): We should not be receiving 0 intervals.
+ synthetic_begin_frame_source_->OnUpdateVSyncParameters(
+ feedback.timestamp, feedback.interval.is_zero()
+ ? BeginFrameArgs::DefaultInterval()
+ : feedback.interval);
+ }
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h
new file mode 100644
index 00000000000..3309aa30433
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -0,0 +1,141 @@
+// 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.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
+
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "components/viz/service/display/skia_output_surface.h"
+#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "gpu/ipc/in_process_command_buffer.h"
+#include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
+#include "third_party/skia/include/core/SkSurfaceCharacterization.h"
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace viz {
+
+class GpuServiceImpl;
+class VizProcessContextProvider;
+class SkiaOutputSurfaceImplOnGpu;
+class SyntheticBeginFrameSource;
+
+class YUVResourceMetadata;
+
+// The SkiaOutputSurface implementation. It is the output surface for
+// SkiaRenderer. It lives on the compositor thread, but it will post tasks
+// to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl
+// create a SkiaOutputSurfaceImplOnGpu on the GPU thread. It will be used
+// for creating a SkSurface from the default framebuffer and providing the
+// SkSurfaceCharacterization for the SkSurface. And then SkiaOutputSurfaceImpl
+// will create SkDeferredDisplayListRecorder and SkCanvas for SkiaRenderer to
+// render into. In SwapBuffers, it detaches a SkDeferredDisplayList from the
+// recorder and plays it back on the framebuffer SkSurface on the GPU thread
+// through SkiaOutputSurfaceImpleOnGpu.
+class SkiaOutputSurfaceImpl : public SkiaOutputSurface {
+ public:
+ SkiaOutputSurfaceImpl(
+ GpuServiceImpl* gpu_service,
+ gpu::SurfaceHandle surface_handle,
+ scoped_refptr<VizProcessContextProvider> context_provider,
+ SyntheticBeginFrameSource* synthetic_begin_frame_source);
+ ~SkiaOutputSurfaceImpl() override;
+
+ // OutputSurface implementation:
+ void BindToClient(OutputSurfaceClient* client) override;
+ void EnsureBackbuffer() override;
+ void DiscardBackbuffer() override;
+ void BindFramebuffer() override;
+ void SetDrawRectangle(const gfx::Rect& draw_rectangle) override;
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha,
+ bool use_stencil) override;
+ void SwapBuffers(OutputSurfaceFrame frame) override;
+ uint32_t GetFramebufferCopyTextureFormat() override;
+ OverlayCandidateValidator* GetOverlayCandidateValidator() const override;
+ bool IsDisplayedAsOverlayPlane() const override;
+ unsigned GetOverlayTextureId() const override;
+ gfx::BufferFormat GetOverlayBufferFormat() const override;
+ bool HasExternalStencilTest() const override;
+ void ApplyExternalStencil() override;
+#if BUILDFLAG(ENABLE_VULKAN)
+ gpu::VulkanSurface* GetVulkanSurface() override;
+#endif
+ unsigned UpdateGpuFence() override;
+
+ // SkiaOutputSurface implementation:
+ SkCanvas* GetSkCanvasForCurrentFrame() override;
+ sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override;
+ sk_sp<SkImage> MakePromiseSkImageFromYUV(
+ std::vector<ResourceMetadata> metadatas,
+ SkYUVColorSpace yuv_color_space) override;
+ gpu::SyncToken SkiaSwapBuffers(OutputSurfaceFrame frame) override;
+ SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
+ const gfx::Size& surface_size,
+ ResourceFormat format,
+ bool mipmap) override;
+ gpu::SyncToken FinishPaintRenderPass() override;
+ sk_sp<SkImage> MakePromiseSkImageFromRenderPass(const RenderPassId& id,
+ const gfx::Size& size,
+ ResourceFormat format,
+ bool mipmap) override;
+ void RemoveRenderPassResource(std::vector<RenderPassId> ids) override;
+
+ private:
+ template <class T>
+ class PromiseTextureHelper;
+ void InitializeOnGpuThread(base::WaitableEvent* event);
+ void RecreateRecorder();
+ void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params);
+ void BufferPresented(const gfx::PresentationFeedback& feedback);
+
+ uint64_t sync_fence_release_ = 0;
+ GpuServiceImpl* const gpu_service_;
+ const gpu::SurfaceHandle surface_handle_;
+ SyntheticBeginFrameSource* const synthetic_begin_frame_source_;
+ OutputSurfaceClient* client_ = nullptr;
+
+ SkSurfaceCharacterization characterization_;
+ std::unique_ptr<SkDeferredDisplayListRecorder> recorder_;
+
+ // The current render pass id set by BeginPaintRenderPass.
+ RenderPassId current_render_pass_id_ = 0;
+
+ // The SkDDL recorder created by BeginPaintRenderPass, and
+ // FinishPaintRenderPass will turn it into a SkDDL and play the SkDDL back on
+ // the GPU thread.
+ std::unique_ptr<SkDeferredDisplayListRecorder> offscreen_surface_recorder_;
+
+ // Sync tokens for resources which are used for the current frame.
+ std::vector<gpu::SyncToken> resource_sync_tokens_;
+
+ // YUV resource metadatas for the current frame or the current render pass.
+ // They should be preprocessed for playing recorded frame into a surface.
+ // TODO(penghuang): Remove it when Skia supports drawing YUV textures
+ // directly.
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas_;
+
+ // The task runner for running task on the client (compositor) thread.
+ scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_;
+
+ // |impl_on_gpu| is created and destroyed on the GPU thread.
+ std::unique_ptr<SkiaOutputSurfaceImplOnGpu> impl_on_gpu_;
+
+ THREAD_CHECKER(thread_checker_);
+
+ base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_;
+ base::WeakPtrFactory<SkiaOutputSurfaceImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImpl);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_H_
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
new file mode 100644
index 00000000000..eccdf7f1a9b
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -0,0 +1,398 @@
+// 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 "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h"
+
+#include "base/atomic_sequence_num.h"
+#include "base/callback_helpers.h"
+#include "base/synchronization/waitable_event.h"
+#include "components/viz/service/display/output_surface_frame.h"
+#include "components/viz/service/gl/gpu_service_impl.h"
+#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/scheduler.h"
+#include "gpu/command_buffer/service/sync_point_manager.h"
+#include "gpu/command_buffer/service/texture_base.h"
+#include "gpu/command_buffer/service/texture_manager.h"
+#include "gpu/ipc/service/image_transport_surface.h"
+#include "third_party/skia/include/private/SkDeferredDisplayList.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_version_info.h"
+
+namespace viz {
+namespace {
+
+base::AtomicSequenceNumber g_next_command_buffer_id;
+
+} // namespace
+
+YUVResourceMetadata::YUVResourceMetadata(
+ std::vector<ResourceMetadata> metadatas,
+ SkYUVColorSpace yuv_color_space)
+ : metadatas_(std::move(metadatas)), yuv_color_space_(yuv_color_space) {
+ DCHECK(metadatas_.size() == 2 || metadatas_.size() == 3);
+}
+
+YUVResourceMetadata::YUVResourceMetadata(YUVResourceMetadata&& other) = default;
+
+YUVResourceMetadata::~YUVResourceMetadata() = default;
+
+YUVResourceMetadata& YUVResourceMetadata::operator=(
+ YUVResourceMetadata&& other) = default;
+
+SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu(
+ GpuServiceImpl* gpu_service,
+ gpu::SurfaceHandle surface_handle,
+ const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
+ const BufferPresentedCallback& buffer_presented_callback)
+ : command_buffer_id_(gpu::CommandBufferId::FromUnsafeValue(
+ g_next_command_buffer_id.GetNext() + 1)),
+ gpu_service_(gpu_service),
+ surface_handle_(surface_handle),
+ did_swap_buffer_complete_callback_(did_swap_buffer_complete_callback),
+ buffer_presented_callback_(buffer_presented_callback),
+ weak_ptr_factory_(this) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
+
+ sync_point_client_state_ =
+ gpu_service_->sync_point_manager()->CreateSyncPointClientState(
+ gpu::CommandBufferNamespace::VIZ_OUTPUT_SURFACE, command_buffer_id_,
+ gpu_service_->skia_output_surface_sequence_id());
+
+ surface_ = gpu::ImageTransportSurface::CreateNativeSurface(
+ weak_ptr_factory_.GetWeakPtr(), surface_handle_, gl::GLSurfaceFormat());
+ DCHECK(surface_);
+
+ if (!gpu_service_->CreateGrContextIfNecessary(surface_.get())) {
+ LOG(FATAL) << "Failed to create GrContext";
+ // TODO(penghuang): handle the failure.
+ }
+
+ DCHECK(gpu_service_->context_for_skia());
+ DCHECK(gpu_service_->gr_context());
+
+ if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) {
+ LOG(FATAL) << "Failed to make current.";
+ // TODO(penghuang): Handle the failure.
+ }
+
+ capabilities_.flipped_output_surface = surface_->FlipsVertically();
+
+ // Get stencil bits from the default frame buffer.
+ auto* current_gl = gpu_service_->context_for_skia()->GetCurrentGL();
+ const auto* version = current_gl->Version;
+ auto* api = current_gl->Api;
+ GLint stencil_bits = 0;
+ if (version->is_desktop_core_profile) {
+ api->glGetFramebufferAttachmentParameterivEXTFn(
+ GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+ &stencil_bits);
+ } else {
+ api->glGetIntegervFn(GL_STENCIL_BITS, &stencil_bits);
+ }
+
+ capabilities_.supports_stencil = stencil_bits > 0;
+}
+
+SkiaOutputSurfaceImplOnGpu::~SkiaOutputSurfaceImplOnGpu() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+}
+
+void SkiaOutputSurfaceImplOnGpu::Reshape(
+ const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha,
+ bool use_stencil,
+ SkSurfaceCharacterization* characterization,
+ base::WaitableEvent* event) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ std::unique_ptr<base::ScopedClosureRunner> scoped_runner;
+ if (event) {
+ scoped_runner = std::make_unique<base::ScopedClosureRunner>(
+ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event)));
+ }
+
+ if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) {
+ LOG(FATAL) << "Failed to make current.";
+ // TODO(penghuang): Handle the failure.
+ }
+ gl::GLSurface::ColorSpace surface_color_space =
+ color_space == gfx::ColorSpace::CreateSCRGBLinear()
+ ? gl::GLSurface::ColorSpace::SCRGB_LINEAR
+ : gl::GLSurface::ColorSpace::UNSPECIFIED;
+ if (!surface_->Resize(size, device_scale_factor, surface_color_space,
+ has_alpha)) {
+ LOG(FATAL) << "Failed to resize.";
+ // TODO(penghuang): Handle the failure.
+ }
+ DCHECK(gpu_service_->context_for_skia()->IsCurrent(surface_.get()));
+ DCHECK(gpu_service_->gr_context());
+
+ SkSurfaceProps surface_props =
+ SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
+
+ GrGLFramebufferInfo framebuffer_info;
+ framebuffer_info.fFBOID = 0;
+ const auto* version_info = gpu_service_->context_for_skia()->GetVersionInfo();
+ framebuffer_info.fFormat = version_info->is_es ? GL_BGRA8_EXT : GL_RGBA8;
+
+ GrBackendRenderTarget render_target(size.width(), size.height(), 0, 8,
+ framebuffer_info);
+
+ sk_surface_ = SkSurface::MakeFromBackendRenderTarget(
+ gpu_service_->gr_context(), render_target, kBottomLeft_GrSurfaceOrigin,
+ kBGRA_8888_SkColorType, nullptr, &surface_props);
+ DCHECK(sk_surface_);
+
+ if (characterization) {
+ sk_surface_->characterize(characterization);
+ DCHECK(characterization->isValid());
+ }
+}
+
+void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
+ OutputSurfaceFrame frame,
+ std::unique_ptr<SkDeferredDisplayList> ddl,
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
+ uint64_t sync_fence_release) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(ddl);
+ DCHECK(sk_surface_);
+
+ if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) {
+ LOG(FATAL) << "Failed to make current.";
+ // TODO(penghuang): Handle the failure.
+ }
+
+ PreprocessYUVResources(std::move(yuv_resource_metadatas));
+
+ sk_surface_->draw(ddl.get());
+ gpu_service_->gr_context()->flush();
+ OnSwapBuffers();
+ surface_->SwapBuffers(
+ base::BindRepeating([](const gfx::PresentationFeedback&) {}));
+ sync_point_client_state_->ReleaseFenceSync(sync_fence_release);
+}
+
+void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
+ RenderPassId id,
+ std::unique_ptr<SkDeferredDisplayList> ddl,
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
+ uint64_t sync_fence_release) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(ddl);
+
+ if (!gpu_service_->context_for_skia()->MakeCurrent(surface_.get())) {
+ LOG(FATAL) << "Failed to make current.";
+ // TODO(penghuang): Handle resize failure.
+ }
+
+ PreprocessYUVResources(std::move(yuv_resource_metadatas));
+
+ auto& surface = offscreen_surfaces_[id];
+ SkSurfaceCharacterization characterization;
+ // TODO(penghuang): Using characterization != ddl->characterization(), when
+ // the SkSurfaceCharacterization::operator!= is implemented in Skia.
+ if (!surface || !surface->characterize(&characterization) ||
+ characterization != ddl->characterization()) {
+ surface = SkSurface::MakeRenderTarget(
+ gpu_service_->gr_context(), ddl->characterization(), SkBudgeted::kNo);
+ DCHECK(surface);
+ }
+ surface->draw(ddl.get());
+ surface->flush();
+ sync_point_client_state_->ReleaseFenceSync(sync_fence_release);
+}
+
+void SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource(
+ std::vector<RenderPassId> ids) {
+ DCHECK(!ids.empty());
+ for (const auto& id : ids) {
+ auto it = offscreen_surfaces_.find(id);
+ DCHECK(it != offscreen_surfaces_.end());
+ offscreen_surfaces_.erase(it);
+ }
+}
+
+void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
+ const ResourceMetadata& metadata,
+ GrBackendTexture* backend_texture) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ auto* mailbox_manager = gpu_service_->mailbox_manager();
+ auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox);
+ if (!texture_base) {
+ DLOG(ERROR) << "Failed to full fill the promise texture.";
+ return;
+ }
+ BindOrCopyTextureIfNecessary(texture_base);
+ GrGLTextureInfo texture_info;
+ texture_info.fTarget = texture_base->target();
+ texture_info.fID = texture_base->service_id();
+ texture_info.fFormat = *metadata.backend_format.getGLFormat();
+ *backend_texture =
+ GrBackendTexture(metadata.size.width(), metadata.size.height(),
+ metadata.mip_mapped, texture_info);
+}
+
+void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
+ const YUVResourceMetadata& yuv_metadata,
+ GrBackendTexture* backend_texture) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ if (yuv_metadata.image())
+ *backend_texture = yuv_metadata.image()->getBackendTexture(true);
+ DLOG_IF(ERROR, !backend_texture->isValid())
+ << "Failed to full fill the promise texture from yuv resources.";
+}
+
+void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
+ const RenderPassId id,
+ GrBackendTexture* backend_texture) {
+ auto it = offscreen_surfaces_.find(id);
+ DCHECK(it != offscreen_surfaces_.end());
+ sk_sp<SkSurface>& surface = it->second;
+ *backend_texture =
+ surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
+ DLOG_IF(ERROR, !backend_texture->isValid())
+ << "Failed to full fill the promise texture created from RenderPassId:"
+ << id;
+}
+
+#if defined(OS_WIN)
+void SkiaOutputSurfaceImplOnGpu::DidCreateAcceleratedSurfaceChildWindow(
+ gpu::SurfaceHandle parent_window,
+ gpu::SurfaceHandle child_window) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+#endif
+
+void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersComplete(
+ gpu::SwapBuffersCompleteParams params) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ params.swap_response.swap_id = pending_swap_completed_ids_.front();
+ pending_swap_completed_ids_.pop_front();
+ did_swap_buffer_complete_callback_.Run(params);
+}
+
+const gpu::gles2::FeatureInfo* SkiaOutputSurfaceImplOnGpu::GetFeatureInfo()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+const gpu::GpuPreferences& SkiaOutputSurfaceImplOnGpu::GetGpuPreferences()
+ const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+ return gpu_preferences_;
+}
+
+void SkiaOutputSurfaceImplOnGpu::SetSnapshotRequestedCallback(
+ const base::Closure& callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+
+void SkiaOutputSurfaceImplOnGpu::BufferPresented(
+ const gfx::PresentationFeedback& feedback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ buffer_presented_callback_.Run(feedback);
+}
+
+void SkiaOutputSurfaceImplOnGpu::AddFilter(IPC::MessageFilter* message_filter) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+}
+
+int32_t SkiaOutputSurfaceImplOnGpu::GetRouteID() const {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+void SkiaOutputSurfaceImplOnGpu::BindOrCopyTextureIfNecessary(
+ gpu::TextureBase* texture_base) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ if (gpu_service_->gpu_preferences().use_passthrough_cmd_decoder)
+ return;
+ // If a texture created with non-passthrough command buffer and bind with
+ // an image, the Chrome will defer copying the image to the texture until
+ // the texture is used. It is for implementing low latency drawing and
+ // avoiding unnecessary texture copy. So we need check the texture image
+ // state, and bind or copy the image to the texture if necessary.
+ auto* texture = static_cast<gpu::gles2::Texture*>(texture_base);
+ gpu::gles2::Texture::ImageState image_state;
+ auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0, &image_state);
+ if (image && image_state == gpu::gles2::Texture::UNBOUND) {
+ glBindTexture(texture_base->target(), texture_base->service_id());
+ if (image->BindTexImage(texture_base->target())) {
+ } else {
+ texture->SetLevelImageState(texture_base->target(), 0,
+ gpu::gles2::Texture::COPIED);
+ if (!image->CopyTexImage(texture_base->target()))
+ LOG(ERROR) << "Failed to copy a gl image to texture.";
+ }
+ }
+}
+
+void SkiaOutputSurfaceImplOnGpu::PreprocessYUVResources(
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas) {
+ // Create SkImage for fullfilling YUV promise image, before drawing the ddl.
+ // TODO(penghuang): Remove the extra step when Skia supports drawing YUV
+ // textures directly.
+ auto* mailbox_manager = gpu_service_->mailbox_manager();
+ for (auto* yuv_metadata : yuv_resource_metadatas) {
+ const auto& metadatas = yuv_metadata->metadatas();
+ DCHECK(metadatas.size() == 2 || metadatas.size() == 3);
+ GrBackendTexture backend_textures[3];
+ size_t i = 0;
+ for (const auto& metadata : metadatas) {
+ auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox);
+ if (!texture_base)
+ break;
+ BindOrCopyTextureIfNecessary(texture_base);
+ GrGLTextureInfo texture_info;
+ texture_info.fTarget = texture_base->target();
+ texture_info.fID = texture_base->service_id();
+ texture_info.fFormat = *metadata.backend_format.getGLFormat();
+ backend_textures[i++] =
+ GrBackendTexture(metadata.size.width(), metadata.size.height(),
+ GrMipMapped::kNo, texture_info);
+ }
+
+ if (i != metadatas.size())
+ continue;
+
+ sk_sp<SkImage> image;
+ if (metadatas.size() == 2) {
+ image = SkImage::MakeFromNV12TexturesCopy(
+ gpu_service_->gr_context(), yuv_metadata->yuv_color_space(),
+ backend_textures, kTopLeft_GrSurfaceOrigin,
+ nullptr /* image_color_space */);
+ DCHECK(image);
+ } else {
+ image = SkImage::MakeFromYUVTexturesCopy(
+ gpu_service_->gr_context(), yuv_metadata->yuv_color_space(),
+ backend_textures, kTopLeft_GrSurfaceOrigin,
+ nullptr /* image_color_space */);
+ DCHECK(image);
+ }
+ yuv_metadata->set_image(std::move(image));
+ }
+}
+
+void SkiaOutputSurfaceImplOnGpu::OnSwapBuffers() {
+ uint64_t swap_id = swap_id_++;
+ pending_swap_completed_ids_.push_back(swap_id);
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
new file mode 100644
index 00000000000..82462b0bf9b
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -0,0 +1,173 @@
+// 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.
+
+#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
+
+#include "base/containers/circular_deque.h"
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "build/build_config.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "components/viz/common/resources/resource_metadata.h"
+#include "components/viz/service/display/output_surface.h"
+#include "components/viz/service/display/output_surface_frame.h"
+#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "gpu/ipc/in_process_command_buffer.h"
+#include "gpu/ipc/service/image_transport_surface_delegate.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+class SkDeferredDisplayList;
+
+namespace base {
+class WaitableEvent;
+}
+
+namespace gl {
+class GLSurface;
+}
+
+namespace gpu {
+class SyncPointClientState;
+}
+
+namespace viz {
+
+class GpuServiceImpl;
+
+// Metadata for YUV promise SkImage.
+class YUVResourceMetadata {
+ public:
+ YUVResourceMetadata(std::vector<ResourceMetadata> metadatas,
+ SkYUVColorSpace yuv_color_space);
+ YUVResourceMetadata(YUVResourceMetadata&& other);
+ ~YUVResourceMetadata();
+ YUVResourceMetadata& operator=(YUVResourceMetadata&& other);
+
+ const std::vector<ResourceMetadata>& metadatas() const { return metadatas_; }
+ SkYUVColorSpace yuv_color_space() const { return yuv_color_space_; }
+ const sk_sp<SkImage> image() const { return image_; }
+ void set_image(sk_sp<SkImage> image) { image_ = image; }
+ const gfx::Size size() const { return metadatas_[0].size; }
+
+ private:
+ // Metadatas for YUV planes.
+ std::vector<ResourceMetadata> metadatas_;
+
+ SkYUVColorSpace yuv_color_space_;
+
+ // The image copied from YUV textures, it is for fullfilling the promise
+ // image.
+ // TODO(penghuang): Remove it when Skia supports drawing YUV textures
+ // directly.
+ sk_sp<SkImage> image_;
+
+ DISALLOW_COPY_AND_ASSIGN(YUVResourceMetadata);
+};
+
+// The SkiaOutputSurface implementation running on the GPU thread. This class
+// should be created, used and destroyed on the GPU thread.
+class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
+ public:
+ using DidSwapBufferCompleteCallback =
+ base::RepeatingCallback<void(gpu::SwapBuffersCompleteParams)>;
+ using BufferPresentedCallback =
+ base::RepeatingCallback<void(const gfx::PresentationFeedback& feedback)>;
+ SkiaOutputSurfaceImplOnGpu(
+ GpuServiceImpl* gpu_service,
+ gpu::SurfaceHandle surface_handle,
+ const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback,
+ const BufferPresentedCallback& buffer_presented_callback);
+ ~SkiaOutputSurfaceImplOnGpu() override;
+
+ gpu::CommandBufferId command_buffer_id() const { return command_buffer_id_; }
+ const OutputSurface::Capabilities capabilities() const {
+ return capabilities_;
+ }
+ const base::WeakPtr<SkiaOutputSurfaceImplOnGpu>& weak_ptr() const {
+ return weak_ptr_;
+ }
+
+ void Reshape(const gfx::Size& size,
+ float device_scale_factor,
+ const gfx::ColorSpace& color_space,
+ bool has_alpha,
+ bool use_stencil,
+ SkSurfaceCharacterization* characterization,
+ base::WaitableEvent* event);
+ void SwapBuffers(OutputSurfaceFrame frame,
+ std::unique_ptr<SkDeferredDisplayList> ddl,
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
+ uint64_t sync_fence_release);
+ void FinishPaintRenderPass(
+ RenderPassId id,
+ std::unique_ptr<SkDeferredDisplayList> ddl,
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
+ uint64_t sync_fence_release);
+ void RemoveRenderPassResource(std::vector<RenderPassId> ids);
+
+ // Fullfill callback for promise SkImage created from a resource.
+ void FullfillPromiseTexture(const ResourceMetadata& metadata,
+ GrBackendTexture* backend_texture);
+ // Fullfill callback for promise SkImage created from YUV resources.
+ void FullfillPromiseTexture(const YUVResourceMetadata& metadata,
+ GrBackendTexture* backend_texture);
+ // Fullfill callback for promise SkImage created from a render pass.
+ void FullfillPromiseTexture(const RenderPassId id,
+ GrBackendTexture* backend_texture);
+
+ private:
+// gpu::ImageTransportSurfaceDelegate implementation:
+#if defined(OS_WIN)
+ void DidCreateAcceleratedSurfaceChildWindow(
+ gpu::SurfaceHandle parent_window,
+ gpu::SurfaceHandle child_window) override;
+#endif
+ void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params) override;
+ const gpu::gles2::FeatureInfo* GetFeatureInfo() const override;
+ const gpu::GpuPreferences& GetGpuPreferences() const override;
+ void SetSnapshotRequestedCallback(const base::Closure& callback) override;
+ void BufferPresented(const gfx::PresentationFeedback& feedback) override;
+ void AddFilter(IPC::MessageFilter* message_filter) override;
+ int32_t GetRouteID() const override;
+
+ void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base);
+ void PreprocessYUVResources(
+ std::vector<YUVResourceMetadata*> yuv_resource_metadatas);
+
+ // Generage the next swap ID and push it to our pending swap ID queues.
+ void OnSwapBuffers();
+
+ const gpu::CommandBufferId command_buffer_id_;
+ GpuServiceImpl* const gpu_service_;
+ const gpu::SurfaceHandle surface_handle_;
+ DidSwapBufferCompleteCallback did_swap_buffer_complete_callback_;
+ BufferPresentedCallback buffer_presented_callback_;
+ scoped_refptr<gpu::SyncPointClientState> sync_point_client_state_;
+ gpu::GpuPreferences gpu_preferences_;
+ scoped_refptr<gl::GLSurface> surface_;
+ sk_sp<SkSurface> sk_surface_;
+ OutputSurface::Capabilities capabilities_;
+
+ // Offscreen surfaces for render passes. It can only be accessed on GPU
+ // thread.
+ base::flat_map<RenderPassId, sk_sp<SkSurface>> offscreen_surfaces_;
+
+ // ID is pushed each time we begin a swap, and popped each time we present or
+ // complete a swap.
+ base::circular_deque<uint64_t> pending_swap_completed_ids_;
+ uint64_t swap_id_ = 0;
+
+ THREAD_CHECKER(thread_checker_);
+
+ base::WeakPtr<SkiaOutputSurfaceImplOnGpu> weak_ptr_;
+ base::WeakPtrFactory<SkiaOutputSurfaceImplOnGpu> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurfaceImplOnGpu);
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_SURFACE_IMPL_ON_GPU_H_
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_mac.cc b/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
index b256bf2d60f..b9357082293 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_mac.cc
@@ -7,7 +7,7 @@
#include "base/mac/foundation_util.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkCanvas.h"
-#include "ui/accelerated_widget_mac/ca_layer_frame_sink.h"
+#include "ui/gfx/ca_layer_params.h"
#include "ui/gfx/mac/io_surface.h"
#include "ui/gfx/skia_util.h"
@@ -16,8 +16,9 @@ namespace viz {
SoftwareOutputDeviceMac::Buffer::Buffer() = default;
SoftwareOutputDeviceMac::Buffer::~Buffer() = default;
-SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(gfx::AcceleratedWidget widget)
- : widget_(widget) {}
+SoftwareOutputDeviceMac::SoftwareOutputDeviceMac(
+ scoped_refptr<base::SequencedTaskRunner> task_runner)
+ : SoftwareOutputDevice(std::move(task_runner)) {}
SoftwareOutputDeviceMac::~SoftwareOutputDeviceMac() {}
@@ -178,24 +179,14 @@ void SoftwareOutputDeviceMac::EndPaint() {
}
current_paint_canvas_.reset();
- if (widget_ != gfx::kNullAcceleratedWidget) {
+ if (client_) {
gfx::CALayerParams ca_layer_params;
ca_layer_params.is_empty = false;
ca_layer_params.scale_factor = scale_factor_;
ca_layer_params.pixel_size = pixel_size_;
ca_layer_params.io_surface_mach_port.reset(
IOSurfaceCreateMachPort(current_paint_buffer_->io_surface));
- ui::CALayerFrameSink* ca_layer_frame_sink =
- ui::CALayerFrameSink::FromAcceleratedWidget(widget_);
- if (ca_layer_frame_sink) {
- ca_layer_frame_sink->SetSuspended(false);
- ca_layer_frame_sink->UpdateCALayerTree(ca_layer_params);
- base::TimeTicks vsync_timebase;
- base::TimeDelta vsync_interval;
- ca_layer_frame_sink->GetVSyncParameters(&vsync_timebase, &vsync_interval);
- if (!update_vsync_callback_.is_null())
- update_vsync_callback_.Run(vsync_timebase, vsync_interval);
- }
+ client_->SoftwareDeviceUpdatedCALayerParams(ca_layer_params);
}
current_paint_buffer_ = nullptr;
@@ -208,26 +199,7 @@ void SoftwareOutputDeviceMac::DiscardBackbuffer() {
void SoftwareOutputDeviceMac::EnsureBackbuffer() {}
gfx::VSyncProvider* SoftwareOutputDeviceMac::GetVSyncProvider() {
- return this;
-}
-
-void SoftwareOutputDeviceMac::GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) {
- update_vsync_callback_ = callback;
-}
-
-bool SoftwareOutputDeviceMac::GetVSyncParametersIfAvailable(
- base::TimeTicks* timebase,
- base::TimeDelta* interval) {
- return false;
-}
-
-bool SoftwareOutputDeviceMac::SupportGetVSyncParametersIfAvailable() const {
- return false;
-}
-
-bool SoftwareOutputDeviceMac::IsHWClock() const {
- return false;
+ return nullptr;
}
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_mac.h b/chromium/components/viz/service/display_embedder/software_output_device_mac.h
index 4066ac56600..f3867356e3d 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_mac.h
+++ b/chromium/components/viz/service/display_embedder/software_output_device_mac.h
@@ -14,17 +14,15 @@
#include "components/viz/service/viz_service_export.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/vsync_provider.h"
class SkCanvas;
namespace viz {
-class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
- public gfx::VSyncProvider {
+class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice {
public:
- explicit SoftwareOutputDeviceMac(gfx::AcceleratedWidget widget);
+ explicit SoftwareOutputDeviceMac(
+ scoped_refptr<base::SequencedTaskRunner> task_runner);
~SoftwareOutputDeviceMac() override;
// SoftwareOutputDevice implementation.
@@ -35,14 +33,6 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
void EnsureBackbuffer() override;
gfx::VSyncProvider* GetVSyncProvider() override;
- // gfx::VSyncProvider implementation.
- void GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) override;
- bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
- base::TimeDelta* interval) override;
- bool SupportGetVSyncParametersIfAvailable() const override;
- bool IsHWClock() const override;
-
// Testing methods.
SkRegion LastCopyRegionForTesting() const {
return last_copy_region_for_testing_;
@@ -66,7 +56,6 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
void UpdateAndCopyBufferDamage(Buffer* previous_paint_buffer,
const SkRegion& new_damage_rect);
- gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
gfx::Size pixel_size_;
float scale_factor_ = 1;
@@ -83,8 +72,6 @@ class VIZ_SERVICE_EXPORT SoftwareOutputDeviceMac : public SoftwareOutputDevice,
// valid only between BeginPaint and EndPaint.
std::unique_ptr<SkCanvas> current_paint_canvas_;
- gfx::VSyncProvider::UpdateVSyncCallback update_vsync_callback_;
-
SkRegion last_copy_region_for_testing_;
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceMac);
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_mac_unittest.mm b/chromium/components/viz/service/display_embedder/software_output_device_mac_unittest.mm
index ed0b8ad3a49..217bf3a2f7f 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_mac_unittest.mm
+++ b/chromium/components/viz/service/display_embedder/software_output_device_mac_unittest.mm
@@ -4,6 +4,7 @@
#include "components/viz/service/display_embedder/software_output_device_mac.h"
+#include "base/threading/sequenced_task_runner_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/skia_util.h"
@@ -12,8 +13,8 @@ namespace viz {
namespace {
TEST(SoftwareOutputDeviceMacTest, Basics) {
- std::unique_ptr<SoftwareOutputDeviceMac> device(
- new SoftwareOutputDeviceMac(gfx::kNullAcceleratedWidget));
+ auto device = std::make_unique<SoftwareOutputDeviceMac>(
+ base::SequencedTaskRunnerHandle::Get());
gfx::Size pixel_size(512, 512);
float scale_factor = 1;
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc b/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
index ee5986fdfb6..46cd8125266 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_ozone_unittest.cc
@@ -46,7 +46,8 @@ class TestPlatformWindowDelegate : public ui::PlatformWindowDelegate {
float device_pixel_ratio) override {
widget_ = widget;
}
- void OnAcceleratedWidgetDestroyed() override { NOTREACHED(); }
+ void OnAcceleratedWidgetDestroying() override {}
+ void OnAcceleratedWidgetDestroyed() override {}
void OnActivationChanged(bool active) override {}
private:
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_win.cc b/chromium/components/viz/service/display_embedder/software_output_device_win.cc
index 61213e77e24..ba84cac14b3 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_win.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_device_win.cc
@@ -4,109 +4,59 @@
#include "components/viz/service/display_embedder/software_output_device_win.h"
-#include "base/debug/alias.h"
#include "base/memory/shared_memory.h"
+#include "base/threading/thread_checker.h"
+#include "components/viz/common/display/use_layered_window.h"
#include "components/viz/common/resources/resource_sizes.h"
+#include "components/viz/service/display_embedder/output_device_backing.h"
+#include "mojo/public/cpp/system/platform_handle.h"
+#include "services/viz/privileged/interfaces/compositing/layered_window_updater.mojom.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h"
-#include "ui/base/win/internal_constants.h"
+#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/gdi_util.h"
#include "ui/gfx/skia_util.h"
namespace viz {
+namespace {
-// If a window is larger than this in bytes, don't even try to create a
-// backing bitmap for it.
-static const size_t kMaxBitmapSizeBytes = 4 * (16384 * 8192);
+// Shared base class for Windows SoftwareOutputDevice implementations.
+class SoftwareOutputDeviceWinBase : public SoftwareOutputDevice {
+ public:
+ explicit SoftwareOutputDeviceWinBase(HWND hwnd) : hwnd_(hwnd) {}
+ ~SoftwareOutputDeviceWinBase() override {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(!in_paint_);
+ }
-OutputDeviceBacking::OutputDeviceBacking() : created_byte_size_(0) {}
+ HWND hwnd() const { return hwnd_; }
-OutputDeviceBacking::~OutputDeviceBacking() {
- DCHECK(devices_.empty());
-}
+ // SoftwareOutputDevice implementation.
+ void Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) override;
+ SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
+ void EndPaint() override;
-void OutputDeviceBacking::Resized() {
- size_t new_size = GetMaxByteSize();
- if (new_size == created_byte_size_)
- return;
- for (SoftwareOutputDeviceWin* device : devices_) {
- device->ReleaseContents();
- }
- backing_.reset();
- created_byte_size_ = 0;
-}
-
-void OutputDeviceBacking::RegisterOutputDevice(
- SoftwareOutputDeviceWin* device) {
- devices_.push_back(device);
-}
-
-void OutputDeviceBacking::UnregisterOutputDevice(
- SoftwareOutputDeviceWin* device) {
- auto it = std::find(devices_.begin(), devices_.end(), device);
- DCHECK(it != devices_.end());
- devices_.erase(it);
- Resized();
-}
-
-base::SharedMemory* OutputDeviceBacking::GetSharedMemory(
- const gfx::Size& size) {
- if (backing_)
- return backing_.get();
- size_t expected_byte_size = GetMaxByteSize();
- size_t required_size;
- if (!ResourceSizes::MaybeSizeInBytes(size, RGBA_8888, &required_size))
- return nullptr;
- if (required_size > expected_byte_size)
- return nullptr;
-
- created_byte_size_ = expected_byte_size;
-
- backing_.reset(new base::SharedMemory);
- base::debug::Alias(&expected_byte_size);
- CHECK(backing_->CreateAnonymous(created_byte_size_));
- return backing_.get();
-}
-
-size_t OutputDeviceBacking::GetMaxByteSize() {
- // Minimum byte size is 1 because creating a 0-byte-long SharedMemory fails.
- size_t max_size = 1;
- for (const SoftwareOutputDeviceWin* device : devices_) {
- size_t current_size;
- if (!ResourceSizes::MaybeSizeInBytes(device->viewport_pixel_size(),
- RGBA_8888, &current_size))
- continue;
- if (current_size > kMaxBitmapSizeBytes)
- continue;
- max_size = std::max(max_size, current_size);
- }
- return max_size;
-}
+ // Called from Resize() if |viewport_pixel_size_| has changed.
+ virtual void ResizeDelegated() = 0;
-SoftwareOutputDeviceWin::SoftwareOutputDeviceWin(OutputDeviceBacking* backing,
- gfx::AcceleratedWidget widget)
- : hwnd_(widget),
- is_hwnd_composited_(false),
- backing_(backing),
- in_paint_(false) {
- is_hwnd_composited_ = !!::GetProp(hwnd_, ui::kWindowTranslucent);
- // Layered windows must be completely updated every time, so they can't
- // share contents with other windows.
- if (is_hwnd_composited_)
- backing_ = nullptr;
- if (backing_)
- backing_->RegisterOutputDevice(this);
-}
+ // Called from BeginPaint() and should return an SkCanvas.
+ virtual SkCanvas* BeginPaintDelegated() = 0;
-SoftwareOutputDeviceWin::~SoftwareOutputDeviceWin() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(!in_paint_);
- if (backing_)
- backing_->UnregisterOutputDevice(this);
-}
+ // Called from EndPaint() if there is damage.
+ virtual void EndPaintDelegated(const gfx::Rect& damage_rect) = 0;
+
+ private:
+ const HWND hwnd_;
+ bool in_paint_ = false;
+
+ THREAD_CHECKER(thread_checker_);
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWinBase);
+};
-void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
- float scale_factor) {
+void SoftwareOutputDeviceWinBase::Resize(const gfx::Size& viewport_pixel_size,
+ float scale_factor) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!in_paint_);
@@ -114,84 +64,301 @@ void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
return;
viewport_pixel_size_ = viewport_pixel_size;
- if (backing_)
- backing_->Resized();
- contents_.reset();
+ ResizeDelegated();
}
-SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) {
+SkCanvas* SoftwareOutputDeviceWinBase::BeginPaint(
+ const gfx::Rect& damage_rect) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!in_paint_);
- if (!contents_) {
- HANDLE shared_section = NULL;
- bool can_create_contents = true;
- if (backing_) {
- base::SharedMemory* memory =
- backing_->GetSharedMemory(viewport_pixel_size_);
- if (memory) {
- shared_section = memory->handle().GetHandle();
- } else {
- can_create_contents = false;
- }
- }
- if (can_create_contents) {
- contents_ = skia::CreatePlatformCanvasWithSharedSection(
- viewport_pixel_size_.width(), viewport_pixel_size_.height(), true,
- shared_section, skia::CRASH_ON_FAILURE);
- }
- }
damage_rect_ = damage_rect;
in_paint_ = true;
- return contents_.get();
+ return BeginPaintDelegated();
}
-void SoftwareOutputDeviceWin::EndPaint() {
+void SoftwareOutputDeviceWinBase::EndPaint() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(in_paint_);
in_paint_ = false;
- SoftwareOutputDevice::EndPaint();
- if (!contents_)
+ gfx::Rect intersected_damage_rect = damage_rect_;
+ intersected_damage_rect.Intersect(gfx::Rect(viewport_pixel_size_));
+ if (intersected_damage_rect.IsEmpty())
return;
- gfx::Rect rect = damage_rect_;
- rect.Intersect(gfx::Rect(viewport_pixel_size_));
- if (rect.IsEmpty())
+ EndPaintDelegated(intersected_damage_rect);
+}
+
+// SoftwareOutputDevice implementation that draws directly to the provided HWND.
+class SoftwareOutputDeviceWinDirect : public SoftwareOutputDeviceWinBase,
+ public OutputDeviceBacking::Client {
+ public:
+ SoftwareOutputDeviceWinDirect(HWND hwnd, OutputDeviceBacking* backing);
+ ~SoftwareOutputDeviceWinDirect() override;
+
+ // SoftwareOutputDeviceWinBase implementation.
+ void ResizeDelegated() override;
+ SkCanvas* BeginPaintDelegated() override;
+ void EndPaintDelegated(const gfx::Rect& damage_rect) override;
+
+ // OutputDeviceBacking::Client implementation.
+ const gfx::Size& GetViewportPixelSize() const override {
+ return viewport_pixel_size_;
+ }
+ void ReleaseCanvas() override { canvas_.reset(); }
+
+ private:
+ OutputDeviceBacking* const backing_;
+ std::unique_ptr<SkCanvas> canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWinDirect);
+};
+
+SoftwareOutputDeviceWinDirect::SoftwareOutputDeviceWinDirect(
+ HWND hwnd,
+ OutputDeviceBacking* backing)
+ : SoftwareOutputDeviceWinBase(hwnd), backing_(backing) {
+ backing_->RegisterClient(this);
+}
+
+SoftwareOutputDeviceWinDirect::~SoftwareOutputDeviceWinDirect() {
+ backing_->UnregisterClient(this);
+}
+
+void SoftwareOutputDeviceWinDirect::ResizeDelegated() {
+ canvas_.reset();
+ backing_->ClientResized();
+}
+
+SkCanvas* SoftwareOutputDeviceWinDirect::BeginPaintDelegated() {
+ if (!canvas_) {
+ // Share pixel backing with other SoftwareOutputDeviceWinDirect instances.
+ // All work happens on the same thread so this is safe.
+ base::SharedMemory* memory =
+ backing_->GetSharedMemory(viewport_pixel_size_);
+ if (memory) {
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), true,
+ memory->handle().GetHandle(), skia::CRASH_ON_FAILURE);
+ }
+ }
+ return canvas_.get();
+}
+
+void SoftwareOutputDeviceWinDirect::EndPaintDelegated(
+ const gfx::Rect& damage_rect) {
+ if (!canvas_)
return;
- HDC dib_dc = skia::GetNativeDrawingContext(contents_.get());
-
- if (is_hwnd_composited_) {
- RECT wr;
- GetWindowRect(hwnd_, &wr);
- SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
- POINT position = {wr.left, wr.top};
- POINT zero = {0, 0};
- BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA};
-
- DWORD style = GetWindowLong(hwnd_, GWL_EXSTYLE);
- DCHECK(!(style & WS_EX_COMPOSITED));
- style |= WS_EX_LAYERED;
- SetWindowLong(hwnd_, GWL_EXSTYLE, style);
-
- ::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero,
- RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
- } else {
- HDC hdc = ::GetDC(hwnd_);
- RECT src_rect = rect.ToRECT();
- skia::CopyHDC(dib_dc, hdc, rect.x(), rect.y(),
- contents_.get()->imageInfo().isOpaque(), src_rect,
- contents_.get()->getTotalMatrix());
-
- ::ReleaseDC(hwnd_, hdc);
+ HDC dib_dc = skia::GetNativeDrawingContext(canvas_.get());
+ HDC hdc = ::GetDC(hwnd());
+ RECT src_rect = damage_rect.ToRECT();
+ skia::CopyHDC(dib_dc, hdc, damage_rect.x(), damage_rect.y(),
+ canvas_->imageInfo().isOpaque(), src_rect,
+ canvas_->getTotalMatrix());
+
+ ::ReleaseDC(hwnd(), hdc);
+}
+
+// SoftwareOutputDevice implementation that uses layered window API to draw to
+// the provided HWND.
+class SoftwareOutputDeviceWinLayered : public SoftwareOutputDeviceWinBase {
+ public:
+ explicit SoftwareOutputDeviceWinLayered(HWND hwnd)
+ : SoftwareOutputDeviceWinBase(hwnd) {}
+ ~SoftwareOutputDeviceWinLayered() override = default;
+
+ // SoftwareOutputDeviceWinBase implementation.
+ void ResizeDelegated() override;
+ SkCanvas* BeginPaintDelegated() override;
+ void EndPaintDelegated(const gfx::Rect& damage_rect) override;
+
+ private:
+ std::unique_ptr<SkCanvas> canvas_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWinLayered);
+};
+
+void SoftwareOutputDeviceWinLayered::ResizeDelegated() {
+ canvas_.reset();
+}
+
+SkCanvas* SoftwareOutputDeviceWinLayered::BeginPaintDelegated() {
+ if (!canvas_) {
+ // Layered windows can't share a pixel backing.
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), true,
+ nullptr, skia::CRASH_ON_FAILURE);
}
+ return canvas_.get();
}
-void SoftwareOutputDeviceWin::ReleaseContents() {
- DCHECK(!in_paint_);
- contents_.reset();
+void SoftwareOutputDeviceWinLayered::EndPaintDelegated(
+ const gfx::Rect& damage_rect) {
+ if (!canvas_)
+ return;
+
+ // Set WS_EX_LAYERED extended window style if not already set.
+ DWORD style = GetWindowLong(hwnd(), GWL_EXSTYLE);
+ DCHECK(!(style & WS_EX_COMPOSITED));
+ if (!(style & WS_EX_LAYERED))
+ SetWindowLong(hwnd(), GWL_EXSTYLE, style | WS_EX_LAYERED);
+
+ RECT wr;
+ GetWindowRect(hwnd(), &wr);
+ SIZE size = {wr.right - wr.left, wr.bottom - wr.top};
+ POINT position = {wr.left, wr.top};
+ POINT zero = {0, 0};
+ BLENDFUNCTION blend = {AC_SRC_OVER, 0x00, 0xFF, AC_SRC_ALPHA};
+
+ HDC dib_dc = skia::GetNativeDrawingContext(canvas_.get());
+ UpdateLayeredWindow(hwnd(), nullptr, &position, &size, dib_dc, &zero,
+ RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
+}
+
+// SoftwareOutputDevice implementation that uses layered window API to draw
+// indirectly. Since UpdateLayeredWindow() is blocked by the GPU sandbox an
+// implementation of mojom::LayeredWindowUpdater in the browser process handles
+// calling UpdateLayeredWindow. Pixel backing is in SharedMemory so no copying
+// between processes is required.
+class SoftwareOutputDeviceWinProxy : public SoftwareOutputDeviceWinBase {
+ public:
+ SoftwareOutputDeviceWinProxy(
+ HWND hwnd,
+ mojom::LayeredWindowUpdaterPtr layered_window_updater);
+ ~SoftwareOutputDeviceWinProxy() override = default;
+
+ // SoftwareOutputDevice implementation.
+ void OnSwapBuffers(base::OnceClosure swap_ack_callback) override;
+
+ // SoftwareOutputDeviceWinBase implementation.
+ void ResizeDelegated() override;
+ SkCanvas* BeginPaintDelegated() override;
+ void EndPaintDelegated(const gfx::Rect& rect) override;
+
+ private:
+ // Runs |swap_ack_callback_| after draw has happened.
+ void DrawAck();
+
+ mojom::LayeredWindowUpdaterPtr layered_window_updater_;
+
+ std::unique_ptr<SkCanvas> canvas_;
+ bool waiting_on_draw_ack_ = false;
+ base::OnceClosure swap_ack_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWinProxy);
+};
+
+SoftwareOutputDeviceWinProxy::SoftwareOutputDeviceWinProxy(
+ HWND hwnd,
+ mojom::LayeredWindowUpdaterPtr layered_window_updater)
+ : SoftwareOutputDeviceWinBase(hwnd),
+ layered_window_updater_(std::move(layered_window_updater)) {
+ DCHECK(layered_window_updater_.is_bound());
+}
+
+void SoftwareOutputDeviceWinProxy::OnSwapBuffers(
+ base::OnceClosure swap_ack_callback) {
+ DCHECK(swap_ack_callback_.is_null());
+
+ // We aren't waiting on DrawAck() and can immediately run the callback.
+ if (!waiting_on_draw_ack_) {
+ task_runner_->PostTask(FROM_HERE, std::move(swap_ack_callback));
+ return;
+ }
+
+ swap_ack_callback_ = std::move(swap_ack_callback);
+}
+
+void SoftwareOutputDeviceWinProxy::ResizeDelegated() {
+ canvas_.reset();
+
+ size_t required_bytes;
+ if (!ResourceSizes::MaybeSizeInBytes(
+ viewport_pixel_size_, ResourceFormat::RGBA_8888, &required_bytes)) {
+ DLOG(ERROR) << "Invalid viewport size " << viewport_pixel_size_.ToString();
+ return;
+ }
+
+ base::SharedMemory shm;
+ if (!shm.CreateAnonymous(required_bytes)) {
+ DLOG(ERROR) << "Failed to allocate " << required_bytes << " bytes";
+ return;
+ }
+
+ // The SkCanvas maps shared memory on creation and unmaps on destruction.
+ canvas_ = skia::CreatePlatformCanvasWithSharedSection(
+ viewport_pixel_size_.width(), viewport_pixel_size_.height(), true,
+ shm.handle().GetHandle(), skia::CRASH_ON_FAILURE);
+
+ // Transfer handle ownership to the browser process.
+ mojo::ScopedSharedBufferHandle scoped_handle = mojo::WrapSharedMemoryHandle(
+ shm.TakeHandle(), required_bytes,
+ mojo::UnwrappedSharedMemoryHandleProtection::kReadWrite);
+
+ layered_window_updater_->OnAllocatedSharedMemory(viewport_pixel_size_,
+ std::move(scoped_handle));
+}
+
+SkCanvas* SoftwareOutputDeviceWinProxy::BeginPaintDelegated() {
+ return canvas_.get();
+}
+
+void SoftwareOutputDeviceWinProxy::EndPaintDelegated(
+ const gfx::Rect& damage_rect) {
+ DCHECK(!waiting_on_draw_ack_);
+
+ if (!canvas_)
+ return;
+
+ layered_window_updater_->Draw(base::BindOnce(
+ &SoftwareOutputDeviceWinProxy::DrawAck, base::Unretained(this)));
+ waiting_on_draw_ack_ = true;
+
+ TRACE_EVENT_ASYNC_BEGIN0("viz", "SoftwareOutputDeviceWinProxy::Draw", this);
+}
+
+void SoftwareOutputDeviceWinProxy::DrawAck() {
+ DCHECK(waiting_on_draw_ack_);
+ DCHECK(!swap_ack_callback_.is_null());
+
+ TRACE_EVENT_ASYNC_END0("viz", "SoftwareOutputDeviceWinProxy::Draw", this);
+
+ waiting_on_draw_ack_ = false;
+ std::move(swap_ack_callback_).Run();
+}
+
+} // namespace
+
+std::unique_ptr<SoftwareOutputDevice> CreateSoftwareOutputDeviceWinBrowser(
+ HWND hwnd,
+ OutputDeviceBacking* backing) {
+ if (NeedsToUseLayerWindow(hwnd))
+ return std::make_unique<SoftwareOutputDeviceWinLayered>(hwnd);
+
+ return std::make_unique<SoftwareOutputDeviceWinDirect>(hwnd, backing);
+}
+
+std::unique_ptr<SoftwareOutputDevice> CreateSoftwareOutputDeviceWinGpu(
+ HWND hwnd,
+ OutputDeviceBacking* backing,
+ mojom::DisplayClient* display_client) {
+ if (NeedsToUseLayerWindow(hwnd)) {
+ DCHECK(display_client);
+
+ // Setup mojom::LayeredWindowUpdater implementation in the browser process
+ // to draw to the HWND.
+ mojom::LayeredWindowUpdaterPtr layered_window_updater;
+ display_client->CreateLayeredWindowUpdater(
+ mojo::MakeRequest(&layered_window_updater));
+
+ return std::make_unique<SoftwareOutputDeviceWinProxy>(
+ hwnd, std::move(layered_window_updater));
+ }
+
+ return std::make_unique<SoftwareOutputDeviceWinDirect>(hwnd, backing);
}
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/software_output_device_win.h b/chromium/components/viz/service/display_embedder/software_output_device_win.h
index ad2a049fc77..aa2dd64bb0d 100644
--- a/chromium/components/viz/service/display_embedder/software_output_device_win.h
+++ b/chromium/components/viz/service/display_embedder/software_output_device_win.h
@@ -5,71 +5,29 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_WIN_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_DEVICE_WIN_H_
-#include <stddef.h>
#include <windows.h>
#include <memory>
-#include <vector>
-#include "base/macros.h"
-#include "base/threading/thread_checker.h"
#include "components/viz/service/display/software_output_device.h"
#include "components/viz/service/viz_service_export.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace base {
-class SharedMemory;
-}
+#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
namespace viz {
-class SoftwareOutputDeviceWin;
-
-class VIZ_SERVICE_EXPORT OutputDeviceBacking {
- public:
- OutputDeviceBacking();
- ~OutputDeviceBacking();
-
- void Resized();
- void RegisterOutputDevice(SoftwareOutputDeviceWin* device);
- void UnregisterOutputDevice(SoftwareOutputDeviceWin* device);
- base::SharedMemory* GetSharedMemory(const gfx::Size& size);
-
- private:
- size_t GetMaxByteSize();
-
- std::vector<SoftwareOutputDeviceWin*> devices_;
- std::unique_ptr<base::SharedMemory> backing_;
- size_t created_byte_size_;
-
- DISALLOW_COPY_AND_ASSIGN(OutputDeviceBacking);
-};
-
-class VIZ_SERVICE_EXPORT SoftwareOutputDeviceWin : public SoftwareOutputDevice {
- public:
- SoftwareOutputDeviceWin(OutputDeviceBacking* backing,
- gfx::AcceleratedWidget widget);
- ~SoftwareOutputDeviceWin() override;
-
- void Resize(const gfx::Size& viewport_pixel_size,
- float scale_factor) override;
- SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override;
- void EndPaint() override;
- gfx::Size viewport_pixel_size() const { return viewport_pixel_size_; }
- void ReleaseContents();
+class OutputDeviceBacking;
- private:
- HWND hwnd_;
- std::unique_ptr<SkCanvas> contents_;
- bool is_hwnd_composited_;
- OutputDeviceBacking* backing_;
- bool in_paint_;
- THREAD_CHECKER(thread_checker_);
+// Creates an appropriate SoftwareOutputDevice implementation for the browser
+// process.
+VIZ_SERVICE_EXPORT std::unique_ptr<SoftwareOutputDevice>
+CreateSoftwareOutputDeviceWinBrowser(HWND hwnd, OutputDeviceBacking* backing);
- DISALLOW_COPY_AND_ASSIGN(SoftwareOutputDeviceWin);
-};
+// Creates an appropriate SoftwareOutputDevice implementation for the GPU
+// process.
+VIZ_SERVICE_EXPORT std::unique_ptr<SoftwareOutputDevice>
+CreateSoftwareOutputDeviceWinGpu(HWND hwnd,
+ OutputDeviceBacking* backing,
+ mojom::DisplayClient* display_client);
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/software_output_surface.cc b/chromium/components/viz/service/display_embedder/software_output_surface.cc
index 370829010ea..fff590968c5 100644
--- a/chromium/components/viz/service/display_embedder/software_output_surface.cc
+++ b/chromium/components/viz/service/display_embedder/software_output_surface.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/threading/sequenced_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/viz/service/display/output_surface_client.h"
@@ -22,11 +21,8 @@
namespace viz {
SoftwareOutputSurface::SoftwareOutputSurface(
- std::unique_ptr<SoftwareOutputDevice> software_device,
- scoped_refptr<base::SequencedTaskRunner> task_runner)
- : OutputSurface(std::move(software_device)),
- task_runner_(std::move(task_runner)),
- weak_factory_(this) {}
+ std::unique_ptr<SoftwareOutputDevice> software_device)
+ : OutputSurface(std::move(software_device)), weak_factory_(this) {}
SoftwareOutputSurface::~SoftwareOutputSurface() = default;
@@ -66,14 +62,16 @@ void SoftwareOutputSurface::SwapBuffers(OutputSurfaceFrame frame) {
base::TimeTicks swap_time = base::TimeTicks::Now();
for (auto& latency : frame.latency_info) {
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, swap_time, 1);
latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- swap_time, 1);
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, swap_time,
+ 1);
}
- // TODO(danakj): Send frame.latency_info somewhere like
- // RenderWidgetHostImpl::OnGpuSwapBuffersCompleted. It should go to the
- // ui::LatencyTracker in the viz process.
+
+ DCHECK(stored_latency_info_.empty())
+ << "A second frame is not expected to "
+ << "arrive before the previous latency info is processed.";
+ stored_latency_info_ = std::move(frame.latency_info);
// TODO(danakj): Update vsync params.
// gfx::VSyncProvider* vsync_provider = software_device()->GetVSyncProvider();
@@ -81,10 +79,9 @@ void SoftwareOutputSurface::SwapBuffers(OutputSurfaceFrame frame) {
// vsync_provider->GetVSyncParameters(update_vsync_parameters_callback_);
// Update refresh_interval_ as well.
- ++swap_id_;
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&SoftwareOutputSurface::SwapBuffersCallback,
- weak_factory_.GetWeakPtr(), swap_id_));
+ software_device()->OnSwapBuffers(base::BindOnce(
+ &SoftwareOutputSurface::SwapBuffersCallback, weak_factory_.GetWeakPtr(),
+ frame.need_presentation_feedback));
}
bool SoftwareOutputSurface::IsDisplayedAsOverlayPlane() const {
@@ -111,21 +108,22 @@ bool SoftwareOutputSurface::HasExternalStencilTest() const {
void SoftwareOutputSurface::ApplyExternalStencil() {}
-bool SoftwareOutputSurface::SurfaceIsSuspendForRecycle() const {
- return false;
-}
-
uint32_t SoftwareOutputSurface::GetFramebufferCopyTextureFormat() {
// Not used for software surfaces.
NOTREACHED();
return 0;
}
-void SoftwareOutputSurface::SwapBuffersCallback(uint64_t swap_id) {
- client_->DidReceiveSwapBuffersAck(swap_id);
- client_->DidReceivePresentationFeedback(
- swap_id,
- gfx::PresentationFeedback(base::TimeTicks::Now(), refresh_interval_, 0u));
+void SoftwareOutputSurface::SwapBuffersCallback(
+ bool need_presentation_feedback) {
+ latency_tracker_.OnGpuSwapBuffersCompleted(stored_latency_info_);
+ client_->DidFinishLatencyInfo(stored_latency_info_);
+ std::vector<ui::LatencyInfo>().swap(stored_latency_info_);
+ client_->DidReceiveSwapBuffersAck();
+ if (need_presentation_feedback) {
+ client_->DidReceivePresentationFeedback(gfx::PresentationFeedback(
+ base::TimeTicks::Now(), refresh_interval_, 0u));
+ }
}
#if BUILDFLAG(ENABLE_VULKAN)
@@ -135,4 +133,8 @@ gpu::VulkanSurface* SoftwareOutputSurface::GetVulkanSurface() {
}
#endif
+unsigned SoftwareOutputSurface::UpdateGpuFence() {
+ return 0;
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/software_output_surface.h b/chromium/components/viz/service/display_embedder/software_output_surface.h
index 70b20326e25..2c78d933167 100644
--- a/chromium/components/viz/service/display_embedder/software_output_surface.h
+++ b/chromium/components/viz/service/display_embedder/software_output_surface.h
@@ -6,17 +6,18 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SOFTWARE_OUTPUT_SURFACE_H_
#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/viz_service_export.h"
+#include "ui/latency/latency_info.h"
+#include "ui/latency/latency_tracker.h"
namespace viz {
class SoftwareOutputDevice;
class VIZ_SERVICE_EXPORT SoftwareOutputSurface : public OutputSurface {
public:
- SoftwareOutputSurface(std::unique_ptr<SoftwareOutputDevice> software_device,
- scoped_refptr<base::SequencedTaskRunner> task_runner);
+ explicit SoftwareOutputSurface(
+ std::unique_ptr<SoftwareOutputDevice> software_device);
~SoftwareOutputSurface() override;
// OutputSurface implementation.
@@ -37,19 +38,19 @@ class VIZ_SERVICE_EXPORT SoftwareOutputSurface : public OutputSurface {
gfx::BufferFormat GetOverlayBufferFormat() const override;
bool HasExternalStencilTest() const override;
void ApplyExternalStencil() override;
- bool SurfaceIsSuspendForRecycle() const override;
uint32_t GetFramebufferCopyTextureFormat() override;
#if BUILDFLAG(ENABLE_VULKAN)
gpu::VulkanSurface* GetVulkanSurface() override;
#endif
+ unsigned UpdateGpuFence() override;
private:
- void SwapBuffersCallback(uint64_t swap_id);
+ void SwapBuffersCallback(bool need_presentation_feedback);
OutputSurfaceClient* client_ = nullptr;
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
base::TimeDelta refresh_interval_;
- uint64_t swap_id_ = 0;
+ std::vector<ui::LatencyInfo> stored_latency_info_;
+ ui::LatencyTracker latency_tracker_;
base::WeakPtrFactory<SoftwareOutputSurface> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SoftwareOutputSurface);
diff --git a/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc b/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc
new file mode 100644
index 00000000000..e32a6e1864e
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/viz_process_context_provider.cc
@@ -0,0 +1,151 @@
+// Copyright 2016 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 "components/viz/service/display_embedder/viz_process_context_provider.h"
+
+#include <stdint.h>
+
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/viz/common/resources/platform_color.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "gpu/command_buffer/client/raster_implementation_gles.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/command_buffer/service/sync_point_manager.h"
+#include "gpu/config/gpu_feature_info.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "gpu/ipc/gl_in_process_context.h"
+#include "gpu/ipc/gpu_in_process_thread_service.h"
+#include "gpu/ipc/in_process_command_buffer.h"
+#include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/khronos/GLES2/gl2ext.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+
+namespace viz {
+
+namespace {
+
+gpu::ContextCreationAttribs CreateAttributes() {
+ gpu::ContextCreationAttribs attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 8;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.fail_if_major_perf_caveat = false;
+ attributes.bind_generates_resource = false;
+ return attributes;
+}
+
+} // namespace
+
+VizProcessContextProvider::VizProcessContextProvider(
+ scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
+ gpu::SurfaceHandle surface_handle,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ gpu::ImageFactory* image_factory,
+ gpu::GpuChannelManagerDelegate* gpu_channel_manager_delegate,
+ const gpu::SharedMemoryLimits& limits)
+ : attributes_(CreateAttributes()),
+ context_(gpu::GLInProcessContext::CreateWithoutInit()),
+ context_result_(
+ context_->Initialize(std::move(service),
+ nullptr,
+ (surface_handle == gpu::kNullSurfaceHandle),
+ surface_handle,
+ attributes_,
+ limits,
+ gpu_memory_buffer_manager,
+ image_factory,
+ gpu_channel_manager_delegate,
+ base::ThreadTaskRunnerHandle::Get())),
+ cache_controller_(std::make_unique<ContextCacheController>(
+ context_->GetImplementation(),
+ base::ThreadTaskRunnerHandle::Get())) {}
+
+VizProcessContextProvider::~VizProcessContextProvider() = default;
+
+void VizProcessContextProvider::AddRef() const {
+ base::RefCountedThreadSafe<VizProcessContextProvider>::AddRef();
+}
+
+void VizProcessContextProvider::Release() const {
+ base::RefCountedThreadSafe<VizProcessContextProvider>::Release();
+}
+
+gpu::ContextResult VizProcessContextProvider::BindToCurrentThread() {
+ return context_result_;
+}
+
+gpu::gles2::GLES2Interface* VizProcessContextProvider::ContextGL() {
+ return context_->GetImplementation();
+}
+
+gpu::ContextSupport* VizProcessContextProvider::ContextSupport() {
+ return context_->GetImplementation();
+}
+
+class GrContext* VizProcessContextProvider::GrContext() {
+ if (gr_context_)
+ return gr_context_->get();
+
+ size_t max_resource_cache_bytes;
+ size_t max_glyph_cache_texture_bytes;
+ skia_bindings::GrContextForGLES2Interface::
+ DetermineCacheLimitsFromAvailableMemory(&max_resource_cache_bytes,
+ &max_glyph_cache_texture_bytes);
+
+ gr_context_.reset(new skia_bindings::GrContextForGLES2Interface(
+ ContextGL(), ContextSupport(), ContextCapabilities(),
+ max_resource_cache_bytes, max_glyph_cache_texture_bytes));
+ return gr_context_->get();
+}
+
+ContextCacheController* VizProcessContextProvider::CacheController() {
+ return cache_controller_.get();
+}
+
+base::Lock* VizProcessContextProvider::GetLock() {
+ return &context_lock_;
+}
+
+const gpu::Capabilities& VizProcessContextProvider::ContextCapabilities()
+ const {
+ return context_->GetCapabilities();
+}
+
+const gpu::GpuFeatureInfo& VizProcessContextProvider::GetGpuFeatureInfo()
+ const {
+ return context_->GetGpuFeatureInfo();
+}
+
+void VizProcessContextProvider::AddObserver(ContextLostObserver* obs) {}
+
+void VizProcessContextProvider::RemoveObserver(ContextLostObserver* obs) {}
+
+uint32_t VizProcessContextProvider::GetCopyTextureInternalFormat() {
+ if (attributes_.alpha_size > 0)
+ return GL_RGBA;
+ DCHECK_NE(attributes_.red_size, 0);
+ DCHECK_NE(attributes_.green_size, 0);
+ DCHECK_NE(attributes_.blue_size, 0);
+ return GL_RGB;
+}
+
+void VizProcessContextProvider::SetUpdateVSyncParametersCallback(
+ const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback&
+ callback) {
+ context_->SetUpdateVSyncParametersCallback(callback);
+}
+
+} // namespace viz
diff --git a/chromium/components/viz/service/display_embedder/viz_process_context_provider.h b/chromium/components/viz/service/display_embedder/viz_process_context_provider.h
new file mode 100644
index 00000000000..a25423e16fe
--- /dev/null
+++ b/chromium/components/viz/service/display_embedder/viz_process_context_provider.h
@@ -0,0 +1,87 @@
+// Copyright 2016 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 COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_VIZ_PROCESS_CONTEXT_PROVIDER_H_
+#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_VIZ_PROCESS_CONTEXT_PROVIDER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/compiler_specific.h"
+#include "base/synchronization/lock.h"
+#include "components/viz/common/gpu/context_cache_controller.h"
+#include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/service/viz_service_export.h"
+#include "gpu/command_buffer/common/context_creation_attribs.h"
+#include "gpu/ipc/in_process_command_buffer.h"
+#include "ui/gfx/native_widget_types.h"
+
+class GrContext;
+
+namespace gpu {
+class GLInProcessContext;
+class GpuChannelManagerDelegate;
+class GpuMemoryBufferManager;
+class ImageFactory;
+struct SharedMemoryLimits;
+} // namespace gpu
+
+namespace skia_bindings {
+class GrContextForGLES2Interface;
+}
+
+namespace viz {
+
+// A ContextProvider used in the viz process to setup an InProcessCommandBuffer
+// for the display compositor.
+class VIZ_SERVICE_EXPORT VizProcessContextProvider
+ : public base::RefCountedThreadSafe<VizProcessContextProvider>,
+ public ContextProvider {
+ public:
+ VizProcessContextProvider(
+ scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
+ gpu::SurfaceHandle surface_handle,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ gpu::ImageFactory* image_factory,
+ gpu::GpuChannelManagerDelegate* gpu_channel_manager_delegate,
+ const gpu::SharedMemoryLimits& limits);
+
+ // ContextProvider implementation.
+ void AddRef() const override;
+ void Release() const override;
+ gpu::ContextResult BindToCurrentThread() override;
+ gpu::gles2::GLES2Interface* ContextGL() override;
+ gpu::ContextSupport* ContextSupport() override;
+ class GrContext* GrContext() override;
+ ContextCacheController* CacheController() override;
+ base::Lock* GetLock() override;
+ const gpu::Capabilities& ContextCapabilities() const override;
+ const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override;
+ void AddObserver(ContextLostObserver* obs) override;
+ void RemoveObserver(ContextLostObserver* obs) override;
+
+ uint32_t GetCopyTextureInternalFormat();
+
+ void SetUpdateVSyncParametersCallback(
+ const gpu::InProcessCommandBuffer::UpdateVSyncParametersCallback&
+ callback);
+
+ protected:
+ friend class base::RefCountedThreadSafe<VizProcessContextProvider>;
+ ~VizProcessContextProvider() override;
+
+ private:
+ const gpu::ContextCreationAttribs attributes_;
+
+ base::Lock context_lock_;
+ std::unique_ptr<gpu::GLInProcessContext> context_;
+ gpu::ContextResult context_result_;
+ std::unique_ptr<skia_bindings::GrContextForGLES2Interface> gr_context_;
+ std::unique_ptr<ContextCacheController> cache_controller_;
+};
+
+} // namespace viz
+
+#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_VIZ_PROCESS_CONTEXT_PROVIDER_H_
diff --git a/chromium/components/viz/service/frame_sinks/DEPS b/chromium/components/viz/service/frame_sinks/DEPS
index 90500834623..5d7cb869719 100644
--- a/chromium/components/viz/service/frame_sinks/DEPS
+++ b/chromium/components/viz/service/frame_sinks/DEPS
@@ -2,7 +2,6 @@
include_rules = [
"+cc/base",
- "+cc/ipc",
"+cc/scheduler",
"+components/viz/service/display",
"+components/viz/service/display_embedder",
@@ -11,3 +10,9 @@ include_rules = [
"+gpu/ipc/common",
"+mojo/public",
]
+
+specific_include_rules = {
+ ".*unittest\.cc": [
+ "+third_party/khronos/GLES2",
+ ]
+}
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
index 052ac635cd0..b086112b6b0 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
@@ -41,10 +41,33 @@ void CompositorFrameSinkImpl::SetWantsAnimateOnlyBeginFrames() {
void CompositorFrameSinkImpl::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
+ base::Optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
+ SubmitCompositorFrameInternal(local_surface_id, std::move(frame),
+ std::move(hit_test_region_list), submit_time,
+ SubmitCompositorFrameSyncCallback());
+}
+
+void CompositorFrameSinkImpl::SubmitCompositorFrameSync(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ SubmitCompositorFrameSyncCallback callback) {
+ SubmitCompositorFrameInternal(local_surface_id, std::move(frame),
+ std::move(hit_test_region_list), submit_time,
+ std::move(callback));
+}
+
+void CompositorFrameSinkImpl::SubmitCompositorFrameInternal(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback) {
const auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ local_surface_id, std::move(frame), std::move(hit_test_region_list),
+ std::move(callback));
if (result == CompositorFrameSinkSupport::ACCEPTED)
return;
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
index a03e101cc88..b05aaea3d51 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_impl.h
@@ -30,16 +30,30 @@ class CompositorFrameSinkImpl : public mojom::CompositorFrameSink {
// mojom::CompositorFrameSink:
void SetNeedsBeginFrame(bool needs_begin_frame) override;
void SetWantsAnimateOnlyBeginFrames() override;
- void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
- CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
- uint64_t submit_time) override;
+ void SubmitCompositorFrame(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time) override;
+ void SubmitCompositorFrameSync(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ SubmitCompositorFrameSyncCallback callback) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id) override;
void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
private:
+ void SubmitCompositorFrameInternal(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback);
+
void OnClientConnectionLost();
mojom::CompositorFrameSinkClientPtr compositor_frame_sink_client_;
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index 4d98fd2eaf2..44baa1dae5e 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -44,6 +44,8 @@ CompositorFrameSinkSupport::~CompositorFrameSinkSupport() {
// Unregister |this| as a BeginFrameObserver so that the
// BeginFrameSource does not call into |this| after it's deleted.
+ callback_received_begin_frame_ = true;
+ callback_received_receive_ack_ = true;
SetNeedsBeginFrame(false);
// For display root surfaces the surface is no longer going to be visible.
@@ -207,7 +209,7 @@ void CompositorFrameSinkSupport::EvictLastActivatedSurface() {
}
void CompositorFrameSinkSupport::SetNeedsBeginFrame(bool needs_begin_frame) {
- needs_begin_frame_ = needs_begin_frame;
+ client_needs_begin_frame_ = needs_begin_frame;
UpdateNeedsBeginFramesInternal();
}
@@ -239,10 +241,11 @@ void CompositorFrameSinkSupport::DidNotProduceFrame(const BeginFrameAck& ack) {
void CompositorFrameSinkSupport::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
+ base::Optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
const auto result = MaybeSubmitCompositorFrame(
- local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ local_surface_id, std::move(frame), std::move(hit_test_region_list),
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
DCHECK_EQ(result, ACCEPTED);
}
@@ -267,13 +270,24 @@ CompositorFrameSinkSupport::SubmitResult
CompositorFrameSinkSupport::MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback callback) {
TRACE_EVENT1("viz", "CompositorFrameSinkSupport::MaybeSubmitCompositorFrame",
"FrameSinkId", frame_sink_id_.ToString());
DCHECK(local_surface_id.is_valid());
DCHECK(!frame.render_pass_list.empty());
DCHECK(!frame.size_in_pixels().IsEmpty());
+ CHECK(callback_received_begin_frame_);
+ CHECK(callback_received_receive_ack_);
+
+ compositor_frame_callback_ = std::move(callback);
+ if (compositor_frame_callback_) {
+ callback_received_begin_frame_ = false;
+ callback_received_receive_ack_ = false;
+ UpdateNeedsBeginFramesInternal();
+ }
+
// Ensure no CopyOutputRequests have been submitted if they are banned.
if (!allow_copy_output_requests_ && frame.HasCopyOutputRequests()) {
TRACE_EVENT_INSTANT0("viz", "CopyOutputRequests not allowed",
@@ -296,7 +310,7 @@ CompositorFrameSinkSupport::MaybeSubmitCompositorFrame(
for (ui::LatencyInfo& latency : frame.metadata.latency_info) {
if (latency.latency_components().size() > 0) {
latency.AddLatencyNumber(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
- 0, 0);
+ 0);
}
}
@@ -422,12 +436,31 @@ SurfaceReference CompositorFrameSinkSupport::MakeTopLevelRootReference(
return SurfaceReference(surface_manager_->GetRootSurfaceId(), surface_id);
}
+void CompositorFrameSinkSupport::HandleCallback() {
+ if (!compositor_frame_callback_ || !callback_received_begin_frame_ ||
+ !callback_received_receive_ack_) {
+ return;
+ }
+
+ std::move(compositor_frame_callback_)
+ .Run(std::move(surface_returned_resources_));
+ surface_returned_resources_.clear();
+}
+
void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
DCHECK_GT(ack_pending_count_, 0);
ack_pending_count_--;
if (!client_)
return;
+ // If we have a callback, we only return the resource on onBeginFrame.
+ if (compositor_frame_callback_) {
+ callback_received_receive_ack_ = true;
+ UpdateNeedsBeginFramesInternal();
+ HandleCallback();
+ return;
+ }
+
client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
surface_returned_resources_.clear();
}
@@ -449,11 +482,17 @@ void CompositorFrameSinkSupport::DidPresentCompositorFrame(
}
void CompositorFrameSinkSupport::OnBeginFrame(const BeginFrameArgs& args) {
- UpdateNeedsBeginFramesInternal();
if (last_activated_surface_id_.is_valid())
surface_manager_->SurfaceDamageExpected(last_activated_surface_id_, args);
last_begin_frame_args_ = args;
- if (client_)
+
+ if (compositor_frame_callback_) {
+ callback_received_begin_frame_ = true;
+ UpdateNeedsBeginFramesInternal();
+ HandleCallback();
+ }
+
+ if (client_ && client_needs_begin_frame_)
client_->OnBeginFrame(args);
}
@@ -471,11 +510,17 @@ void CompositorFrameSinkSupport::UpdateNeedsBeginFramesInternal() {
if (!begin_frame_source_)
return;
- if (needs_begin_frame_ == added_frame_observer_)
+ // We require a begin frame if there's a callback pending, or if the client
+ // requested it.
+ bool needs_begin_frame =
+ client_needs_begin_frame_ ||
+ (compositor_frame_callback_ && !callback_received_begin_frame_);
+
+ if (needs_begin_frame == added_frame_observer_)
return;
- added_frame_observer_ = needs_begin_frame_;
- if (needs_begin_frame_)
+ added_frame_observer_ = needs_begin_frame;
+ if (needs_begin_frame)
begin_frame_source_->AddObserver(this);
else
begin_frame_source_->RemoveObserver(this);
@@ -507,6 +552,7 @@ gfx::Size CompositorFrameSinkSupport::GetActiveFrameSize() {
if (last_activated_surface_id_.is_valid()) {
Surface* current_surface =
surface_manager_->GetSurfaceForId(last_activated_surface_id_);
+ DCHECK(current_surface);
if (current_surface->HasActiveFrame()) {
DCHECK(current_surface->GetActiveFrame().size_in_pixels() ==
current_surface->size_in_pixels());
@@ -528,6 +574,16 @@ void CompositorFrameSinkSupport::RequestCopyOfOutput(
}
}
+const CompositorFrameMetadata*
+CompositorFrameSinkSupport::GetLastActivatedFrameMetadata() {
+ if (!last_activated_surface_id_.is_valid())
+ return nullptr;
+ Surface* surface =
+ surface_manager_->GetSurfaceForId(last_activated_surface_id_);
+ DCHECK(surface);
+ return &surface->GetActiveFrame().metadata;
+}
+
HitTestAggregator* CompositorFrameSinkSupport::GetHitTestAggregator() {
DCHECK(is_root_);
return hit_test_aggregator_.get();
@@ -554,11 +610,12 @@ const char* CompositorFrameSinkSupport::GetSubmitResultAsString(
void CompositorFrameSinkSupport::OnAggregatedDamage(
const LocalSurfaceId& local_surface_id,
- const gfx::Size& frame_size_in_pixels,
+ const CompositorFrame& frame,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time) const {
DCHECK(!damage_rect.IsEmpty());
+ const gfx::Size& frame_size_in_pixels = frame.size_in_pixels();
if (aggregated_damage_callback_) {
aggregated_damage_callback_.Run(local_surface_id, frame_size_in_pixels,
damage_rect, expected_display_time);
@@ -566,7 +623,7 @@ void CompositorFrameSinkSupport::OnAggregatedDamage(
for (CapturableFrameSink::Client* client : capture_clients_) {
client->OnFrameDamaged(frame_size_in_pixels, damage_rect,
- expected_display_time);
+ expected_display_time, frame.metadata);
}
}
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 863b4b8b998..8317b21c9e6 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/quads/compositor_frame.h"
@@ -110,7 +111,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
void SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list = nullptr,
+ base::Optional<HitTestRegionList> hit_test_region_list = base::nullopt,
uint64_t submit_time = 0);
// Returns false if the notification was not valid (a duplicate).
bool DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
@@ -130,7 +131,8 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
SubmitResult MaybeSubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list);
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback);
// CapturableFrameSink implementation.
void AttachCaptureClient(CapturableFrameSink::Client* client) override;
@@ -138,6 +140,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
gfx::Size GetActiveFrameSize() override;
void RequestCopyOfOutput(const LocalSurfaceId& local_surface_id,
std::unique_ptr<CopyOutputRequest> request) override;
+ const CompositorFrameMetadata* GetLastActivatedFrameMetadata() override;
HitTestAggregator* GetHitTestAggregator();
@@ -183,10 +186,14 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
Surface* CreateSurface(const SurfaceInfo& surface_info);
void OnAggregatedDamage(const LocalSurfaceId& local_surface_id,
- const gfx::Size& frame_size_in_pixels,
+ const CompositorFrame& frame,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time) const;
+ // For the sync API calls, if we are blocking a client callback, runs it once
+ // BeginFrame and FrameAck are done.
+ void HandleCallback();
+
mojom::CompositorFrameSinkClient* const client_;
FrameSinkManagerImpl* const frame_sink_manager_;
@@ -218,7 +225,7 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
BeginFrameArgs last_begin_frame_args_;
// Whether a request for begin frames has been issued.
- bool needs_begin_frame_ = false;
+ bool client_needs_begin_frame_ = false;
// Whether or not a frame observer has been added.
bool added_frame_observer_ = false;
@@ -263,6 +270,11 @@ class VIZ_SERVICE_EXPORT CompositorFrameSinkSupport
std::vector<std::pair<LocalSurfaceId, std::unique_ptr<CopyOutputRequest>>>
copy_output_requests_;
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback
+ compositor_frame_callback_;
+ bool callback_received_begin_frame_ = true;
+ bool callback_received_receive_ack_ = true;
+
base::WeakPtrFactory<CompositorFrameSinkSupport> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CompositorFrameSinkSupport);
diff --git a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index f9d67412f48..9852c9b2f18 100644
--- a/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -5,7 +5,6 @@
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "base/macros.h"
-#include "cc/resources/resource_provider.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_result.h"
#include "components/viz/common/quads/compositor_frame.h"
@@ -23,6 +22,7 @@
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/khronos/GLES2/gl2.h"
using testing::UnorderedElementsAre;
using testing::IsEmpty;
@@ -70,13 +70,7 @@ class MockFrameSinkManagerClient : public mojom::FrameSinkManagerClient {
MOCK_METHOD1(OnFirstSurfaceActivation, void(const SurfaceInfo&));
void OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_sizes) override {}
- void SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) override {}
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) override {}
void OnFrameTokenChanged(const FrameSinkId& frame_sink_id,
uint32_t frame_token) override {}
@@ -130,7 +124,8 @@ class CompositorFrameSinkSupportTest : public testing::Test {
auto frame = MakeDefaultCompositorFrame();
frame.render_pass_list.back()->copy_requests.push_back(std::move(request));
const auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), nullptr);
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
switch (result) {
case CompositorFrameSinkSupport::ACCEPTED:
return true;
@@ -540,22 +535,28 @@ TEST_F(CompositorFrameSinkSupportTest, MonotonicallyIncreasingLocalSurfaceIds) {
LocalSurfaceId local_surface_id5(8, 1, kArbitraryToken);
LocalSurfaceId local_surface_id6(9, 3, kArbitraryToken);
auto result = support->MaybeSubmitCompositorFrame(
- local_surface_id1, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id1, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
result = support->MaybeSubmitCompositorFrame(
- local_surface_id2, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id2, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
result = support->MaybeSubmitCompositorFrame(
- local_surface_id3, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id3, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
result = support->MaybeSubmitCompositorFrame(
- local_surface_id4, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id4, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
result = support->MaybeSubmitCompositorFrame(
- local_surface_id5, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id5, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
result = support->MaybeSubmitCompositorFrame(
- local_surface_id6, MakeDefaultCompositorFrame(), nullptr);
+ local_surface_id6, MakeDefaultCompositorFrame(), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
manager_.InvalidateFrameSinkId(kAnotherArbitraryFrameSinkId);
@@ -775,7 +776,8 @@ TEST_F(CompositorFrameSinkSupportTest, ZeroDeviceScaleFactor) {
.SetDeviceScaleFactor(0.f)
.Build();
const auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id_, std::move(frame), nullptr);
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
EXPECT_FALSE(GetSurfaceForId(id));
}
@@ -789,8 +791,9 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
auto frame = CompositorFrameBuilder()
.AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
.Build();
- auto result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
- std::move(frame), nullptr);
+ auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
@@ -799,8 +802,9 @@ TEST_F(CompositorFrameSinkSupportTest, FrameSizeMismatch) {
frame = CompositorFrameBuilder()
.AddRenderPass(gfx::Rect(5, 4), gfx::Rect())
.Build();
- result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
- std::move(frame), nullptr);
+ result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
}
@@ -815,8 +819,9 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.AddDefaultRenderPass()
.SetDeviceScaleFactor(0.5f)
.Build();
- auto result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
- std::move(frame), nullptr);
+ auto result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::ACCEPTED, result);
EXPECT_TRUE(GetSurfaceForId(id));
@@ -826,8 +831,9 @@ TEST_F(CompositorFrameSinkSupportTest, DeviceScaleFactorMismatch) {
.AddDefaultRenderPass()
.SetDeviceScaleFactor(0.4f)
.Build();
- result = support_->MaybeSubmitCompositorFrame(local_surface_id_,
- std::move(frame), nullptr);
+ result = support_->MaybeSubmitCompositorFrame(
+ local_surface_id_, std::move(frame), base::nullopt,
+ mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
EXPECT_EQ(CompositorFrameSinkSupport::SURFACE_INVARIANTS_VIOLATION, result);
}
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
index 56be759068b..ed6ac7abfaf 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "cc/trees/layer_tree_frame_sink_client.h"
+#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
@@ -30,13 +31,11 @@ DirectLayerTreeFrameSink::DirectLayerTreeFrameSink(
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- SharedBitmapManager* shared_bitmap_manager,
bool use_viz_hit_test)
: LayerTreeFrameSink(std::move(context_provider),
std::move(worker_context_provider),
std::move(compositor_task_runner),
- gpu_memory_buffer_manager,
- shared_bitmap_manager),
+ gpu_memory_buffer_manager),
frame_sink_id_(frame_sink_id),
support_manager_(support_manager),
frame_sink_manager_(frame_sink_manager),
@@ -90,23 +89,79 @@ void DirectLayerTreeFrameSink::DetachFromClient() {
cc::LayerTreeFrameSink::DetachFromClient();
}
+static HitTestRegionList CreateHitTestData(const CompositorFrame& frame) {
+ HitTestRegionList hit_test_region_list;
+ hit_test_region_list.flags = HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestMine;
+ hit_test_region_list.bounds.set_size(frame.size_in_pixels());
+
+ for (const auto& render_pass : frame.render_pass_list) {
+ // Skip the render_pass if the transform is not invertible (i.e. it will not
+ // be able to receive events).
+ gfx::Transform transform_from_root_target;
+ if (!render_pass->transform_to_root_target.GetInverse(
+ &transform_from_root_target)) {
+ continue;
+ }
+
+ for (const DrawQuad* quad : render_pass->quad_list) {
+ if (quad->material == DrawQuad::SURFACE_CONTENT) {
+ const SurfaceDrawQuad* surface_quad =
+ SurfaceDrawQuad::MaterialCast(quad);
+
+ // Skip the quad if the FrameSinkId between fallback and primary is not
+ // the same, because we don't know which FrameSinkId would be used to
+ // draw this quad.
+ if (surface_quad->fallback_surface_id.has_value() &&
+ surface_quad->fallback_surface_id->frame_sink_id() !=
+ surface_quad->primary_surface_id.frame_sink_id()) {
+ continue;
+ }
+
+ // Skip the quad if the transform is not invertible (i.e. it will not
+ // be able to receive events).
+ gfx::Transform target_to_quad_transform;
+ if (!quad->shared_quad_state->quad_to_target_transform.GetInverse(
+ &target_to_quad_transform)) {
+ continue;
+ }
+
+ hit_test_region_list.regions.emplace_back();
+ HitTestRegion* hit_test_region = &hit_test_region_list.regions.back();
+ hit_test_region->frame_sink_id =
+ surface_quad->primary_surface_id.frame_sink_id();
+ hit_test_region->flags = HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestChildSurface;
+ hit_test_region->rect = surface_quad->rect;
+ hit_test_region->transform =
+ target_to_quad_transform * transform_from_root_target;
+ }
+ }
+ }
+ return hit_test_region_list;
+}
+
void DirectLayerTreeFrameSink::SubmitCompositorFrame(CompositorFrame frame) {
DCHECK(frame.metadata.begin_frame_ack.has_damage);
DCHECK_LE(BeginFrameArgs::kStartingFrameNumber,
frame.metadata.begin_frame_ack.sequence_number);
- if (!local_surface_id_.is_valid() ||
- frame.size_in_pixels() != last_swap_frame_size_ ||
+ if (frame.size_in_pixels() != last_swap_frame_size_ ||
frame.device_scale_factor() != device_scale_factor_) {
- local_surface_id_ = parent_local_surface_id_allocator_.GenerateId();
+ parent_local_surface_id_allocator_.GenerateId();
last_swap_frame_size_ = frame.size_in_pixels();
device_scale_factor_ = frame.device_scale_factor();
- display_->SetLocalSurfaceId(local_surface_id_, device_scale_factor_);
+ display_->SetLocalSurfaceId(
+ parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ device_scale_factor_);
}
- auto hit_test_region_list = CreateHitTestData(frame);
- support_->SubmitCompositorFrame(local_surface_id_, std::move(frame),
- std::move(hit_test_region_list));
+ HitTestRegionList hit_test_region_list = CreateHitTestData(frame);
+ support_->SubmitCompositorFrame(
+ parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId(),
+ std::move(frame), std::move(hit_test_region_list));
}
void DirectLayerTreeFrameSink::DidNotProduceFrame(const BeginFrameAck& ack) {
@@ -153,6 +208,12 @@ void DirectLayerTreeFrameSink::DisplayDidReceiveCALayerParams(
display_client_->OnDisplayReceivedCALayerParams(ca_layer_params);
}
+void DirectLayerTreeFrameSink::DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ // TODO(samans): Implement this method once the plumbing for latency info also
+ // works for non-OOP-D.
+}
+
void DirectLayerTreeFrameSink::DidReceiveCompositorFrameAck(
const std::vector<ReturnedResource>& resources) {
// Submitting a CompositorFrame can synchronously draw and dispatch a frame
@@ -204,57 +265,4 @@ void DirectLayerTreeFrameSink::OnContextLost() {
// The display will be listening for OnContextLost(). Do nothing here.
}
-mojom::HitTestRegionListPtr DirectLayerTreeFrameSink::CreateHitTestData(
- const CompositorFrame& frame) const {
- auto hit_test_region_list = mojom::HitTestRegionList::New();
- hit_test_region_list->flags =
- mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine;
- hit_test_region_list->bounds.set_size(frame.size_in_pixels());
-
- for (const auto& render_pass : frame.render_pass_list) {
- // Skip the render_pass if the transform is not invertible (i.e. it will not
- // be able to receive events).
- gfx::Transform transform_from_root_target;
- if (!render_pass->transform_to_root_target.GetInverse(
- &transform_from_root_target)) {
- continue;
- }
-
- for (const DrawQuad* quad : render_pass->quad_list) {
- if (quad->material == DrawQuad::SURFACE_CONTENT) {
- const SurfaceDrawQuad* surface_quad =
- SurfaceDrawQuad::MaterialCast(quad);
-
- // Skip the quad if the FrameSinkId between fallback and primary is not
- // the same, because we don't know which FrameSinkId would be used to
- // draw this quad.
- if (surface_quad->fallback_surface_id.has_value() &&
- surface_quad->fallback_surface_id->frame_sink_id() !=
- surface_quad->primary_surface_id.frame_sink_id()) {
- continue;
- }
-
- // Skip the quad if the transform is not invertible (i.e. it will not
- // be able to receive events).
- gfx::Transform target_to_quad_transform;
- if (!quad->shared_quad_state->quad_to_target_transform.GetInverse(
- &target_to_quad_transform)) {
- continue;
- }
-
- auto hit_test_region = mojom::HitTestRegion::New();
- hit_test_region->frame_sink_id =
- surface_quad->primary_surface_id.frame_sink_id();
- hit_test_region->flags = mojom::kHitTestMouse | mojom::kHitTestTouch |
- mojom::kHitTestChildSurface;
- hit_test_region->rect = surface_quad->rect;
- hit_test_region->transform =
- target_to_quad_transform * transform_from_root_target;
- hit_test_region_list->regions.push_back(std::move(hit_test_region));
- }
- }
- }
- return hit_test_region_list;
-}
-
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
index 1bdfcf37560..a37812702df 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink.h
@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_SERVICE_FRAME_SINKS_DIRECT_LAYER_TREE_FRAME_SINK_H_
#include "base/macros.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "cc/trees/layer_tree_frame_sink.h"
#include "components/viz/common/frame_sinks/begin_frame_source.h"
@@ -16,14 +17,10 @@
#include "services/viz/privileged/interfaces/compositing/display_private.mojom.h"
#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
-namespace cc {
-class LocalSurfaceIdAllocator;
-class FrameSinkManagerImpl;
-} // namespace cc
-
namespace viz {
class CompositorFrameSinkSupportManager;
class Display;
+class FrameSinkManagerImpl;
// This class submits compositor frames to an in-process Display, with the
// client's frame being the root surface of the Display.
@@ -45,7 +42,6 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
scoped_refptr<RasterContextProvider> worker_context_provider,
scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
- SharedBitmapManager* shared_bitmap_manager,
bool use_viz_hit_test);
~DirectLayerTreeFrameSink() override;
@@ -65,6 +61,8 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
void DisplayDidDrawAndSwap() override;
void DisplayDidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) override;
+ void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
private:
// mojom::CompositorFrameSinkClient implementation:
@@ -86,8 +84,6 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
// ContextLostObserver implementation:
void OnContextLost() override;
- mojom::HitTestRegionListPtr CreateHitTestData(
- const CompositorFrame& frame) const;
void DidReceiveCompositorFrameAckInternal(
const std::vector<ReturnedResource>& resources);
@@ -97,7 +93,6 @@ class VIZ_SERVICE_EXPORT DirectLayerTreeFrameSink
std::unique_ptr<CompositorFrameSinkSupport> support_;
const FrameSinkId frame_sink_id_;
- LocalSurfaceId local_surface_id_;
CompositorFrameSinkSupportManager* const support_manager_;
FrameSinkManagerImpl* frame_sink_manager_;
ParentLocalSurfaceIdAllocator parent_local_surface_id_allocator_;
diff --git a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
index 2ab44fe66c1..26f1c30b484 100644
--- a/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/direct_layer_tree_frame_sink_unittest.cc
@@ -86,7 +86,7 @@ class DirectLayerTreeFrameSinkTest : public testing::Test {
layer_tree_frame_sink_ = std::make_unique<TestDirectLayerTreeFrameSink>(
kArbitraryFrameSinkId, &support_manager_, &frame_sink_manager_,
display_.get(), nullptr /* display_client */, context_provider_,
- nullptr, task_runner_, &gpu_memory_buffer_manager_, &bitmap_manager_,
+ nullptr, task_runner_, &gpu_memory_buffer_manager_,
false /* use_viz_hit_test */);
layer_tree_frame_sink_->BindToClient(&layer_tree_frame_sink_client_);
display_->Resize(display_size_);
@@ -157,21 +157,6 @@ TEST_F(DirectLayerTreeFrameSinkTest, NoDamageDoesNotTriggerSwapBuffers) {
EXPECT_EQ(1u, display_output_surface_->num_sent_frames());
}
-TEST_F(DirectLayerTreeFrameSinkTest, SuspendedDoesNotTriggerSwapBuffers) {
- SwapBuffersWithDamage(display_rect_);
- EXPECT_EQ(1u, display_output_surface_->num_sent_frames());
- display_output_surface_->set_suspended_for_recycle(true);
- task_runner_->RunUntilIdle();
- EXPECT_EQ(1u, display_output_surface_->num_sent_frames());
- SwapBuffersWithDamage(display_rect_);
- task_runner_->RunUntilIdle();
- EXPECT_EQ(1u, display_output_surface_->num_sent_frames());
- display_output_surface_->set_suspended_for_recycle(false);
- SwapBuffersWithDamage(display_rect_);
- task_runner_->RunUntilIdle();
- EXPECT_EQ(2u, display_output_surface_->num_sent_frames());
-}
-
// Test that hit_test_region_list are created correctly for the browser.
TEST_F(DirectLayerTreeFrameSinkTest, HitTestRegionList) {
RenderPassList pass_list;
@@ -200,7 +185,9 @@ TEST_F(DirectLayerTreeFrameSinkTest, HitTestRegionList) {
display_.get(), display_->CurrentSurfaceId().frame_sink_id());
EXPECT_TRUE(hit_test_region_list);
EXPECT_EQ(display_rect_, hit_test_region_list->bounds);
- EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestMine,
hit_test_region_list->flags);
EXPECT_FALSE(hit_test_region_list->regions.size());
@@ -276,18 +263,21 @@ TEST_F(DirectLayerTreeFrameSinkTest, HitTestRegionList) {
display_.get(), display_->CurrentSurfaceId().frame_sink_id());
EXPECT_TRUE(hit_test_region_list1);
EXPECT_EQ(display_rect_, hit_test_region_list1->bounds);
- EXPECT_EQ(mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestMine,
+ EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestMine,
hit_test_region_list1->flags);
EXPECT_EQ(1u, hit_test_region_list1->regions.size());
EXPECT_EQ(child_surface_id.frame_sink_id(),
- hit_test_region_list1->regions[0]->frame_sink_id);
- EXPECT_EQ(
- mojom::kHitTestMouse | mojom::kHitTestTouch | mojom::kHitTestChildSurface,
- hit_test_region_list1->regions[0]->flags);
- EXPECT_EQ(gfx::Rect(20, 20), hit_test_region_list1->regions[0]->rect);
+ hit_test_region_list1->regions[0].frame_sink_id);
+ EXPECT_EQ(HitTestRegionFlags::kHitTestMouse |
+ HitTestRegionFlags::kHitTestTouch |
+ HitTestRegionFlags::kHitTestChildSurface,
+ hit_test_region_list1->regions[0].flags);
+ EXPECT_EQ(gfx::Rect(20, 20), hit_test_region_list1->regions[0].rect);
gfx::Transform transform2_inverse;
EXPECT_TRUE(transform2.GetInverse(&transform2_inverse));
- EXPECT_EQ(transform2_inverse, hit_test_region_list1->regions[0]->transform);
+ EXPECT_EQ(transform2_inverse, hit_test_region_list1->regions[0].transform);
}
} // namespace
diff --git a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
index ac084ea4666..bb147945b45 100644
--- a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
@@ -144,11 +144,13 @@ void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
std::move(params->external_begin_frame_controller_client)));
}
+ mojom::DisplayClientPtr display_client(std::move(params->display_client));
+
std::unique_ptr<SyntheticBeginFrameSource> begin_frame_source;
auto display = display_provider_->CreateDisplay(
params->frame_sink_id, params->widget, params->gpu_compositing,
- external_begin_frame_controller.get(), params->renderer_settings,
- &begin_frame_source);
+ display_client.get(), external_begin_frame_controller.get(),
+ params->renderer_settings, &begin_frame_source);
// Creating display failed. Drop the CompositorFrameSink message pipes here
// and let host send a new request, potential with a different compositing
@@ -164,8 +166,7 @@ void FrameSinkManagerImpl::CreateRootCompositorFrameSink(
std::move(params->compositor_frame_sink),
mojom::CompositorFrameSinkClientPtr(
std::move(params->compositor_frame_sink_client)),
- std::move(params->display_private),
- mojom::DisplayClientPtr(std::move(params->display_client)));
+ std::move(params->display_private), std::move(display_client));
}
void FrameSinkManagerImpl::CreateCompositorFrameSink(
@@ -352,25 +353,10 @@ void FrameSinkManagerImpl::OnSurfaceDamageExpected(const SurfaceId& surface_id,
void FrameSinkManagerImpl::OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (client_) {
- client_->OnAggregatedHitTestRegionListUpdated(
- frame_sink_id, std::move(active_handle), active_handle_size,
- std::move(idle_handle), idle_handle_size);
- }
-}
-
-void FrameSinkManagerImpl::SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) {
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (client_) {
- client_->SwitchActiveAggregatedHitTestRegionList(frame_sink_id,
- active_handle_index);
+ client_->OnAggregatedHitTestRegionListUpdated(frame_sink_id, hit_test_data);
}
}
@@ -526,7 +512,7 @@ bool FrameSinkManagerImpl::ChildContains(
void FrameSinkManagerImpl::SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
- mojom::HitTestRegionListPtr hit_test_region_list) {
+ base::Optional<HitTestRegionList> hit_test_region_list) {
hit_test_manager_.SubmitHitTestRegionList(surface_id, frame_index,
std::move(hit_test_region_list));
}
diff --git a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
index e4821698459..7f2352e9367 100644
--- a/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
+++ b/chromium/components/viz/service/frame_sinks/frame_sink_manager_impl.h
@@ -16,6 +16,8 @@
#include "base/containers/unique_ptr_adapters.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/optional.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "components/viz/common/constants.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
@@ -112,13 +114,7 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
// HitTestAggregatorDelegate implementation:
void OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) override;
- void SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) override;
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) override;
// CompositorFrameSinkSupport, hierarchy, and BeginFrameSource can be
// registered and unregistered in any order with respect to each other.
@@ -152,7 +148,7 @@ class VIZ_SERVICE_EXPORT FrameSinkManagerImpl
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
uint64_t frame_index,
- mojom::HitTestRegionListPtr hit_test_region_list);
+ base::Optional<HitTestRegionList> hit_test_region_list);
// Instantiates |video_detector_| for tests where we simulate the passage of
// time.
diff --git a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index 731741e3bec..654022b75a3 100644
--- a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -103,7 +103,7 @@ void RootCompositorFrameSinkImpl::SetWantsAnimateOnlyBeginFrames() {
void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
const LocalSurfaceId& local_surface_id,
CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
+ base::Optional<HitTestRegionList> hit_test_region_list,
uint64_t submit_time) {
// Update display when size or local surface id changes.
if (support_->last_activated_local_surface_id() != local_surface_id) {
@@ -112,7 +112,8 @@ void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
}
const auto result = support_->MaybeSubmitCompositorFrame(
- local_surface_id, std::move(frame), std::move(hit_test_region_list));
+ local_surface_id, std::move(frame), std::move(hit_test_region_list),
+ SubmitCompositorFrameSyncCallback());
if (result == CompositorFrameSinkSupport::ACCEPTED)
return;
@@ -125,6 +126,15 @@ void RootCompositorFrameSinkImpl::SubmitCompositorFrame(
OnClientConnectionLost();
}
+void RootCompositorFrameSinkImpl::SubmitCompositorFrameSync(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ SubmitCompositorFrameSyncCallback callback) {
+ NOTIMPLEMENTED();
+}
+
void RootCompositorFrameSinkImpl::DidNotProduceFrame(
const BeginFrameAck& begin_frame_ack) {
support_->DidNotProduceFrame(begin_frame_ack);
@@ -167,6 +177,11 @@ void RootCompositorFrameSinkImpl::DisplayDidReceiveCALayerParams(
display_client_->OnDisplayReceivedCALayerParams(ca_layer_params);
}
+void RootCompositorFrameSinkImpl::DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) {
+ display_client_->DidSwapAfterSnapshotRequestReceived(latency_info);
+}
+
void RootCompositorFrameSinkImpl::DisplayDidDrawAndSwap() {}
void RootCompositorFrameSinkImpl::OnClientConnectionLost() {
diff --git a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
index c5f72f85568..35295866214 100644
--- a/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
+++ b/chromium/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -55,14 +55,21 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
// mojom::CompositorFrameSink:
void SetNeedsBeginFrame(bool needs_begin_frame) override;
void SetWantsAnimateOnlyBeginFrames() override;
- void SubmitCompositorFrame(const LocalSurfaceId& local_surface_id,
- CompositorFrame frame,
- mojom::HitTestRegionListPtr hit_test_region_list,
- uint64_t submit_time) override;
+ void SubmitCompositorFrame(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time) override;
void DidNotProduceFrame(const BeginFrameAck& begin_frame_ack) override;
void DidAllocateSharedBitmap(mojo::ScopedSharedBufferHandle buffer,
const SharedBitmapId& id) override;
void DidDeleteSharedBitmap(const SharedBitmapId& id) override;
+ void SubmitCompositorFrameSync(
+ const LocalSurfaceId& local_surface_id,
+ CompositorFrame frame,
+ base::Optional<HitTestRegionList> hit_test_region_list,
+ uint64_t submit_time,
+ SubmitCompositorFrameSyncCallback callback) override;
private:
// DisplayClient:
@@ -72,6 +79,8 @@ class RootCompositorFrameSinkImpl : public mojom::CompositorFrameSink,
void DisplayDidDrawAndSwap() override;
void DisplayDidReceiveCALayerParams(
const gfx::CALayerParams& ca_layer_params) override;
+ void DidSwapAfterSnapshotRequestReceived(
+ const std::vector<ui::LatencyInfo>& latency_info) override;
void OnClientConnectionLost();
diff --git a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
index 860743d07bc..8b83cea05dd 100644
--- a/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -868,16 +868,14 @@ TEST_F(SurfaceSynchronizationTest, LimitLatencyInfo) {
const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
const ui::LatencyComponentType latency_type1 =
- ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+ ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT;
const int64_t latency_id1 = 234;
- const int64_t latency_sequence_number1 = 5645432;
const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
const int64_t latency_id2 = 31434351;
- const int64_t latency_sequence_number2 = 663788;
// Submit a frame with latency info
ui::LatencyInfo info;
- info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+ info.AddLatencyNumber(latency_type1, latency_id1);
CompositorFrameBuilder builder;
builder.AddDefaultRenderPass();
@@ -897,7 +895,7 @@ TEST_F(SurfaceSynchronizationTest, LimitLatencyInfo) {
// Submit another frame with some other latency info and a different
// LocalSurfaceId.
ui::LatencyInfo info2;
- info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+ info2.AddLatencyNumber(latency_type2, latency_id2);
builder.AddDefaultRenderPass();
for (int i = 0; i < 60; ++i)
@@ -927,16 +925,14 @@ TEST_F(SurfaceSynchronizationTest,
const SurfaceId parent_id1 = MakeSurfaceId(kParentFrameSink, 1);
const SurfaceId parent_id2 = MakeSurfaceId(kParentFrameSink, 2);
const ui::LatencyComponentType latency_type1 =
- ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT;
const int64_t latency_id1 = 234;
- const int64_t latency_sequence_number1 = 5645432;
const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
const int64_t latency_id2 = 31434351;
- const int64_t latency_sequence_number2 = 663788;
// Submit a frame with latency info
ui::LatencyInfo info;
- info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+ info.AddLatencyNumber(latency_type1, latency_id1);
CompositorFrame frame = CompositorFrameBuilder()
.AddDefaultRenderPass()
@@ -955,7 +951,7 @@ TEST_F(SurfaceSynchronizationTest,
// Submit another frame with some other latency info and a different
// LocalSurfaceId.
ui::LatencyInfo info2;
- info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+ info2.AddLatencyNumber(latency_type2, latency_id2);
CompositorFrame frame2 = CompositorFrameBuilder()
.AddDefaultRenderPass()
@@ -987,7 +983,6 @@ TEST_F(SurfaceSynchronizationTest,
ui::LatencyInfo::LatencyComponent comp1;
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
- EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
EXPECT_TRUE(aggregated_latency_info.FindLatency(
@@ -1004,16 +999,14 @@ TEST_F(SurfaceSynchronizationTest,
const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
const ui::LatencyComponentType latency_type1 =
- ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT;
const int64_t latency_id1 = 234;
- const int64_t latency_sequence_number1 = 5645432;
const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
const int64_t latency_id2 = 31434351;
- const int64_t latency_sequence_number2 = 663788;
// Submit a frame with no unresolved dependecy.
ui::LatencyInfo info;
- info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+ info.AddLatencyNumber(latency_type1, latency_id1);
CompositorFrame frame = MakeDefaultCompositorFrame();
frame.metadata.latency_info.push_back(info);
@@ -1023,7 +1016,7 @@ TEST_F(SurfaceSynchronizationTest,
// Submit a frame with unresolved dependencies.
ui::LatencyInfo info2;
- info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+ info2.AddLatencyNumber(latency_type2, latency_id2);
CompositorFrame frame2 = MakeCompositorFrame(
{child_id}, empty_surface_ids(), std::vector<TransferableResource>());
@@ -1065,7 +1058,6 @@ TEST_F(SurfaceSynchronizationTest,
ui::LatencyInfo::LatencyComponent comp1;
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
- EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
EXPECT_TRUE(aggregated_latency_info.FindLatency(
@@ -1082,16 +1074,14 @@ TEST_F(SurfaceSynchronizationTest,
const SurfaceId child_id = MakeSurfaceId(kChildFrameSink1, 1);
const ui::LatencyComponentType latency_type1 =
- ui::BROWSER_SNAPSHOT_FRAME_NUMBER_COMPONENT;
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT;
const int64_t latency_id1 = 234;
- const int64_t latency_sequence_number1 = 5645432;
const ui::LatencyComponentType latency_type2 = ui::TAB_SHOW_COMPONENT;
const int64_t latency_id2 = 31434351;
- const int64_t latency_sequence_number2 = 663788;
// Submit a frame with no unresolved dependencies.
ui::LatencyInfo info;
- info.AddLatencyNumber(latency_type1, latency_id1, latency_sequence_number1);
+ info.AddLatencyNumber(latency_type1, latency_id1);
CompositorFrame frame = MakeDefaultCompositorFrame();
frame.metadata.latency_info.push_back(info);
@@ -1108,7 +1098,7 @@ TEST_F(SurfaceSynchronizationTest,
// Submit a frame with a new local surface id and with unresolved
// dependencies.
ui::LatencyInfo info2;
- info2.AddLatencyNumber(latency_type2, latency_id2, latency_sequence_number2);
+ info2.AddLatencyNumber(latency_type2, latency_id2);
CompositorFrame frame2 = MakeCompositorFrame(
{child_id}, empty_surface_ids(), std::vector<TransferableResource>());
@@ -1146,7 +1136,6 @@ TEST_F(SurfaceSynchronizationTest,
ui::LatencyInfo::LatencyComponent comp1;
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type1, latency_id1, &comp1));
- EXPECT_EQ(latency_sequence_number1, comp1.sequence_number);
EXPECT_TRUE(
aggregated_latency_info.FindLatency(latency_type2, latency_id2, nullptr));
EXPECT_TRUE(aggregated_latency_info.FindLatency(
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/OWNERS b/chromium/components/viz/service/frame_sinks/video_capture/OWNERS
index 02bdb39030f..e837b5fcb0d 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/OWNERS
+++ b/chromium/components/viz/service/frame_sinks/video_capture/OWNERS
@@ -1 +1,3 @@
miu@chromium.org
+
+# COMPONENT: Internals>Media>ScreenCapture
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h b/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
index 908d2756891..ed9e14e507f 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h
@@ -16,6 +16,7 @@ class Rect;
namespace viz {
+class CompositorFrameMetadata;
class CopyOutputRequest;
class LocalSurfaceId;
@@ -35,9 +36,11 @@ class CapturableFrameSink {
// |damage_rect| being the region within that has changed (never empty).
// |expected_display_time| indicates when the content change was expected to
// appear on the Display.
- virtual void OnFrameDamaged(const gfx::Size& frame_size,
- const gfx::Rect& damage_rect,
- base::TimeTicks expected_display_time) = 0;
+ virtual void OnFrameDamaged(
+ const gfx::Size& frame_size,
+ const gfx::Rect& damage_rect,
+ base::TimeTicks expected_display_time,
+ const CompositorFrameMetadata& frame_metadata) = 0;
};
virtual ~CapturableFrameSink() = default;
@@ -59,6 +62,10 @@ class CapturableFrameSink {
virtual void RequestCopyOfOutput(
const LocalSurfaceId& local_surface_id,
std::unique_ptr<CopyOutputRequest> request) = 0;
+
+ // Returns the CompositorFrameMetadata of the last activated CompositorFrame.
+ // Return null if no CompositorFrame has activated yet.
+ virtual const CompositorFrameMetadata* GetLastActivatedFrameMetadata() = 0;
};
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
index c93861ff014..7a8c0af9c0d 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.cc
@@ -311,13 +311,15 @@ void FrameSinkVideoCapturerImpl::RefreshSoon() {
}
MaybeCaptureFrame(VideoCaptureOracle::kRefreshRequest,
- gfx::Rect(oracle_.source_size()), clock_->NowTicks());
+ gfx::Rect(oracle_.source_size()), clock_->NowTicks(),
+ *resolved_target_->GetLastActivatedFrameMetadata());
}
void FrameSinkVideoCapturerImpl::OnFrameDamaged(
const gfx::Size& frame_size,
const gfx::Rect& damage_rect,
- base::TimeTicks expected_display_time) {
+ base::TimeTicks expected_display_time,
+ const CompositorFrameMetadata& frame_metadata) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(!frame_size.IsEmpty());
DCHECK(!damage_rect.IsEmpty());
@@ -332,13 +334,14 @@ void FrameSinkVideoCapturerImpl::OnFrameDamaged(
}
MaybeCaptureFrame(VideoCaptureOracle::kCompositorUpdate, damage_rect,
- expected_display_time);
+ expected_display_time, frame_metadata);
}
void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
VideoCaptureOracle::Event event,
const gfx::Rect& damage_rect,
- base::TimeTicks event_time) {
+ base::TimeTicks event_time,
+ const CompositorFrameMetadata& frame_metadata) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(resolved_target_);
@@ -436,6 +439,14 @@ void FrameSinkVideoCapturerImpl::MaybeCaptureFrame(
metadata->SetDouble(VideoFrameMetadata::FRAME_RATE,
1.0 / oracle_.min_capture_period().InSecondsF());
metadata->SetTimeTicks(VideoFrameMetadata::REFERENCE_TIME, event_time);
+ metadata->SetDouble(VideoFrameMetadata::DEVICE_SCALE_FACTOR,
+ frame_metadata.device_scale_factor);
+ metadata->SetDouble(VideoFrameMetadata::PAGE_SCALE_FACTOR,
+ frame_metadata.page_scale_factor);
+ metadata->SetDouble(VideoFrameMetadata::ROOT_SCROLL_OFFSET_X,
+ frame_metadata.root_scroll_offset.x());
+ metadata->SetDouble(VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y,
+ frame_metadata.root_scroll_offset.y());
oracle_.RecordCapture(utilization);
const int64_t frame_number = next_capture_frame_number_++;
@@ -542,18 +553,11 @@ void FrameSinkVideoCapturerImpl::DidCopyFrame(
frame = nullptr;
}
} else {
- // TODO(samans): Avoid doing an extra copy by implementing a method similar
- // to ReadI420Planes() that copies directly from GPU memory into shared
- // memory. https://crbug.com/822264
+ int stride = frame->stride(VideoFrame::kARGBPlane);
DCHECK_EQ(media::PIXEL_FORMAT_ARGB, pixel_format_);
- const SkBitmap& bitmap = result->AsSkBitmap();
- if (bitmap.readyToDraw()) {
- SkImageInfo image_info = SkImageInfo::MakeN32(
- bitmap.width(), bitmap.height(), kPremul_SkAlphaType);
- const int stride = frame->stride(VideoFrame::kARGBPlane);
- uint8_t* const pixels = frame->visible_data(VideoFrame::kARGBPlane) +
- content_rect.y() * stride + content_rect.x() * 4;
- bitmap.readPixels(image_info, pixels, stride, 0, 0);
+ uint8_t* const pixels = frame->visible_data(VideoFrame::kARGBPlane) +
+ content_rect.y() * stride + content_rect.x() * 4;
+ if (result->ReadRGBAPlane(pixels, stride)) {
media::LetterboxVideoFrame(
frame.get(), gfx::Rect(content_rect.origin(),
AdjustSizeForPixelFormat(result->size())));
@@ -643,7 +647,6 @@ void FrameSinkVideoCapturerImpl::MaybeDeliverFrame(
info->timestamp = frame->timestamp();
info->metadata = frame->metadata()->GetInternalValues().Clone();
info->pixel_format = frame->format();
- info->storage_type = media::VideoPixelStorage::CPU;
info->coded_size = frame->coded_size();
info->visible_rect = frame->visible_rect();
const gfx::Rect update_rect = frame->visible_rect();
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
index 8dbfb0525ee..c1c552d4b51 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl.h
@@ -17,6 +17,8 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/unguessable_token.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/service/frame_sinks/video_capture/capturable_frame_sink.h"
#include "components/viz/service/frame_sinks/video_capture/in_flight_frame_delivery.h"
@@ -27,6 +29,7 @@
#include "mojo/public/cpp/bindings/binding.h"
#include "services/viz/privileged/interfaces/compositing/frame_sink_video_capture.mojom.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/vector2d_f.h"
namespace gfx {
class Size;
@@ -156,14 +159,16 @@ class VIZ_SERVICE_EXPORT FrameSinkVideoCapturerImpl final
// CapturableFrameSink::Client implementation:
void OnFrameDamaged(const gfx::Size& frame_size,
const gfx::Rect& damage_rect,
- base::TimeTicks target_display_time) final;
+ base::TimeTicks target_display_time,
+ const CompositorFrameMetadata& frame_metadata) final;
// Consults the VideoCaptureOracle to decide whether to capture a frame,
// then ensures prerequisites are met before initiating the capture: that
// there is a consumer present and that the pipeline is not already full.
void MaybeCaptureFrame(media::VideoCaptureOracle::Event event,
const gfx::Rect& damage_rect,
- base::TimeTicks event_time);
+ base::TimeTicks event_time,
+ const CompositorFrameMetadata& frame_metadata);
// Extracts the image data from the copy output |result|, populating the
// |content_rect| region of a [possibly letterboxed] video |frame|.
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
index e5efebcfac0..babe29ca1b1 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/frame_sink_video_capturer_impl_unittest.cc
@@ -39,6 +39,29 @@ using testing::Return;
namespace viz {
namespace {
+// Returns true if |frame|'s device scale factor, page scale factor and root
+// scroll offset are equal to the expected values.
+bool CompareVarsInCompositorFrameMetadata(
+ const VideoFrame& frame,
+ float device_scale_factor,
+ float page_scale_factor,
+ const gfx::Vector2dF& root_scroll_offset) {
+ double dsf, psf, rso_x, rso_y;
+ bool valid = true;
+
+ valid &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::DEVICE_SCALE_FACTOR, &dsf);
+ valid &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::PAGE_SCALE_FACTOR, &psf);
+ valid &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_X, &rso_x);
+ valid &= frame.metadata()->GetDouble(
+ media::VideoFrameMetadata::ROOT_SCROLL_OFFSET_Y, &rso_y);
+
+ return valid && dsf == device_scale_factor && psf == page_scale_factor &&
+ gfx::Vector2dF(rso_x, rso_y) == root_scroll_offset;
+}
+
// Dummy frame sink ID.
constexpr FrameSinkId kFrameSinkId = FrameSinkId(1, 1);
@@ -52,6 +75,10 @@ constexpr gfx::Size kSourceSize = gfx::Size(100, 100);
// The size of the VideoFrames produced by the capturer.
constexpr gfx::Size kCaptureSize = gfx::Size(32, 18);
+constexpr float kDefaultDeviceScaleFactor = 1.f;
+constexpr float kDefaultPageScaleFactor = 1.f;
+constexpr gfx::Vector2dF kDefaultRootScrollOffset = gfx::Vector2dF(0, 0);
+
// The location of the letterboxed content within each VideoFrame. All pixels
// outside of this region should be black.
constexpr gfx::Rect kContentRect = gfx::Rect(6, 0, 18, 18);
@@ -182,6 +209,12 @@ class SolidColorI420Result : public CopyOutputResult {
class FakeCapturableFrameSink : public CapturableFrameSink {
public:
+ FakeCapturableFrameSink() {
+ metadata_.root_scroll_offset = kDefaultRootScrollOffset;
+ metadata_.page_scale_factor = kDefaultPageScaleFactor;
+ metadata_.device_scale_factor = kDefaultDeviceScaleFactor;
+ }
+
Client* attached_client() const { return client_; }
void AttachCaptureClient(Client* client) override {
@@ -216,6 +249,14 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
std::move(request), std::move(result)));
}
+ const CompositorFrameMetadata* GetLastActivatedFrameMetadata() override {
+ return &metadata_;
+ }
+
+ void set_metadata(const CompositorFrameMetadata& metadata) {
+ metadata_ = metadata.Clone();
+ }
+
void SetCopyOutputColor(YUVColor color) { color_ = color; }
int num_copy_results() const { return results_.size(); }
@@ -229,6 +270,7 @@ class FakeCapturableFrameSink : public CapturableFrameSink {
private:
CapturableFrameSink::Client* client_ = nullptr;
YUVColor color_ = {0xde, 0xad, 0xbf};
+ CompositorFrameMetadata metadata_;
std::vector<base::OnceClosure> results_;
};
@@ -335,9 +377,20 @@ class FrameSinkVideoCapturerTest : public testing::Test {
task_runner_->FastForwardBy(GetNextVsync() - task_runner_->NowTicks());
}
- void NotifyFrameDamaged() {
+ void NotifyFrameDamaged(
+ float device_scale_factor = kDefaultDeviceScaleFactor,
+ float page_scale_factor = kDefaultPageScaleFactor,
+ gfx::Vector2dF root_scroll_offset = kDefaultRootScrollOffset) {
+ CompositorFrameMetadata metadata;
+
+ metadata.device_scale_factor = device_scale_factor;
+ metadata.page_scale_factor = page_scale_factor;
+ metadata.root_scroll_offset = root_scroll_offset;
+
+ frame_sink_.set_metadata(metadata);
+
capturer_.OnFrameDamaged(kSourceSize, gfx::Rect(kSourceSize),
- GetNextVsync());
+ GetNextVsync(), metadata);
}
void NotifyTargetWentAway() {
@@ -363,7 +416,7 @@ class FrameSinkVideoCapturerTest : public testing::Test {
};
// Tests that the capturer attaches to a frame sink immediately, in the case
-// where the frame sink was already known by the manger.
+// where the frame sink was already known by the manager.
TEST_F(FrameSinkVideoCapturerTest, ResolvesTargetImmediately) {
EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
.WillRepeatedly(Return(&frame_sink_));
@@ -857,4 +910,65 @@ TEST_F(FrameSinkVideoCapturerTest, EventuallySendsARefreshFrame) {
StopCapture();
}
+// Tests that CompositorFrameMetadata variables (|device_scale_factor|,
+// |page_scale_factor| and |root_scroll_offset|) are sent along with each frame,
+// and refreshes cause variables of the cached CompositorFrameMetadata
+// (|last_frame_metadata|) to be used.
+TEST_F(FrameSinkVideoCapturerTest, CompositorFrameMetadataReachesConsumer) {
+ EXPECT_CALL(frame_sink_manager_, FindCapturableFrameSink(kFrameSinkId))
+ .WillRepeatedly(Return(&frame_sink_));
+ capturer_.ChangeTarget(kFrameSinkId);
+
+ MockConsumer consumer;
+ // Initial refresh frame for starting capture, plus later refresh.
+ const int num_refresh_frames = 2;
+ const int num_update_frames = 1;
+ EXPECT_CALL(consumer, OnFrameCapturedMock(_, _, _))
+ .Times(num_refresh_frames + num_update_frames);
+ EXPECT_CALL(consumer, OnTargetLost(_)).Times(0);
+ EXPECT_CALL(consumer, OnStopped()).Times(1);
+ StartCapture(&consumer);
+
+ // With the start, an immediate refresh occurred. Simulate a copy result.
+ // Expect to see the refresh frame delivered to the consumer, along with
+ // default metadata values.
+ int cur_frame_index = 0, expected_frames_count = 1;
+ frame_sink_.SendCopyOutputResult(cur_frame_index);
+ EXPECT_EQ(expected_frames_count, consumer.num_frames_received());
+ EXPECT_TRUE(CompareVarsInCompositorFrameMetadata(
+ *(consumer.TakeFrame(cur_frame_index)), kDefaultDeviceScaleFactor,
+ kDefaultPageScaleFactor, kDefaultRootScrollOffset));
+ consumer.SendDoneNotification(cur_frame_index);
+
+ // The metadata used to signal a frame damage and verify that it reaches the
+ // consumer.
+ const float kNewDeviceScaleFactor = 3.5;
+ const float kNewPageScaleFactor = 1.5;
+ const gfx::Vector2dF kNewRootScrollOffset = gfx::Vector2dF(100, 200);
+
+ // Notify frame damage with new metadata, and expect that the refresh frame
+ // is delivered to the consumer with this new metadata.
+ AdvanceClockToNextVsync();
+ NotifyFrameDamaged(kNewDeviceScaleFactor, kNewPageScaleFactor,
+ kNewRootScrollOffset);
+ frame_sink_.SendCopyOutputResult(++cur_frame_index);
+ EXPECT_EQ(++expected_frames_count, consumer.num_frames_received());
+ EXPECT_TRUE(CompareVarsInCompositorFrameMetadata(
+ *(consumer.TakeFrame(cur_frame_index)), kNewDeviceScaleFactor,
+ kNewPageScaleFactor, kNewRootScrollOffset));
+ consumer.SendDoneNotification(cur_frame_index);
+
+ // Request a refresh frame. Because the refresh request was made just after
+ // the last frame capture, the refresh retry timer should be started.
+ // Expect that the refresh frame is delivered to the consumer with the same
+ // metadata from the previous frame.
+ capturer_.RequestRefreshFrame();
+ AdvanceClockForRefreshTimer();
+ EXPECT_EQ(++expected_frames_count, consumer.num_frames_received());
+ EXPECT_TRUE(CompareVarsInCompositorFrameMetadata(
+ *(consumer.TakeFrame(++cur_frame_index)), kNewDeviceScaleFactor,
+ kNewPageScaleFactor, kNewRootScrollOffset));
+ StopCapture();
+}
+
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
index cb888449836..383a616c7c1 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
+++ b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.cc
@@ -207,10 +207,10 @@ bool InterprocessFramePool::CanLogSharedMemoryFailure() {
}
InterprocessFramePool::PooledBuffer::PooledBuffer() = default;
-InterprocessFramePool::PooledBuffer::PooledBuffer(PooledBuffer&& other) =
- default;
+InterprocessFramePool::PooledBuffer::PooledBuffer(
+ PooledBuffer&& other) noexcept = default;
InterprocessFramePool::PooledBuffer& InterprocessFramePool::PooledBuffer::
-operator=(PooledBuffer&& other) = default;
+operator=(PooledBuffer&& other) noexcept = default;
InterprocessFramePool::PooledBuffer::~PooledBuffer() = default;
} // namespace viz
diff --git a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
index f75d9214bfe..c1882e16b23 100644
--- a/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
+++ b/chromium/components/viz/service/frame_sinks/video_capture/interprocess_frame_pool.h
@@ -72,8 +72,8 @@ class VIZ_SERVICE_EXPORT InterprocessFramePool {
mojo::ScopedSharedBufferMapping mapping;
PooledBuffer();
- PooledBuffer(PooledBuffer&&);
- PooledBuffer& operator=(PooledBuffer&&);
+ PooledBuffer(PooledBuffer&&) noexcept;
+ PooledBuffer& operator=(PooledBuffer&&) noexcept;
~PooledBuffer();
};
diff --git a/chromium/components/viz/service/frame_sinks/video_detector.h b/chromium/components/viz/service/frame_sinks/video_detector.h
index 90e240e39cc..c0119ebb240 100644
--- a/chromium/components/viz/service/frame_sinks/video_detector.h
+++ b/chromium/components/viz/service/frame_sinks/video_detector.h
@@ -7,6 +7,7 @@
#include <unordered_map>
+#include "base/sequenced_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "base/timer/timer.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.cc b/chromium/components/viz/service/gl/gpu_service_impl.cc
index 811eda2f35b..9beb6b89684 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl.cc
@@ -17,7 +17,6 @@
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "components/crash/core/common/crash_key.h"
-#include "components/viz/common/gpu/in_process_context_provider.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/command_buffer/service/scheduler.h"
@@ -115,7 +114,10 @@ GpuServiceImpl::GpuServiceImpl(
std::unique_ptr<gpu::GpuWatchdogThread> watchdog_thread,
scoped_refptr<base::SingleThreadTaskRunner> io_runner,
const gpu::GpuFeatureInfo& gpu_feature_info,
- const gpu::GpuPreferences& gpu_preferences)
+ const gpu::GpuPreferences& gpu_preferences,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu)
: main_runner_(base::ThreadTaskRunnerHandle::Get()),
io_runner_(std::move(io_runner)),
watchdog_thread_(std::move(watchdog_thread)),
@@ -124,6 +126,8 @@ GpuServiceImpl::GpuServiceImpl(
gpu_preferences_(gpu_preferences),
gpu_info_(gpu_info),
gpu_feature_info_(gpu_feature_info),
+ gpu_info_for_hardware_gpu_(gpu_info_for_hardware_gpu),
+ gpu_feature_info_for_hardware_gpu_(gpu_feature_info_for_hardware_gpu),
bindings_(std::make_unique<mojo::BindingSet<mojom::GpuService>>()),
weak_ptr_factory_(this) {
DCHECK(!io_runner_->BelongsToCurrentThread());
@@ -191,7 +195,9 @@ void GpuServiceImpl::InitializeWithHost(
gpu::SyncPointManager* sync_point_manager,
base::WaitableEvent* shutdown_event) {
DCHECK(main_runner_->BelongsToCurrentThread());
- gpu_host->DidInitialize(gpu_info_, gpu_feature_info_);
+ gpu_host->DidInitialize(gpu_info_, gpu_feature_info_,
+ gpu_info_for_hardware_gpu_,
+ gpu_feature_info_for_hardware_gpu_);
gpu_host_ =
mojom::ThreadSafeGpuHostPtr::Create(gpu_host.PassInterface(), io_runner_);
if (!in_host_process()) {
@@ -436,13 +442,15 @@ void GpuServiceImpl::GetVideoMemoryUsageStats(
}
// Currently, this function only supports the Windows platform.
-void GpuServiceImpl::GetGpuSupportedRuntimeVersion() {
+void GpuServiceImpl::GetGpuSupportedRuntimeVersion(
+ GetGpuSupportedRuntimeVersionCallback callback) {
#if defined(OS_WIN)
if (io_runner_->BelongsToCurrentThread()) {
+ auto wrap_callback = WrapCallback(io_runner_, std::move(callback));
main_runner_->PostTask(
FROM_HERE,
base::BindOnce(&GpuServiceImpl::GetGpuSupportedRuntimeVersion,
- weak_ptr_));
+ weak_ptr_, std::move(wrap_callback)));
return;
}
DCHECK(main_runner_->BelongsToCurrentThread());
@@ -453,6 +461,7 @@ void GpuServiceImpl::GetGpuSupportedRuntimeVersion() {
DCHECK(command_line->HasSwitch("disable-gpu-sandbox") || in_host_process());
gpu::RecordGpuSupportedRuntimeVersionHistograms(&gpu_info_);
+ std::move(callback).Run(gpu_info_);
if (!in_host_process()) {
// The unsandboxed GPU process fulfilled its duty. Rest
// in peace.
@@ -535,9 +544,6 @@ void GpuServiceImpl::UpdateGpuInfoPlatform(
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
DCHECK(command_line->HasSwitch("disable-gpu-sandbox") || in_host_process());
- gpu::GetGpuSupportedD3DVersion(&gpu_info_);
- gpu::GetGpuSupportedVulkanVersion(&gpu_info_);
-
// We can continue on shutdown here because we're not writing any critical
// state in this task.
base::PostTaskAndReplyWithResult(
@@ -714,12 +720,13 @@ void GpuServiceImpl::DestroyAllChannels() {
gpu_channel_manager_->DestroyAllChannels();
}
-void GpuServiceImpl::OnBackgrounded() {
+void GpuServiceImpl::OnBackgroundCleanup() {
// Currently only called on Android.
#if defined(OS_ANDROID)
if (io_runner_->BelongsToCurrentThread()) {
main_runner_->PostTask(
- FROM_HERE, base::BindOnce(&GpuServiceImpl::OnBackgrounded, weak_ptr_));
+ FROM_HERE,
+ base::BindOnce(&GpuServiceImpl::OnBackgroundCleanup, weak_ptr_));
return;
}
DVLOG(1) << "GPU: Performing background cleanup";
@@ -729,6 +736,16 @@ void GpuServiceImpl::OnBackgrounded() {
#endif
}
+void GpuServiceImpl::OnBackgrounded() {
+ if (watchdog_thread_)
+ watchdog_thread_->OnBackgrounded();
+}
+
+void GpuServiceImpl::OnForegrounded() {
+ if (watchdog_thread_)
+ watchdog_thread_->OnForegrounded();
+}
+
void GpuServiceImpl::Crash() {
DCHECK(io_runner_->BelongsToCurrentThread());
DVLOG(1) << "GPU: Simulating GPU crash";
diff --git a/chromium/components/viz/service/gl/gpu_service_impl.h b/chromium/components/viz/service/gl/gpu_service_impl.h
index a29e320f906..15c1bb76964 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl.h
+++ b/chromium/components/viz/service/gl/gpu_service_impl.h
@@ -62,7 +62,10 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
std::unique_ptr<gpu::GpuWatchdogThread> watchdog,
scoped_refptr<base::SingleThreadTaskRunner> io_runner,
const gpu::GpuFeatureInfo& gpu_feature_info,
- const gpu::GpuPreferences& gpu_preferences);
+ const gpu::GpuPreferences& gpu_preferences,
+ const base::Optional<gpu::GPUInfo>& gpu_info_for_hardware_gpu,
+ const base::Optional<gpu::GpuFeatureInfo>&
+ gpu_feature_info_for_hardware_gpu);
~GpuServiceImpl() override;
@@ -184,7 +187,8 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void GetVideoMemoryUsageStats(
GetVideoMemoryUsageStatsCallback callback) override;
void RequestCompleteGpuInfo(RequestCompleteGpuInfoCallback callback) override;
- void GetGpuSupportedRuntimeVersion() override;
+ void GetGpuSupportedRuntimeVersion(
+ GetGpuSupportedRuntimeVersionCallback callback) override;
void RequestHDRStatus(RequestHDRStatusCallback callback) override;
void LoadedShader(const std::string& key, const std::string& data) override;
void DestroyingVideoSurface(int32_t surface_id,
@@ -192,7 +196,9 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
void WakeUpGpu() override;
void GpuSwitched() override;
void DestroyAllChannels() override;
+ void OnBackgroundCleanup() override;
void OnBackgrounded() override;
+ void OnForegrounded() override;
void Crash() override;
void Hang() override;
void ThrowJavaException() override;
@@ -226,6 +232,11 @@ class VIZ_SERVICE_EXPORT GpuServiceImpl : public gpu::GpuChannelManagerDelegate,
// Information about general chrome feature support for the GPU.
gpu::GpuFeatureInfo gpu_feature_info_;
+ // What we would have gotten if we haven't fallen back to SwiftShader or
+ // pure software (in the viz case).
+ base::Optional<gpu::GPUInfo> gpu_info_for_hardware_gpu_;
+ base::Optional<gpu::GpuFeatureInfo> gpu_feature_info_for_hardware_gpu_;
+
scoped_refptr<mojom::ThreadSafeGpuHostPtr> gpu_host_;
std::unique_ptr<gpu::GpuChannelManager> gpu_channel_manager_;
std::unique_ptr<media::MediaGpuChannelManager> media_gpu_channel_manager_;
diff --git a/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc b/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
index c36a072fc58..5120ef5d7f1 100644
--- a/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
+++ b/chromium/components/viz/service/gl/gpu_service_impl_unittest.cc
@@ -8,7 +8,6 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "gpu/config/gpu_info.h"
@@ -51,7 +50,8 @@ class GpuServiceTest : public testing::Test {
ASSERT_TRUE(io_thread_.Start());
gpu_service_ = std::make_unique<GpuServiceImpl>(
gpu::GPUInfo(), nullptr /* watchdog_thread */, io_thread_.task_runner(),
- gpu::GpuFeatureInfo(), gpu::GpuPreferences());
+ gpu::GpuFeatureInfo(), gpu::GpuPreferences(), gpu::GPUInfo(),
+ gpu::GpuFeatureInfo());
}
void TearDown() override {
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
index 11f6db2762d..d598f2cdb57 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.cc
@@ -5,7 +5,7 @@
#include "components/viz/service/hit_test/hit_test_aggregator.h"
#include "base/metrics/histogram_macros.h"
-#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
+#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/service/hit_test/hit_test_aggregator_delegate.h"
#include "third_party/skia/include/core/SkMatrix44.h"
@@ -25,78 +25,34 @@ HitTestAggregator::HitTestAggregator(
initial_region_size_(initial_region_size),
incremental_region_size_(initial_region_size),
max_region_size_(max_region_size),
- weak_ptr_factory_(this) {
- AllocateHitTestRegionArray();
-}
+ weak_ptr_factory_(this) {}
HitTestAggregator::~HitTestAggregator() = default;
void HitTestAggregator::Aggregate(const SurfaceId& display_surface_id) {
DCHECK(referenced_child_regions_.empty());
- AppendRoot(display_surface_id);
- referenced_child_regions_.clear();
- Swap();
-}
-
-void HitTestAggregator::GrowRegionList() {
- ResizeHitTestRegionArray(write_size_ + incremental_region_size_);
-}
-
-void HitTestAggregator::Swap() {
- SwapHandles();
- if (!handle_replaced_) {
- delegate_->SwitchActiveAggregatedHitTestRegionList(root_frame_sink_id_,
- active_handle_index_);
- return;
- }
- delegate_->OnAggregatedHitTestRegionListUpdated(
- root_frame_sink_id_,
- read_handle_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
- read_size_,
- write_handle_->Clone(mojo::SharedBufferHandle::AccessMode::READ_ONLY),
- write_size_);
- active_handle_index_ = 0;
- handle_replaced_ = false;
-}
+ // Reset states.
+ hit_test_data_.clear();
+ hit_test_data_capacity_ = initial_region_size_;
+ hit_test_data_size_ = 0;
+ hit_test_data_.resize(hit_test_data_capacity_);
-void HitTestAggregator::AllocateHitTestRegionArray() {
- ResizeHitTestRegionArray(initial_region_size_);
- SwapHandles();
- ResizeHitTestRegionArray(initial_region_size_);
+ AppendRoot(display_surface_id);
+ referenced_child_regions_.clear();
+ SendHitTestData();
}
-void HitTestAggregator::ResizeHitTestRegionArray(uint32_t size) {
- size_t num_bytes = size * sizeof(AggregatedHitTestRegion);
- write_handle_ = mojo::SharedBufferHandle::Create(num_bytes);
- DCHECK(write_handle_.is_valid());
- auto new_buffer_ = write_handle_->Map(num_bytes);
- DCHECK(new_buffer_);
- handle_replaced_ = true;
-
- AggregatedHitTestRegion* region = (AggregatedHitTestRegion*)new_buffer_.get();
- if (write_size_)
- memcpy(region, write_buffer_.get(), write_size_);
- else
- region[0].child_count = kEndOfList;
-
- write_size_ = size;
- write_buffer_ = std::move(new_buffer_);
-}
-
-void HitTestAggregator::SwapHandles() {
- using std::swap;
-
- swap(read_handle_, write_handle_);
- swap(read_size_, write_size_);
- swap(read_buffer_, write_buffer_);
- active_handle_index_ = !active_handle_index_;
+void HitTestAggregator::SendHitTestData() {
+ hit_test_data_.resize(hit_test_data_size_);
+ delegate_->OnAggregatedHitTestRegionListUpdated(root_frame_sink_id_,
+ hit_test_data_);
}
void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
SCOPED_UMA_HISTOGRAM_TIMER("Event.VizHitTest.AggregateTime");
- const mojom::HitTestRegionList* hit_test_region_list =
+ const HitTestRegionList* hit_test_region_list =
hit_test_manager_->GetActiveHitTestRegionList(
local_surface_id_lookup_delegate_, surface_id.frame_sink_id());
if (!hit_test_region_list)
@@ -106,7 +62,7 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
size_t region_index = 1;
for (const auto& region : hit_test_region_list->regions) {
- if (region_index >= write_size_ - 1)
+ if (region_index >= hit_test_data_capacity_ - 1)
break;
region_index = AppendRegion(region_index, region);
}
@@ -117,31 +73,30 @@ void HitTestAggregator::AppendRoot(const SurfaceId& surface_id) {
SetRegionAt(0, surface_id.frame_sink_id(), hit_test_region_list->flags,
hit_test_region_list->bounds, hit_test_region_list->transform,
child_count);
- MarkEndAt(region_index);
}
size_t HitTestAggregator::AppendRegion(size_t region_index,
- const mojom::HitTestRegionPtr& region) {
+ const HitTestRegion& region) {
size_t parent_index = region_index++;
- if (region_index >= write_size_ - 1) {
- if (write_size_ > max_region_size_) {
- MarkEndAt(parent_index);
+ if (region_index >= hit_test_data_capacity_ - 1) {
+ if (hit_test_data_capacity_ > max_region_size_) {
return region_index;
} else {
- GrowRegionList();
+ hit_test_data_capacity_ += incremental_region_size_;
+ hit_test_data_.resize(hit_test_data_capacity_);
}
}
- uint32_t flags = region->flags;
- gfx::Transform transform = region->transform;
+ uint32_t flags = region.flags;
+ gfx::Transform transform = region.transform;
- if (region->flags & mojom::kHitTestChildSurface) {
- if (referenced_child_regions_.count(region->frame_sink_id))
+ if (region.flags & HitTestRegionFlags::kHitTestChildSurface) {
+ if (referenced_child_regions_.count(region.frame_sink_id))
return parent_index;
- const mojom::HitTestRegionList* hit_test_region_list =
+ const HitTestRegionList* hit_test_region_list =
hit_test_manager_->GetActiveHitTestRegionList(
- local_surface_id_lookup_delegate_, region->frame_sink_id);
+ local_surface_id_lookup_delegate_, region.frame_sink_id);
if (!hit_test_region_list) {
// Hit-test data not found with this FrameSinkId. This means that it
// failed to find a surface corresponding to this FrameSinkId at surface
@@ -149,7 +104,7 @@ size_t HitTestAggregator::AppendRegion(size_t region_index,
return parent_index;
}
- referenced_child_regions_.insert(region->frame_sink_id);
+ referenced_child_regions_.insert(region.frame_sink_id);
// Rather than add a node in the tree for this hit_test_region_list
// element we can simplify the tree by merging the flags and transform
@@ -161,14 +116,14 @@ size_t HitTestAggregator::AppendRegion(size_t region_index,
for (const auto& child_region : hit_test_region_list->regions) {
region_index = AppendRegion(region_index, child_region);
- if (region_index >= write_size_ - 1)
+ if (region_index >= hit_test_data_capacity_ - 1)
break;
}
}
DCHECK_GE(region_index - parent_index - 1, 0u);
int32_t child_count = region_index - parent_index - 1;
- SetRegionAt(parent_index, region->frame_sink_id, flags, region->rect,
- transform, child_count);
+ SetRegionAt(parent_index, region.frame_sink_id, flags, region.rect, transform,
+ child_count);
return region_index;
}
@@ -178,21 +133,9 @@ void HitTestAggregator::SetRegionAt(size_t index,
const gfx::Rect& rect,
const gfx::Transform& transform,
int32_t child_count) {
- AggregatedHitTestRegion* regions =
- static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
- AggregatedHitTestRegion* element = &regions[index];
-
- element->frame_sink_id = frame_sink_id;
- element->flags = flags;
- element->rect = rect;
- element->child_count = child_count;
- element->set_transform(transform);
-}
-
-void HitTestAggregator::MarkEndAt(size_t index) {
- AggregatedHitTestRegion* regions =
- static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
- regions[index].child_count = kEndOfList;
+ hit_test_data_[index] = AggregatedHitTestRegion(frame_sink_id, flags, rect,
+ transform, child_count);
+ hit_test_data_size_++;
}
} // namespace viz
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator.h b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
index 4eb67bb5a48..b4999a0ddcf 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator.h
@@ -10,19 +10,16 @@
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/service/surfaces/surface_observer.h"
#include "components/viz/service/viz_service_export.h"
-#include "services/viz/public/interfaces/hit_test/hit_test_region_list.mojom.h"
namespace viz {
class HitTestAggregatorDelegate;
+struct HitTestRegion;
// HitTestAggregator assembles the list of HitTestRegion objects that define the
// hit test information required for one display. Active HitTestRegionList
-// information is obtained from the HitTestManager. The resulting list is made
-// available in shared memory and used by HitTestQuery to enable efficient hit
-// testing across processes.
-//
-// This is intended to be created in the viz or GPU process. For mus+ash this
-// will be true after the mus process split.
+// information is obtained from the HitTestManager. The resulting list is sent
+// to HitTestQuery for event targeting. This is intended to be created in the
+// viz or GPU process.
class VIZ_SERVICE_EXPORT HitTestAggregator {
public:
// |delegate| owns and outlives HitTestAggregator.
@@ -31,71 +28,38 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
HitTestAggregatorDelegate* delegate,
LatestLocalSurfaceIdLookupDelegate* local_surface_id_lookup_delegate,
const FrameSinkId& frame_sink_id,
- uint32_t initial_region_size = 1024,
- uint32_t max_region_size = 100 * 1024);
+ uint32_t initial_region_size = 100,
+ uint32_t max_region_size = 100 * 100);
~HitTestAggregator();
// Called after surfaces have been aggregated into the DisplayFrame.
// In this call HitTestRegionList structures received from active surfaces
- // are aggregated into the HitTestRegionList structure in
- // shared memory used for event targetting.
+ // are aggregated into |hit_test_data_|.
void Aggregate(const SurfaceId& display_surface_id);
- // Called at BeginFrame. Swaps buffers in shared memory and tells its
- // delegate.
- void Swap();
-
private:
friend class TestHitTestAggregator;
- // Allocates memory for the AggregatedHitTestRegion array.
- void AllocateHitTestRegionArray();
-
- // Resizes memory for the AggregatedHitTestRegion array. |size| indicates the
- // number of elements.
- void ResizeHitTestRegionArray(uint32_t size);
-
- void GrowRegionList();
- void SwapHandles();
+ void SendHitTestData();
// Appends the root element to the AggregatedHitTestRegion array.
void AppendRoot(const SurfaceId& surface_id);
// Appends a |region| to the HitTestRegionList structure to recursively
- // build the tree. |region_index| indicates the current index of the end of
+ // build the tree. |region_index| indicates the current index of the end of
// the list.
- size_t AppendRegion(size_t region_index,
- const mojom::HitTestRegionPtr& region);
+ size_t AppendRegion(size_t region_index, const HitTestRegion& region);
// Populates the HitTestRegion element at the given element |index|.
- // Access to the HitTestRegion list is localized to this call
- // in order to prevent errors if the array is resized during aggregation.
void SetRegionAt(size_t index,
const FrameSinkId& frame_sink_id,
uint32_t flags,
const gfx::Rect& rect,
const gfx::Transform& transform,
int32_t child_count);
- // Marks the element at the given index as the end of list.
- void MarkEndAt(size_t index);
const HitTestManager* const hit_test_manager_;
- mojo::ScopedSharedBufferHandle read_handle_;
- mojo::ScopedSharedBufferHandle write_handle_;
-
- // The number of elements allocated.
- uint32_t read_size_ = 0;
- uint32_t write_size_ = 0;
-
- mojo::ScopedSharedBufferMapping read_buffer_;
- mojo::ScopedSharedBufferMapping write_buffer_;
-
- bool handle_replaced_ = false;
-
- // Can only be 0 or 1 when we only have two buffers.
- uint8_t active_handle_index_ = 0;
-
HitTestAggregatorDelegate* const delegate_;
LatestLocalSurfaceIdLookupDelegate* const local_surface_id_lookup_delegate_;
@@ -110,6 +74,10 @@ class VIZ_SERVICE_EXPORT HitTestAggregator {
const uint32_t incremental_region_size_;
const uint32_t max_region_size_;
+ uint32_t hit_test_data_capacity_ = 0;
+ uint32_t hit_test_data_size_ = 0;
+ std::vector<AggregatedHitTestRegion> hit_test_data_;
+
// This is the set of FrameSinkIds referenced in the aggregation so far, used
// to detect cycles.
base::flat_set<FrameSinkId> referenced_child_regions_;
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h b/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
index 51b9b338c79..c6b06cc6992 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator_delegate.h
@@ -5,23 +5,16 @@
#ifndef COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_DELEGATE_H_
#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_DELEGATE_H_
+#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
+
namespace viz {
// Used by HitTestAggregator to talk to FrameSinkManagerImpl.
class HitTestAggregatorDelegate {
public:
- // Called if any of the buffer that stores the aggregated hit-test data is
- // updated (e.g. destroyed, reallocated etc.). |active_handle| and
- // |idle_handle| both must be valid.
+ // Called to send |hit_test_data| when we receive new data.
virtual void OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) = 0;
-
- virtual void SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) = 0;
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) = 0;
protected:
// The dtor is protected so that HitTestAggregator does not take ownership.
diff --git a/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc b/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
index 08135e64416..d59985209db 100644
--- a/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_aggregator_unittest.cc
@@ -7,6 +7,7 @@
#include <map>
#include <memory>
+#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/host_frame_sink_manager.h"
@@ -40,34 +41,18 @@ class TestHostFrameSinkManager : public HostFrameSinkManager {
void OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) override {
- DCHECK(active_handle.is_valid() && idle_handle.is_valid());
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) override {
buffer_frame_sink_id_ = frame_sink_id;
- handle_buffers_[0] = active_handle->Map(active_handle_size *
- sizeof(AggregatedHitTestRegion));
- handle_buffers_[1] =
- idle_handle->Map(idle_handle_size * sizeof(AggregatedHitTestRegion));
- SwitchActiveAggregatedHitTestRegionList(buffer_frame_sink_id_, 0);
+ active_list_ = hit_test_data;
}
- void SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) override {
- active_list_ = static_cast<AggregatedHitTestRegion*>(
- handle_buffers_[active_handle_index].get());
- }
-
- AggregatedHitTestRegion* regions() { return active_list_; }
+ const std::vector<AggregatedHitTestRegion>& regions() { return active_list_; }
const FrameSinkId& buffer_frame_sink_id() { return buffer_frame_sink_id_; }
private:
FrameSinkId buffer_frame_sink_id_;
- mojo::ScopedSharedBufferMapping handle_buffers_[2];
- AggregatedHitTestRegion* active_list_;
+ std::vector<AggregatedHitTestRegion> active_list_;
DISALLOW_COPY_AND_ASSIGN(TestHostFrameSinkManager);
};
@@ -83,25 +68,11 @@ class TestFrameSinkManagerImpl : public FrameSinkManagerImpl {
void OnAggregatedHitTestRegionListUpdated(
const FrameSinkId& frame_sink_id,
- mojo::ScopedSharedBufferHandle active_handle,
- uint32_t active_handle_size,
- mojo::ScopedSharedBufferHandle idle_handle,
- uint32_t idle_handle_size) override {
- // Do not check if it's on valid thread for tests.
- if (host_client_) {
- host_client_->OnAggregatedHitTestRegionListUpdated(
- frame_sink_id, std::move(active_handle), active_handle_size,
- std::move(idle_handle), idle_handle_size);
- }
- }
-
- void SwitchActiveAggregatedHitTestRegionList(
- const FrameSinkId& frame_sink_id,
- uint8_t active_handle_index) override {
+ const std::vector<AggregatedHitTestRegion>& hit_test_data) override {
// Do not check if it's on valid thread for tests.
if (host_client_) {
- host_client_->SwitchActiveAggregatedHitTestRegionList(
- frame_sink_id, active_handle_index);
+ host_client_->OnAggregatedHitTestRegionListUpdated(frame_sink_id,
+ hit_test_data);
}
}
@@ -127,28 +98,8 @@ class TestHitTestAggregator final : public HitTestAggregator {
frame_sink_id_(frame_sink_id) {}
~TestHitTestAggregator() = default;
- int GetRegionCount() const {
- AggregatedHitTestRegion* start =
- static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
- AggregatedHitTestRegion* end = start;
- while (end->child_count != kEndOfList)
- end++;
- return end - start;
- }
- int GetHitTestRegionListSize() { return read_size_; }
- void SwapHandles() {
- delegate_->SwitchActiveAggregatedHitTestRegionList(frame_sink_id_,
- active_handle_index_);
- }
-
- void Reset() {
- AggregatedHitTestRegion* regions =
- static_cast<AggregatedHitTestRegion*>(write_buffer_.get());
- regions[0].child_count = kEndOfList;
-
- regions = static_cast<AggregatedHitTestRegion*>(read_buffer_.get());
- regions[0].child_count = kEndOfList;
- }
+ int GetRegionCount() const { return hit_test_data_size_; }
+ int GetHitTestRegionListCapacity() { return hit_test_data_capacity_; }
private:
const FrameSinkId frame_sink_id_;
@@ -187,24 +138,24 @@ class HitTestAggregatorTest : public testing::Test {
SurfaceId surface_id = MakeSurfaceId(client_id);
client_id++;
- auto hit_test_region_list = mojom::HitTestRegionList::New();
- hit_test_region_list->flags = mojom::kHitTestMine;
- hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList hit_test_region_list;
+ hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
for (int i = 0; i < 8; i++) {
- auto hit_test_region = mojom::HitTestRegion::New();
- hit_test_region->rect.SetRect(100, 100, 100, 100);
+ HitTestRegion hit_test_region;
+ hit_test_region.rect.SetRect(100, 100, 100, 100);
SurfaceId child_surface_id = MakeSurfaceId(client_id);
- hit_test_region->frame_sink_id = child_surface_id.frame_sink_id();
+ hit_test_region.frame_sink_id = child_surface_id.frame_sink_id();
if (depth > 0) {
- hit_test_region->flags = mojom::kHitTestChildSurface;
+ hit_test_region.flags = HitTestRegionFlags::kHitTestChildSurface;
client_id =
CreateAndSubmitHitTestRegionListWith8Children(client_id, depth - 1);
} else {
- hit_test_region->flags = mojom::kHitTestMine;
+ hit_test_region.flags = HitTestRegionFlags::kHitTestMine;
}
- hit_test_region_list->regions.push_back(std::move(hit_test_region));
+ hit_test_region_list.regions.push_back(std::move(hit_test_region));
}
if (surface_id.frame_sink_id() == kDisplayFrameSink) {
@@ -229,7 +180,7 @@ class HitTestAggregatorTest : public testing::Test {
return hit_test_aggregator_.get();
}
- AggregatedHitTestRegion* host_regions() {
+ const std::vector<AggregatedHitTestRegion>& host_regions() {
return host_frame_sink_manager_->regions();
}
@@ -284,30 +235,26 @@ TEST_F(HitTestAggregatorTest, OneSurface) {
SurfaceId display_surface_id = MakeSurfaceId(kDisplayClientId);
- auto hit_test_region_list = mojom::HitTestRegionList::New();
- hit_test_region_list->flags = mojom::kHitTestMine;
- hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList hit_test_region_list;
+ hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
support()->SubmitCompositorFrame(display_surface_id.local_surface_id(),
MakeDefaultCompositorFrame(),
std::move(hit_test_region_list));
local_surface_id_lookup_delegate()->SetSurfaceIdMap(display_surface_id);
aggregator->Aggregate(display_surface_id);
- aggregator->SwapHandles();
// Expect 1 entry routing all events to the one surface (display root).
EXPECT_EQ(aggregator->GetRegionCount(), 1);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, display_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 0);
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, display_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 0);
}
// One opaque embedder with two regions.
@@ -325,22 +272,22 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_r1 = mojom::HitTestRegion::New();
- e_hit_test_region_r1->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_r1->flags = mojom::kHitTestMine;
- e_hit_test_region_r1->rect.SetRect(100, 100, 200, 400);
+ HitTestRegion e_hit_test_region_r1;
+ e_hit_test_region_r1.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_r1.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_r1.rect.SetRect(100, 100, 200, 400);
- auto e_hit_test_region_r2 = mojom::HitTestRegion::New();
- e_hit_test_region_r2->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_r2->flags = mojom::kHitTestMine;
- e_hit_test_region_r2->rect.SetRect(400, 100, 300, 400);
+ HitTestRegion e_hit_test_region_r2;
+ e_hit_test_region_r2.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_r2.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_r2.rect.SetRect(400, 100, 300, 400);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r1));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_r2));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_r1));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_r2));
support()->SubmitCompositorFrame(e_surface_id.local_surface_id(),
MakeDefaultCompositorFrame(),
@@ -348,30 +295,26 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoRegions) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 2);
-
- region = &regions[1];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 400));
- EXPECT_EQ(region->child_count, 0);
- region = &regions[2];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->rect, gfx::Rect(400, 100, 300, 400));
- EXPECT_EQ(region->child_count, 0);
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 2);
+
+ region = host_regions()[1];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 200, 400));
+ EXPECT_EQ(region.child_count, 0);
+
+ region = host_regions()[2];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.rect, gfx::Rect(400, 100, 300, 400));
+ EXPECT_EQ(region.child_count, 0);
}
// One embedder with two children.
@@ -392,26 +335,26 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
SurfaceId c1_surface_id = MakeSurfaceId(kDisplayClientId + 1);
SurfaceId c2_surface_id = MakeSurfaceId(kDisplayClientId + 2);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_c1 = mojom::HitTestRegion::New();
- e_hit_test_region_c1->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c1->frame_sink_id = c1_surface_id.frame_sink_id();
- e_hit_test_region_c1->rect.SetRect(100, 100, 200, 300);
+ HitTestRegion e_hit_test_region_c1;
+ e_hit_test_region_c1.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c1.frame_sink_id = c1_surface_id.frame_sink_id();
+ e_hit_test_region_c1.rect.SetRect(100, 100, 200, 300);
- auto e_hit_test_region_c2 = mojom::HitTestRegion::New();
- e_hit_test_region_c2->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c2->frame_sink_id = c2_surface_id.frame_sink_id();
- e_hit_test_region_c2->rect.SetRect(400, 100, 400, 300);
+ HitTestRegion e_hit_test_region_c2;
+ e_hit_test_region_c2.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c2.frame_sink_id = c2_surface_id.frame_sink_id();
+ e_hit_test_region_c2.rect.SetRect(400, 100, 400, 300);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c2));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c1));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c2));
- auto c1_hit_test_region_list = mojom::HitTestRegionList::New();
+ HitTestRegionList c1_hit_test_region_list;
- auto c2_hit_test_region_list = mojom::HitTestRegionList::New();
+ HitTestRegionList c2_hit_test_region_list;
// Submit in unexpected order.
@@ -435,32 +378,28 @@ TEST_F(HitTestAggregatorTest, OneEmbedderTwoChildren) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(c2_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 2);
-
- region = &regions[1];
- EXPECT_EQ(region->flags, mojom::kHitTestChildSurface);
- EXPECT_EQ(region->frame_sink_id, c1_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 300));
- EXPECT_EQ(region->child_count, 0);
-
- region = &regions[2];
- EXPECT_EQ(region->flags, mojom::kHitTestChildSurface);
- EXPECT_EQ(region->frame_sink_id, c2_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(400, 100, 400, 300));
- EXPECT_EQ(region->child_count, 0);
+
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 2);
+
+ region = host_regions()[1];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestChildSurface);
+ EXPECT_EQ(region.frame_sink_id, c1_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 200, 300));
+ EXPECT_EQ(region.child_count, 0);
+
+ region = host_regions()[2];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestChildSurface);
+ EXPECT_EQ(region.frame_sink_id, c2_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(400, 100, 400, 300));
+ EXPECT_EQ(region.child_count, 0);
}
// Occluded child frame (OOPIF).
@@ -481,26 +420,26 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_div = mojom::HitTestRegion::New();
- e_hit_test_region_div->flags = mojom::kHitTestMine;
- e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+ HitTestRegion e_hit_test_region_div;
+ e_hit_test_region_div.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_div.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_div.rect.SetRect(200, 200, 300, 200);
- auto e_hit_test_region_c = mojom::HitTestRegion::New();
- e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
- e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+ HitTestRegion e_hit_test_region_c;
+ e_hit_test_region_c.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c.frame_sink_id = c_surface_id.frame_sink_id();
+ e_hit_test_region_c.rect.SetRect(100, 100, 200, 500);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_div));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c));
- auto c_hit_test_region_list = mojom::HitTestRegionList::New();
- c_hit_test_region_list->flags = mojom::kHitTestMine;
- c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
+ HitTestRegionList c_hit_test_region_list;
+ c_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c_hit_test_region_list.bounds.SetRect(0, 0, 200, 500);
// Submit in unexpected order.
auto support2 = std::make_unique<CompositorFrameSinkSupport>(
@@ -516,32 +455,30 @@ TEST_F(HitTestAggregatorTest, OccludedChildFrame) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 2);
-
- region = &regions[1];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
- EXPECT_EQ(region->child_count, 0);
-
- region = &regions[2];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 500));
- EXPECT_EQ(region->child_count, 0);
+
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 2);
+
+ region = host_regions()[1];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region.child_count, 0);
+
+ region = host_regions()[2];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 200, 500));
+ EXPECT_EQ(region.child_count, 0);
}
// Foreground child frame (OOPIF).
@@ -563,26 +500,26 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_div = mojom::HitTestRegion::New();
- e_hit_test_region_div->flags = mojom::kHitTestMine;
- e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+ HitTestRegion e_hit_test_region_div;
+ e_hit_test_region_div.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_div.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_div.rect.SetRect(200, 200, 300, 200);
- auto e_hit_test_region_c = mojom::HitTestRegion::New();
- e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
- e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+ HitTestRegion e_hit_test_region_c;
+ e_hit_test_region_c.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c.frame_sink_id = c_surface_id.frame_sink_id();
+ e_hit_test_region_c.rect.SetRect(100, 100, 200, 500);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_div));
- auto c_hit_test_region_list = mojom::HitTestRegionList::New();
- c_hit_test_region_list->flags = mojom::kHitTestMine;
- c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
+ HitTestRegionList c_hit_test_region_list;
+ c_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c_hit_test_region_list.bounds.SetRect(0, 0, 200, 500);
// Submit in unexpected order.
@@ -599,32 +536,30 @@ TEST_F(HitTestAggregatorTest, ForegroundChildFrame) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 3);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 2);
-
- region = &regions[1];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 200, 500));
- EXPECT_EQ(region->child_count, 0);
-
- region = &regions[2];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
- EXPECT_EQ(region->child_count, 0);
+
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 2);
+
+ region = host_regions()[1];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 200, 500));
+ EXPECT_EQ(region.child_count, 0);
+
+ region = host_regions()[2];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region.child_count, 0);
}
// One embedder with a clipped child with a tab and transparent background.
@@ -648,42 +583,42 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
SurfaceId a_surface_id = MakeSurfaceId(kDisplayClientId + 2);
SurfaceId b_surface_id = MakeSurfaceId(kDisplayClientId + 3);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_c = mojom::HitTestRegion::New();
- e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
- e_hit_test_region_c->rect.SetRect(300, 100, 1600, 800);
- e_hit_test_region_c->transform.Translate(200, 100);
+ HitTestRegion e_hit_test_region_c;
+ e_hit_test_region_c.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c.frame_sink_id = c_surface_id.frame_sink_id();
+ e_hit_test_region_c.rect.SetRect(300, 100, 1600, 800);
+ e_hit_test_region_c.transform.Translate(200, 100);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c));
- auto c_hit_test_region_list = mojom::HitTestRegionList::New();
- c_hit_test_region_list->flags = mojom::kHitTestIgnore;
- c_hit_test_region_list->bounds.SetRect(0, 0, 1600, 800);
+ HitTestRegionList c_hit_test_region_list;
+ c_hit_test_region_list.flags = HitTestRegionFlags::kHitTestIgnore;
+ c_hit_test_region_list.bounds.SetRect(0, 0, 1600, 800);
- auto c_hit_test_region_a = mojom::HitTestRegion::New();
- c_hit_test_region_a->flags = mojom::kHitTestChildSurface;
- c_hit_test_region_a->frame_sink_id = a_surface_id.frame_sink_id();
- c_hit_test_region_a->rect.SetRect(0, 0, 200, 100);
+ HitTestRegion c_hit_test_region_a;
+ c_hit_test_region_a.flags = HitTestRegionFlags::kHitTestChildSurface;
+ c_hit_test_region_a.frame_sink_id = a_surface_id.frame_sink_id();
+ c_hit_test_region_a.rect.SetRect(0, 0, 200, 100);
- auto c_hit_test_region_b = mojom::HitTestRegion::New();
- c_hit_test_region_b->flags = mojom::kHitTestChildSurface;
- c_hit_test_region_b->frame_sink_id = b_surface_id.frame_sink_id();
- c_hit_test_region_b->rect.SetRect(0, 100, 800, 600);
+ HitTestRegion c_hit_test_region_b;
+ c_hit_test_region_b.flags = HitTestRegionFlags::kHitTestChildSurface;
+ c_hit_test_region_b.frame_sink_id = b_surface_id.frame_sink_id();
+ c_hit_test_region_b.rect.SetRect(0, 100, 800, 600);
- c_hit_test_region_list->regions.push_back(std::move(c_hit_test_region_a));
- c_hit_test_region_list->regions.push_back(std::move(c_hit_test_region_b));
+ c_hit_test_region_list.regions.push_back(std::move(c_hit_test_region_a));
+ c_hit_test_region_list.regions.push_back(std::move(c_hit_test_region_b));
- auto a_hit_test_region_list = mojom::HitTestRegionList::New();
- a_hit_test_region_list->flags = mojom::kHitTestMine;
- a_hit_test_region_list->bounds.SetRect(0, 0, 200, 100);
+ HitTestRegionList a_hit_test_region_list;
+ a_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ a_hit_test_region_list.bounds.SetRect(0, 0, 200, 100);
- auto b_hit_test_region_list = mojom::HitTestRegionList::New();
- b_hit_test_region_list->flags = mojom::kHitTestMine;
- b_hit_test_region_list->bounds.SetRect(0, 100, 800, 600);
+ HitTestRegionList b_hit_test_region_list;
+ b_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ b_hit_test_region_list.bounds.SetRect(0, 100, 800, 600);
// Submit in unexpected order.
@@ -714,43 +649,45 @@ TEST_F(HitTestAggregatorTest, ClippedChildWithTabAndTransparentBackground) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 4);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
- AggregatedHitTestRegion* region = nullptr;
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 3);
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 3);
-
- region = &regions[1];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestIgnore, region->flags);
- EXPECT_EQ(region->frame_sink_id, c_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(300, 100, 1600, 800));
- EXPECT_EQ(region->child_count, 2);
+ region = host_regions()[1];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestIgnore,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(300, 100, 1600, 800));
+ EXPECT_EQ(region.child_count, 2);
gfx::Point point(300, 300);
- gfx::Transform transform(region->transform());
+ gfx::Transform transform(region.transform());
transform.TransformPointReverse(&point);
EXPECT_TRUE(point == gfx::Point(100, 200));
- region = &regions[2];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, a_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 200, 100));
- EXPECT_EQ(region->child_count, 0);
-
- region = &regions[3];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, b_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 100, 800, 600));
- EXPECT_EQ(region->child_count, 0);
+ region = host_regions()[2];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, a_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 200, 100));
+ EXPECT_EQ(region.child_count, 0);
+
+ region = host_regions()[3];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, b_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 100, 800, 600));
+ EXPECT_EQ(region.child_count, 0);
}
// Three children deep.
@@ -775,42 +712,42 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
SurfaceId c2_surface_id = MakeSurfaceId(kDisplayClientId + 2);
SurfaceId c3_surface_id = MakeSurfaceId(kDisplayClientId + 3);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_c1 = mojom::HitTestRegion::New();
- e_hit_test_region_c1->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c1->frame_sink_id = c1_surface_id.frame_sink_id();
- e_hit_test_region_c1->rect.SetRect(100, 100, 700, 700);
+ HitTestRegion e_hit_test_region_c1;
+ e_hit_test_region_c1.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c1.frame_sink_id = c1_surface_id.frame_sink_id();
+ e_hit_test_region_c1.rect.SetRect(100, 100, 700, 700);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c1));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c1));
- auto c1_hit_test_region_list = mojom::HitTestRegionList::New();
- c1_hit_test_region_list->flags = mojom::kHitTestMine;
- c1_hit_test_region_list->bounds.SetRect(0, 0, 600, 600);
+ HitTestRegionList c1_hit_test_region_list;
+ c1_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c1_hit_test_region_list.bounds.SetRect(0, 0, 600, 600);
- auto c1_hit_test_region_c2 = mojom::HitTestRegion::New();
- c1_hit_test_region_c2->flags = mojom::kHitTestChildSurface;
- c1_hit_test_region_c2->frame_sink_id = c2_surface_id.frame_sink_id();
- c1_hit_test_region_c2->rect.SetRect(100, 100, 500, 500);
+ HitTestRegion c1_hit_test_region_c2;
+ c1_hit_test_region_c2.flags = HitTestRegionFlags::kHitTestChildSurface;
+ c1_hit_test_region_c2.frame_sink_id = c2_surface_id.frame_sink_id();
+ c1_hit_test_region_c2.rect.SetRect(100, 100, 500, 500);
- c1_hit_test_region_list->regions.push_back(std::move(c1_hit_test_region_c2));
+ c1_hit_test_region_list.regions.push_back(std::move(c1_hit_test_region_c2));
- auto c2_hit_test_region_list = mojom::HitTestRegionList::New();
- c2_hit_test_region_list->flags = mojom::kHitTestMine;
- c2_hit_test_region_list->bounds.SetRect(0, 0, 400, 400);
+ HitTestRegionList c2_hit_test_region_list;
+ c2_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c2_hit_test_region_list.bounds.SetRect(0, 0, 400, 400);
- auto c2_hit_test_region_c3 = mojom::HitTestRegion::New();
- c2_hit_test_region_c3->flags = mojom::kHitTestChildSurface;
- c2_hit_test_region_c3->frame_sink_id = c3_surface_id.frame_sink_id();
- c2_hit_test_region_c3->rect.SetRect(100, 100, 300, 300);
+ HitTestRegion c2_hit_test_region_c3;
+ c2_hit_test_region_c3.flags = HitTestRegionFlags::kHitTestChildSurface;
+ c2_hit_test_region_c3.frame_sink_id = c3_surface_id.frame_sink_id();
+ c2_hit_test_region_c3.rect.SetRect(100, 100, 300, 300);
- c2_hit_test_region_list->regions.push_back(std::move(c2_hit_test_region_c3));
+ c2_hit_test_region_list.regions.push_back(std::move(c2_hit_test_region_c3));
- auto c3_hit_test_region_list = mojom::HitTestRegionList::New();
- c3_hit_test_region_list->flags = mojom::kHitTestMine;
- c3_hit_test_region_list->bounds.SetRect(0, 0, 200, 200);
+ HitTestRegionList c3_hit_test_region_list;
+ c3_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c3_hit_test_region_list.bounds.SetRect(0, 0, 200, 200);
// Submit in unexpected order.
@@ -841,38 +778,40 @@ TEST_F(HitTestAggregatorTest, ThreeChildrenDeep) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(c2_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_EQ(aggregator->GetRegionCount(), 4);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
-
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 3);
-
- region = &regions[1];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, c1_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 700, 700));
- EXPECT_EQ(region->child_count, 2);
-
- region = &regions[2];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, c2_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 500, 500));
- EXPECT_EQ(region->child_count, 1);
-
- region = &regions[3];
- EXPECT_EQ(mojom::kHitTestChildSurface | mojom::kHitTestMine, region->flags);
- EXPECT_EQ(region->frame_sink_id, c3_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(100, 100, 300, 300));
- EXPECT_EQ(region->child_count, 0);
+
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 3);
+
+ region = host_regions()[1];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c1_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 700, 700));
+ EXPECT_EQ(region.child_count, 2);
+
+ region = host_regions()[2];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c2_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 500, 500));
+ EXPECT_EQ(region.child_count, 1);
+
+ region = host_regions()[3];
+ EXPECT_EQ(HitTestRegionFlags::kHitTestChildSurface |
+ HitTestRegionFlags::kHitTestMine,
+ region.flags);
+ EXPECT_EQ(region.frame_sink_id, c3_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(100, 100, 300, 300));
+ EXPECT_EQ(region.child_count, 0);
}
// Missing / late child.
@@ -893,26 +832,26 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_div = mojom::HitTestRegion::New();
- e_hit_test_region_div->flags = mojom::kHitTestMine;
- e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+ HitTestRegion e_hit_test_region_div;
+ e_hit_test_region_div.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_div.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_div.rect.SetRect(200, 200, 300, 200);
- auto e_hit_test_region_c = mojom::HitTestRegion::New();
- e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
- e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+ HitTestRegion e_hit_test_region_c;
+ e_hit_test_region_c.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c.frame_sink_id = c_surface_id.frame_sink_id();
+ e_hit_test_region_c.rect.SetRect(100, 100, 200, 500);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_div));
- auto c_hit_test_region_list = mojom::HitTestRegionList::New();
- c_hit_test_region_list->flags = mojom::kHitTestMine;
- c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
+ HitTestRegionList c_hit_test_region_list;
+ c_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c_hit_test_region_list.bounds.SetRect(0, 0, 200, 500);
// Submit in unexpected order.
@@ -922,27 +861,23 @@ TEST_F(HitTestAggregatorTest, MissingChildFrame) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
// Child c didn't submit any CompositorFrame. Events should go to parent.
EXPECT_EQ(aggregator->GetRegionCount(), 2);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- AggregatedHitTestRegion* region = nullptr;
- region = &regions[0];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(0, 0, 1024, 768));
- EXPECT_EQ(region->child_count, 1);
-
- region = &regions[1];
- EXPECT_EQ(region->flags, mojom::kHitTestMine);
- EXPECT_EQ(region->frame_sink_id, e_surface_id.frame_sink_id());
- EXPECT_EQ(region->rect, gfx::Rect(200, 200, 300, 200));
- EXPECT_EQ(region->child_count, 0);
+ AggregatedHitTestRegion region = host_regions()[0];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(0, 0, 1024, 768));
+ EXPECT_EQ(region.child_count, 1);
+
+ region = host_regions()[1];
+ EXPECT_EQ(region.flags, HitTestRegionFlags::kHitTestMine);
+ EXPECT_EQ(region.frame_sink_id, e_surface_id.frame_sink_id());
+ EXPECT_EQ(region.rect, gfx::Rect(200, 200, 300, 200));
+ EXPECT_EQ(region.child_count, 0);
}
// Exceed limits to ensure that bounds and resize work.
@@ -970,14 +905,13 @@ TEST_F(HitTestAggregatorTest, ExceedLimits) {
TestHitTestAggregator* aggregator = hit_test_aggregator();
EXPECT_EQ(aggregator->GetRegionCount(), 0);
- EXPECT_LT(aggregator->GetHitTestRegionListSize(), 4096);
+ EXPECT_LT(aggregator->GetHitTestRegionListCapacity(), 4096);
SurfaceId display_surface_id = MakeSurfaceId(kDisplayClientId);
CreateAndSubmitHitTestRegionListWith8Children(kDisplayClientId, 3);
aggregator->Aggregate(display_surface_id);
- aggregator->SwapHandles();
// Expect 4680 regions:
// 8 children 4 levels deep 8*8*8*8 is 4096
@@ -985,17 +919,10 @@ TEST_F(HitTestAggregatorTest, ExceedLimits) {
// 1 root + 1
// -----
// 4681.
- EXPECT_GE(aggregator->GetHitTestRegionListSize(), 4681);
+ EXPECT_GE(aggregator->GetHitTestRegionListCapacity(), 4681);
EXPECT_EQ(host_buffer_frame_sink_id(), kDisplayFrameSink);
- AggregatedHitTestRegion* regions = host_regions();
-
- uint32_t count = 0;
- while (regions->child_count != kEndOfList) {
- regions++;
- count++;
- }
- EXPECT_EQ(count, 4681u);
+ EXPECT_EQ(host_regions().size(), 4681u);
}
TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
@@ -1004,26 +931,26 @@ TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
SurfaceId e_surface_id = MakeSurfaceId(kDisplayClientId);
SurfaceId c_surface_id = MakeSurfaceId(kDisplayClientId + 1);
- auto e_hit_test_region_list = mojom::HitTestRegionList::New();
- e_hit_test_region_list->flags = mojom::kHitTestMine;
- e_hit_test_region_list->bounds.SetRect(0, 0, 1024, 768);
+ HitTestRegionList e_hit_test_region_list;
+ e_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_list.bounds.SetRect(0, 0, 1024, 768);
- auto e_hit_test_region_div = mojom::HitTestRegion::New();
- e_hit_test_region_div->flags = mojom::kHitTestMine;
- e_hit_test_region_div->frame_sink_id = e_surface_id.frame_sink_id();
- e_hit_test_region_div->rect.SetRect(200, 200, 300, 200);
+ HitTestRegion e_hit_test_region_div;
+ e_hit_test_region_div.flags = HitTestRegionFlags::kHitTestMine;
+ e_hit_test_region_div.frame_sink_id = e_surface_id.frame_sink_id();
+ e_hit_test_region_div.rect.SetRect(200, 200, 300, 200);
- auto e_hit_test_region_c = mojom::HitTestRegion::New();
- e_hit_test_region_c->flags = mojom::kHitTestChildSurface;
- e_hit_test_region_c->frame_sink_id = c_surface_id.frame_sink_id();
- e_hit_test_region_c->rect.SetRect(100, 100, 200, 500);
+ HitTestRegion e_hit_test_region_c;
+ e_hit_test_region_c.flags = HitTestRegionFlags::kHitTestChildSurface;
+ e_hit_test_region_c.frame_sink_id = c_surface_id.frame_sink_id();
+ e_hit_test_region_c.rect.SetRect(100, 100, 200, 500);
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_c));
- e_hit_test_region_list->regions.push_back(std::move(e_hit_test_region_div));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_c));
+ e_hit_test_region_list.regions.push_back(std::move(e_hit_test_region_div));
- auto c_hit_test_region_list = mojom::HitTestRegionList::New();
- c_hit_test_region_list->flags = mojom::kHitTestMine;
- c_hit_test_region_list->bounds.SetRect(0, 0, 200, 500);
+ HitTestRegionList c_hit_test_region_list;
+ c_hit_test_region_list.flags = HitTestRegionFlags::kHitTestMine;
+ c_hit_test_region_list.bounds.SetRect(0, 0, 200, 500);
EXPECT_FALSE(hit_test_manager()->GetActiveHitTestRegionList(
local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
@@ -1045,7 +972,6 @@ TEST_F(HitTestAggregatorTest, DiscardedSurfaces) {
local_surface_id_lookup_delegate()->SetSurfaceIdMap(e_surface_id);
aggregator->Aggregate(e_surface_id);
- aggregator->SwapHandles();
EXPECT_TRUE(hit_test_manager()->GetActiveHitTestRegionList(
local_surface_id_lookup_delegate(), e_surface_id.frame_sink_id()));
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager.cc b/chromium/components/viz/service/hit_test/hit_test_manager.cc
index 886ac9f42c3..4f3e7e1ae9d 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.cc
@@ -54,17 +54,19 @@ void HitTestManager::OnSurfaceActivated(
void HitTestManager::SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
- mojom::HitTestRegionListPtr hit_test_region_list) {
- if (!ValidateHitTestRegionList(surface_id, hit_test_region_list))
+ base::Optional<HitTestRegionList> hit_test_region_list) {
+ if (!hit_test_region_list)
+ return;
+ if (!ValidateHitTestRegionList(surface_id, &*hit_test_region_list))
return;
// TODO(gklassen): Runtime validation that hit_test_region_list is valid.
// TODO(gklassen): Inform FrameSink that the hit_test_region_list is invalid.
// TODO(gklassen): FrameSink needs to inform the host of a difficult renderer.
hit_test_region_lists_[surface_id][frame_index] =
- std::move(hit_test_region_list);
+ std::move(*hit_test_region_list);
}
-const mojom::HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
+const HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
LatestLocalSurfaceIdLookupDelegate* delegate,
const FrameSinkId& frame_sink_id) const {
if (!delegate)
@@ -89,23 +91,20 @@ const mojom::HitTestRegionList* HitTestManager::GetActiveHitTestRegionList(
if (search2 == frame_index_map.end())
return nullptr;
- return search2->second.get();
+ return &search2->second;
}
bool HitTestManager::ValidateHitTestRegionList(
const SurfaceId& surface_id,
- const mojom::HitTestRegionListPtr& hit_test_region_list) {
- if (!hit_test_region_list)
- return false;
+ HitTestRegionList* hit_test_region_list) {
if (hit_test_region_list->regions.size() > kMaxRegionsPerSurface)
return false;
for (auto& region : hit_test_region_list->regions) {
// TODO(gklassen): Ensure that |region->frame_sink_id| is a child of
// |frame_sink_id|.
- if (region->frame_sink_id.client_id() == 0) {
- region->frame_sink_id =
- FrameSinkId(surface_id.frame_sink_id().client_id(),
- region->frame_sink_id.sink_id());
+ if (region.frame_sink_id.client_id() == 0) {
+ region.frame_sink_id = FrameSinkId(surface_id.frame_sink_id().client_id(),
+ region.frame_sink_id.sink_id());
}
}
return true;
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager.h b/chromium/components/viz/service/hit_test/hit_test_manager.h
index 457f846c1bf..ae4ae6064ad 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager.h
+++ b/chromium/components/viz/service/hit_test/hit_test_manager.h
@@ -5,6 +5,7 @@
#ifndef COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
#define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_MANAGER_H_
+#include "base/optional.h"
#include "components/viz/common/hit_test/aggregated_hit_test_region.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/service/surfaces/surface_manager.h"
@@ -40,22 +41,23 @@ class VIZ_SERVICE_EXPORT HitTestManager : public SurfaceObserver {
void SubmitHitTestRegionList(
const SurfaceId& surface_id,
const uint64_t frame_index,
- mojom::HitTestRegionListPtr hit_test_region_list);
+ base::Optional<HitTestRegionList> hit_test_region_list);
// Returns the HitTestRegionList corresponding to the given
// |frame_sink_id| and the active CompositorFrame matched by frame_index.
- const mojom::HitTestRegionList* GetActiveHitTestRegionList(
+ // The returned pointer is not stable and should not be stored or used after
+ // calling any non-const methods on this class.
+ const HitTestRegionList* GetActiveHitTestRegionList(
LatestLocalSurfaceIdLookupDelegate* delegate,
const FrameSinkId& frame_sink_id) const;
private:
- bool ValidateHitTestRegionList(
- const SurfaceId& surface_id,
- const mojom::HitTestRegionListPtr& hit_test_region_list);
+ bool ValidateHitTestRegionList(const SurfaceId& surface_id,
+ HitTestRegionList* hit_test_region_list);
SurfaceManager* const surface_manager_;
- std::map<SurfaceId, base::flat_map<uint64_t, mojom::HitTestRegionListPtr>>
+ std::map<SurfaceId, base::flat_map<uint64_t, HitTestRegionList>>
hit_test_region_lists_;
DISALLOW_COPY_AND_ASSIGN(HitTestManager);
diff --git a/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc b/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
index da94df12037..734d626750d 100644
--- a/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
+++ b/chromium/components/viz/service/hit_test/hit_test_manager_fuzzer.cc
@@ -14,7 +14,6 @@
#include "components/viz/service/hit_test/hit_test_manager.h"
#include "components/viz/test/compositor_frame_helpers.h"
#include "components/viz/test/test_latest_local_surface_id_lookup_delegate.h"
-#include "mojo/edk/embedder/embedder.h"
namespace {
@@ -44,7 +43,7 @@ void SubmitHitTestRegionList(
const uint32_t depth);
void AddHitTestRegion(base::FuzzedDataProvider* fuzz,
- std::vector<viz::mojom::HitTestRegionPtr>* regions,
+ std::vector<viz::HitTestRegion>* regions,
uint32_t child_count,
viz::TestLatestLocalSurfaceIdLookupDelegate* delegate,
viz::FrameSinkManagerImpl* frame_sink_manager,
@@ -54,22 +53,22 @@ void AddHitTestRegion(base::FuzzedDataProvider* fuzz,
return;
// If there's not enough space left for a HitTestRegion, then skip.
- if (fuzz->remaining_bytes() < sizeof(viz::mojom::HitTestRegion))
+ if (fuzz->remaining_bytes() < sizeof(viz::HitTestRegion))
return;
- auto hit_test_region = viz::mojom::HitTestRegion::New();
- hit_test_region->flags = fuzz->ConsumeUint16();
+ viz::HitTestRegion hit_test_region;
+ hit_test_region.flags = fuzz->ConsumeUint16();
if (fuzz->ConsumeBool())
- hit_test_region->flags |= viz::mojom::kHitTestChildSurface;
- hit_test_region->frame_sink_id =
+ hit_test_region.flags |= viz::HitTestRegionFlags::kHitTestChildSurface;
+ hit_test_region.frame_sink_id =
viz::FrameSinkId(fuzz->ConsumeUint8(), fuzz->ConsumeUint8());
- hit_test_region->rect =
+ hit_test_region.rect =
gfx::Rect(fuzz->ConsumeUint8(), fuzz->ConsumeUint8(),
fuzz->ConsumeUint16(), fuzz->ConsumeUint16());
- hit_test_region->transform = GetNextTransform(fuzz);
+ hit_test_region.transform = GetNextTransform(fuzz);
if (fuzz->ConsumeBool() &&
- (hit_test_region->flags & viz::mojom::kHitTestChildSurface)) {
+ (hit_test_region.flags & viz::HitTestRegionFlags::kHitTestChildSurface)) {
// If there's not enough space left for a LocalSurfaceId, then skip.
if (fuzz->remaining_bytes() < sizeof(viz::LocalSurfaceId))
return;
@@ -100,49 +99,40 @@ void SubmitHitTestRegionList(
bool support_is_root,
const uint32_t depth) {
// If there's not enough space left for a HitTestRegionList, then skip.
- if ((fuzz->remaining_bytes() < sizeof(viz::mojom::HitTestRegionList)) ||
+ if (fuzz->remaining_bytes() < sizeof(viz::HitTestRegionList) + sizeof(bool) ||
depth > kMaxDepthAllowed) {
return;
}
- auto hit_test_region_list = viz::mojom::HitTestRegionList::New();
- hit_test_region_list->flags = fuzz->ConsumeUint16();
- if (fuzz->ConsumeBool())
- hit_test_region_list->flags |= viz::mojom::kHitTestChildSurface;
- hit_test_region_list->bounds =
- gfx::Rect(fuzz->ConsumeUint8(), fuzz->ConsumeUint8(),
- fuzz->ConsumeUint16(), fuzz->ConsumeUint16());
- hit_test_region_list->transform = GetNextTransform(fuzz);
-
- uint32_t child_count = fuzz->ConsumeUint16();
- AddHitTestRegion(fuzz, &hit_test_region_list->regions, child_count, delegate,
- frame_sink_manager, surface_id, depth + 1);
+ base::Optional<viz::HitTestRegionList> hit_test_region_list;
+ if (fuzz->ConsumeBool()) {
+ hit_test_region_list.emplace();
+ hit_test_region_list->flags = fuzz->ConsumeUint16();
+ if (fuzz->ConsumeBool())
+ hit_test_region_list->flags |=
+ viz::HitTestRegionFlags::kHitTestChildSurface;
+ hit_test_region_list->bounds =
+ gfx::Rect(fuzz->ConsumeUint8(), fuzz->ConsumeUint8(),
+ fuzz->ConsumeUint16(), fuzz->ConsumeUint16());
+ hit_test_region_list->transform = GetNextTransform(fuzz);
+
+ uint32_t child_count = fuzz->ConsumeUint16();
+ AddHitTestRegion(fuzz, &hit_test_region_list->regions, child_count,
+ delegate, frame_sink_manager, surface_id, depth + 1);
+ }
delegate->SetSurfaceIdMap(surface_id);
viz::CompositorFrameSinkSupport support(
nullptr /* client */, frame_sink_manager, surface_id.frame_sink_id(),
support_is_root, false /* needs_sync_points */);
- support.SubmitCompositorFrame(
- surface_id.local_surface_id(), viz::MakeDefaultCompositorFrame(),
- fuzz->ConsumeBool() ? std::move(hit_test_region_list) : nullptr);
+ support.SubmitCompositorFrame(surface_id.local_surface_id(),
+ viz::MakeDefaultCompositorFrame(),
+ std::move(hit_test_region_list));
}
-class Environment {
- public:
- Environment() {
- // Initialize environment so that we can create the mojo shared memory
- // handles.
- base::CommandLine::Init(0, nullptr);
- mojo::edk::Init();
- }
-};
-
} // namespace
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t num_bytes) {
- // Initialize the environment only once.
- static Environment environment;
-
base::FuzzedDataProvider fuzz(data, num_bytes);
viz::FrameSinkManagerImpl frame_sink_manager;
viz::TestLatestLocalSurfaceIdLookupDelegate delegate;
diff --git a/chromium/components/viz/service/main/viz_main_impl.cc b/chromium/components/viz/service/main/viz_main_impl.cc
index 82cb08d85fc..72b26afce32 100644
--- a/chromium/components/viz/service/main/viz_main_impl.cc
+++ b/chromium/components/viz/service/main/viz_main_impl.cc
@@ -143,7 +143,9 @@ VizMainImpl::VizMainImpl(Delegate* delegate,
gpu_service_ = std::make_unique<GpuServiceImpl>(
gpu_init_->gpu_info(), gpu_init_->TakeWatchdogThread(), io_task_runner(),
- gpu_init_->gpu_feature_info(), gpu_init_->gpu_preferences());
+ gpu_init_->gpu_feature_info(), gpu_init_->gpu_preferences(),
+ gpu_init_->gpu_info_for_hardware_gpu(),
+ gpu_init_->gpu_feature_info_for_hardware_gpu());
}
VizMainImpl::~VizMainImpl() {
@@ -259,11 +261,10 @@ void VizMainImpl::CreateFrameSinkManagerInternal(
DCHECK(gpu_service_);
DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread());
- constexpr bool use_virtualized_gl_context = false;
gpu_command_service_ = base::MakeRefCounted<gpu::GpuInProcessThreadService>(
- use_virtualized_gl_context, gpu_thread_task_runner_,
- gpu_service_->sync_point_manager(), gpu_service_->mailbox_manager(),
- gpu_service_->share_group(), gpu_service_->gpu_feature_info(),
+ gpu_thread_task_runner_, gpu_service_->sync_point_manager(),
+ gpu_service_->mailbox_manager(), gpu_service_->share_group(),
+ gpu_service_->gpu_feature_info(),
gpu_service_->gpu_channel_manager()->gpu_preferences());
compositor_thread_task_runner_->PostTask(
@@ -279,7 +280,7 @@ void VizMainImpl::CreateFrameSinkManagerOnCompositorThread(
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
display_provider_ = std::make_unique<GpuDisplayProvider>(
- params->restart_id, gpu_command_service_,
+ params->restart_id, gpu_service_.get(), gpu_command_service_,
gpu_service_->gpu_channel_manager(),
command_line->HasSwitch(switches::kHeadless),
command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw));
diff --git a/chromium/components/viz/service/main/viz_main_impl.h b/chromium/components/viz/service/main/viz_main_impl.h
index 96b04e47911..fcb3f5680ba 100644
--- a/chromium/components/viz/service/main/viz_main_impl.h
+++ b/chromium/components/viz/service/main/viz_main_impl.h
@@ -6,6 +6,7 @@
#define COMPONENTS_VIZ_SERVICE_MAIN_VIZ_MAIN_IMPL_H_
#include "base/power_monitor/power_monitor.h"
+#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "components/discardable_memory/client/client_discardable_shared_memory_manager.h"
#include "gpu/ipc/in_process_command_buffer.h"
diff --git a/chromium/components/viz/service/surfaces/surface.cc b/chromium/components/viz/service/surfaces/surface.cc
index de5eeb930a3..9f8a1bc373e 100644
--- a/chromium/components/viz/service/surfaces/surface.cc
+++ b/chromium/components/viz/service/surfaces/surface.cc
@@ -494,8 +494,7 @@ void Surface::NotifyAggregatedDamage(const gfx::Rect& damage_rect,
return;
active_frame_data_->aggregated_damage_callback.Run(
- surface_id().local_surface_id(),
- active_frame_data_->frame.size_in_pixels(), damage_rect,
+ surface_id().local_surface_id(), active_frame_data_->frame, damage_rect,
expected_display_time);
}
diff --git a/chromium/components/viz/service/surfaces/surface.h b/chromium/components/viz/service/surfaces/surface.h
index 4d9a63a029f..b0331b956e9 100644
--- a/chromium/components/viz/service/surfaces/surface.h
+++ b/chromium/components/viz/service/surfaces/surface.h
@@ -72,7 +72,7 @@ class VIZ_SERVICE_EXPORT Surface final : public SurfaceDeadlineClient {
public:
using AggregatedDamageCallback =
base::RepeatingCallback<void(const LocalSurfaceId& local_surface_id,
- const gfx::Size& frame_size_in_pixels,
+ const CompositorFrame& frame,
const gfx::Rect& damage_rect,
base::TimeTicks expected_display_time)>;
using PresentedCallback =
diff --git a/chromium/components/viz/service/surfaces/surface_client.h b/chromium/components/viz/service/surfaces/surface_client.h
index 7c1fcdd8299..a4d2a6a7a1d 100644
--- a/chromium/components/viz/service/surfaces/surface_client.h
+++ b/chromium/components/viz/service/surfaces/surface_client.h
@@ -10,14 +10,10 @@
#include "base/macros.h"
#include "components/viz/service/viz_service_export.h"
-namespace cc {
-struct ReturnedResource;
-struct TransferableResource;
-} // namespace cc
-
namespace viz {
-
+struct ReturnedResource;
class Surface;
+struct TransferableResource;
class VIZ_SERVICE_EXPORT SurfaceClient {
public:
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
index f60a39b08af..4e86b838144 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.cc
@@ -59,7 +59,7 @@ void SurfaceDependencyDeadline::InheritFrom(
}
bool SurfaceDependencyDeadline::operator==(
- const SurfaceDependencyDeadline& other) {
+ const SurfaceDependencyDeadline& other) const {
return begin_frame_source_ == other.begin_frame_source_ &&
deadline_ == other.deadline_;
}
diff --git a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
index bc5913b7ed3..9c0349dfdd8 100644
--- a/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
+++ b/chromium/components/viz/service/surfaces/surface_dependency_deadline.h
@@ -45,8 +45,8 @@ class VIZ_SERVICE_EXPORT SurfaceDependencyDeadline : public BeginFrameObserver {
// Takes on the same BeginFrameSource and deadline as |other|.
void InheritFrom(const SurfaceDependencyDeadline& other);
- bool operator==(const SurfaceDependencyDeadline& other);
- bool operator!=(const SurfaceDependencyDeadline& other) {
+ bool operator==(const SurfaceDependencyDeadline& other) const;
+ bool operator!=(const SurfaceDependencyDeadline& other) const {
return !(*this == other);
}
diff --git a/chromium/components/viz/service/surfaces/surface_hittest.cc b/chromium/components/viz/service/surfaces/surface_hittest.cc
index 9ba95d40956..14c50d37f84 100644
--- a/chromium/components/viz/service/surfaces/surface_hittest.cc
+++ b/chromium/components/viz/service/surfaces/surface_hittest.cc
@@ -137,13 +137,13 @@ bool SurfaceHittest::GetTargetSurfaceAtPointInternal(
continue;
}
- // If a point hits a Surface after hitting a non-Surface quad, we should
- // defer to the renderer. Some DrawQuads are not valid hit test targets
- // and information needed to distinguish them is not available here.
- if (non_surface_was_hit) {
- *out_query_renderer = true;
+ // For any point that hits a Surface, we should defer to the renderer.
+ // Some DrawQuads are not valid hit test targets and information
+ // needed to distinguish them is not available here.
+ *out_query_renderer = true;
+
+ if (non_surface_was_hit)
return true;
- }
gfx::Transform transform_to_child_space;
if (GetTargetSurfaceAtPointInternal(
diff --git a/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc b/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
index ed2cf41fd84..e82a5050c29 100644
--- a/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
+++ b/chromium/components/viz/service/surfaces/surface_hittest_unittest.cc
@@ -121,10 +121,10 @@ TEST_F(SurfaceHittestTest, Hittest_BadCompositorFrameDoesNotCrash) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
{
SurfaceHittest hittest(nullptr, surface_manager());
@@ -145,10 +145,10 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
TestCase tests[] = {
{root_surface_id, gfx::Point(100, 100), root_surface_id,
gfx::Point(100, 100), false},
@@ -165,8 +165,8 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
// Add a reference to the child surface on the root surface.
ParentLocalSurfaceIdAllocator child_allocator;
- LocalSurfaceId child_local_surface_id = child_allocator.GenerateId();
- SurfaceId child_surface_id(kChildFrameSink, child_local_surface_id);
+ SurfaceId child_surface_id(kChildFrameSink,
+ child_allocator.GetCurrentLocalSurfaceId());
gfx::Rect child_rect(200, 200);
CreateSurfaceDrawQuad(
root_pass,
@@ -176,10 +176,10 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
// Creates a child surface.
RenderPass* child_pass = nullptr;
@@ -194,19 +194,19 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
root_rect, child_solid_quad_rect);
// Submit the frame.
- child_support().SubmitCompositorFrame(child_local_surface_id,
- std::move(child_frame));
+ child_support().SubmitCompositorFrame(
+ child_allocator.GetCurrentLocalSurfaceId(), std::move(child_frame));
TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
gfx::Point(10, 10), false},
{root_surface_id, gfx::Point(99, 99), root_surface_id,
- gfx::Point(99, 99), false},
+ gfx::Point(99, 99), true},
{root_surface_id, gfx::Point(100, 100), child_surface_id,
gfx::Point(50, 50), true},
{root_surface_id, gfx::Point(199, 199), child_surface_id,
gfx::Point(149, 149), true},
{root_surface_id, gfx::Point(200, 200), root_surface_id,
- gfx::Point(200, 200), false},
+ gfx::Point(200, 200), true},
{root_surface_id, gfx::Point(290, 290), root_surface_id,
gfx::Point(290, 290), false}};
@@ -219,8 +219,8 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
gfx::Transform(1.0f, 0.0f, 0.0f, 75.0f, 0.0f, 1.0f, 0.0f, 75.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f),
root_rect, child_rect, child_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
// Verify that point (100, 100) no longer falls on the child surface.
// Verify that the transform to the child surface's space has also shifted.
@@ -235,7 +235,7 @@ TEST_F(SurfaceHittestTest, Hittest_ChildSurface) {
&transform, &query_renderer));
transform.TransformPoint(&point);
EXPECT_EQ(gfx::Point(100, 100), point);
- EXPECT_EQ(query_renderer, false);
+ EXPECT_EQ(query_renderer, true);
gfx::Point point_in_target_space(100, 100);
gfx::Transform target_transform;
@@ -263,8 +263,8 @@ TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
// Add a reference to the child surface on the root surface.
ParentLocalSurfaceIdAllocator child_allocator;
- LocalSurfaceId child_local_surface_id = child_allocator.GenerateId();
- SurfaceId child_surface_id(kChildFrameSink, child_local_surface_id);
+ SurfaceId child_surface_id(kChildFrameSink,
+ child_allocator.GetCurrentLocalSurfaceId());
gfx::Rect child_rect(200, 200);
CreateSurfaceDrawQuad(
root_pass,
@@ -274,10 +274,10 @@ TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
// Creates a child surface.
RenderPass* child_pass = nullptr;
@@ -292,8 +292,8 @@ TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
root_rect, child_solid_quad_rect);
// Submit the frame.
- child_support().SubmitCompositorFrame(child_local_surface_id,
- std::move(child_frame));
+ child_support().SubmitCompositorFrame(
+ child_allocator.GetCurrentLocalSurfaceId(), std::move(child_frame));
TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
gfx::Point(10, 10), false},
@@ -304,7 +304,7 @@ TEST_F(SurfaceHittestTest, Hittest_OccludedChildSurface) {
{root_surface_id, gfx::Point(199, 199), child_surface_id,
gfx::Point(149, 149), true},
{root_surface_id, gfx::Point(200, 200), root_surface_id,
- gfx::Point(200, 200), false},
+ gfx::Point(200, 200), true},
{root_surface_id, gfx::Point(290, 290), root_surface_id,
gfx::Point(290, 290), false}};
@@ -326,7 +326,8 @@ TEST_F(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
// Add a reference to the child surface on the root surface.
ParentLocalSurfaceIdAllocator child_allocator;
- LocalSurfaceId child_local_surface_id = child_allocator.GenerateId();
+ LocalSurfaceId child_local_surface_id =
+ child_allocator.GetCurrentLocalSurfaceId();
SurfaceId child_surface_id(kChildFrameSink, child_local_surface_id);
gfx::Rect child_rect(200, 200);
CreateSurfaceDrawQuad(
@@ -337,10 +338,10 @@ TEST_F(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
// Creates a child surface.
RenderPass* child_pass = nullptr;
@@ -355,19 +356,19 @@ TEST_F(SurfaceHittestTest, Hittest_InvalidRenderPassDrawQuad) {
root_rect, child_solid_quad_rect);
// Submit the frame.
- child_support().SubmitCompositorFrame(child_local_surface_id,
- std::move(child_frame));
+ child_support().SubmitCompositorFrame(
+ child_allocator.GetCurrentLocalSurfaceId(), std::move(child_frame));
TestCase tests[] = {{root_surface_id, gfx::Point(10, 10), root_surface_id,
gfx::Point(10, 10), false},
{root_surface_id, gfx::Point(99, 99), root_surface_id,
- gfx::Point(99, 99), false},
+ gfx::Point(99, 99), true},
{root_surface_id, gfx::Point(100, 100), child_surface_id,
gfx::Point(50, 50), true},
{root_surface_id, gfx::Point(199, 199), child_surface_id,
gfx::Point(149, 149), true},
{root_surface_id, gfx::Point(200, 200), root_surface_id,
- gfx::Point(200, 200), false},
+ gfx::Point(200, 200), true},
{root_surface_id, gfx::Point(290, 290), root_surface_id,
gfx::Point(290, 290), false}};
@@ -409,10 +410,10 @@ TEST_F(SurfaceHittestTest, Hittest_RenderPassDrawQuad) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
TestCase tests[] = {// These tests just miss the RenderPassDrawQuad.
{root_surface_id, gfx::Point(49, 49), root_surface_id,
@@ -443,8 +444,8 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
// Add a reference to the child surface on the root surface.
ParentLocalSurfaceIdAllocator child_allocator;
- LocalSurfaceId child_local_surface_id = child_allocator.GenerateId();
- SurfaceId child_surface_id(kChildFrameSink, child_local_surface_id);
+ SurfaceId child_surface_id(kChildFrameSink,
+ child_allocator.GetCurrentLocalSurfaceId());
gfx::Rect child_rect(200, 200);
CreateSurfaceDrawQuad(
root_pass,
@@ -454,10 +455,10 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
// Submit the root frame.
ParentLocalSurfaceIdAllocator root_allocator;
- LocalSurfaceId root_local_surface_id = root_allocator.GenerateId();
- SurfaceId root_surface_id(kRootFrameSink, root_local_surface_id);
- root_support().SubmitCompositorFrame(root_local_surface_id,
- std::move(root_frame));
+ SurfaceId root_surface_id(kRootFrameSink,
+ root_allocator.GetCurrentLocalSurfaceId());
+ root_support().SubmitCompositorFrame(
+ root_allocator.GetCurrentLocalSurfaceId(), std::move(root_frame));
// Creates a child surface.
RenderPass* child_pass = nullptr;
@@ -472,8 +473,8 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
root_rect, child_solid_quad_rect);
// Submit the frame.
- child_support().SubmitCompositorFrame(child_local_surface_id,
- std::move(child_frame));
+ child_support().SubmitCompositorFrame(
+ child_allocator.GetCurrentLocalSurfaceId(), std::move(child_frame));
TestCase test_expectations_without_insets[] = {
{root_surface_id, gfx::Point(55, 55), child_surface_id, gfx::Point(5, 5),
@@ -485,9 +486,9 @@ TEST_F(SurfaceHittestTest, Hittest_SingleSurface_WithInsetsDelegate) {
{root_surface_id, gfx::Point(244, 244), child_surface_id,
gfx::Point(194, 194), true},
{root_surface_id, gfx::Point(50, 50), root_surface_id, gfx::Point(50, 50),
- false},
+ true},
{root_surface_id, gfx::Point(249, 249), root_surface_id,
- gfx::Point(249, 249), false},
+ gfx::Point(249, 249), true},
};
TestSurfaceHittestDelegate empty_delegate;