Linux: Depend on liberation-fonts package for RPMs.
[chromium-blink-merge.git] / cc / playback / display_item_list_unittest.cc
blobdc8fd1445759454ec5cc0d5ac142ba4c13731409
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/playback/display_item_list.h"
7 #include <vector>
9 #include "cc/output/filter_operation.h"
10 #include "cc/output/filter_operations.h"
11 #include "cc/playback/clip_display_item.h"
12 #include "cc/playback/display_item_list_settings.h"
13 #include "cc/playback/drawing_display_item.h"
14 #include "cc/playback/filter_display_item.h"
15 #include "cc/playback/transform_display_item.h"
16 #include "cc/test/skia_common.h"
17 #include "skia/ext/refptr.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/skia/include/core/SkBitmap.h"
20 #include "third_party/skia/include/core/SkCanvas.h"
21 #include "third_party/skia/include/core/SkColor.h"
22 #include "third_party/skia/include/core/SkPictureRecorder.h"
23 #include "third_party/skia/include/core/SkSurface.h"
24 #include "third_party/skia/include/effects/SkImageSource.h"
25 #include "third_party/skia/include/utils/SkPictureUtils.h"
26 #include "ui/gfx/geometry/rect_conversions.h"
27 #include "ui/gfx/skia_util.h"
29 namespace cc {
31 TEST(DisplayItemListTest, SingleDrawingItem) {
32 gfx::Rect layer_rect(100, 100);
33 SkPictureRecorder recorder;
34 skia::RefPtr<SkCanvas> canvas;
35 skia::RefPtr<SkPicture> picture;
36 SkPaint blue_paint;
37 blue_paint.setColor(SK_ColorBLUE);
38 SkPaint red_paint;
39 red_paint.setColor(SK_ColorRED);
40 unsigned char pixels[4 * 100 * 100] = {0};
41 DisplayItemListSettings settings;
42 settings.use_cached_picture = true;
43 scoped_refptr<DisplayItemList> list =
44 DisplayItemList::Create(layer_rect, settings);
46 gfx::PointF offset(8.f, 9.f);
47 gfx::RectF recording_rect(offset, layer_rect.size());
48 canvas = skia::SharePtr(
49 recorder.beginRecording(gfx::RectFToSkRect(recording_rect)));
50 canvas->translate(offset.x(), offset.y());
51 canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint);
52 canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint);
53 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
54 auto* item = list->CreateAndAppendItem<DrawingDisplayItem>();
55 item->SetNew(picture);
56 list->Finalize();
57 DrawDisplayList(pixels, layer_rect, list);
59 SkBitmap expected_bitmap;
60 unsigned char expected_pixels[4 * 100 * 100] = {0};
61 SkImageInfo info =
62 SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
63 expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
64 SkCanvas expected_canvas(expected_bitmap);
65 expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
66 expected_canvas.drawRectCoords(0.f + offset.x(), 0.f + offset.y(),
67 60.f + offset.x(), 60.f + offset.y(),
68 red_paint);
69 expected_canvas.drawRectCoords(50.f + offset.x(), 50.f + offset.y(),
70 75.f + offset.x(), 75.f + offset.y(),
71 blue_paint);
73 EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
76 TEST(DisplayItemListTest, ClipItem) {
77 gfx::Rect layer_rect(100, 100);
78 SkPictureRecorder recorder;
79 skia::RefPtr<SkCanvas> canvas;
80 skia::RefPtr<SkPicture> picture;
81 SkPaint blue_paint;
82 blue_paint.setColor(SK_ColorBLUE);
83 SkPaint red_paint;
84 red_paint.setColor(SK_ColorRED);
85 unsigned char pixels[4 * 100 * 100] = {0};
86 DisplayItemListSettings settings;
87 settings.use_cached_picture = true;
88 scoped_refptr<DisplayItemList> list =
89 DisplayItemList::Create(layer_rect, settings);
91 gfx::PointF first_offset(8.f, 9.f);
92 gfx::RectF first_recording_rect(first_offset, layer_rect.size());
93 canvas = skia::SharePtr(
94 recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect)));
95 canvas->translate(first_offset.x(), first_offset.y());
96 canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint);
97 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
98 auto* item1 = list->CreateAndAppendItem<DrawingDisplayItem>();
99 item1->SetNew(picture.Pass());
101 gfx::Rect clip_rect(60, 60, 10, 10);
102 auto* item2 = list->CreateAndAppendItem<ClipDisplayItem>();
103 item2->SetNew(clip_rect, std::vector<SkRRect>());
105 gfx::PointF second_offset(2.f, 3.f);
106 gfx::RectF second_recording_rect(second_offset, layer_rect.size());
107 canvas = skia::SharePtr(
108 recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect)));
109 canvas->translate(second_offset.x(), second_offset.y());
110 canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint);
111 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
112 auto* item3 = list->CreateAndAppendItem<DrawingDisplayItem>();
113 item3->SetNew(picture.Pass());
115 list->CreateAndAppendItem<EndClipDisplayItem>();
116 list->Finalize();
118 DrawDisplayList(pixels, layer_rect, list);
120 SkBitmap expected_bitmap;
121 unsigned char expected_pixels[4 * 100 * 100] = {0};
122 SkImageInfo info =
123 SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
124 expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
125 SkCanvas expected_canvas(expected_bitmap);
126 expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
127 expected_canvas.drawRectCoords(0.f + first_offset.x(), 0.f + first_offset.y(),
128 60.f + first_offset.x(),
129 60.f + first_offset.y(), red_paint);
130 expected_canvas.clipRect(gfx::RectToSkRect(clip_rect));
131 expected_canvas.drawRectCoords(
132 50.f + second_offset.x(), 50.f + second_offset.y(),
133 75.f + second_offset.x(), 75.f + second_offset.y(), blue_paint);
135 EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
138 TEST(DisplayItemListTest, TransformItem) {
139 gfx::Rect layer_rect(100, 100);
140 SkPictureRecorder recorder;
141 skia::RefPtr<SkCanvas> canvas;
142 skia::RefPtr<SkPicture> picture;
143 SkPaint blue_paint;
144 blue_paint.setColor(SK_ColorBLUE);
145 SkPaint red_paint;
146 red_paint.setColor(SK_ColorRED);
147 unsigned char pixels[4 * 100 * 100] = {0};
148 DisplayItemListSettings settings;
149 settings.use_cached_picture = true;
150 scoped_refptr<DisplayItemList> list =
151 DisplayItemList::Create(layer_rect, settings);
153 gfx::PointF first_offset(8.f, 9.f);
154 gfx::RectF first_recording_rect(first_offset, layer_rect.size());
155 canvas = skia::SharePtr(
156 recorder.beginRecording(gfx::RectFToSkRect(first_recording_rect)));
157 canvas->translate(first_offset.x(), first_offset.y());
158 canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint);
159 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
160 auto* item1 = list->CreateAndAppendItem<DrawingDisplayItem>();
161 item1->SetNew(picture);
163 gfx::Transform transform;
164 transform.Rotate(45.0);
165 auto* item2 = list->CreateAndAppendItem<TransformDisplayItem>();
166 item2->SetNew(transform);
168 gfx::PointF second_offset(2.f, 3.f);
169 gfx::RectF second_recording_rect(second_offset, layer_rect.size());
170 canvas = skia::SharePtr(
171 recorder.beginRecording(gfx::RectFToSkRect(second_recording_rect)));
172 canvas->translate(second_offset.x(), second_offset.y());
173 canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint);
174 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
175 auto* item3 = list->CreateAndAppendItem<DrawingDisplayItem>();
176 item3->SetNew(picture);
178 list->CreateAndAppendItem<EndTransformDisplayItem>();
179 list->Finalize();
181 DrawDisplayList(pixels, layer_rect, list);
183 SkBitmap expected_bitmap;
184 unsigned char expected_pixels[4 * 100 * 100] = {0};
185 SkImageInfo info =
186 SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
187 expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
188 SkCanvas expected_canvas(expected_bitmap);
189 expected_canvas.clipRect(gfx::RectToSkRect(layer_rect));
190 expected_canvas.drawRectCoords(0.f + first_offset.x(), 0.f + first_offset.y(),
191 60.f + first_offset.x(),
192 60.f + first_offset.y(), red_paint);
193 expected_canvas.setMatrix(transform.matrix());
194 expected_canvas.drawRectCoords(
195 50.f + second_offset.x(), 50.f + second_offset.y(),
196 75.f + second_offset.x(), 75.f + second_offset.y(), blue_paint);
198 EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
201 TEST(DisplayItemListTest, FilterItem) {
202 gfx::Rect layer_rect(100, 100);
203 FilterOperations filters;
204 unsigned char pixels[4 * 100 * 100] = {0};
205 DisplayItemListSettings settings;
206 settings.use_cached_picture = true;
207 scoped_refptr<DisplayItemList> list =
208 DisplayItemList::Create(layer_rect, settings);
210 skia::RefPtr<SkSurface> source_surface =
211 skia::AdoptRef(SkSurface::NewRasterN32Premul(50, 50));
212 SkCanvas* source_canvas = source_surface->getCanvas();
213 source_canvas->clear(SkColorSetRGB(128, 128, 128));
214 skia::RefPtr<SkImage> source_image =
215 skia::AdoptRef(source_surface->newImageSnapshot());
217 // For most SkImageFilters, the |dst| bounds computed by computeFastBounds are
218 // dependent on the provided |src| bounds. This means, for example, that
219 // translating |src| results in a corresponding translation of |dst|. But this
220 // is not the case for all SkImageFilters; for some of them (e.g.
221 // SkImageSource), the computation of |dst| in computeFastBounds doesn't
222 // involve |src| at all. Incorrectly assuming such a relationship (e.g. by
223 // translating |dst| after it is computed by computeFastBounds, rather than
224 // translating |src| before it provided to computedFastBounds) can cause
225 // incorrect clipping of filter output. To test for this, we include an
226 // SkImageSource filter in |filters|. Here, |src| is |filter_bounds|, defined
227 // below.
228 skia::RefPtr<SkImageFilter> image_filter =
229 skia::AdoptRef(SkImageSource::Create(source_image.get()));
230 filters.Append(FilterOperation::CreateReferenceFilter(image_filter));
231 filters.Append(FilterOperation::CreateBrightnessFilter(0.5f));
232 gfx::RectF filter_bounds(10.f, 10.f, 50.f, 50.f);
233 auto* item = list->CreateAndAppendItem<FilterDisplayItem>();
234 item->SetNew(filters, filter_bounds);
235 list->CreateAndAppendItem<EndFilterDisplayItem>();
236 list->Finalize();
238 DrawDisplayList(pixels, layer_rect, list);
240 SkBitmap expected_bitmap;
241 unsigned char expected_pixels[4 * 100 * 100] = {0};
242 SkPaint paint;
243 paint.setColor(SkColorSetRGB(64, 64, 64));
244 SkImageInfo info =
245 SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
246 expected_bitmap.installPixels(info, expected_pixels, info.minRowBytes());
247 SkCanvas expected_canvas(expected_bitmap);
248 expected_canvas.drawRect(RectFToSkRect(filter_bounds), paint);
250 EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
253 TEST(DisplayItemListTest, CompactingItems) {
254 gfx::Rect layer_rect(100, 100);
255 SkPictureRecorder recorder;
256 skia::RefPtr<SkCanvas> canvas;
257 skia::RefPtr<SkPicture> picture;
258 SkPaint blue_paint;
259 blue_paint.setColor(SK_ColorBLUE);
260 SkPaint red_paint;
261 red_paint.setColor(SK_ColorRED);
262 unsigned char pixels[4 * 100 * 100] = {0};
264 gfx::PointF offset(8.f, 9.f);
265 gfx::RectF recording_rect(offset, layer_rect.size());
267 DisplayItemListSettings no_caching_settings;
268 no_caching_settings.use_cached_picture = false;
269 scoped_refptr<DisplayItemList> list_without_caching =
270 DisplayItemList::Create(layer_rect, no_caching_settings);
272 canvas = skia::SharePtr(
273 recorder.beginRecording(gfx::RectFToSkRect(recording_rect)));
274 canvas->translate(offset.x(), offset.y());
275 canvas->drawRectCoords(0.f, 0.f, 60.f, 60.f, red_paint);
276 canvas->drawRectCoords(50.f, 50.f, 75.f, 75.f, blue_paint);
277 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
278 auto* item1 = list_without_caching->CreateAndAppendItem<DrawingDisplayItem>();
279 item1->SetNew(picture);
280 list_without_caching->Finalize();
281 DrawDisplayList(pixels, layer_rect, list_without_caching);
283 unsigned char expected_pixels[4 * 100 * 100] = {0};
284 DisplayItemListSettings caching_settings;
285 caching_settings.use_cached_picture = true;
286 scoped_refptr<DisplayItemList> list_with_caching =
287 DisplayItemList::Create(layer_rect, caching_settings);
288 auto* item2 = list_with_caching->CreateAndAppendItem<DrawingDisplayItem>();
289 item2->SetNew(picture);
290 list_with_caching->Finalize();
291 DrawDisplayList(expected_pixels, layer_rect, list_with_caching);
293 EXPECT_EQ(0, memcmp(pixels, expected_pixels, 4 * 100 * 100));
296 TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithCachedPicture) {
297 gfx::Rect layer_rect(1000, 1000);
298 SkPictureRecorder recorder;
299 skia::RefPtr<SkCanvas> canvas;
300 skia::RefPtr<SkPicture> picture;
302 DisplayItemListSettings settings;
303 settings.use_cached_picture = true;
304 scoped_refptr<DisplayItemList> list =
305 DisplayItemList::Create(layer_rect, settings);
306 canvas =
307 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
309 SkPath path;
310 path.moveTo(0, 0);
311 path.lineTo(0, 100);
312 path.lineTo(50, 50);
313 path.lineTo(100, 100);
314 path.lineTo(100, 0);
315 path.close();
317 SkPaint paint;
318 paint.setAntiAlias(true);
319 canvas->drawPath(path, paint);
321 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
322 DrawingDisplayItem* item = list->CreateAndAppendItem<DrawingDisplayItem>();
323 item->SetNew(picture);
324 list->Finalize();
326 // A single DrawingDisplayItem with a large AA concave path shouldn't trigger
327 // a veto.
328 EXPECT_TRUE(list->IsSuitableForGpuRasterization());
330 list = DisplayItemList::Create(layer_rect, settings);
331 canvas =
332 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
333 for (int i = 0; i < 10; ++i)
334 canvas->drawPath(path, paint);
335 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
336 item = list->CreateAndAppendItem<DrawingDisplayItem>();
337 item->SetNew(picture);
338 list->Finalize();
340 // A single DrawingDisplayItem with several large AA concave paths should
341 // trigger a veto.
342 EXPECT_FALSE(list->IsSuitableForGpuRasterization());
344 list = DisplayItemList::Create(layer_rect, settings);
345 for (int i = 0; i < 10; ++i) {
346 canvas =
347 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
348 canvas->drawPath(path, paint);
349 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
350 item = list->CreateAndAppendItem<DrawingDisplayItem>();
351 item->SetNew(picture);
353 list->Finalize();
355 // Having several DrawingDisplayItems that each contain a large AA concave
356 // path should trigger a veto.
357 EXPECT_FALSE(list->IsSuitableForGpuRasterization());
360 TEST(DisplayItemListTest, IsSuitableForGpuRasterizationWithoutCachedPicture) {
361 gfx::Rect layer_rect(1000, 1000);
362 SkPictureRecorder recorder;
363 skia::RefPtr<SkCanvas> canvas;
364 skia::RefPtr<SkPicture> picture;
366 DisplayItemListSettings settings;
367 settings.use_cached_picture = false;
368 scoped_refptr<DisplayItemList> list =
369 DisplayItemList::Create(layer_rect, settings);
370 canvas =
371 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
373 SkPath path;
374 path.moveTo(0, 0);
375 path.lineTo(0, 100);
376 path.lineTo(50, 50);
377 path.lineTo(100, 100);
378 path.lineTo(100, 0);
379 path.close();
381 SkPaint paint;
382 paint.setAntiAlias(true);
383 canvas->drawPath(path, paint);
385 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
386 DrawingDisplayItem* item = list->CreateAndAppendItem<DrawingDisplayItem>();
387 item->SetNew(picture);
388 list->Finalize();
390 // A single DrawingDisplayItem with a large AA concave path shouldn't trigger
391 // a veto.
392 EXPECT_TRUE(list->IsSuitableForGpuRasterization());
394 list = DisplayItemList::Create(layer_rect, settings);
395 canvas =
396 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
397 for (int i = 0; i < 10; ++i)
398 canvas->drawPath(path, paint);
399 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
400 item = list->CreateAndAppendItem<DrawingDisplayItem>();
401 item->SetNew(picture);
402 list->Finalize();
404 // A single DrawingDisplayItem with several large AA concave paths should
405 // trigger a veto.
406 EXPECT_FALSE(list->IsSuitableForGpuRasterization());
408 list = DisplayItemList::Create(layer_rect, settings);
409 for (int i = 0; i < 10; ++i) {
410 canvas =
411 skia::SharePtr(recorder.beginRecording(gfx::RectToSkRect(layer_rect)));
412 canvas->drawPath(path, paint);
413 picture = skia::AdoptRef(recorder.endRecordingAsPicture());
414 item = list->CreateAndAppendItem<DrawingDisplayItem>();
415 item->SetNew(picture);
417 list->Finalize();
419 // Without a cached picture, having several DrawingDisplayItems that each
420 // contain a single large AA concave will not trigger a veto, since each item
421 // is individually suitable for GPU rasterization.
422 EXPECT_TRUE(list->IsSuitableForGpuRasterization());
425 TEST(DisplayItemListTest, ApproximateMemoryUsage) {
426 const int kNumCommandsInTestSkPicture = 1000;
427 scoped_refptr<DisplayItemList> list;
428 size_t memory_usage;
430 // Make an SkPicture whose size is known.
431 gfx::Rect layer_rect(100, 100);
432 SkPictureRecorder recorder;
433 SkPaint blue_paint;
434 blue_paint.setColor(SK_ColorBLUE);
435 SkCanvas* canvas = recorder.beginRecording(gfx::RectToSkRect(layer_rect));
436 for (int i = 0; i < kNumCommandsInTestSkPicture; i++)
437 canvas->drawPaint(blue_paint);
438 skia::RefPtr<SkPicture> picture =
439 skia::AdoptRef(recorder.endRecordingAsPicture());
440 size_t picture_size = SkPictureUtils::ApproximateBytesUsed(picture.get());
441 ASSERT_GE(picture_size, kNumCommandsInTestSkPicture * sizeof(blue_paint));
443 // Using a cached picture, we should get about the right size.
444 DisplayItemListSettings caching_settings;
445 caching_settings.use_cached_picture = true;
446 list = DisplayItemList::Create(layer_rect, caching_settings);
447 auto* item = list->CreateAndAppendItem<DrawingDisplayItem>();
448 item->SetNew(picture);
449 list->Finalize();
450 memory_usage = list->ApproximateMemoryUsage();
451 EXPECT_GE(memory_usage, picture_size);
452 EXPECT_LE(memory_usage, 2 * picture_size);
454 // Using no cached picture, we should still get the right size.
455 DisplayItemListSettings no_caching_settings;
456 no_caching_settings.use_cached_picture = false;
457 list = DisplayItemList::Create(layer_rect, no_caching_settings);
458 item = list->CreateAndAppendItem<DrawingDisplayItem>();
459 item->SetNew(picture);
460 list->Finalize();
461 memory_usage = list->ApproximateMemoryUsage();
462 EXPECT_GE(memory_usage, picture_size);
463 EXPECT_LE(memory_usage, 2 * picture_size);
465 // To avoid double counting, we expect zero size to be computed if both the
466 // picture and items are retained (currently this only happens due to certain
467 // categories being traced).
468 list = new DisplayItemList(layer_rect, caching_settings, true);
469 item = list->CreateAndAppendItem<DrawingDisplayItem>();
470 item->SetNew(picture);
471 list->Finalize();
472 memory_usage = list->ApproximateMemoryUsage();
473 EXPECT_EQ(static_cast<size_t>(0), memory_usage);
476 } // namespace cc