| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "cc/paint/paint_op_buffer.h" | 5 #include "cc/paint/paint_op_buffer.h" |
| 6 #include "cc/paint/display_item_list.h" | 6 #include "cc/paint/display_item_list.h" |
| 7 #include "cc/test/skia_common.h" | 7 #include "cc/test/skia_common.h" |
| 8 #include "cc/test/test_skcanvas.h" | 8 #include "cc/test/test_skcanvas.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "third_party/skia/include/effects/SkDashPathEffect.h" | 10 #include "third_party/skia/include/effects/SkDashPathEffect.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 | 13 |
| 14 template <typename T> | 14 template <typename T> |
| 15 void CheckRefCnt(const T& obj, int32_t count) { | 15 void CheckRefCnt(const T& obj, int32_t count) { |
| 16 // Skia doesn't define getRefCnt in all builds. | 16 // Skia doesn't define getRefCnt in all builds. |
| 17 #ifdef SK_DEBUG | 17 #ifdef SK_DEBUG |
| 18 EXPECT_EQ(obj->getRefCnt(), count); | 18 EXPECT_EQ(obj->getRefCnt(), count); |
| 19 #endif | 19 #endif |
| 20 } | 20 } |
| 21 | 21 |
| 22 } // namespace | 22 } // namespace |
| 23 | 23 |
| 24 namespace cc { | 24 namespace cc { |
| 25 | 25 |
| 26 TEST(PaintOpBufferTest, Empty) { | 26 TEST(PaintOpBufferTest, Empty) { |
| 27 PaintOpBuffer buffer; | 27 PaintOpBuffer buffer; |
| 28 EXPECT_EQ(buffer.approximateOpCount(), 0); | 28 EXPECT_EQ(buffer.size(), 0u); |
| 29 EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer)); | 29 EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer)); |
| 30 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); | 30 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); |
| 31 | 31 |
| 32 buffer.Reset(); | 32 buffer.Reset(); |
| 33 EXPECT_EQ(buffer.approximateOpCount(), 0); | 33 EXPECT_EQ(buffer.size(), 0u); |
| 34 EXPECT_EQ(buffer.approximateBytesUsed(), sizeof(PaintOpBuffer)); | 34 EXPECT_EQ(buffer.bytes_used(), sizeof(PaintOpBuffer)); |
| 35 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); | 35 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); |
| 36 } | 36 } |
| 37 | 37 |
| 38 TEST(PaintOpBufferTest, SimpleAppend) { | 38 TEST(PaintOpBufferTest, SimpleAppend) { |
| 39 SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5); | 39 SkRect rect = SkRect::MakeXYWH(2, 3, 4, 5); |
| 40 PaintFlags flags; | 40 PaintFlags flags; |
| 41 flags.setColor(SK_ColorMAGENTA); | 41 flags.setColor(SK_ColorMAGENTA); |
| 42 flags.setAlpha(100); | 42 flags.setAlpha(100); |
| 43 SkColor draw_color = SK_ColorRED; | 43 SkColor draw_color = SK_ColorRED; |
| 44 SkBlendMode blend = SkBlendMode::kSrc; | 44 SkBlendMode blend = SkBlendMode::kSrc; |
| 45 | 45 |
| 46 PaintOpBuffer buffer; | 46 PaintOpBuffer buffer; |
| 47 buffer.push<SaveLayerOp>(&rect, &flags); | 47 buffer.push<SaveLayerOp>(&rect, &flags); |
| 48 buffer.push<SaveOp>(); | 48 buffer.push<SaveOp>(); |
| 49 buffer.push<DrawColorOp>(draw_color, blend); | 49 buffer.push<DrawColorOp>(draw_color, blend); |
| 50 buffer.push<RestoreOp>(); | 50 buffer.push<RestoreOp>(); |
| 51 | 51 |
| 52 EXPECT_EQ(buffer.approximateOpCount(), 4); | 52 EXPECT_EQ(buffer.size(), 4u); |
| 53 | 53 |
| 54 PaintOpBuffer::Iterator iter(&buffer); | 54 PaintOpBuffer::Iterator iter(&buffer); |
| 55 ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer); | 55 ASSERT_EQ(iter->GetType(), PaintOpType::SaveLayer); |
| 56 SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter); | 56 SaveLayerOp* save_op = static_cast<SaveLayerOp*>(*iter); |
| 57 EXPECT_EQ(save_op->bounds, rect); | 57 EXPECT_EQ(save_op->bounds, rect); |
| 58 EXPECT_TRUE(save_op->flags == flags); | 58 EXPECT_TRUE(save_op->flags == flags); |
| 59 ++iter; | 59 ++iter; |
| 60 | 60 |
| 61 ASSERT_EQ(iter->GetType(), PaintOpType::Save); | 61 ASSERT_EQ(iter->GetType(), PaintOpType::Save); |
| 62 ++iter; | 62 ++iter; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 87 SkColorFilter::MakeModeFilter(SK_ColorMAGENTA, SkBlendMode::kSrcOver); | 87 SkColorFilter::MakeModeFilter(SK_ColorMAGENTA, SkBlendMode::kSrcOver); |
| 88 flags.setColorFilter(filter); | 88 flags.setColorFilter(filter); |
| 89 CheckRefCnt(filter, 2); | 89 CheckRefCnt(filter, 2); |
| 90 | 90 |
| 91 buffer.push_with_data<DrawTextOp>(text, arraysize(text), 0.f, 0.f, flags); | 91 buffer.push_with_data<DrawTextOp>(text, arraysize(text), 0.f, 0.f, flags); |
| 92 CheckRefCnt(filter, 3); | 92 CheckRefCnt(filter, 3); |
| 93 | 93 |
| 94 // Verify that when the first op has data, which may not fit in the | 94 // Verify that when the first op has data, which may not fit in the |
| 95 // PaintRecord internal buffer, that it adds a noop as the first op | 95 // PaintRecord internal buffer, that it adds a noop as the first op |
| 96 // and then appends the "op with data" into the heap buffer. | 96 // and then appends the "op with data" into the heap buffer. |
| 97 ASSERT_EQ(buffer.approximateOpCount(), 2); | 97 ASSERT_EQ(buffer.size(), 2u); |
| 98 EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::Noop); | 98 EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::Noop); |
| 99 | 99 |
| 100 // Verify iteration behavior and brief smoke test of op state. | 100 // Verify iteration behavior and brief smoke test of op state. |
| 101 { | 101 { |
| 102 PaintOpBuffer::Iterator iter(&buffer); | 102 PaintOpBuffer::Iterator iter(&buffer); |
| 103 PaintOp* noop = *iter; | 103 PaintOp* noop = *iter; |
| 104 EXPECT_EQ(buffer.GetFirstOp(), noop); | 104 EXPECT_EQ(buffer.GetFirstOp(), noop); |
| 105 ++iter; | 105 ++iter; |
| 106 | 106 |
| 107 PaintOp* op = *iter; | 107 PaintOp* op = *iter; |
| 108 ASSERT_EQ(op->GetType(), PaintOpType::DrawText); | 108 ASSERT_EQ(op->GetType(), PaintOpType::DrawText); |
| 109 DrawTextOp* draw_text_op = static_cast<DrawTextOp*>(op); | 109 DrawTextOp* draw_text_op = static_cast<DrawTextOp*>(op); |
| 110 EXPECT_EQ(draw_text_op->bytes, arraysize(text)); | 110 EXPECT_EQ(draw_text_op->bytes, arraysize(text)); |
| 111 | 111 |
| 112 const void* data = draw_text_op->GetData(); | 112 const void* data = draw_text_op->GetData(); |
| 113 EXPECT_EQ(memcmp(data, text, arraysize(text)), 0); | 113 EXPECT_EQ(memcmp(data, text, arraysize(text)), 0); |
| 114 | 114 |
| 115 ++iter; | 115 ++iter; |
| 116 EXPECT_FALSE(iter); | 116 EXPECT_FALSE(iter); |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Reset, verify state, and append an op that will fit in the first slot. | 119 // Reset, verify state, and append an op that will fit in the first slot. |
| 120 buffer.Reset(); | 120 buffer.Reset(); |
| 121 CheckRefCnt(filter, 2); | 121 CheckRefCnt(filter, 2); |
| 122 | 122 |
| 123 ASSERT_EQ(buffer.approximateOpCount(), 0); | 123 ASSERT_EQ(buffer.size(), 0u); |
| 124 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); | 124 EXPECT_EQ(PaintOpBuffer::Iterator(&buffer), false); |
| 125 | 125 |
| 126 SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); | 126 SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); |
| 127 buffer.push<DrawRectOp>(rect, flags); | 127 buffer.push<DrawRectOp>(rect, flags); |
| 128 CheckRefCnt(filter, 3); | 128 CheckRefCnt(filter, 3); |
| 129 | 129 |
| 130 ASSERT_EQ(buffer.approximateOpCount(), 1); | 130 ASSERT_EQ(buffer.size(), 1u); |
| 131 EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::DrawRect); | 131 EXPECT_EQ(buffer.GetFirstOp()->GetType(), PaintOpType::DrawRect); |
| 132 | 132 |
| 133 PaintOpBuffer::Iterator iter(&buffer); | 133 PaintOpBuffer::Iterator iter(&buffer); |
| 134 ASSERT_EQ(iter->GetType(), PaintOpType::DrawRect); | 134 ASSERT_EQ(iter->GetType(), PaintOpType::DrawRect); |
| 135 DrawRectOp* draw_rect_op = static_cast<DrawRectOp*>(*iter); | 135 DrawRectOp* draw_rect_op = static_cast<DrawRectOp*>(*iter); |
| 136 EXPECT_EQ(draw_rect_op->rect, rect); | 136 EXPECT_EQ(draw_rect_op->rect, rect); |
| 137 | 137 |
| 138 ++iter; | 138 ++iter; |
| 139 EXPECT_FALSE(iter); | 139 EXPECT_FALSE(iter); |
| 140 | 140 |
| 141 buffer.Reset(); | 141 buffer.Reset(); |
| 142 ASSERT_EQ(buffer.approximateOpCount(), 0); | 142 ASSERT_EQ(buffer.size(), 0u); |
| 143 CheckRefCnt(filter, 2); | 143 CheckRefCnt(filter, 2); |
| 144 } | 144 } |
| 145 | 145 |
| 146 TEST(PaintOpBufferTest, Peek) { | 146 TEST(PaintOpBufferTest, Peek) { |
| 147 PaintOpBuffer buffer; | 147 PaintOpBuffer buffer; |
| 148 | 148 |
| 149 uint8_t alpha = 100; | 149 uint8_t alpha = 100; |
| 150 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); | 150 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); |
| 151 PaintFlags draw_flags; | 151 PaintFlags draw_flags; |
| 152 buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), draw_flags); | 152 buffer.push<DrawRectOp>(SkRect::MakeXYWH(1, 2, 3, 4), draw_flags); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 174 PaintOpBuffer buffer; | 174 PaintOpBuffer buffer; |
| 175 | 175 |
| 176 buffer.push<SaveOp>(); | 176 buffer.push<SaveOp>(); |
| 177 PaintFlags flags; | 177 PaintFlags flags; |
| 178 char text1[] = "asdfasdf"; | 178 char text1[] = "asdfasdf"; |
| 179 buffer.push_with_data<DrawTextOp>(text1, arraysize(text1), 0.f, 0.f, flags); | 179 buffer.push_with_data<DrawTextOp>(text1, arraysize(text1), 0.f, 0.f, flags); |
| 180 | 180 |
| 181 char text2[] = "qwerty"; | 181 char text2[] = "qwerty"; |
| 182 buffer.push_with_data<DrawTextOp>(text2, arraysize(text2), 0.f, 0.f, flags); | 182 buffer.push_with_data<DrawTextOp>(text2, arraysize(text2), 0.f, 0.f, flags); |
| 183 | 183 |
| 184 ASSERT_EQ(buffer.approximateOpCount(), 3); | 184 ASSERT_EQ(buffer.size(), 3u); |
| 185 | 185 |
| 186 // Verify iteration behavior and brief smoke test of op state. | 186 // Verify iteration behavior and brief smoke test of op state. |
| 187 PaintOpBuffer::Iterator iter(&buffer); | 187 PaintOpBuffer::Iterator iter(&buffer); |
| 188 PaintOp* save_op = *iter; | 188 PaintOp* save_op = *iter; |
| 189 EXPECT_EQ(save_op->GetType(), PaintOpType::Save); | 189 EXPECT_EQ(save_op->GetType(), PaintOpType::Save); |
| 190 ++iter; | 190 ++iter; |
| 191 | 191 |
| 192 PaintOp* op1 = *iter; | 192 PaintOp* op1 = *iter; |
| 193 ASSERT_EQ(op1->GetType(), PaintOpType::DrawText); | 193 ASSERT_EQ(op1->GetType(), PaintOpType::DrawText); |
| 194 DrawTextOp* draw_text_op1 = static_cast<DrawTextOp*>(op1); | 194 DrawTextOp* draw_text_op1 = static_cast<DrawTextOp*>(op1); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 // is a DrawRecord that itself has a single draw op. | 369 // is a DrawRecord that itself has a single draw op. |
| 370 TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleOp) { | 370 TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleOp) { |
| 371 sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); | 371 sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); |
| 372 | 372 |
| 373 PaintFlags draw_flags; | 373 PaintFlags draw_flags; |
| 374 draw_flags.setColor(SK_ColorMAGENTA); | 374 draw_flags.setColor(SK_ColorMAGENTA); |
| 375 draw_flags.setAlpha(50); | 375 draw_flags.setAlpha(50); |
| 376 EXPECT_TRUE(draw_flags.SupportsFoldingAlpha()); | 376 EXPECT_TRUE(draw_flags.SupportsFoldingAlpha()); |
| 377 SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); | 377 SkRect rect = SkRect::MakeXYWH(1, 2, 3, 4); |
| 378 record->push<DrawRectOp>(rect, draw_flags); | 378 record->push<DrawRectOp>(rect, draw_flags); |
| 379 EXPECT_EQ(record->approximateOpCount(), 1); | 379 EXPECT_EQ(record->size(), 1u); |
| 380 | 380 |
| 381 PaintOpBuffer buffer; | 381 PaintOpBuffer buffer; |
| 382 | 382 |
| 383 uint8_t alpha = 100; | 383 uint8_t alpha = 100; |
| 384 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); | 384 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); |
| 385 buffer.push<DrawRecordOp>(std::move(record)); | 385 buffer.push<DrawRecordOp>(std::move(record)); |
| 386 buffer.push<RestoreOp>(); | 386 buffer.push<RestoreOp>(); |
| 387 | 387 |
| 388 SaveCountingCanvas canvas; | 388 SaveCountingCanvas canvas; |
| 389 buffer.playback(&canvas); | 389 buffer.playback(&canvas); |
| 390 | 390 |
| 391 EXPECT_EQ(0, canvas.save_count_); | 391 EXPECT_EQ(0, canvas.save_count_); |
| 392 EXPECT_EQ(0, canvas.restore_count_); | 392 EXPECT_EQ(0, canvas.restore_count_); |
| 393 EXPECT_EQ(rect, canvas.draw_rect_); | 393 EXPECT_EQ(rect, canvas.draw_rect_); |
| 394 | 394 |
| 395 float expected_alpha = alpha * 50 / 255.f; | 395 float expected_alpha = alpha * 50 / 255.f; |
| 396 EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f); | 396 EXPECT_LE(std::abs(expected_alpha - canvas.paint_.getAlpha()), 1.f); |
| 397 } | 397 } |
| 398 | 398 |
| 399 // The same as the above SingleOpRecord test, but the single op is not | 399 // The same as the above SingleOpRecord test, but the single op is not |
| 400 // a draw op. So, there's no way to fold in the save layer optimization. | 400 // a draw op. So, there's no way to fold in the save layer optimization. |
| 401 // Verify that the optimization doesn't apply and that this doesn't crash. | 401 // Verify that the optimization doesn't apply and that this doesn't crash. |
| 402 // See: http://crbug.com/712093. | 402 // See: http://crbug.com/712093. |
| 403 TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleNonDrawOp) { | 403 TEST(PaintOpBufferTest, SaveDrawRestore_SingleOpRecordWithSingleNonDrawOp) { |
| 404 sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); | 404 sk_sp<PaintRecord> record = sk_make_sp<PaintRecord>(); |
| 405 record->push<NoopOp>(); | 405 record->push<NoopOp>(); |
| 406 EXPECT_EQ(record->approximateOpCount(), 1); | 406 EXPECT_EQ(record->size(), 1u); |
| 407 EXPECT_FALSE(record->GetFirstOp()->IsDrawOp()); | 407 EXPECT_FALSE(record->GetFirstOp()->IsDrawOp()); |
| 408 | 408 |
| 409 PaintOpBuffer buffer; | 409 PaintOpBuffer buffer; |
| 410 | 410 |
| 411 uint8_t alpha = 100; | 411 uint8_t alpha = 100; |
| 412 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); | 412 buffer.push<SaveLayerAlphaOp>(nullptr, alpha); |
| 413 buffer.push<DrawRecordOp>(std::move(record)); | 413 buffer.push<DrawRecordOp>(std::move(record)); |
| 414 buffer.push<RestoreOp>(); | 414 buffer.push<RestoreOp>(); |
| 415 | 415 |
| 416 SaveCountingCanvas canvas; | 416 SaveCountingCanvas canvas; |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 | 520 |
| 521 // Drawing a record with slow paths into another adds the same | 521 // Drawing a record with slow paths into another adds the same |
| 522 // number of slow paths as the record. | 522 // number of slow paths as the record. |
| 523 auto buffer2 = sk_make_sp<PaintOpBuffer>(); | 523 auto buffer2 = sk_make_sp<PaintOpBuffer>(); |
| 524 EXPECT_EQ(buffer2->numSlowPaths(), 0); | 524 EXPECT_EQ(buffer2->numSlowPaths(), 0); |
| 525 buffer2->push<DrawRecordOp>(buffer); | 525 buffer2->push<DrawRecordOp>(buffer); |
| 526 EXPECT_EQ(buffer->numSlowPaths(), buffer2->numSlowPaths()); | 526 EXPECT_EQ(buffer->numSlowPaths(), buffer2->numSlowPaths()); |
| 527 } | 527 } |
| 528 | 528 |
| 529 } // namespace cc | 529 } // namespace cc |
| OLD | NEW |