1 //
2 // Copyright 2016 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 // RobustClientMemoryTest.cpp : Tests of the GL_ANGLE_robust_client_memory extension.
8
9 #include "test_utils/ANGLETest.h"
10
11 #include "test_utils/gl_raii.h"
12
13 namespace angle
14 {
15
16 constexpr GLsizei kWindowSize = 128;
17
18 class RobustClientMemoryTest : public ANGLETest<>
19 {
20 protected:
RobustClientMemoryTest()21 RobustClientMemoryTest()
22 {
23 setWindowWidth(kWindowSize);
24 setWindowHeight(kWindowSize);
25 setConfigRedBits(8);
26 setConfigGreenBits(8);
27 setConfigBlueBits(8);
28 setConfigAlphaBits(8);
29 }
30
extensionsPresent() const31 bool extensionsPresent() const
32 {
33 if (!IsGLExtensionEnabled("GL_ANGLE_robust_client_memory"))
34 {
35 std::cout << "Test skipped because GL_ANGLE_robust_client_memory is not available.";
36 return false;
37 }
38
39 return true;
40 }
41 };
42
43 // Test basic usage and validation of glGetIntegervRobustANGLE
TEST_P(RobustClientMemoryTest,GetInteger)44 TEST_P(RobustClientMemoryTest, GetInteger)
45 {
46 if (!extensionsPresent())
47 {
48 return;
49 }
50
51 // Verify that the robust and regular entry points return the same values
52 GLint resultRobust;
53 GLsizei length;
54 glGetIntegervRobustANGLE(GL_MAX_VERTEX_ATTRIBS, 1, &length, &resultRobust);
55 EXPECT_GL_NO_ERROR();
56 EXPECT_EQ(1, length);
57
58 GLint resultRegular;
59 glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &resultRegular);
60 EXPECT_GL_NO_ERROR();
61 EXPECT_EQ(resultRegular, resultRobust);
62
63 // Query a dynamic value
64 GLint numCompressedFormats;
65 glGetIntegervRobustANGLE(GL_NUM_COMPRESSED_TEXTURE_FORMATS, 1, &length, &numCompressedFormats);
66 ASSERT_GL_NO_ERROR();
67 EXPECT_EQ(1, length);
68
69 if (numCompressedFormats > 0)
70 {
71 std::vector<GLint> resultBuf(numCompressedFormats * 2, 0);
72
73 // Test when the bufSize is too low
74 glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS, numCompressedFormats - 1, &length,
75 resultBuf.data());
76 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
77 EXPECT_TRUE(std::all_of(resultBuf.begin(), resultBuf.end(),
78 [](GLint value) { return value == 0; }));
79
80 // Make sure the GL doesn't touch the end of the buffer
81 glGetIntegervRobustANGLE(GL_COMPRESSED_TEXTURE_FORMATS,
82 static_cast<GLsizei>(resultBuf.size()), &length, resultBuf.data());
83 EXPECT_GL_NO_ERROR();
84 EXPECT_EQ(numCompressedFormats, length);
85 EXPECT_TRUE(std::none_of(resultBuf.begin(), resultBuf.begin() + length,
86 [](GLint value) { return value == 0; }));
87 EXPECT_TRUE(std::all_of(resultBuf.begin() + length, resultBuf.end(),
88 [](GLint value) { return value == 0; }));
89 }
90
91 // Test with null length
92 glGetIntegervRobustANGLE(GL_MAX_VARYING_VECTORS, 1, nullptr, &resultRobust);
93 EXPECT_GL_NO_ERROR();
94
95 glGetIntegervRobustANGLE(GL_MAX_VIEWPORT_DIMS, 1, nullptr, &resultRobust);
96 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
97
98 GLint maxViewportDims[2];
99 glGetIntegervRobustANGLE(GL_MAX_VIEWPORT_DIMS, 2, nullptr, maxViewportDims);
100 EXPECT_GL_NO_ERROR();
101 }
102
103 // Test basic usage and validation of glTexImage2DRobustANGLE and glTexSubImage2DRobustANGLE
TEST_P(RobustClientMemoryTest,TexImage2D)104 TEST_P(RobustClientMemoryTest, TexImage2D)
105 {
106 if (!extensionsPresent())
107 {
108 return;
109 }
110 GLTexture tex;
111 glBindTexture(GL_TEXTURE_2D, tex);
112
113 GLsizei dataDimension = 1024;
114 std::vector<GLubyte> rgbaData(dataDimension * dataDimension * 4);
115
116 // Test the regular case
117 glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
118 GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
119 rgbaData.data());
120 EXPECT_GL_NO_ERROR();
121
122 glTexSubImage2DRobustANGLE(GL_TEXTURE_2D, 0, 0, 0, dataDimension, dataDimension, GL_RGBA,
123 GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
124 rgbaData.data());
125 EXPECT_GL_NO_ERROR();
126
127 // Test with a data size that is too small
128 glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
129 GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()) / 2,
130 rgbaData.data());
131 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
132
133 glTexSubImage2DRobustANGLE(GL_TEXTURE_2D, 0, 0, 0, dataDimension, dataDimension, GL_RGBA,
134 GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()) / 2,
135 rgbaData.data());
136 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
137
138 if (getClientMajorVersion() >= 3)
139 {
140 // Set an unpack parameter that would cause the driver to read past the end of the buffer
141 glPixelStorei(GL_UNPACK_ROW_LENGTH, dataDimension + 1);
142 glTexImage2DRobustANGLE(GL_TEXTURE_2D, 0, GL_RGBA, dataDimension, dataDimension, 0, GL_RGBA,
143 GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
144 rgbaData.data());
145 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
146 }
147 }
148
149 // Test basic usage and validation of glReadPixelsRobustANGLE
TEST_P(RobustClientMemoryTest,ReadPixels)150 TEST_P(RobustClientMemoryTest, ReadPixels)
151 {
152 if (!extensionsPresent())
153 {
154 return;
155 }
156
157 // TODO(ynovikov): Looks like a driver bug on Intel HD 530 http://anglebug.com/42260689
158 ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsDesktopOpenGL());
159
160 GLsizei dataDimension = 16;
161 std::vector<GLubyte> rgbaData(dataDimension * dataDimension * 4);
162
163 // Test the regular case
164 GLsizei length = 0;
165 GLsizei width = 0;
166 GLsizei height = 0;
167 glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
168 static_cast<GLsizei>(rgbaData.size()), &length, &width, &height,
169 rgbaData.data());
170 EXPECT_GL_NO_ERROR();
171 EXPECT_EQ(static_cast<GLsizei>(rgbaData.size()), length);
172 EXPECT_EQ(dataDimension, width);
173 EXPECT_EQ(dataDimension, height);
174
175 // Test a case that would be partially clipped
176 glReadPixelsRobustANGLE(-1, kWindowSize - dataDimension + 3, dataDimension, dataDimension,
177 GL_RGBA, GL_UNSIGNED_BYTE, static_cast<GLsizei>(rgbaData.size()),
178 &length, &width, &height, rgbaData.data());
179 EXPECT_GL_NO_ERROR();
180 EXPECT_EQ(static_cast<GLsizei>(rgbaData.size()), length);
181 EXPECT_EQ(dataDimension - 1, width);
182 EXPECT_EQ(dataDimension - 3, height);
183
184 // Test with a data size that is too small
185 glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
186 static_cast<GLsizei>(rgbaData.size()) - 1, &length, nullptr, nullptr,
187 rgbaData.data());
188 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
189
190 if (getClientMajorVersion() >= 3)
191 {
192 // Set a pack parameter that would cause the driver to write past the end of the buffer
193 glPixelStorei(GL_PACK_ROW_LENGTH, dataDimension + 1);
194 glReadPixelsRobustANGLE(0, 0, dataDimension, dataDimension, GL_RGBA, GL_UNSIGNED_BYTE,
195 static_cast<GLsizei>(rgbaData.size()), &length, nullptr, nullptr,
196 rgbaData.data());
197 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
198 }
199 }
200
201 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
202 // tests should be run against.
203 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(RobustClientMemoryTest);
204
205 } // namespace angle
206