1 //
2 // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "gmock/gmock.h"
8 #include "gtest/gtest.h"
9
10 #include "libANGLE/Buffer.h"
11 #include "libANGLE/Caps.h"
12 #include "libANGLE/TransformFeedback.h"
13 #include "libANGLE/renderer/BufferImpl_mock.h"
14 #include "libANGLE/renderer/TransformFeedbackImpl_mock.h"
15 #include "tests/angle_unittests_utils.h"
16
17 using ::testing::_;
18 using ::testing::get;
19 using ::testing::Return;
20 using ::testing::SetArgumentPointee;
21
22 namespace
23 {
24
ACTION(CreateMockTransformFeedbackImpl)25 ACTION(CreateMockTransformFeedbackImpl)
26 {
27 return new rx::MockTransformFeedbackImpl(arg0);
28 }
29
30 class TransformFeedbackTest : public testing::Test
31 {
32 protected:
TransformFeedbackTest()33 TransformFeedbackTest() : mImpl(nullptr), mFeedback(nullptr) {}
34
SetUp()35 void SetUp() override
36 {
37 EXPECT_CALL(mMockFactory, createTransformFeedback(_))
38 .WillOnce(CreateMockTransformFeedbackImpl())
39 .RetiresOnSaturation();
40
41 // Set a reasonable number of tf attributes
42 mCaps.maxTransformFeedbackSeparateAttributes = 8;
43
44 mFeedback = new gl::TransformFeedback(&mMockFactory, gl::TransformFeedbackID{1}, mCaps);
45 mFeedback->addRef();
46
47 mImpl = rx::GetImplAs<rx::MockTransformFeedbackImpl>(mFeedback);
48 EXPECT_CALL(*mImpl, destructor());
49 }
50
TearDown()51 void TearDown() override
52 {
53 if (mFeedback)
54 {
55 mFeedback->release(nullptr);
56 }
57
58 // Only needed because the mock is leaked if bugs are present,
59 // which logs an error, but does not cause the test to fail.
60 // Ordinarily mocks are verified when destroyed.
61 testing::Mock::VerifyAndClear(mImpl);
62 }
63
64 rx::MockGLFactory mMockFactory;
65 rx::MockTransformFeedbackImpl *mImpl;
66 gl::TransformFeedback *mFeedback;
67 gl::Caps mCaps;
68 };
69
TEST_F(TransformFeedbackTest,SideEffectsOfStartAndStop)70 TEST_F(TransformFeedbackTest, SideEffectsOfStartAndStop)
71 {
72 testing::InSequence seq;
73
74 EXPECT_FALSE(mFeedback->isActive());
75 EXPECT_CALL(*mImpl, begin(nullptr, gl::PrimitiveMode::Triangles));
76 EXPECT_EQ(angle::Result::Continue,
77 mFeedback->begin(nullptr, gl::PrimitiveMode::Triangles, nullptr));
78 EXPECT_TRUE(mFeedback->isActive());
79 EXPECT_EQ(gl::PrimitiveMode::Triangles, mFeedback->getPrimitiveMode());
80 EXPECT_CALL(*mImpl, end(nullptr));
81 EXPECT_EQ(angle::Result::Continue, mFeedback->end(nullptr));
82 EXPECT_FALSE(mFeedback->isActive());
83 }
84
TEST_F(TransformFeedbackTest,SideEffectsOfPauseAndResume)85 TEST_F(TransformFeedbackTest, SideEffectsOfPauseAndResume)
86 {
87 testing::InSequence seq;
88
89 EXPECT_FALSE(mFeedback->isActive());
90 EXPECT_CALL(*mImpl, begin(nullptr, gl::PrimitiveMode::Triangles));
91 EXPECT_EQ(angle::Result::Continue,
92 mFeedback->begin(nullptr, gl::PrimitiveMode::Triangles, nullptr));
93 EXPECT_FALSE(mFeedback->isPaused());
94 EXPECT_CALL(*mImpl, pause(nullptr));
95 EXPECT_EQ(angle::Result::Continue, mFeedback->pause(nullptr));
96 EXPECT_TRUE(mFeedback->isPaused());
97 EXPECT_CALL(*mImpl, resume(nullptr));
98 EXPECT_EQ(angle::Result::Continue, mFeedback->resume(nullptr));
99 EXPECT_FALSE(mFeedback->isPaused());
100 EXPECT_CALL(*mImpl, end(nullptr));
101 EXPECT_EQ(angle::Result::Continue, mFeedback->end(nullptr));
102 }
103
TEST_F(TransformFeedbackTest,BufferBinding)104 TEST_F(TransformFeedbackTest, BufferBinding)
105 {
106 rx::MockBufferImpl *bufferImpl = new rx::MockBufferImpl;
107 EXPECT_CALL(*bufferImpl, destructor()).Times(1).RetiresOnSaturation();
108
109 rx::MockGLFactory mockGLFactory;
110 EXPECT_CALL(mockGLFactory, createBuffer(_))
111 .Times(1)
112 .WillOnce(Return(bufferImpl))
113 .RetiresOnSaturation();
114
115 gl::Buffer *buffer = new gl::Buffer(&mockGLFactory, {1});
116
117 static const size_t bindIndex = 0;
118
119 EXPECT_EQ(mFeedback->getIndexedBufferCount(),
120 static_cast<GLuint>(mCaps.maxTransformFeedbackSeparateAttributes));
121
122 EXPECT_CALL(*mImpl, bindIndexedBuffer(_, _, _));
123 EXPECT_EQ(angle::Result::Continue,
124 mFeedback->bindIndexedBuffer(nullptr, bindIndex, buffer, 0, 1));
125 for (size_t i = 0; i < mFeedback->getIndexedBufferCount(); i++)
126 {
127 if (i == bindIndex)
128 {
129 EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), buffer);
130 }
131 else
132 {
133 EXPECT_EQ(mFeedback->getIndexedBuffer(i).get(), nullptr);
134 }
135 }
136
137 // force-release the feedback object to ensure the buffer is released.
138 const size_t releaseCount = mFeedback->getRefCount();
139 for (size_t count = 0; count < releaseCount; ++count)
140 {
141 mFeedback->release(nullptr);
142 }
143
144 mFeedback = nullptr;
145
146 testing::Mock::VerifyAndClear(bufferImpl);
147 }
148
149 } // anonymous namespace
150