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 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 #include "util/EGLWindow.h"
10
11 using namespace angle;
12
13 class PbufferTest : public ANGLETest
14 {
15 protected:
PbufferTest()16 PbufferTest()
17 {
18 setWindowWidth(512);
19 setWindowHeight(512);
20 setConfigRedBits(8);
21 setConfigGreenBits(8);
22 setConfigBlueBits(8);
23 setConfigAlphaBits(8);
24 }
25
testSetUp()26 void testSetUp() override
27 {
28 constexpr char kVS[] =
29 R"(precision highp float;
30 attribute vec4 position;
31 varying vec2 texcoord;
32
33 void main()
34 {
35 gl_Position = position;
36 texcoord = (position.xy * 0.5) + 0.5;
37 texcoord.y = 1.0 - texcoord.y;
38 })";
39
40 constexpr char kFS[] =
41 R"(precision highp float;
42 uniform sampler2D tex;
43 varying vec2 texcoord;
44
45 void main()
46 {
47 gl_FragColor = texture2D(tex, texcoord);
48 })";
49
50 mTextureProgram = CompileProgram(kVS, kFS);
51 if (mTextureProgram == 0)
52 {
53 FAIL() << "shader compilation failed.";
54 }
55
56 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
57
58 EGLWindow *window = getEGLWindow();
59
60 EGLint surfaceType = 0;
61 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_SURFACE_TYPE,
62 &surfaceType);
63 mSupportsPbuffers = (surfaceType & EGL_PBUFFER_BIT) != 0;
64
65 EGLint bindToTextureRGBA = 0;
66 eglGetConfigAttrib(window->getDisplay(), window->getConfig(), EGL_BIND_TO_TEXTURE_RGBA,
67 &bindToTextureRGBA);
68 mSupportsBindTexImage = (bindToTextureRGBA == EGL_TRUE);
69
70 const EGLint pBufferAttributes[] = {
71 EGL_WIDTH, static_cast<EGLint>(mPbufferSize),
72 EGL_HEIGHT, static_cast<EGLint>(mPbufferSize),
73 EGL_TEXTURE_FORMAT, mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
74 EGL_TEXTURE_TARGET, mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
75 EGL_NONE, EGL_NONE,
76 };
77
78 mPbuffer =
79 eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
80 if (mSupportsPbuffers)
81 {
82 ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
83 ASSERT_EGL_SUCCESS();
84 }
85 else
86 {
87 ASSERT_EQ(mPbuffer, EGL_NO_SURFACE);
88 ASSERT_EGL_ERROR(EGL_BAD_MATCH);
89 }
90
91 ASSERT_GL_NO_ERROR();
92 }
93
testTearDown()94 void testTearDown() override
95 {
96 glDeleteProgram(mTextureProgram);
97
98 if (mPbuffer)
99 {
100 EGLWindow *window = getEGLWindow();
101 eglDestroySurface(window->getDisplay(), mPbuffer);
102 }
103 }
104
recreatePbufferInSrgbColorspace()105 void recreatePbufferInSrgbColorspace()
106 {
107 EGLWindow *window = getEGLWindow();
108
109 if (mPbuffer)
110 {
111 eglDestroySurface(window->getDisplay(), mPbuffer);
112 }
113
114 const EGLint pBufferSrgbAttributes[] = {
115 EGL_WIDTH,
116 static_cast<EGLint>(mPbufferSize),
117 EGL_HEIGHT,
118 static_cast<EGLint>(mPbufferSize),
119 EGL_TEXTURE_FORMAT,
120 mSupportsBindTexImage ? EGL_TEXTURE_RGBA : EGL_NO_TEXTURE,
121 EGL_TEXTURE_TARGET,
122 mSupportsBindTexImage ? EGL_TEXTURE_2D : EGL_NO_TEXTURE,
123 EGL_GL_COLORSPACE_KHR,
124 EGL_GL_COLORSPACE_SRGB_KHR,
125 EGL_NONE,
126 EGL_NONE,
127 };
128
129 mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(),
130 pBufferSrgbAttributes);
131 }
132
133 GLuint mTextureProgram;
134 GLint mTextureUniformLocation;
135
136 const size_t mPbufferSize = 32;
137 EGLSurface mPbuffer = EGL_NO_SURFACE;
138 bool mSupportsPbuffers;
139 bool mSupportsBindTexImage;
140 };
141
142 // Test clearing a Pbuffer and checking the color is correct
TEST_P(PbufferTest,Clearing)143 TEST_P(PbufferTest, Clearing)
144 {
145 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
146
147 EGLWindow *window = getEGLWindow();
148
149 // Clear the window surface to blue and verify
150 window->makeCurrent();
151 ASSERT_EGL_SUCCESS();
152
153 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
154 glClear(GL_COLOR_BUFFER_BIT);
155 ASSERT_GL_NO_ERROR();
156 EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, getWindowHeight() / 2, GLColor::blue);
157
158 // Apply the Pbuffer and clear it to purple and verify
159 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
160 ASSERT_EGL_SUCCESS();
161
162 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
163 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
164 glClear(GL_COLOR_BUFFER_BIT);
165 ASSERT_GL_NO_ERROR();
166 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
167 0, 255, 255);
168
169 // Rebind the window surface and verify that it is still blue
170 window->makeCurrent();
171 ASSERT_EGL_SUCCESS();
172 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 0, 0, 255, 255);
173 }
174
175 // Bind the Pbuffer to a texture and verify it renders correctly
TEST_P(PbufferTest,BindTexImage)176 TEST_P(PbufferTest, BindTexImage)
177 {
178 // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
179 // textures.
180 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
181
182 EGLWindow *window = getEGLWindow();
183
184 // Apply the Pbuffer and clear it to purple
185 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
186 ASSERT_EGL_SUCCESS();
187
188 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
189 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
190 glClear(GL_COLOR_BUFFER_BIT);
191 ASSERT_GL_NO_ERROR();
192
193 EXPECT_PIXEL_COLOR_EQ(static_cast<GLint>(mPbufferSize) / 2,
194 static_cast<GLint>(mPbufferSize) / 2, GLColor::magenta);
195
196 // Apply the window surface
197 window->makeCurrent();
198
199 // Create a texture and bind the Pbuffer to it
200 GLuint texture = 0;
201 glGenTextures(1, &texture);
202 glBindTexture(GL_TEXTURE_2D, texture);
203 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
207 EXPECT_GL_NO_ERROR();
208
209 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
210 glViewport(0, 0, getWindowWidth(), getWindowHeight());
211 ASSERT_EGL_SUCCESS();
212
213 // Draw a quad and verify that it is purple
214 glUseProgram(mTextureProgram);
215 glUniform1i(mTextureUniformLocation, 0);
216
217 drawQuad(mTextureProgram, "position", 0.5f);
218 EXPECT_GL_NO_ERROR();
219
220 // Unbind the texture
221 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
222 ASSERT_EGL_SUCCESS();
223
224 // Verify that purple was drawn
225 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
226
227 glDeleteTextures(1, &texture);
228 }
229
230 // Test clearing a Pbuffer in sRGB colorspace and checking the color is correct.
231 // Then bind the Pbuffer to a texture and verify it renders correctly
TEST_P(PbufferTest,ClearAndBindTexImageSrgb)232 TEST_P(PbufferTest, ClearAndBindTexImageSrgb)
233 {
234 EGLWindow *window = getEGLWindow();
235
236 // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
237 // textures.
238 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
239 ANGLE_SKIP_TEST_IF(
240 !IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_colorspace"));
241 // Possible GLES driver bug on Pixel2 devices: http://anglebug.com/5321
242 ANGLE_SKIP_TEST_IF(IsPixel2() && IsOpenGLES());
243
244 GLubyte kLinearColor[] = {132, 55, 219, 255};
245 GLubyte kSrgbColor[] = {190, 128, 238, 255};
246
247 // Switch to sRGB
248 recreatePbufferInSrgbColorspace();
249 EGLint colorspace = 0;
250 eglQuerySurface(window->getDisplay(), mPbuffer, EGL_GL_COLORSPACE, &colorspace);
251 EXPECT_EQ(colorspace, EGL_GL_COLORSPACE_SRGB_KHR);
252
253 // Clear the Pbuffer surface with `kLinearColor`
254 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
255 ASSERT_EGL_SUCCESS();
256
257 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
258 glClearColor(kLinearColor[0] / 255.0f, kLinearColor[1] / 255.0f, kLinearColor[2] / 255.0f,
259 kLinearColor[3] / 255.0f);
260 glClear(GL_COLOR_BUFFER_BIT);
261 ASSERT_GL_NO_ERROR();
262
263 // Expect glReadPixels to be `kSrgbColor` with a tolerance of 1
264 EXPECT_PIXEL_NEAR(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2,
265 kSrgbColor[0], kSrgbColor[1], kSrgbColor[2], kSrgbColor[3], 1);
266
267 window->makeCurrent();
268
269 // Create a texture and bind the Pbuffer to it
270 GLuint texture = 0;
271 glGenTextures(1, &texture);
272 glBindTexture(GL_TEXTURE_2D, texture);
273 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
274 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
275 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
276 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
277 EXPECT_GL_NO_ERROR();
278
279 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
280 glViewport(0, 0, getWindowWidth(), getWindowHeight());
281 ASSERT_EGL_SUCCESS();
282
283 // Sample from a texture with `kSrgbColor` data and render into a surface in linear colorspace.
284 glUseProgram(mTextureProgram);
285 glUniform1i(mTextureUniformLocation, 0);
286
287 drawQuad(mTextureProgram, "position", 0.5f);
288 EXPECT_GL_NO_ERROR();
289
290 // Unbind the texture
291 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
292 ASSERT_EGL_SUCCESS();
293
294 // Expect glReadPixels to be `kLinearColor` with a tolerance of 1
295 EXPECT_PIXEL_NEAR(getWindowWidth() / 2, getWindowHeight() / 2, kLinearColor[0], kLinearColor[1],
296 kLinearColor[2], kLinearColor[3], 1);
297
298 glDeleteTextures(1, &texture);
299 }
300
301 // Test clearing a Pbuffer in sRGB colorspace and checking the color is correct.
302 // Then bind the Pbuffer to a texture and verify it renders correctly.
303 // Then change texture state to skip decode and verify it renders correctly.
TEST_P(PbufferTest,ClearAndBindTexImageSrgbSkipDecode)304 TEST_P(PbufferTest, ClearAndBindTexImageSrgbSkipDecode)
305 {
306 EGLWindow *window = getEGLWindow();
307
308 // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
309 // textures.
310 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
311 ANGLE_SKIP_TEST_IF(
312 !IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_colorspace"));
313 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_sRGB_decode"));
314 // Possible GLES driver bug on Pixel devices: http://anglebug.com/5321
315 ANGLE_SKIP_TEST_IF((IsPixel2() || IsPixel4()) && IsOpenGLES());
316
317 GLubyte kLinearColor[] = {132, 55, 219, 255};
318 GLubyte kSrgbColor[] = {190, 128, 238, 255};
319
320 // Switch to sRGB
321 recreatePbufferInSrgbColorspace();
322 EGLint colorspace = 0;
323 eglQuerySurface(window->getDisplay(), mPbuffer, EGL_GL_COLORSPACE, &colorspace);
324 EXPECT_EQ(colorspace, EGL_GL_COLORSPACE_SRGB_KHR);
325
326 // Clear the Pbuffer surface with `kLinearColor`
327 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
328 ASSERT_EGL_SUCCESS();
329
330 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
331 glClearColor(kLinearColor[0] / 255.0f, kLinearColor[1] / 255.0f, kLinearColor[2] / 255.0f,
332 kLinearColor[3] / 255.0f);
333 glClear(GL_COLOR_BUFFER_BIT);
334 ASSERT_GL_NO_ERROR();
335
336 // Expect glReadPixels to be `kSrgbColor` with a tolerance of 1
337 EXPECT_PIXEL_NEAR(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2,
338 kSrgbColor[0], kSrgbColor[1], kSrgbColor[2], kSrgbColor[3], 1);
339
340 window->makeCurrent();
341
342 // Create a texture and bind the Pbuffer to it
343 GLuint texture = 0;
344 glGenTextures(1, &texture);
345 glBindTexture(GL_TEXTURE_2D, texture);
346 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
347 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
348 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
349 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
350 EXPECT_GL_NO_ERROR();
351
352 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
353 glViewport(0, 0, getWindowWidth(), getWindowHeight());
354 ASSERT_EGL_SUCCESS();
355
356 // Sample from a texture with `kSrgbColor` data and render into a surface in linear colorspace.
357 glUseProgram(mTextureProgram);
358 glUniform1i(mTextureUniformLocation, 0);
359
360 drawQuad(mTextureProgram, "position", 0.5f);
361 EXPECT_GL_NO_ERROR();
362
363 // Expect glReadPixels to be `kLinearColor` with a tolerance of 1
364 EXPECT_PIXEL_NEAR(getWindowWidth() / 2, getWindowHeight() / 2, kLinearColor[0], kLinearColor[1],
365 kLinearColor[2], kLinearColor[3], 1);
366
367 // Set skip decode for the texture
368 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
369 drawQuad(mTextureProgram, "position", 0.5f);
370
371 // Texture is in skip decode mode, expect glReadPixels to be `kSrgbColor` with tolerance of 1
372 EXPECT_PIXEL_NEAR(getWindowWidth() / 2, getWindowHeight() / 2, kSrgbColor[0], kSrgbColor[1],
373 kSrgbColor[2], kSrgbColor[3], 1);
374
375 // Unbind the texture
376 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
377 ASSERT_EGL_SUCCESS();
378
379 glDeleteTextures(1, &texture);
380 }
381
382 // Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
383 // size information is correctly updated.
TEST_P(PbufferTest,TextureSizeReset)384 TEST_P(PbufferTest, TextureSizeReset)
385 {
386 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers);
387 ANGLE_SKIP_TEST_IF(!mSupportsBindTexImage);
388 ANGLE_SKIP_TEST_IF(IsARM64() && IsWindows() && IsD3D());
389
390 GLTexture texture;
391 glBindTexture(GL_TEXTURE_2D, texture);
392 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
393 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
394 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
395 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
396 EXPECT_GL_NO_ERROR();
397
398 glUseProgram(mTextureProgram);
399 glUniform1i(mTextureUniformLocation, 0);
400
401 // Fill the texture with white pixels
402 std::vector<GLColor> whitePixels(mPbufferSize * mPbufferSize, GLColor::white);
403 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(mPbufferSize),
404 static_cast<GLsizei>(mPbufferSize), 0, GL_RGBA, GL_UNSIGNED_BYTE,
405 whitePixels.data());
406 EXPECT_GL_NO_ERROR();
407
408 // Draw the white texture and verify that the pixels are correct
409 drawQuad(mTextureProgram, "position", 0.5f);
410 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
411
412 // Bind the EGL surface and draw with it, results are undefined since nothing has
413 // been written to it
414 EGLWindow *window = getEGLWindow();
415 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
416 drawQuad(mTextureProgram, "position", 0.5f);
417 EXPECT_GL_NO_ERROR();
418
419 // Clear the back buffer to a unique color (green)
420 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
421 glClear(GL_COLOR_BUFFER_BIT);
422 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
423
424 // Unbind the EGL surface and try to draw with the texture again, the texture's size should
425 // now be zero and incomplete so the back buffer should be black
426 eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
427 drawQuad(mTextureProgram, "position", 0.5f);
428 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
429 }
430
431 // Bind a Pbuffer, redefine the texture, and verify it renders correctly
TEST_P(PbufferTest,BindTexImageAndRedefineTexture)432 TEST_P(PbufferTest, BindTexImageAndRedefineTexture)
433 {
434 // Test skipped because Pbuffers are not supported or Pbuffer does not support binding to RGBA
435 // textures.
436 ANGLE_SKIP_TEST_IF(!mSupportsPbuffers || !mSupportsBindTexImage);
437
438 EGLWindow *window = getEGLWindow();
439
440 // Apply the Pbuffer and clear it to purple
441 eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
442 ASSERT_EGL_SUCCESS();
443
444 glViewport(0, 0, static_cast<GLsizei>(mPbufferSize), static_cast<GLsizei>(mPbufferSize));
445 glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
446 glClear(GL_COLOR_BUFFER_BIT);
447 ASSERT_GL_NO_ERROR();
448
449 EXPECT_PIXEL_EQ(static_cast<GLint>(mPbufferSize) / 2, static_cast<GLint>(mPbufferSize) / 2, 255,
450 0, 255, 255);
451
452 // Apply the window surface
453 window->makeCurrent();
454
455 // Create a texture and bind the Pbuffer to it
456 GLuint texture = 0;
457 glGenTextures(1, &texture);
458 glBindTexture(GL_TEXTURE_2D, texture);
459 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
460 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
461 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
463 EXPECT_GL_NO_ERROR();
464
465 eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
466 glViewport(0, 0, getWindowWidth(), getWindowHeight());
467 ASSERT_EGL_SUCCESS();
468
469 // Redefine the texture
470 unsigned int pixelValue = 0xFFFF00FF;
471 std::vector<unsigned int> pixelData(getWindowWidth() * getWindowHeight(), pixelValue);
472 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
473 GL_UNSIGNED_BYTE, &pixelData[0]);
474
475 // Draw a quad and verify that it is magenta
476 glUseProgram(mTextureProgram);
477 glUniform1i(mTextureUniformLocation, 0);
478
479 drawQuad(mTextureProgram, "position", 0.5f);
480 EXPECT_GL_NO_ERROR();
481
482 // Verify that magenta was drawn
483 EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
484
485 glDeleteTextures(1, &texture);
486 }
487
488 ANGLE_INSTANTIATE_TEST_ES2(PbufferTest);
489