1 #include "ANGLETest.h"
2
3 #include <cstdint>
4
5 class BufferDataTest : public ANGLETest
6 {
7 protected:
BufferDataTest()8 BufferDataTest()
9 : mBuffer(0),
10 mProgram(0),
11 mAttribLocation(-1)
12 {
13 setWindowWidth(16);
14 setWindowHeight(16);
15 setConfigRedBits(8);
16 setConfigGreenBits(8);
17 setConfigBlueBits(8);
18 setConfigAlphaBits(8);
19 setConfigDepthBits(24);
20 }
21
SetUp()22 virtual void SetUp()
23 {
24 ANGLETest::SetUp();
25
26 const char * vsSource = SHADER_SOURCE
27 (
28 attribute vec4 position;
29 attribute float in_attrib;
30 varying float v_attrib;
31 void main()
32 {
33 v_attrib = in_attrib;
34 gl_Position = position;
35 }
36 );
37
38 const char * fsSource = SHADER_SOURCE
39 (
40 precision mediump float;
41 varying float v_attrib;
42 void main()
43 {
44 gl_FragColor = vec4(v_attrib, 0, 0, 1);
45 }
46 );
47
48 glGenBuffers(1, &mBuffer);
49 ASSERT_NE(mBuffer, 0U);
50
51 mProgram = CompileProgram(vsSource, fsSource);
52 ASSERT_NE(mProgram, 0U);
53
54 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
55 ASSERT_NE(mAttribLocation, -1);
56
57 glClearColor(0, 0, 0, 0);
58 glClearDepthf(0.0);
59 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
60
61 glDisable(GL_DEPTH_TEST);
62
63 ASSERT_GL_NO_ERROR();
64 }
65
TearDown()66 virtual void TearDown()
67 {
68 glDeleteBuffers(1, &mBuffer);
69 glDeleteProgram(mProgram);
70
71 ANGLETest::TearDown();
72 }
73
74 GLuint mBuffer;
75 GLuint mProgram;
76 GLint mAttribLocation;
77 };
78
TEST_F(BufferDataTest,NULLData)79 TEST_F(BufferDataTest, NULLData)
80 {
81 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
82 EXPECT_GL_NO_ERROR();
83
84 const int numIterations = 128;
85 for (int i = 0; i < numIterations; ++i)
86 {
87 GLsizei bufferSize = sizeof(GLfloat) * (i + 1);
88 glBufferData(GL_ARRAY_BUFFER, bufferSize, NULL, GL_STATIC_DRAW);
89 EXPECT_GL_NO_ERROR();
90
91 for (int j = 0; j < bufferSize; j++)
92 {
93 for (int k = 0; k < bufferSize - j; k++)
94 {
95 glBufferSubData(GL_ARRAY_BUFFER, k, j, NULL);
96 EXPECT_GL_NO_ERROR();
97 }
98 }
99 }
100 }
101
TEST_F(BufferDataTest,ZeroNonNULLData)102 TEST_F(BufferDataTest, ZeroNonNULLData)
103 {
104 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
105 EXPECT_GL_NO_ERROR();
106
107 char *zeroData = new char[0];
108 glBufferData(GL_ARRAY_BUFFER, 0, zeroData, GL_STATIC_DRAW);
109 EXPECT_GL_NO_ERROR();
110
111 glBufferSubData(GL_ARRAY_BUFFER, 0, 0, zeroData);
112 EXPECT_GL_NO_ERROR();
113
114 delete [] zeroData;
115 }
116
TEST_F(BufferDataTest,NULLResolvedData)117 TEST_F(BufferDataTest, NULLResolvedData)
118 {
119 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
120 glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_DYNAMIC_DRAW);
121
122 glUseProgram(mProgram);
123 glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, NULL);
124 glEnableVertexAttribArray(mAttribLocation);
125 glBindBuffer(GL_ARRAY_BUFFER, 0);
126
127 drawQuad(mProgram, "position", 0.5f);
128 }
129
TEST_F(BufferDataTest,HugeSetDataShouldNotCrash)130 TEST_F(BufferDataTest, HugeSetDataShouldNotCrash)
131 {
132 glBindBuffer(GL_ARRAY_BUFFER, mBuffer);
133 EXPECT_GL_NO_ERROR();
134
135 GLsizei allocSize = std::numeric_limits<GLsizei>::max() >> 2;
136
137 uint8_t *data = NULL;
138 while (data == NULL && allocSize >= 4)
139 {
140 data = new (std::nothrow) uint8_t[allocSize];
141
142 if (data == NULL)
143 {
144 allocSize >>= 1;
145 }
146 }
147
148 ASSERT_NE(static_cast<uint8_t*>(NULL), data);
149 memset(data, 0, allocSize);
150
151 float * fValue = reinterpret_cast<float*>(data);
152 for (unsigned int f = 0; f < 6; f++)
153 {
154 fValue[f] = 1.0f;
155 }
156
157 glBufferData(GL_ARRAY_BUFFER, allocSize, data, GL_STATIC_DRAW);
158
159 GLenum error = glGetError();
160 if (error == GL_NO_ERROR)
161 {
162 // If we didn't fail because of an out of memory error, try drawing a quad
163 // using the large buffer
164
165 // DISABLED because it takes a long time, but left for posterity
166
167 //glUseProgram(mProgram);
168 //glVertexAttribPointer(mAttribLocation, 1, GL_FLOAT, GL_FALSE, 4, NULL);
169 //glEnableVertexAttribArray(mAttribLocation);
170 //glBindBuffer(GL_ARRAY_BUFFER, 0);
171 //drawQuad(mProgram, "position", 0.5f);
172 //swapBuffers();
173
174 //// Draw operations can also generate out-of-memory, which is in-spec
175 //error = glGetError();
176 //if (error == GL_NO_ERROR)
177 //{
178 // GLint viewportSize[4];
179 // glGetIntegerv(GL_VIEWPORT, viewportSize);
180
181 // GLint midPixelX = (viewportSize[0] + viewportSize[2]) / 2;
182 // GLint midPixelY = (viewportSize[1] + viewportSize[3]) / 2;
183
184 // EXPECT_PIXEL_EQ(midPixelX, midPixelY, 255, 0, 0, 255);
185 //}
186 //else
187 //{
188 // EXPECT_EQ(GL_OUT_OF_MEMORY, error);
189 //}
190 }
191 else
192 {
193 EXPECT_EQ(GL_OUT_OF_MEMORY, error);
194 }
195
196 delete[] data;
197 }
198
199 class IndexedBufferCopyTest : public ANGLETest
200 {
201 protected:
IndexedBufferCopyTest()202 IndexedBufferCopyTest()
203 {
204 setWindowWidth(16);
205 setWindowHeight(16);
206 setConfigRedBits(8);
207 setConfigGreenBits(8);
208 setConfigBlueBits(8);
209 setConfigAlphaBits(8);
210 setConfigDepthBits(24);
211 setClientVersion(3);
212 }
213
SetUp()214 virtual void SetUp()
215 {
216 ANGLETest::SetUp();
217
218 const char * vsSource = SHADER_SOURCE
219 (
220 attribute vec3 in_attrib;
221 varying vec3 v_attrib;
222 void main()
223 {
224 v_attrib = in_attrib;
225 gl_Position = vec4(0.0, 0.0, 0.5, 1.0);
226 gl_PointSize = 100.0;
227 }
228 );
229
230 const char * fsSource = SHADER_SOURCE
231 (
232 precision mediump float;
233 varying vec3 v_attrib;
234 void main()
235 {
236 gl_FragColor = vec4(v_attrib, 1);
237 }
238 );
239
240 glGenBuffers(2, mBuffers);
241 ASSERT_NE(mBuffers[0], 0U);
242 ASSERT_NE(mBuffers[1], 0U);
243
244 glGenBuffers(1, &mElementBuffer);
245 ASSERT_NE(mElementBuffer, 0U);
246
247 mProgram = CompileProgram(vsSource, fsSource);
248 ASSERT_NE(mProgram, 0U);
249
250 mAttribLocation = glGetAttribLocation(mProgram, "in_attrib");
251 ASSERT_NE(mAttribLocation, -1);
252
253 glClearColor(0, 0, 0, 0);
254 glDisable(GL_DEPTH_TEST);
255 glClear(GL_COLOR_BUFFER_BIT);
256
257 ASSERT_GL_NO_ERROR();
258 }
259
TearDown()260 virtual void TearDown()
261 {
262 glDeleteBuffers(2, mBuffers);
263 glDeleteBuffers(1, &mElementBuffer);
264 glDeleteProgram(mProgram);
265
266 ANGLETest::TearDown();
267 }
268
269 GLuint mBuffers[2];
270 GLuint mElementBuffer;
271 GLuint mProgram;
272 GLint mAttribLocation;
273 };
274
275 // The following test covers an ANGLE bug where our index ranges
276 // weren't updated from CopyBufferSubData calls
277 // https://code.google.com/p/angleproject/issues/detail?id=709
TEST_F(IndexedBufferCopyTest,IndexRangeBug)278 TEST_F(IndexedBufferCopyTest, IndexRangeBug)
279 {
280 unsigned char vertexData[] = { 255, 0, 0, 0, 0, 0 };
281 unsigned int indexData[] = { 0, 1 };
282
283 glBindBuffer(GL_ARRAY_BUFFER, mBuffers[0]);
284 glBufferData(GL_ARRAY_BUFFER, sizeof(char) * 6, vertexData, GL_STATIC_DRAW);
285
286 glUseProgram(mProgram);
287 glVertexAttribPointer(mAttribLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE, 3, NULL);
288 glEnableVertexAttribArray(mAttribLocation);
289
290 ASSERT_GL_NO_ERROR();
291
292 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mElementBuffer);
293 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int) * 1, indexData, GL_STATIC_DRAW);
294
295 glUseProgram(mProgram);
296
297 ASSERT_GL_NO_ERROR();
298
299 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
300
301 EXPECT_GL_NO_ERROR();
302 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
303
304 glBindBuffer(GL_COPY_READ_BUFFER, mBuffers[1]);
305 glBufferData(GL_COPY_READ_BUFFER, 4, &indexData[1], GL_STATIC_DRAW);
306
307 glBindBuffer(GL_COPY_WRITE_BUFFER, mElementBuffer);
308
309 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(int));
310
311 ASSERT_GL_NO_ERROR();
312
313 glClear(GL_COLOR_BUFFER_BIT);
314 EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
315
316 unsigned char newData[] = { 0, 255, 0 };
317 glBufferSubData(GL_ARRAY_BUFFER, 3, 3, newData);
318
319 glDrawElements(GL_POINTS, 1, GL_UNSIGNED_INT, NULL);
320
321 EXPECT_GL_NO_ERROR();
322 EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
323 }
324