summaryrefslogtreecommitdiff
path: root/chromium/components/viz/service/display
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-24 12:15:48 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-08-28 13:30:04 +0000
commitb014812705fc80bff0a5c120dfcef88f349816dc (patch)
tree25a2e2d9fa285f1add86aa333389a839f81a39ae /chromium/components/viz/service/display
parent9f4560b1027ae06fdb497023cdcaf91b8511fa74 (diff)
downloadqtwebengine-chromium-b014812705fc80bff0a5c120dfcef88f349816dc.tar.gz
BASELINE: Update Chromium to 68.0.3440.125
Change-Id: I23f19369e01f688e496f5bf179abb521ad73874f Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/viz/service/display')
-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
58 files changed, 5764 insertions, 1602 deletions
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.