xref: /aosp_15_r20/external/angle/src/libANGLE/Image_unittest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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 // Image_unittest.cpp : Unittets of the Image and ImageSibling classes.
8 
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 
12 #include "libANGLE/Image.h"
13 #include "libANGLE/Renderbuffer.h"
14 #include "libANGLE/Texture.h"
15 #include "libANGLE/renderer/ImageImpl_mock.h"
16 #include "libANGLE/renderer/RenderbufferImpl_mock.h"
17 #include "libANGLE/renderer/TextureImpl_mock.h"
18 #include "tests/angle_unittests_utils.h"
19 
20 using ::testing::_;
21 using ::testing::NiceMock;
22 using ::testing::Return;
23 
24 namespace angle
25 {
ACTION(CreateMockImageImpl)26 ACTION(CreateMockImageImpl)
27 {
28     return new rx::MockImageImpl(arg0);
29 }
30 
31 // Verify ref counts are maintained between images and their siblings when objects are deleted
TEST(ImageTest,RefCounting)32 TEST(ImageTest, RefCounting)
33 {
34     NiceMock<rx::MockGLFactory> mockGLFactory;
35     NiceMock<rx::MockEGLFactory> mockEGLFactory;
36 
37     // Create a texture and an EGL image that uses the texture as its source
38     rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
39     EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
40     gl::Texture *texture = new gl::Texture(&mockGLFactory, {1}, gl::TextureType::_2D);
41     texture->addRef();
42 
43     EXPECT_CALL(mockEGLFactory, createImage(_, _, _, _))
44         .WillOnce(CreateMockImageImpl())
45         .RetiresOnSaturation();
46 
47     egl::Image *image = new egl::Image(&mockEGLFactory, {1}, nullptr, EGL_GL_TEXTURE_2D, texture,
48                                        egl::AttributeMap());
49     rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
50     image->addRef();
51 
52     // Verify that the image does not add a ref to its source so that the source may still be
53     // deleted
54     EXPECT_EQ(1u, texture->getRefCount());
55     EXPECT_EQ(1u, image->getRefCount());
56 
57     // Create a renderbuffer and set it as a target of the EGL image
58     rx::MockRenderbufferImpl *renderbufferImpl = new rx::MockRenderbufferImpl();
59     EXPECT_CALL(mockGLFactory, createRenderbuffer(_)).WillOnce(Return(renderbufferImpl));
60     gl::Renderbuffer *renderbuffer = new gl::Renderbuffer(&mockGLFactory, {1});
61     renderbuffer->addRef();
62 
63     EXPECT_CALL(*renderbufferImpl, setStorageEGLImageTarget(_, _))
64         .WillOnce(Return(angle::Result::Continue))
65         .RetiresOnSaturation();
66     EXPECT_EQ(angle::Result::Continue, renderbuffer->setStorageEGLImageTarget(nullptr, image));
67 
68     // Verify that the renderbuffer added a ref to the image and the image did not add a ref to
69     // the renderbuffer
70     EXPECT_EQ(1u, texture->getRefCount());
71     EXPECT_EQ(2u, image->getRefCount());
72     EXPECT_EQ(1u, renderbuffer->getRefCount());
73 
74     // Simulate deletion of the texture and verify that it is deleted but the image still exists
75     EXPECT_CALL(*imageImpl, orphan(_, _))
76         .WillOnce(Return(angle::Result::Continue))
77         .RetiresOnSaturation();
78     EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
79     texture->release(nullptr);
80     EXPECT_EQ(2u, image->getRefCount());
81     EXPECT_EQ(1u, renderbuffer->getRefCount());
82 
83     // Simulate deletion of the image and verify that it still exists because the renderbuffer holds
84     // a ref
85     image->release(nullptr);
86     EXPECT_EQ(1u, image->getRefCount());
87     EXPECT_EQ(1u, renderbuffer->getRefCount());
88 
89     // Simulate deletion of the renderbuffer and verify that the deletion cascades to all objects
90     EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
91     EXPECT_CALL(*imageImpl, orphan(_, _))
92         .WillOnce(Return(angle::Result::Continue))
93         .RetiresOnSaturation();
94 
95     EXPECT_CALL(*renderbufferImpl, destructor()).Times(1).RetiresOnSaturation();
96 
97     renderbuffer->release(nullptr);
98 }
99 
100 // Verify that respecifying textures releases references to the Image.
TEST(ImageTest,RespecificationReleasesReferences)101 TEST(ImageTest, RespecificationReleasesReferences)
102 {
103     NiceMock<rx::MockGLFactory> mockGLFactory;
104     NiceMock<rx::MockEGLFactory> mockEGLFactory;
105 
106     // Create a texture and an EGL image that uses the texture as its source
107     rx::MockTextureImpl *textureImpl = new rx::MockTextureImpl();
108     EXPECT_CALL(mockGLFactory, createTexture(_)).WillOnce(Return(textureImpl));
109     gl::Texture *texture = new gl::Texture(&mockGLFactory, {1}, gl::TextureType::_2D);
110     texture->addRef();
111 
112     gl::PixelUnpackState defaultUnpackState;
113 
114     EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
115         .WillOnce(Return(angle::Result::Continue))
116         .RetiresOnSaturation();
117     EXPECT_EQ(
118         angle::Result::Continue,
119         texture->setImage(nullptr, defaultUnpackState, nullptr, gl::TextureTarget::_2D, 0, GL_RGBA8,
120                           gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
121 
122     EXPECT_CALL(mockEGLFactory, createImage(_, _, _, _))
123         .WillOnce(CreateMockImageImpl())
124         .RetiresOnSaturation();
125 
126     egl::Image *image = new egl::Image(&mockEGLFactory, {1}, nullptr, EGL_GL_TEXTURE_2D, texture,
127                                        egl::AttributeMap());
128     image->addRef();
129 
130     // Verify that the image did not add a ref to it's source.
131     EXPECT_EQ(1u, texture->getRefCount());
132     EXPECT_EQ(1u, image->getRefCount());
133 
134     // Respecify the texture and verify that the image is orphaned
135     rx::MockImageImpl *imageImpl = static_cast<rx::MockImageImpl *>(image->getImplementation());
136     EXPECT_CALL(*imageImpl, orphan(_, _))
137         .WillOnce(Return(angle::Result::Continue))
138         .RetiresOnSaturation();
139     EXPECT_CALL(*textureImpl, setImage(_, _, _, _, _, _, _, _, _))
140         .WillOnce(Return(angle::Result::Continue))
141         .RetiresOnSaturation();
142 
143     EXPECT_EQ(
144         angle::Result::Continue,
145         texture->setImage(nullptr, defaultUnpackState, nullptr, gl::TextureTarget::_2D, 0, GL_RGBA8,
146                           gl::Extents(1, 1, 1), GL_RGBA, GL_UNSIGNED_BYTE, nullptr));
147 
148     EXPECT_EQ(1u, texture->getRefCount());
149     EXPECT_EQ(1u, image->getRefCount());
150 
151     // Delete the texture and verify that the image still exists
152     EXPECT_CALL(*textureImpl, destructor()).Times(1).RetiresOnSaturation();
153     texture->release(nullptr);
154 
155     EXPECT_EQ(1u, image->getRefCount());
156 
157     // Delete the image
158     EXPECT_CALL(*imageImpl, destructor()).Times(1).RetiresOnSaturation();
159     image->release(nullptr);
160 }
161 }  // namespace angle
162