xref: /aosp_15_r20/external/angle/src/libANGLE/TransformFeedback_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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