Commit 1bf98894 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Measure text pixels in LCD text and in non-LCD text

This can be used to evaluate the effectiveness of measures to increase
LCD text.

(TBR for trivial change under tools/perf/measurements)
TBR=wenbinzhang@chromium.org

Bug: 642885
Change-Id: I97dd8aca06a91f5cd1d7f922ac70345e0e3a986c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2136698
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757078}
parent 6f086a44
......@@ -13,6 +13,7 @@
#include "base/values.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/picture_layer_impl.h"
#include "cc/paint/display_item_list.h"
#include "cc/raster/playback_image_provider.h"
#include "cc/raster/raster_buffer_provider.h"
#include "cc/trees/layer_tree_host_impl.h"
......@@ -158,6 +159,10 @@ void RasterizeAndRecordBenchmarkImpl::DidCompleteCommit(
rasterize_results_.pixels_rasterized_with_non_solid_color);
result->SetInteger("pixels_rasterized_as_opaque",
rasterize_results_.pixels_rasterized_as_opaque);
result->SetInteger("visible_pixels_for_lcd_text",
rasterize_results_.visible_pixels_for_lcd_text);
result->SetInteger("visible_pixels_for_non_lcd_text",
rasterize_results_.visible_pixels_for_non_lcd_text);
result->SetInteger("total_layers", rasterize_results_.total_layers);
result->SetInteger("total_picture_layers",
rasterize_results_.total_picture_layers);
......@@ -180,6 +185,14 @@ void RasterizeAndRecordBenchmarkImpl::RunOnLayer(PictureLayerImpl* layer) {
return;
}
int text_pixels =
layer->GetRasterSource()->GetDisplayItemList()->AreaOfDrawText(
layer->visible_layer_rect());
if (layer->CanUseLCDText())
rasterize_results_.visible_pixels_for_lcd_text += text_pixels;
else
rasterize_results_.visible_pixels_for_non_lcd_text += text_pixels;
FixedInvalidationPictureLayerTilingClient client(layer,
gfx::Rect(layer->bounds()));
......@@ -230,6 +243,8 @@ RasterizeAndRecordBenchmarkImpl::RasterizeResults::RasterizeResults()
: pixels_rasterized(0),
pixels_rasterized_with_non_solid_color(0),
pixels_rasterized_as_opaque(0),
visible_pixels_for_lcd_text(0),
visible_pixels_for_non_lcd_text(0),
total_layers(0),
total_picture_layers(0),
total_picture_layers_with_no_content(0),
......
......@@ -41,6 +41,8 @@ class RasterizeAndRecordBenchmarkImpl : public MicroBenchmarkImpl {
int pixels_rasterized;
int pixels_rasterized_with_non_solid_color;
int pixels_rasterized_as_opaque;
int visible_pixels_for_lcd_text;
int visible_pixels_for_non_lcd_text;
base::TimeDelta total_best_time;
int total_layers;
int total_picture_layers;
......
......@@ -31,27 +31,28 @@ bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) {
return true;
}
void FillTextContent(const PaintOpBuffer* buffer,
std::vector<NodeId>* content) {
template <typename Function>
void IterateTextContent(const PaintOpBuffer* buffer, const Function& yield) {
for (auto* op : PaintOpBuffer::Iterator(buffer)) {
if (op->GetType() == PaintOpType::DrawTextBlob) {
content->push_back(static_cast<DrawTextBlobOp*>(op)->node_id);
yield(static_cast<DrawTextBlobOp*>(op));
} else if (op->GetType() == PaintOpType::DrawRecord) {
FillTextContent(static_cast<DrawRecordOp*>(op)->record.get(), content);
IterateTextContent(static_cast<DrawRecordOp*>(op)->record.get(), yield);
}
}
}
void FillTextContentByOffsets(const PaintOpBuffer* buffer,
template <typename Function>
void IterateTextContentByOffsets(const PaintOpBuffer* buffer,
const std::vector<size_t>& offsets,
std::vector<NodeId>* content) {
const Function& yield) {
if (!buffer)
return;
for (auto* op : PaintOpBuffer::OffsetIterator(buffer, &offsets)) {
if (op->GetType() == PaintOpType::DrawTextBlob) {
content->push_back(static_cast<DrawTextBlobOp*>(op)->node_id);
yield(static_cast<DrawTextBlobOp*>(op));
} else if (op->GetType() == PaintOpType::DrawRecord) {
FillTextContent(static_cast<DrawRecordOp*>(op)->record.get(), content);
IterateTextContent(static_cast<DrawRecordOp*>(op)->record.get(), yield);
}
}
}
......@@ -85,7 +86,23 @@ void DisplayItemList::CaptureContent(const gfx::Rect& rect,
std::vector<NodeId>* content) const {
std::vector<size_t> offsets;
rtree_.Search(rect, &offsets);
FillTextContentByOffsets(&paint_op_buffer_, offsets, content);
IterateTextContentByOffsets(
&paint_op_buffer_, offsets,
[content](const DrawTextBlobOp* op) { content->push_back(op->node_id); });
}
double DisplayItemList::AreaOfDrawText(const gfx::Rect& rect) const {
std::vector<size_t> offsets;
rtree_.Search(rect, &offsets);
double area = 0;
IterateTextContentByOffsets(
&paint_op_buffer_, offsets, [&area](const DrawTextBlobOp* op) {
// This is not fully accurate, e.g. when there is transform operations,
// but is good for statistics purpose.
SkRect bounds = op->blob->bounds();
area += static_cast<double>(bounds.width()) * bounds.height();
});
return area;
}
void DisplayItemList::Finalize() {
......
......@@ -62,11 +62,15 @@ class CC_PAINT_EXPORT DisplayItemList
void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const;
// Captures the DrawTextBlobOp within |rect| and returns the associated
// NodeId in |content|.
// Captures |DrawTextBlobOp|s intersecting |rect| and returns the associated
// |NodeId|s in |content|.
void CaptureContent(const gfx::Rect& rect,
std::vector<NodeId>* content) const;
// Returns the approximate total area covered by |DrawTextBlobOp|s
// intersecting |rect|, used for statistics purpose.
double AreaOfDrawText(const gfx::Rect& rect) const;
void StartPaint() {
#if DCHECK_IS_ON()
DCHECK(!IsPainting());
......
......@@ -1132,4 +1132,55 @@ TEST_F(DisplayItemListTest, TotalOpCount) {
EXPECT_EQ(8u, list->TotalOpCount());
}
TEST_F(DisplayItemListTest, AreaOfDrawText) {
auto list = base::MakeRefCounted<DisplayItemList>();
auto sub_list = base::MakeRefCounted<DisplayItemList>();
auto text_blob1 = SkTextBlob::MakeFromString("ABCD", SkFont());
auto text_blob1_bounds = text_blob1->bounds();
auto text_blob1_area = text_blob1_bounds.width() * text_blob1_bounds.height();
auto text_blob2 = SkTextBlob::MakeFromString("EFG", SkFont());
auto text_blob2_bounds = text_blob2->bounds();
auto text_blob2_area = text_blob2_bounds.width() * text_blob2_bounds.height();
sub_list->StartPaint();
sub_list->push<DrawRectOp>(SkRect::MakeWH(100, 200), PaintFlags());
sub_list->push<DrawTextBlobOp>(text_blob1, 0, 0, PaintFlags());
sub_list->EndPaintOfUnpaired(gfx::Rect());
auto record = sub_list->ReleaseAsRecord();
list->StartPaint();
list->push<SaveOp>();
list->push<TranslateOp>(100, 100);
list->push<DrawRecordOp>(record);
list->push<RestoreOp>();
list->EndPaintOfUnpaired(gfx::Rect(100, 100, 100, 200));
list->StartPaint();
list->push<SaveOp>();
list->push<TranslateOp>(100, 400);
list->push<DrawRecordOp>(record);
list->push<RestoreOp>();
list->EndPaintOfUnpaired(gfx::Rect(100, 400, 100, 200));
list->StartPaint();
list->push<DrawRectOp>(SkRect::MakeWH(100, 100), PaintFlags());
list->push<DrawTextBlobOp>(text_blob2, 10, 20, PaintFlags());
list->EndPaintOfUnpaired(gfx::Rect(0, 0, 100, 100));
list->StartPaint();
list->push<DrawTextBlobOp>(text_blob2, 400, 100, PaintFlags());
list->push<DrawRectOp>(SkRect::MakeXYWH(400, 100, 100, 100), PaintFlags());
list->EndPaintOfUnpaired(gfx::Rect(400, 100, 100, 100));
list->Finalize();
// This includes the DrawTextBlobOp in the first DrawRecordOp the the first
// direct DrawTextBlobOp.
EXPECT_EQ(static_cast<int>(text_blob1_area + text_blob2_area),
static_cast<int>(list->AreaOfDrawText(gfx::Rect(0, 0, 200, 200))));
// This includes all DrawTextBlobOps.
EXPECT_EQ(static_cast<int>(text_blob1_area * 2 + text_blob2_area * 2),
static_cast<int>(list->AreaOfDrawText(gfx::Rect(0, 0, 500, 500))));
}
} // namespace cc
......@@ -94,23 +94,11 @@ class RasterizeAndRecordMicro(legacy_page_test.LegacyPageTest):
record_time_partial_invalidation)
if self._report_detailed_results:
pixels_rasterized_with_non_solid_color = \
data['pixels_rasterized_with_non_solid_color']
pixels_rasterized_as_opaque = data['pixels_rasterized_as_opaque']
total_layers = data['total_layers']
total_picture_layers = data['total_picture_layers']
total_picture_layers_with_no_content = \
data['total_picture_layers_with_no_content']
total_picture_layers_off_screen = data['total_picture_layers_off_screen']
results.AddMeasurement('pixels_rasterized_with_non_solid_color',
'count', pixels_rasterized_with_non_solid_color)
results.AddMeasurement('pixels_rasterized_as_opaque', 'count',
pixels_rasterized_as_opaque)
results.AddMeasurement('total_layers', 'count', total_layers)
results.AddMeasurement('total_picture_layers', 'count',
total_picture_layers)
results.AddMeasurement('total_picture_layers_with_no_content', 'count',
total_picture_layers_with_no_content)
results.AddMeasurement('total_picture_layers_off_screen', 'count',
total_picture_layers_off_screen)
for metric in ('pixels_rasterized_with_non_solid_color',
'pixels_rasterized_as_opaque',
'visible_pixels_for_lcd_text',
'visible_pixels_for_non_lcd_text', 'total_layers',
'total_picture_layers',
'total_picture_layers_with_no_content',
'total_picture_layers_off_screen'):
results.AddMeasurement(metric, 'count', data[metric])
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