Add tests of basic Pbuffer functionality.
BUG=angleproject:890
Change-Id: I8f82414d1875f80269bd9dd1f629e5b7903cb584
Reviewed-on: https://chromium-review.googlesource.com/264380
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/tests/end2end_tests/PbufferTest.cpp b/src/tests/end2end_tests/PbufferTest.cpp
new file mode 100644
index 0000000..72379cd
--- /dev/null
+++ b/src/tests/end2end_tests/PbufferTest.cpp
@@ -0,0 +1,214 @@
+#include "ANGLETest.h"
+
+// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
+ANGLE_TYPED_TEST_CASE(PbufferTest, ES2_D3D9, ES2_D3D11);
+
+template<typename T>
+class PbufferTest : public ANGLETest
+{
+ protected:
+ PbufferTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
+ {
+ setWindowWidth(512);
+ setWindowHeight(512);
+ setConfigRedBits(8);
+ setConfigGreenBits(8);
+ setConfigBlueBits(8);
+ setConfigAlphaBits(8);
+ }
+
+ virtual void SetUp()
+ {
+ ANGLETest::SetUp();
+
+ const std::string vsSource = SHADER_SOURCE
+ (
+ precision highp float;
+ attribute vec4 position;
+ varying vec2 texcoord;
+
+ void main()
+ {
+ gl_Position = position;
+ texcoord = (position.xy * 0.5) + 0.5;
+ texcoord.y = 1.0 - texcoord.y;
+ }
+ );
+
+ const std::string textureFSSource = SHADER_SOURCE
+ (
+ precision highp float;
+ uniform sampler2D tex;
+ varying vec2 texcoord;
+
+ void main()
+ {
+ gl_FragColor = texture2D(tex, texcoord);
+ }
+ );
+
+ mTextureProgram = CompileProgram(vsSource, textureFSSource);
+ if (mTextureProgram == 0)
+ {
+ FAIL() << "shader compilation failed.";
+ }
+
+ mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
+
+ const EGLint pBufferAttributes[] =
+ {
+ EGL_WIDTH, mPbufferSize,
+ EGL_HEIGHT, mPbufferSize,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLWindow *window = getEGLWindow();
+ mPbuffer = eglCreatePbufferSurface(window->getDisplay(), window->getConfig(), pBufferAttributes);
+ ASSERT_NE(mPbuffer, EGL_NO_SURFACE);
+
+ ASSERT_EGL_SUCCESS();
+ ASSERT_GL_NO_ERROR();
+ }
+
+ virtual void TearDown()
+ {
+ glDeleteProgram(mTextureProgram);
+
+ EGLWindow *window = getEGLWindow();
+ eglDestroySurface(window->getDisplay(), mPbuffer);
+
+ ANGLETest::TearDown();
+ }
+
+ GLuint mTextureProgram;
+ GLint mTextureUniformLocation;
+
+ const size_t mPbufferSize = 32;
+ EGLSurface mPbuffer;
+};
+
+// Test clearing a Pbuffer and checking the color is correct
+TYPED_TEST(PbufferTest, Clearing)
+{
+ EGLWindow *window = getEGLWindow();
+
+ // Clear the window surface to blue and verify
+ eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+ ASSERT_EGL_SUCCESS();
+
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 0, 0, 255, 255);
+
+ // Apply the Pbuffer and clear it to purple and verify
+ eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
+ ASSERT_EGL_SUCCESS();
+
+ glViewport(0, 0, mPbufferSize, mPbufferSize);
+ glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(mPbufferSize / 2, mPbufferSize / 2, 255, 0, 255, 255);
+
+ // Rebind the window serfance and verify that it is still blue
+ eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+ ASSERT_EGL_SUCCESS();
+ EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 0, 0, 255, 255);
+}
+
+// Bind the Pbuffer to a texture and verify it renders correctly
+TYPED_TEST(PbufferTest, BindTexImage)
+{
+ EGLWindow *window = getEGLWindow();
+
+ // Apply the Pbuffer and clear it to purple
+ eglMakeCurrent(window->getDisplay(), mPbuffer, mPbuffer, window->getContext());
+ ASSERT_EGL_SUCCESS();
+
+ glViewport(0, 0, mPbufferSize, mPbufferSize);
+ glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ ASSERT_GL_NO_ERROR();
+
+ EXPECT_PIXEL_EQ(mPbufferSize / 2, mPbufferSize / 2, 255, 0, 255, 255);
+
+ // Apply the window surface
+ eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(), window->getContext());
+
+ // Create a texture and bind the Pbuffer to it
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ EXPECT_GL_NO_ERROR();
+
+ eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+ glViewport(0, 0, window->getWidth(), window->getHeight());
+ ASSERT_EGL_SUCCESS();
+
+ // Draw a quad and verify that it is purple
+ glUseProgram(mTextureProgram);
+ glUniform1i(mTextureUniformLocation, 0);
+
+ drawQuad(mTextureProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+
+ // Unbind the texture
+ eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+ ASSERT_EGL_SUCCESS();
+
+ // Verify that purple was drawn
+ EXPECT_PIXEL_EQ(window->getWidth() / 2, window->getHeight() / 2, 255, 0, 255, 255);
+
+ glDeleteTextures(1, &texture);
+}
+
+// Verify that when eglBind/ReleaseTexImage are called, the texture images are freed and their
+// size information is correctly updated.
+TYPED_TEST(PbufferTest, TextureSizeReset)
+{
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ EXPECT_GL_NO_ERROR();
+
+ glUseProgram(mTextureProgram);
+ glUniform1i(mTextureUniformLocation, 0);
+
+ // Fill the texture with white pixels
+ std::vector<GLubyte> whitePixels(mPbufferSize * mPbufferSize * 4, 255);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mPbufferSize, mPbufferSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, &whitePixels[0]);
+ EXPECT_GL_NO_ERROR();
+
+ // Draw the white texture and verify that the pixels are correct
+ drawQuad(mTextureProgram, "position", 0.5f);
+ EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+ // Bind the EGL surface and draw with it, results are undefined since nothing has
+ // been written to it
+ EGLWindow *window = getEGLWindow();
+ eglBindTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+ drawQuad(mTextureProgram, "position", 0.5f);
+ EXPECT_GL_NO_ERROR();
+
+ // Clear the back buffer to a unique color (green)
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
+
+ // Unbind the EGL surface and try to draw with the texture again, the texture's size should
+ // now be zero and incomplete so the back buffer should be black
+ eglReleaseTexImage(window->getDisplay(), mPbuffer, EGL_BACK_BUFFER);
+ drawQuad(mTextureProgram, "position", 0.5f);
+ EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 255);
+}