Commit 418507c6 authored by Khushal's avatar Khushal Committed by Commit Bot

cc/viz: Support animated images in Webview resource-less draw.

The image animation system selects the frame index for the animation
during tile raster. As a result updating the frame of the image is
missed for Webview resourceless draw mode which does not use these tiles
and later rasterizes the display list in SoftwareRenderer. Plumb through
the animation state on the PictureDrawQuad and use it to select the
frame index for image at raster.

R=boliu@chromium.org, danakj@chromium.org

Bug: 849565
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I20f48a664ae816da29e7d55012b7da4dec488ede
Reviewed-on: https://chromium-review.googlesource.com/1087321Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Commit-Queue: Khushal <khushalsagar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565066}
parent 66797144
......@@ -336,10 +336,23 @@ void PictureLayerImpl::AppendQuads(viz::RenderPass* render_pass,
gfx::Size texture_size = quad_content_rect.size();
gfx::RectF texture_rect = gfx::RectF(gfx::SizeF(texture_size));
viz::PictureDrawQuad::ImageAnimationMap image_animation_map;
const auto* controller = layer_tree_impl()->image_animation_controller();
WhichTree tree = layer_tree_impl()->IsPendingTree()
? WhichTree::PENDING_TREE
: WhichTree::ACTIVE_TREE;
for (const auto& image_data : raster_source_->GetDisplayItemList()
->discardable_image_map()
.animated_images_metadata()) {
image_animation_map[image_data.paint_image_id] =
controller->GetFrameIndexForImage(image_data.paint_image_id, tree);
}
auto* quad = render_pass->CreateAndAppendDrawQuad<viz::PictureDrawQuad>();
quad->SetNew(shared_quad_state, geometry_rect, visible_geometry_rect,
needs_blending, texture_rect, texture_size, nearest_neighbor_,
viz::RGBA_8888, quad_content_rect, max_contents_scale,
std::move(image_animation_map),
raster_source_->GetDisplayItemList());
ValidateQuadResources(quad);
return;
......
......@@ -158,6 +158,9 @@ class CC_PAINT_EXPORT PaintImage {
// Returns the total number of frames known to exist in this image.
size_t FrameCount() const;
// Returns an SkImage for the frame at |index|.
sk_sp<SkImage> GetSkImageForFrame(size_t index) const;
std::string ToString() const;
private:
......@@ -180,9 +183,6 @@ class CC_PAINT_EXPORT PaintImage {
void CreateSkImage();
PaintImage MakeSubset(const gfx::Rect& subset) const;
// Returns an SkImage for the frame at |index|.
sk_sp<SkImage> GetSkImageForFrame(size_t index) const;
sk_sp<SkImage> sk_image_;
sk_sp<PaintRecord> paint_record_;
gfx::Rect paint_record_rect_;
......
......@@ -29,7 +29,10 @@ bool FakePaintImageGenerator::GetPixels(const SkImageInfo& info,
uint32_t lazy_pixel_ref) {
if (image_backing_memory_.empty())
return false;
frames_decoded_.insert(frame_index);
if (frames_decoded_count_.find(frame_index) == frames_decoded_count_.end())
frames_decoded_count_[frame_index] = 1;
else
frames_decoded_count_[frame_index]++;
CHECK(image_pixmap_.readPixels(info, pixels, row_bytes, 0, 0));
return true;
}
......
......@@ -5,7 +5,7 @@
#ifndef CC_TEST_FAKE_PAINT_IMAGE_GENERATOR_H_
#define CC_TEST_FAKE_PAINT_IMAGE_GENERATOR_H_
#include "base/containers/flat_set.h"
#include "base/containers/flat_map.h"
#include "cc/paint/paint_image_generator.h"
namespace cc {
......@@ -31,15 +31,15 @@ class FakePaintImageGenerator : public PaintImageGenerator {
size_t frame_index,
uint32_t lazy_pixel_ref) override;
const base::flat_set<size_t>& frames_decoded() const {
return frames_decoded_;
const base::flat_map<size_t, int>& frames_decoded() const {
return frames_decoded_count_;
}
void reset_frames_decoded() { frames_decoded_.clear(); }
void reset_frames_decoded() { frames_decoded_count_.clear(); }
private:
std::vector<uint8_t> image_backing_memory_;
SkPixmap image_pixmap_;
base::flat_set<size_t> frames_decoded_;
base::flat_map<size_t, int> frames_decoded_count_;
};
} // namespace cc
......
......@@ -49,7 +49,8 @@ class SynchronousLayerTreeFrameSink : public viz::TestLayerTreeFrameSink {
const viz::RendererSettings& renderer_settings,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
double refresh_rate,
viz::BeginFrameSource* begin_frame_source)
viz::BeginFrameSource* begin_frame_source,
bool use_software_renderer)
: viz::TestLayerTreeFrameSink(std::move(compositor_context_provider),
std::move(worker_context_provider),
gpu_memory_buffer_manager,
......@@ -59,6 +60,7 @@ class SynchronousLayerTreeFrameSink : public viz::TestLayerTreeFrameSink {
false,
refresh_rate,
begin_frame_source),
use_software_renderer_(use_software_renderer),
task_runner_(std::move(task_runner)),
weak_factory_(this) {}
~SynchronousLayerTreeFrameSink() override = default;
......@@ -105,13 +107,15 @@ class SynchronousLayerTreeFrameSink : public viz::TestLayerTreeFrameSink {
}
void DispatchInvalidation() {
frame_request_pending_ = false;
client_->OnDraw(gfx::Transform(SkMatrix::I()), viewport_, false);
client_->OnDraw(gfx::Transform(SkMatrix::I()), viewport_,
use_software_renderer_);
}
bool frame_request_pending_ = false;
bool frame_ack_pending_ = false;
LayerTreeFrameSinkClient* client_ = nullptr;
gfx::Rect viewport_;
const bool use_software_renderer_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::WeakPtrFactory<SynchronousLayerTreeFrameSink> weak_factory_;
};
......@@ -996,9 +1000,10 @@ void LayerTreeTest::RunTest(CompositorMode mode) {
void LayerTreeTest::RequestNewLayerTreeFrameSink() {
scoped_refptr<viz::TestContextProvider> shared_context_provider =
viz::TestContextProvider::Create();
use_software_renderer_ ? nullptr : viz::TestContextProvider::Create();
scoped_refptr<viz::TestContextProvider> worker_context_provider =
viz::TestContextProvider::CreateWorker();
use_software_renderer_ ? nullptr
: viz::TestContextProvider::CreateWorker();
viz::RendererSettings renderer_settings;
// Spend less time waiting for BeginFrame because the output is
......@@ -1030,7 +1035,7 @@ LayerTreeTest::CreateLayerTreeFrameSink(
return std::make_unique<SynchronousLayerTreeFrameSink>(
compositor_context_provider, std::move(worker_context_provider),
gpu_memory_buffer_manager(), renderer_settings, impl_task_runner_,
refresh_rate, begin_frame_source_);
refresh_rate, begin_frame_source_, use_software_renderer_);
}
return std::make_unique<viz::TestLayerTreeFrameSink>(
......@@ -1044,6 +1049,10 @@ std::unique_ptr<viz::OutputSurface>
LayerTreeTest::CreateDisplayOutputSurfaceOnThread(
scoped_refptr<viz::ContextProvider> compositor_context_provider) {
// By default the Display shares a context with the LayerTreeHostImpl.
if (use_software_renderer_) {
return viz::FakeOutputSurface::CreateSoftware(
std::make_unique<viz::SoftwareOutputDevice>());
}
return viz::FakeOutputSurface::Create3d(
std::move(compositor_context_provider));
}
......
......@@ -172,6 +172,7 @@ class LayerTreeTest : public testing::Test, public TestHooks {
}
bool use_skia_renderer_ = false;
bool use_software_renderer_ = false;
private:
virtual void DispatchAddNoDamageAnimation(
......
......@@ -8260,6 +8260,28 @@ class LayerTreeHostTestImageAnimationSynchronousScheduling
MULTI_THREAD_TEST_F(LayerTreeHostTestImageAnimationSynchronousScheduling);
class LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw
: public LayerTreeHostTestImageAnimationSynchronousScheduling {
public:
void InitializeSettings(LayerTreeSettings* settings) override {
LayerTreeHostTestImageAnimationSynchronousScheduling::InitializeSettings(
settings);
use_software_renderer_ = true;
}
void AfterTest() override {
LayerTreeHostTestImageAnimationSynchronousScheduling::AfterTest();
// 3 frames decoded twice, once during tile raster and once during raster
// for PictureDrawQuad.
for (size_t i = 0u; i < 3u; ++i) {
EXPECT_EQ(generator_->frames_decoded().find(i)->second, 2);
}
}
};
MULTI_THREAD_TEST_F(
LayerTreeHostTestImageAnimationSynchronousSchedulingSoftwareDraw);
class LayerTreeHostTestImageDecodingHints : public LayerTreeHostTest {
public:
void BeginTest() override { PostSetNeedsCommitToMainThread(); }
......
......@@ -459,7 +459,7 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
CREATE_QUAD_NEW(PictureDrawQuad, visible_rect, needs_blending, tex_coord_rect,
texture_size, nearest_neighbor, texture_format, content_rect,
contents_scale, display_item_list);
contents_scale, {}, display_item_list);
EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material);
EXPECT_EQ(visible_rect, copy_quad->visible_rect);
EXPECT_EQ(needs_blending, copy_quad->needs_blending);
......@@ -473,7 +473,7 @@ TEST(DrawQuadTest, CopyPictureDrawQuad) {
CREATE_QUAD_ALL(PictureDrawQuad, tex_coord_rect, texture_size,
nearest_neighbor, texture_format, content_rect,
contents_scale, display_item_list);
contents_scale, {}, display_item_list);
EXPECT_EQ(DrawQuad::PICTURE_CONTENT, copy_quad->material);
EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
EXPECT_EQ(texture_size, copy_quad->texture_size);
......
......@@ -28,6 +28,7 @@ void PictureDrawQuad::SetNew(
ResourceFormat texture_format,
const gfx::Rect& content_rect,
float contents_scale,
ImageAnimationMap image_animation_map,
scoped_refptr<cc::DisplayItemList> display_item_list) {
ContentDrawQuadBase::SetNew(
shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, visible_rect,
......@@ -36,6 +37,7 @@ void PictureDrawQuad::SetNew(
nearest_neighbor, false);
this->content_rect = content_rect;
this->contents_scale = contents_scale;
this->image_animation_map = std::move(image_animation_map);
this->display_item_list = std::move(display_item_list);
this->texture_format = texture_format;
}
......@@ -51,6 +53,7 @@ void PictureDrawQuad::SetAll(
ResourceFormat texture_format,
const gfx::Rect& content_rect,
float contents_scale,
ImageAnimationMap image_animation_map,
scoped_refptr<cc::DisplayItemList> display_item_list) {
ContentDrawQuadBase::SetAll(
shared_quad_state, DrawQuad::PICTURE_CONTENT, rect, visible_rect,
......@@ -59,6 +62,7 @@ void PictureDrawQuad::SetAll(
nearest_neighbor, false);
this->content_rect = content_rect;
this->contents_scale = contents_scale;
this->image_animation_map = std::move(image_animation_map);
this->display_item_list = std::move(display_item_list);
this->texture_format = texture_format;
}
......
......@@ -7,8 +7,10 @@
#include <memory>
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "cc/paint/display_item_list.h"
#include "cc/paint/paint_image.h"
#include "components/viz/common/quads/content_draw_quad_base.h"
#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/viz_common_export.h"
......@@ -25,6 +27,7 @@ class VIZ_COMMON_EXPORT PictureDrawQuad : public ContentDrawQuadBase {
PictureDrawQuad(const PictureDrawQuad& other);
~PictureDrawQuad() override;
using ImageAnimationMap = base::flat_map<cc::PaintImage::Id, size_t>;
void SetNew(const SharedQuadState* shared_quad_state,
const gfx::Rect& rect,
const gfx::Rect& visible_rect,
......@@ -35,6 +38,7 @@ class VIZ_COMMON_EXPORT PictureDrawQuad : public ContentDrawQuadBase {
ResourceFormat texture_format,
const gfx::Rect& content_rect,
float contents_scale,
ImageAnimationMap image_animation_map,
scoped_refptr<cc::DisplayItemList> display_item_list);
void SetAll(const SharedQuadState* shared_quad_state,
......@@ -47,10 +51,12 @@ class VIZ_COMMON_EXPORT PictureDrawQuad : public ContentDrawQuadBase {
ResourceFormat texture_format,
const gfx::Rect& content_rect,
float contents_scale,
ImageAnimationMap image_animation_map,
scoped_refptr<cc::DisplayItemList> display_item_list);
gfx::Rect content_rect;
float contents_scale;
ImageAnimationMap image_animation_map;
scoped_refptr<cc::DisplayItemList> display_item_list;
ResourceFormat texture_format;
......
......@@ -1360,7 +1360,7 @@ TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
blue_quad->SetNew(this->front_quad_state_, this->quad_rect_, this->quad_rect_,
needs_blending, gfx::RectF(this->quad_rect_),
this->quad_rect_.size(), false, RGBA_8888, this->quad_rect_,
1.f, blue_raster_source->GetDisplayItemList());
1.f, {}, blue_raster_source->GetDisplayItemList());
std::unique_ptr<cc::FakeRecordingSource> green_recording =
cc::FakeRecordingSource::CreateFilledRecordingSource(
......@@ -1376,7 +1376,7 @@ TYPED_TEST(IntersectingQuadSoftwareTest, PictureQuads) {
green_quad->SetNew(this->back_quad_state_, this->quad_rect_, this->quad_rect_,
needs_blending, gfx::RectF(this->quad_rect_),
this->quad_rect_.size(), false, RGBA_8888,
this->quad_rect_, 1.f,
this->quad_rect_, 1.f, {},
green_raster_source->GetDisplayItemList());
SCOPED_TRACE("IntersectingPictureQuadsPass");
this->AppendBackgroundAndRunTest(
......@@ -3094,7 +3094,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
viewport, // Intentionally bigger than clip.
viewport, needs_blending, gfx::RectF(viewport),
viewport.size(), nearest_neighbor, texture_format, viewport,
1.f, blue_raster_source->GetDisplayItemList());
1.f, {}, blue_raster_source->GetDisplayItemList());
// One viewport-filling green quad.
std::unique_ptr<cc::FakeRecordingSource> green_recording =
......@@ -3113,7 +3113,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadIdentityScale) {
auto* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad->SetNew(green_shared_state, viewport, viewport, needs_blending,
gfx::RectF(0.f, 0.f, 1.f, 1.f), viewport.size(),
nearest_neighbor, texture_format, viewport, 1.f,
nearest_neighbor, texture_format, viewport, 1.f, {},
green_raster_source->GetDisplayItemList());
RenderPassList pass_list;
......@@ -3155,7 +3155,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
auto* green_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad->SetNew(green_shared_state, viewport, viewport, needs_blending,
gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
texture_format, viewport, 1.f,
texture_format, viewport, 1.f, {},
green_raster_source->GetDisplayItemList());
// One viewport-filling white quad.
......@@ -3175,7 +3175,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadOpacity) {
auto* white_quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
white_quad->SetNew(white_shared_state, viewport, viewport, needs_blending,
gfx::RectF(0, 0, 1, 1), viewport.size(), nearest_neighbor,
texture_format, viewport, 1.f,
texture_format, viewport, 1.f, {},
white_raster_source->GetDisplayItemList());
RenderPassList pass_list;
......@@ -3250,7 +3250,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadDisableImageFiltering) {
auto* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
quad->SetNew(shared_state, viewport, viewport, needs_blending,
gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
texture_format, viewport, 1.f,
texture_format, viewport, 1.f, {},
raster_source->GetDisplayItemList());
RenderPassList pass_list;
......@@ -3302,7 +3302,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNearestNeighbor) {
auto* quad = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
quad->SetNew(shared_state, viewport, viewport, needs_blending,
gfx::RectF(0, 0, 2, 2), viewport.size(), nearest_neighbor,
texture_format, viewport, 1.f,
texture_format, viewport, 1.f, {},
raster_source->GetDisplayItemList());
RenderPassList pass_list;
......@@ -3522,14 +3522,14 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
top_right_green_shared_quad_state, green_rect1, green_rect1,
needs_blending, gfx::RectF(gfx::SizeF(green_rect1.size())),
green_rect1.size(), nearest_neighbor, texture_format, green_rect1, 1.f,
green_raster_source->GetDisplayItemList());
{}, green_raster_source->GetDisplayItemList());
auto* green_quad2 = pass->CreateAndAppendDrawQuad<PictureDrawQuad>();
green_quad2->SetNew(
top_right_green_shared_quad_state, green_rect2, green_rect2,
needs_blending, gfx::RectF(gfx::SizeF(green_rect2.size())),
green_rect2.size(), nearest_neighbor, texture_format, green_rect2, 1.f,
green_raster_source->GetDisplayItemList());
{}, green_raster_source->GetDisplayItemList());
// Add a green clipped checkerboard in the bottom right to help test
// interleaving picture quad content and solid color content.
......@@ -3593,7 +3593,7 @@ TYPED_TEST(SoftwareRendererPixelTest, PictureDrawQuadNonIdentityScale) {
blue_quad->SetNew(blue_shared_state, quad_content_rect, quad_content_rect,
needs_blending, gfx::RectF(quad_content_rect),
content_union_rect.size(), nearest_neighbor, texture_format,
content_union_rect, contents_scale,
content_union_rect, contents_scale, {},
raster_source->GetDisplayItemList());
// Fill left half of viewport with green.
......
......@@ -6,6 +6,7 @@
#include "base/trace_event/trace_event.h"
#include "cc/base/math_util.h"
#include "cc/paint/image_provider.h"
#include "cc/paint/render_surface_filters.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/frame_sinks/copy_output_request.h"
......@@ -37,6 +38,32 @@
#include "ui/gfx/transform.h"
namespace viz {
namespace {
class AnimatedImagesProvider : public cc::ImageProvider {
public:
AnimatedImagesProvider(
const PictureDrawQuad::ImageAnimationMap* image_animation_map)
: image_animation_map_(image_animation_map) {}
~AnimatedImagesProvider() override = default;
ScopedDecodedDrawImage GetDecodedDrawImage(
const cc::DrawImage& draw_image) override {
const auto& paint_image = draw_image.paint_image();
auto it = image_animation_map_->find(paint_image.stable_id());
size_t frame_index = it == image_animation_map_->end()
? paint_image.frame_index()
: it->second;
return ScopedDecodedDrawImage(cc::DecodedDrawImage(
paint_image.GetSkImageForFrame(frame_index), SkSize::Make(0, 0),
SkSize::Make(1.f, 1.f), draw_image.filter_quality(),
true /* is_budgeted */));
}
private:
const PictureDrawQuad::ImageAnimationMap* image_animation_map_;
};
} // namespace
SoftwareRenderer::SoftwareRenderer(const RendererSettings* settings,
OutputSurface* output_surface,
......@@ -326,11 +353,14 @@ void SoftwareRenderer::DrawPictureQuad(const PictureDrawQuad* quad) {
// Treat all subnormal values as zero for performance.
cc::ScopedSubnormalFloatDisabler disabler;
// Use an image provider to select the correct frame for animated images.
AnimatedImagesProvider image_provider(&quad->image_animation_map);
raster_canvas->save();
raster_canvas->translate(-quad->content_rect.x(), -quad->content_rect.y());
raster_canvas->clipRect(gfx::RectToSkRect(quad->content_rect));
raster_canvas->scale(quad->contents_scale, quad->contents_scale);
quad->display_item_list->Raster(raster_canvas);
quad->display_item_list->Raster(raster_canvas, &image_provider);
raster_canvas->restore();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment