1 //
2 // Copyright 2019 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 // GetImageTest:
7 // Tests for the ANGLE_get_image extension.
8 //
9
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12
13 using namespace angle;
14
15 namespace
16 {
17 constexpr uint32_t kSize = 32;
18 constexpr char kExtensionName[] = "GL_ANGLE_get_image";
19 constexpr uint32_t kSmallSize = 2;
20
21 class GetImageTest : public ANGLETest
22 {
23 public:
GetImageTest()24 GetImageTest()
25 {
26 setWindowWidth(kSize);
27 setWindowHeight(kSize);
28 setConfigRedBits(8);
29 setConfigGreenBits(8);
30 setConfigBlueBits(8);
31 setConfigAlphaBits(8);
32 }
33 };
34
35 class GetImageTestNoExtensions : public ANGLETest
36 {
37 public:
GetImageTestNoExtensions()38 GetImageTestNoExtensions() { setExtensionsEnabled(false); }
39 };
40
InitTextureWithSize(uint32_t size,void * pixelData)41 GLTexture InitTextureWithSize(uint32_t size, void *pixelData)
42 {
43 // Create a simple texture.
44 GLTexture tex;
45 glBindTexture(GL_TEXTURE_2D, tex);
46 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
47 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
48 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
49 return tex;
50 }
51
InitSimpleTexture()52 GLTexture InitSimpleTexture()
53 {
54 std::vector<GLColor> pixelData(kSize * kSize, GLColor::red);
55 return InitTextureWithSize(kSize, pixelData.data());
56 }
57
InitRenderbufferWithSize(uint32_t size)58 GLRenderbuffer InitRenderbufferWithSize(uint32_t size)
59 {
60 // Create a simple renderbuffer.
61 GLRenderbuffer renderbuf;
62 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
63 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, size, size);
64 return renderbuf;
65 }
66
InitSimpleRenderbuffer()67 GLRenderbuffer InitSimpleRenderbuffer()
68 {
69 return InitRenderbufferWithSize(kSize);
70 }
71
72 // Test validation for the extension functions.
TEST_P(GetImageTest,NegativeAPI)73 TEST_P(GetImageTest, NegativeAPI)
74 {
75 // Verify the extension is enabled.
76 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
77
78 // Draw once with simple texture.
79 GLTexture tex = InitSimpleTexture();
80 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
81 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
82 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
83 ASSERT_GL_NO_ERROR();
84
85 // Pack pixels tightly.
86 glPixelStorei(GL_PACK_ALIGNMENT, 1);
87
88 // Verify GetTexImage can work with correct parameters.
89 std::vector<GLColor> buffer(kSize * kSize);
90 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
91 EXPECT_GL_NO_ERROR();
92
93 // Test invalid texture target.
94 glGetTexImageANGLE(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
95 EXPECT_GL_ERROR(GL_INVALID_ENUM);
96
97 // Test invalid texture level.
98 glGetTexImageANGLE(GL_TEXTURE_2D, -1, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
99 EXPECT_GL_ERROR(GL_INVALID_VALUE);
100 glGetTexImageANGLE(GL_TEXTURE_2D, 2000, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
101 EXPECT_GL_ERROR(GL_INVALID_VALUE);
102
103 // Test invalid format and type.
104 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
105 EXPECT_GL_ERROR(GL_INVALID_ENUM);
106 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_NONE, buffer.data());
107 EXPECT_GL_ERROR(GL_INVALID_ENUM);
108
109 // Create a simple renderbuffer.
110 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
111 ASSERT_GL_NO_ERROR();
112
113 // Verify GetRenderbufferImage can work with correct parameters.
114 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
115 EXPECT_GL_NO_ERROR();
116
117 // Test invalid renderbuffer target.
118 glGetRenderbufferImageANGLE(GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
119 EXPECT_GL_ERROR(GL_INVALID_ENUM);
120
121 // Test invalid renderbuffer format/type.
122 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
123 EXPECT_GL_ERROR(GL_INVALID_ENUM);
124 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_NONE, buffer.data());
125 EXPECT_GL_ERROR(GL_INVALID_ENUM);
126
127 // Pack buffer tests. Requires ES 3+ or extension.
128 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_NV_pixel_buffer_object"))
129 {
130 // Test valid pack buffer.
131 GLBuffer packBuffer;
132 glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
133 glBufferData(GL_PIXEL_PACK_BUFFER, kSize * kSize * sizeof(GLColor), nullptr,
134 GL_STATIC_DRAW);
135 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
136 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
137 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
138 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
139
140 // Test too small pack buffer.
141 glBufferData(GL_PIXEL_PACK_BUFFER, kSize, nullptr, GL_STATIC_DRAW);
142 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
143 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
144 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
145 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
146 }
147 }
148
149 // Simple test for GetTexImage
TEST_P(GetImageTest,GetTexImage)150 TEST_P(GetImageTest, GetTexImage)
151 {
152 // Verify the extension is enabled.
153 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
154
155 constexpr uint32_t kSmallSize = 2;
156 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
157 GLColor::yellow};
158
159 glViewport(0, 0, kSmallSize, kSmallSize);
160
161 // Draw once with simple texture.
162 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
163 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
164 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
165 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
166 ASSERT_GL_NO_ERROR();
167
168 // Pack pixels tightly.
169 glPixelStorei(GL_PACK_ALIGNMENT, 1);
170
171 // Verify GetImage.
172 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
173 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
174 EXPECT_GL_NO_ERROR();
175 EXPECT_EQ(expectedData, actualData);
176 }
177
178 // Simple cube map test for GetTexImage
TEST_P(GetImageTest,CubeMap)179 TEST_P(GetImageTest, CubeMap)
180 {
181 // Verify the extension is enabled.
182 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
183
184 const std::array<std::array<GLColor, kSmallSize * kSmallSize>, kCubeFaces.size()> expectedData =
185 {{
186 {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
187 {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
188 {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
189 {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
190 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
191 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
192 }};
193
194 GLTexture texture;
195 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
196
197 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
198 {
199 glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA,
200 GL_UNSIGNED_BYTE, expectedData[faceIndex].data());
201 }
202 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
203 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
204
205 // Pack pixels tightly.
206 glPixelStorei(GL_PACK_ALIGNMENT, 1);
207
208 // Verify GetImage.
209 std::array<GLColor, kSmallSize *kSmallSize> actualData = {};
210 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
211 {
212 glGetTexImageANGLE(kCubeFaces[faceIndex], 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
213 EXPECT_GL_NO_ERROR();
214 EXPECT_EQ(expectedData[faceIndex], actualData);
215 }
216 }
217
218 // Simple test for GetRenderbufferImage
TEST_P(GetImageTest,GetRenderbufferImage)219 TEST_P(GetImageTest, GetRenderbufferImage)
220 {
221 // Verify the extension is enabled.
222 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
223
224 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
225 GLColor::yellow};
226
227 glViewport(0, 0, kSmallSize, kSmallSize);
228
229 // Set up a simple Framebuffer with a Renderbuffer.
230 GLRenderbuffer renderbuffer = InitRenderbufferWithSize(kSmallSize);
231 GLFramebuffer framebuffer;
232 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
233 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
234 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
235
236 // Draw once with simple texture.
237 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
238 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
239 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
240 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
241 ASSERT_GL_NO_ERROR();
242
243 // Pack pixels tightly.
244 glPixelStorei(GL_PACK_ALIGNMENT, 1);
245
246 // Verify GetImage.
247 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
248 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
249 EXPECT_GL_NO_ERROR();
250 EXPECT_EQ(expectedData, actualData);
251 }
252
253 // Verifies that the extension enums and entry points are invalid when the extension is disabled.
TEST_P(GetImageTestNoExtensions,EntryPointsInactive)254 TEST_P(GetImageTestNoExtensions, EntryPointsInactive)
255 {
256 // Verify the extension is not enabled.
257 ASSERT_FALSE(IsGLExtensionEnabled(kExtensionName));
258
259 // Draw once with simple texture.
260 GLTexture tex = InitSimpleTexture();
261 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
262 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
263 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
264 ASSERT_GL_NO_ERROR();
265
266 // Query implementation format and type. Should give invalid enum.
267 GLint param;
268 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
269 EXPECT_GL_ERROR(GL_INVALID_ENUM);
270
271 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
272 EXPECT_GL_ERROR(GL_INVALID_ENUM);
273
274 // Verify calling GetTexImage produces an error.
275 std::vector<GLColor> buffer(kSize * kSize, 0);
276 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
277 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
278
279 // Create a simple renderbuffer.
280 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
281 ASSERT_GL_NO_ERROR();
282
283 // Query implementation format and type. Should give invalid enum.
284 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
285 EXPECT_GL_ERROR(GL_INVALID_ENUM);
286
287 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
288 EXPECT_GL_ERROR(GL_INVALID_ENUM);
289
290 // Verify calling GetRenderbufferImage produces an error.
291 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
292 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
293 }
294
295 ANGLE_INSTANTIATE_TEST(GetImageTest, ES2_VULKAN(), ES3_VULKAN());
296 ANGLE_INSTANTIATE_TEST(GetImageTestNoExtensions, ES2_VULKAN(), ES3_VULKAN());
297 } // namespace