#include "ui/gl/delegated_ink_point_renderer_gpu.h"
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/win/hidden_window.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gl/dc_layer_tree.h"
#include "ui/gl/dcomp_presenter.h"
#include "ui/gl/direct_composition_support.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_test_helper.h"
namespace gl {
namespace {
const int kMicrosecondsBetweenEachPoint = 10;
class DelegatedInkPointRendererGpuTest : public testing::Test {
public:
DelegatedInkPointRendererGpuTest() : parent_window_(ui::GetHiddenWindow()) {}
DCompPresenter* presenter() { return presenter_.get(); }
DCLayerTree* layer_tree() { return presenter()->GetLayerTreeForTesting(); }
DCLayerTree::DelegatedInkRenderer* ink_renderer() {
return layer_tree()->GetInkRendererForTesting();
}
void SendDelegatedInkPoint(const gfx::DelegatedInkPoint& point) {
stored_points_[point.pointer_id()].push_back(point);
ink_renderer()->StoreDelegatedInkPoint(point);
}
void SendDelegatedInkPointBasedOnPrevious(uint32_t pointer_id) {
EXPECT_TRUE(stored_points_.find(pointer_id) != stored_points_.end());
EXPECT_TRUE(!stored_points_[pointer_id].empty());
auto last_point = stored_points_[pointer_id].back();
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
last_point.point() + gfx::Vector2dF(5, 5),
last_point.timestamp() +
base::Microseconds(kMicrosecondsBetweenEachPoint),
last_point.pointer_id()));
}
void SendDelegatedInkPointBasedOnPrevious() {
EXPECT_EQ(stored_points_.size(), 1u);
SendDelegatedInkPointBasedOnPrevious(stored_points_.begin()->first);
}
void SendMetadata(const gfx::DelegatedInkMetadata& metadata) {
ink_renderer()->SetDelegatedInkTrailStartPoint(
std::make_unique<gfx::DelegatedInkMetadata>(metadata));
}
void SendNewTrailMetadata() {
EXPECT_EQ(stored_points_.size(), 1u);
auto points_it = stored_points_.find(stored_points_.begin()->first);
EXPECT_TRUE(points_it != stored_points_.end());
auto points_vec = points_it->second;
EXPECT_GT(points_vec.size(), 0u);
auto& last_point = points_vec.back();
gfx::DelegatedInkMetadata metadata(
last_point.point() + gfx::Vector2dF(5, 5), 3,
SK_ColorBLACK,
last_point.timestamp() +
base::Microseconds(kMicrosecondsBetweenEachPoint),
gfx::RectF(0, 0, 100, 100), false);
ink_renderer()->SetDelegatedInkTrailStartPoint(
std::make_unique<gfx::DelegatedInkMetadata>(metadata));
}
gfx::DelegatedInkMetadata SendMetadataBasedOnStoredPoint(int32_t pointer_id,
uint64_t point) {
EXPECT_TRUE(stored_points_.find(pointer_id) != stored_points_.end());
EXPECT_GE(stored_points_[pointer_id].size(), point);
const gfx::DelegatedInkPoint& ink_point = stored_points_[pointer_id][point];
gfx::DelegatedInkMetadata metadata(
ink_point.point(), 3, SK_ColorBLACK, ink_point.timestamp(),
gfx::RectF(0, 0, 100, 100), false);
SendMetadata(metadata);
return metadata;
}
gfx::DelegatedInkMetadata SendMetadataBasedOnStoredPoint(uint64_t point) {
EXPECT_EQ(stored_points_.size(), 1u);
return SendMetadataBasedOnStoredPoint(stored_points_.begin()->first, point);
}
void StoredMetadataMatchesSentMetadata(
const gfx::DelegatedInkMetadata& sent_metadata) {
gfx::DelegatedInkMetadata* renderer_metadata =
ink_renderer()->MetadataForTesting();
EXPECT_TRUE(renderer_metadata);
EXPECT_EQ(renderer_metadata->point(), sent_metadata.point());
EXPECT_EQ(renderer_metadata->diameter(), sent_metadata.diameter());
EXPECT_EQ(renderer_metadata->color(), sent_metadata.color());
EXPECT_EQ(renderer_metadata->timestamp(), sent_metadata.timestamp());
EXPECT_EQ(renderer_metadata->presentation_area(),
sent_metadata.presentation_area());
EXPECT_EQ(renderer_metadata->is_hovering(), sent_metadata.is_hovering());
}
protected:
void SetUp() override {
display_ = gl::init::InitializeGLNoExtensionsOneOff(
true,
gl::GpuPreference::kDefault);
if (!gl::DirectCompositionSupported()) {
GTEST_SKIP()
<< "GL implementation not using DirectComposition, skipping test.";
}
std::tie(gl_surface_, context_) =
GLTestHelper::CreateOffscreenGLSurfaceAndContext();
CreateDCompPresenter();
if (!presenter_->SupportsDelegatedInk()) {
GTEST_SKIP() << "Delegated ink unsupported, skipping test.";
}
constexpr gfx::Size window_size(100, 100);
EXPECT_TRUE(presenter_->Resize(window_size, 1.0, gfx::ColorSpace(), true));
ink_renderer()->InitializeForTesting(gl::GetDirectCompositionDevice());
}
void TearDown() override {
context_.reset();
gl_surface_.reset();
if (presenter_) {
DestroyPresenter(std::move(presenter_));
}
gl::init::ShutdownGL(display_, false);
}
private:
void CreateDCompPresenter() {
DCompPresenter::Settings settings;
presenter_ = base::MakeRefCounted<DCompPresenter>(settings);
if (parent_window_)
::SetParent(presenter_->GetWindow(), parent_window_);
}
void DestroyPresenter(scoped_refptr<DCompPresenter> presenter) {
scoped_refptr<base::TaskRunner> task_runner =
presenter->GetWindowTaskRunnerForTesting();
EXPECT_TRUE(presenter->HasOneRef());
presenter = nullptr;
base::RunLoop run_loop;
task_runner->PostTask(FROM_HERE, run_loop.QuitClosure());
run_loop.Run();
}
HWND parent_window_;
scoped_refptr<GLSurface> gl_surface_;
scoped_refptr<DCompPresenter> presenter_;
scoped_refptr<GLContext> context_;
raw_ptr<GLDisplay> display_ = nullptr;
std::map<int32_t, std::vector<gfx::DelegatedInkPoint>> stored_points_;
};
TEST_F(DelegatedInkPointRendererGpuTest, StoreAndRemovePointsAndTokens) {
const int32_t kPointerId = 1;
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
gfx::PointF(10, 10), base::TimeTicks::Now(), kPointerId));
const uint64_t kPointsToStore = 5u;
for (uint64_t i = 1; i < kPointsToStore; ++i)
SendDelegatedInkPointBasedOnPrevious();
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
kPointsToStore);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(), 0u);
EXPECT_FALSE(ink_renderer()->MetadataForTesting());
EXPECT_TRUE(ink_renderer()->WaitForNewTrailToDrawForTesting());
gfx::DelegatedInkMetadata metadata = SendMetadataBasedOnStoredPoint(0);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
kPointsToStore);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(), kPointsToStore);
EXPECT_FALSE(ink_renderer()->WaitForNewTrailToDrawForTesting());
StoredMetadataMatchesSentMetadata(metadata);
const uint64_t kPointToSend = 3u;
metadata = SendMetadataBasedOnStoredPoint(kPointToSend);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
kPointsToStore - kPointToSend - 1);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(),
kPointsToStore - kPointToSend - 1);
StoredMetadataMatchesSentMetadata(metadata);
gfx::DelegatedInkPoint last_point =
ink_renderer()->DelegatedInkPointsForTesting(kPointerId).rbegin()->first;
metadata = gfx::DelegatedInkMetadata(
last_point.point() + gfx::Vector2dF(2, 2), 3, SK_ColorBLACK,
last_point.timestamp() + base::Microseconds(20),
gfx::RectF(0, 0, 100, 100), false);
SendMetadata(metadata);
EXPECT_EQ(ink_renderer()->DelegatedInkPointPointerIdCountForTesting(), 0u);
StoredMetadataMatchesSentMetadata(metadata);
}
TEST_F(DelegatedInkPointRendererGpuTest, DrawPointsAsTheyArrive) {
gfx::DelegatedInkMetadata metadata(
gfx::PointF(12, 12), 3, SK_ColorBLACK,
base::TimeTicks::Now(), gfx::RectF(10, 10, 90, 90), false);
SendMetadata(metadata);
const int32_t kPointerId = 1;
const uint64_t kPointsToSend = 5u;
for (uint64_t i = 1u; i <= kPointsToSend; ++i) {
if (i == 1) {
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
metadata.point(), metadata.timestamp(), kPointerId));
} else {
SendDelegatedInkPointBasedOnPrevious();
}
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
i);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(), i);
}
gfx::DelegatedInkPoint last_point =
ink_renderer()->DelegatedInkPointsForTesting(kPointerId).rbegin()->first;
gfx::DelegatedInkPoint outside_point(
gfx::PointF(5, 5), last_point.timestamp() + base::Microseconds(10),
1);
EXPECT_FALSE(metadata.presentation_area().Contains(outside_point.point()));
SendDelegatedInkPoint(outside_point);
const uint64_t kTotalPointsSent = kPointsToSend + 1u;
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
kTotalPointsSent);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(), kPointsToSend);
const uint64_t kMetadataToSend = 3u;
SendMetadataBasedOnStoredPoint(kMetadataToSend);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId).size(),
kTotalPointsSent - kMetadataToSend - 1);
EXPECT_EQ(ink_renderer()->InkTrailTokenCountForTesting(), 1u);
}
TEST_F(DelegatedInkPointRendererGpuTest, MultiplePointerIds) {
const int32_t kPointerId1 = 1;
const int32_t kPointerId2 = 2;
const base::TimeTicks timestamp = base::TimeTicks::Now();
const int kPointerId2PointsAheadOfPointerId1 = 3;
SendDelegatedInkPoint(
gfx::DelegatedInkPoint(gfx::PointF(16, 22), timestamp, kPointerId1));
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
gfx::PointF(40, 13.3f),
timestamp + base::Microseconds(kPointerId2PointsAheadOfPointerId1 *
kMicrosecondsBetweenEachPoint),
kPointerId2));
uint64_t pointer_id_1_count = 1u;
uint64_t pointer_id_2_count = 1u;
const uint64_t kTotalPoints = 9u;
for (uint64_t i = 0u; i < kTotalPoints; ++i) {
if (i % 2 == 0) {
SendDelegatedInkPointBasedOnPrevious(kPointerId1);
pointer_id_1_count++;
} else {
SendDelegatedInkPointBasedOnPrevious(kPointerId2);
pointer_id_2_count++;
}
}
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId1).size(),
pointer_id_1_count);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId2).size(),
pointer_id_2_count);
const uint64_t kMetadataToSendForPointerId1 = 1u;
SendMetadataBasedOnStoredPoint(kPointerId1, kMetadataToSendForPointerId1);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId1).size(),
pointer_id_1_count - kMetadataToSendForPointerId1);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId2).size(),
pointer_id_2_count);
const uint64_t kMetadataToSendForPointerId2 = 2u;
SendMetadataBasedOnStoredPoint(kPointerId2, kMetadataToSendForPointerId2);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId1).size(),
pointer_id_1_count - kPointerId2PointsAheadOfPointerId1 -
kMetadataToSendForPointerId2);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId2).size(),
pointer_id_2_count - kMetadataToSendForPointerId2);
const int32_t kPointerId3 = 3;
const int kPointerId3PointsAheadOfPointerId1 = 5;
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
gfx::PointF(23, 64),
timestamp + base::Microseconds(kPointerId3PointsAheadOfPointerId1 *
kMicrosecondsBetweenEachPoint),
kPointerId3));
const uint64_t kPointsWithPointerId3 = 4u;
for (uint64_t i = 1u; i < kPointsWithPointerId3; ++i)
SendDelegatedInkPointBasedOnPrevious(kPointerId3);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId1).size(),
pointer_id_1_count - kPointerId2PointsAheadOfPointerId1 -
kMetadataToSendForPointerId2);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId2).size(),
pointer_id_2_count - kMetadataToSendForPointerId2);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId3).size(),
kPointsWithPointerId3);
const uint64_t kMetadataToSendForPointerId3 = 1u;
SendMetadataBasedOnStoredPoint(kPointerId3, kMetadataToSendForPointerId3);
EXPECT_EQ(ink_renderer()->DelegatedInkPointPointerIdCountForTesting(), 2u);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId2).size(),
pointer_id_2_count - kMetadataToSendForPointerId2 -
kMetadataToSendForPointerId3);
EXPECT_EQ(ink_renderer()->DelegatedInkPointsForTesting(kPointerId3).size(),
kPointsWithPointerId3 - kMetadataToSendForPointerId3);
}
TEST_F(DelegatedInkPointRendererGpuTest, MaximumPointerIds) {
const base::TimeTicks kEarliestTimestamp =
base::TimeTicks::Now() -
base::Microseconds(kMicrosecondsBetweenEachPoint);
const int32_t kEarliestTimestampPointerId = 4;
base::TimeTicks timestamp = base::TimeTicks::Now();
gfx::PointF point(34.4f, 20);
const uint64_t kMaxNumberOfPointerIds =
ink_renderer()->GetMaximumNumberOfPointerIdsForTesting();
for (uint64_t pointer_id = 0; pointer_id < kMaxNumberOfPointerIds;
++pointer_id) {
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
point,
pointer_id == kEarliestTimestampPointerId ? kEarliestTimestamp
: timestamp,
pointer_id));
point += gfx::Vector2dF(5, 5);
timestamp += base::Microseconds(kMicrosecondsBetweenEachPoint);
}
EXPECT_EQ(ink_renderer()->DelegatedInkPointPointerIdCountForTesting(),
kMaxNumberOfPointerIds);
EXPECT_TRUE(
ink_renderer()->CheckForPointerIdForTesting(kEarliestTimestampPointerId));
SendDelegatedInkPoint(
gfx::DelegatedInkPoint(point, timestamp, kMaxNumberOfPointerIds));
EXPECT_EQ(ink_renderer()->DelegatedInkPointPointerIdCountForTesting(),
kMaxNumberOfPointerIds);
EXPECT_FALSE(
ink_renderer()->CheckForPointerIdForTesting(kEarliestTimestampPointerId));
point += gfx::Vector2dF(5, 5);
timestamp = kEarliestTimestamp + base::Microseconds(5);
const int32_t kEarlyTimestampPointerId = kMaxNumberOfPointerIds + 1;
SendDelegatedInkPoint(
gfx::DelegatedInkPoint(point, timestamp, kEarlyTimestampPointerId));
EXPECT_EQ(ink_renderer()->DelegatedInkPointPointerIdCountForTesting(),
kMaxNumberOfPointerIds);
EXPECT_FALSE(
ink_renderer()->CheckForPointerIdForTesting(kEarlyTimestampPointerId));
}
TEST_F(DelegatedInkPointRendererGpuTest, ReportTimeToDraw) {
const std::string kHistogramName =
"Renderer.DelegatedInkTrail.OS.TimeToDrawPointsMillis";
const base::HistogramTester histogram_tester;
constexpr int32_t kPointerId = 1u;
EXPECT_TRUE(ink_renderer()->PointstoBeDrawnForTesting().empty());
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 0);
const base::TimeTicks timestamp = base::TimeTicks::Now();
SendDelegatedInkPoint(
gfx::DelegatedInkPoint(gfx::PointF(20, 20), timestamp, kPointerId));
SendMetadataBasedOnStoredPoint(0);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting().size(), 1u);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting()[0].timestamp(),
timestamp);
SendDelegatedInkPointBasedOnPrevious(kPointerId);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting().size(), 2u);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting()[1].timestamp(),
timestamp + base::Microseconds(kMicrosecondsBetweenEachPoint));
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 2);
EXPECT_TRUE(ink_renderer()->PointstoBeDrawnForTesting().empty());
}
TEST_F(DelegatedInkPointRendererGpuTest,
PointsToBeDrawnIsClearedWithNewMetadata) {
constexpr int32_t kPointerId = 1u;
const base::TimeTicks timestamp = base::TimeTicks::Now();
SendDelegatedInkPoint(
gfx::DelegatedInkPoint(gfx::PointF(20, 20), timestamp, kPointerId));
SendMetadataBasedOnStoredPoint(0);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting().size(), 1u);
SendDelegatedInkPointBasedOnPrevious();
SendDelegatedInkPointBasedOnPrevious();
SendDelegatedInkPointBasedOnPrevious();
SendMetadataBasedOnStoredPoint(3);
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting().size(), 1u);
SendNewTrailMetadata();
EXPECT_EQ(ink_renderer()->PointstoBeDrawnForTesting().size(), 0u);
}
TEST_F(DelegatedInkPointRendererGpuTest, ReportLatencyImprovement) {
const std::string kHistogramName =
"Renderer.DelegatedInkTrail.LatencyImprovement.OS.WithoutPrediction";
const base::HistogramTester histogram_tester;
constexpr int32_t kPointerId = 1u;
ink_renderer()->ReportPointsDrawn();
EXPECT_TRUE(ink_renderer()->PointstoBeDrawnForTesting().empty());
histogram_tester.ExpectTotalCount(kHistogramName, 0);
gfx::DelegatedInkPoint point_1(gfx::PointF(20, 20), base::TimeTicks::Now(),
kPointerId);
gfx::DelegatedInkPoint point_2(
point_1.point() + gfx::Vector2dF(5, 5),
point_1.timestamp() + base::Milliseconds(kMicrosecondsBetweenEachPoint),
kPointerId);
gfx::DelegatedInkPoint point_3(
point_2.point() + gfx::Vector2dF(5, 5),
point_2.timestamp() + base::Milliseconds(kMicrosecondsBetweenEachPoint),
kPointerId);
SendDelegatedInkPoint(point_1);
SendDelegatedInkPoint(point_2);
SendDelegatedInkPoint(point_3);
SendMetadataBasedOnStoredPoint(0);
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectUniqueSample(kHistogramName,
kMicrosecondsBetweenEachPoint * 2, 1);
EXPECT_TRUE(ink_renderer()->PointstoBeDrawnForTesting().empty());
}
TEST_F(DelegatedInkPointRendererGpuTest, ReportOutstandingPointsToDraw) {
const std::string kHistogramName =
"Renderer.DelegatedInkTrail.OS.OutstandingPointsToDraw";
const base::HistogramTester histogram_tester;
constexpr int32_t kPointerId = 1u;
histogram_tester.ExpectTotalCount(kHistogramName, 0);
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
gfx::PointF(10, 10), base::TimeTicks::Now(), kPointerId));
ink_renderer()->ReportPointsDrawn();
SendMetadataBasedOnStoredPoint(0);
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectUniqueSample(kHistogramName, 1, 1);
SendDelegatedInkPointBasedOnPrevious();
SendDelegatedInkPointBasedOnPrevious();
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectBucketCount(kHistogramName, 2, 1);
histogram_tester.ExpectBucketCount(kHistogramName, 1, 1);
SendDelegatedInkPointBasedOnPrevious();
SendDelegatedInkPointBasedOnPrevious();
SendDelegatedInkPointBasedOnPrevious();
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectBucketCount(kHistogramName, 3, 1);
histogram_tester.ExpectBucketCount(kHistogramName, 2, 1);
histogram_tester.ExpectBucketCount(kHistogramName, 1, 1);
}
TEST_F(DelegatedInkPointRendererGpuTest, TestTimeFromDelegatedInkToApiPaint) {
const std::string kHistogramName =
"Renderer.DelegatedInkTrail.OS.TimeFromDelegatedInkToApiPaint";
const base::HistogramTester histogram_tester;
constexpr int32_t kPointerId = 1u;
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 0);
SendDelegatedInkPoint(gfx::DelegatedInkPoint(
gfx::PointF(10, 10), base::TimeTicks::Now(), kPointerId));
SendMetadataBasedOnStoredPoint(0);
ink_renderer()->ReportPointsDrawn();
gfx::DelegatedInkPoint last_point =
ink_renderer()->DelegatedInkPointsForTesting(kPointerId).rbegin()->first;
EXPECT_TRUE(last_point.paint_timestamp().has_value());
histogram_tester.ExpectTotalCount(kHistogramName, 0);
SendDelegatedInkPointBasedOnPrevious();
ink_renderer()->ReportPointsDrawn();
SendMetadataBasedOnStoredPoint(1);
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 1);
SendDelegatedInkPointBasedOnPrevious();
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 1);
SendMetadataBasedOnStoredPoint(2);
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 2);
SendDelegatedInkPointBasedOnPrevious();
ink_renderer()->ReportPointsDrawn();
last_point =
ink_renderer()->DelegatedInkPointsForTesting(kPointerId).rbegin()->first;
SendMetadata(gfx::DelegatedInkMetadata(
last_point.point() + gfx::Vector2dF(2, 2), 3, SK_ColorBLACK,
last_point.timestamp() + base::Microseconds(20),
gfx::RectF(0, 0, 100, 100), false));
ink_renderer()->ReportPointsDrawn();
histogram_tester.ExpectTotalCount(kHistogramName, 2);
}
}
}