1 // Copyright 2018 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.
4
5 #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
6
7 #include "base/test/null_task_runner.h"
8 #include "base/test/task_environment.h"
9 #include "components/viz/common/resources/single_release_callback.h"
10 #include "components/viz/test/test_gles2_interface.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
14 #include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
15 #include "third_party/blink/renderer/platform/graphics/test/fake_gles2_interface.h"
16 #include "third_party/blink/renderer/platform/graphics/test/fake_web_graphics_context_3d_provider.h"
17 #include "third_party/blink/renderer/platform/graphics/test/gpu_test_utils.h"
18 #include "third_party/blink/renderer/platform/wtf/functional.h"
19 #include "third_party/skia/include/core/SkSurface.h"
20
21 namespace blink {
22 namespace {
23
24 using testing::_;
25 using testing::ElementsAreArray;
26 using testing::InSequence;
27 using testing::MatcherCast;
28 using testing::Pointee;
29 using testing::SetArgPointee;
30 using testing::SetArrayArgument;
31 using testing::Test;
32
33 class MockGLES2InterfaceWithSyncTokenSupport : public viz::TestGLES2Interface {
34 public:
35 MOCK_METHOD1(GenUnverifiedSyncTokenCHROMIUM, void(GLbyte*));
36 MOCK_METHOD1(WaitSyncTokenCHROMIUM, void(const GLbyte*));
37 };
38
SyncTokenMatcher(const gpu::SyncToken & token)39 GLbyte SyncTokenMatcher(const gpu::SyncToken& token) {
40 return reinterpret_cast<const GLbyte*>(&token)[0];
41 }
42
GenTestSyncToken(GLbyte id)43 gpu::SyncToken GenTestSyncToken(GLbyte id) {
44 gpu::SyncToken token;
45 // Store id in the first byte
46 reinterpret_cast<GLbyte*>(&token)[0] = id;
47 return token;
48 }
49
CreateBitmap()50 scoped_refptr<StaticBitmapImage> CreateBitmap() {
51 auto mailbox = gpu::Mailbox::GenerateForSharedImage();
52 auto release_callback = viz::SingleReleaseCallback::Create(
53 base::BindOnce([](const gpu::SyncToken&, bool) {}));
54 return AcceleratedStaticBitmapImage::CreateFromCanvasMailbox(
55 mailbox, GenTestSyncToken(100), 0, SkImageInfo::MakeN32Premul(100, 100),
56 GL_TEXTURE_2D, true, SharedGpuContext::ContextProviderWrapper(),
57 base::PlatformThread::CurrentRef(),
58 base::MakeRefCounted<base::NullTaskRunner>(),
59 std::move(release_callback));
60 }
61
62 class AcceleratedStaticBitmapImageTest : public Test {
63 public:
SetUp()64 void SetUp() override {
65 auto gl = std::make_unique<MockGLES2InterfaceWithSyncTokenSupport>();
66 gl_ = gl.get();
67 context_provider_ = viz::TestContextProvider::Create(std::move(gl));
68 InitializeSharedGpuContext(context_provider_.get());
69 }
TearDown()70 void TearDown() override {
71 gl_ = nullptr;
72 SharedGpuContext::ResetForTesting();
73 }
74
75 protected:
76 base::test::TaskEnvironment task_environment_;
77 MockGLES2InterfaceWithSyncTokenSupport* gl_;
78 scoped_refptr<viz::TestContextProvider> context_provider_;
79 };
80
TEST_F(AcceleratedStaticBitmapImageTest,SkImageCached)81 TEST_F(AcceleratedStaticBitmapImageTest, SkImageCached) {
82 auto bitmap = CreateBitmap();
83
84 sk_sp<SkImage> stored_image =
85 bitmap->PaintImageForCurrentFrame().GetSkImage();
86 auto stored_image2 = bitmap->PaintImageForCurrentFrame().GetSkImage();
87 EXPECT_EQ(stored_image.get(), stored_image2.get());
88 }
89
TEST_F(AcceleratedStaticBitmapImageTest,CopyToTextureSynchronization)90 TEST_F(AcceleratedStaticBitmapImageTest, CopyToTextureSynchronization) {
91 auto bitmap = CreateBitmap();
92
93 MockGLES2InterfaceWithSyncTokenSupport destination_gl;
94
95 testing::Mock::VerifyAndClearExpectations(gl_);
96 testing::Mock::VerifyAndClearExpectations(&destination_gl);
97
98 InSequence s; // Indicate to gmock that order of EXPECT_CALLs is important
99
100 // Anterior synchronization. Wait on the sync token for the mailbox on the
101 // dest context.
102 EXPECT_CALL(destination_gl, WaitSyncTokenCHROMIUM(Pointee(SyncTokenMatcher(
103 bitmap->GetMailboxHolder().sync_token))));
104
105 // Posterior synchronization. Generate a sync token on the destination context
106 // to ensure mailbox is destroyed after the copy.
107 const gpu::SyncToken sync_token2 = GenTestSyncToken(2);
108 EXPECT_CALL(destination_gl, GenUnverifiedSyncTokenCHROMIUM(_))
109 .WillOnce(SetArrayArgument<0>(
110 sync_token2.GetConstData(),
111 sync_token2.GetConstData() + sizeof(gpu::SyncToken)));
112
113 IntPoint dest_point(0, 0);
114 IntRect source_sub_rectangle(0, 0, 10, 10);
115 ASSERT_TRUE(bitmap->CopyToTexture(
116 &destination_gl, GL_TEXTURE_2D, 1 /*dest_texture_id*/,
117 0 /*dest_texture_level*/, false /*unpack_premultiply_alpha*/,
118 false /*unpack_flip_y*/, dest_point, source_sub_rectangle));
119
120 testing::Mock::VerifyAndClearExpectations(&gl_);
121 testing::Mock::VerifyAndClearExpectations(&destination_gl);
122
123 // Final wait is postponed until destruction.
124 EXPECT_EQ(bitmap->GetMailboxHolder().sync_token, sync_token2);
125 }
126
127 } // namespace
128 } // namespace blink
129