1 #include "ANGLETest.h" 2 3 #include <cstdint> 4 5 class BufferDataTest : public ANGLETest 6 { 7 protected: 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 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 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 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 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 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 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: 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 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 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 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