aboutsummaryrefslogtreecommitdiff
path: root/tests/unittests/unittests.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/unittests/unittests.cpp')
-rw-r--r--tests/unittests/unittests.cpp802
1 files changed, 781 insertions, 21 deletions
diff --git a/tests/unittests/unittests.cpp b/tests/unittests/unittests.cpp
index 7ae84da3c..99cbb6117 100644
--- a/tests/unittests/unittests.cpp
+++ b/tests/unittests/unittests.cpp
@@ -97,6 +97,7 @@ protected:
EGL_ALPHA_SIZE, 8,
EGL_NONE
};
+
EGLint num_config = -1;
EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config);
EXPECT_EQ(EGL_SUCCESS, eglGetError());
@@ -203,29 +204,43 @@ protected:
EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
}
- GLuint createProgram(const std::string& vs, const std::string& fs)
+ struct ProgramHandles {
+ GLuint program;
+ GLuint vsShader;
+ GLuint fsShader;
+ };
+
+ ProgramHandles createProgram(const std::string& vs, const std::string& fs)
{
- GLuint program = glCreateProgram();
+ ProgramHandles ph;
+ ph.program = glCreateProgram();
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- GLuint vsShader = glCreateShader(GL_VERTEX_SHADER);
+ ph.vsShader = glCreateShader(GL_VERTEX_SHADER);
const char* vsSource[1] = { vs.c_str() };
- glShaderSource(vsShader, 1, vsSource, nullptr);
- glCompileShader(vsShader);
+ glShaderSource(ph.vsShader, 1, vsSource, nullptr);
+ glCompileShader(ph.vsShader);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- GLuint fsShader = glCreateShader(GL_FRAGMENT_SHADER);
+ ph.fsShader = glCreateShader(GL_FRAGMENT_SHADER);
const char* fsSource[1] = { fs.c_str() };
- glShaderSource(fsShader, 1, fsSource, nullptr);
- glCompileShader(fsShader);
+ glShaderSource(ph.fsShader, 1, fsSource, nullptr);
+ glCompileShader(ph.fsShader);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- glAttachShader(program, vsShader);
- glAttachShader(program, fsShader);
- glLinkProgram(program);
+ glAttachShader(ph.program, ph.vsShader);
+ glAttachShader(ph.program, ph.fsShader);
+ glLinkProgram(ph.program);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- return program;
+ return ph;
+ }
+
+ void deleteProgram(const ProgramHandles& ph)
+ {
+ glDeleteShader(ph.fsShader);
+ glDeleteShader(ph.vsShader);
+ glDeleteProgram(ph.program);
}
void drawQuad(GLuint program)
@@ -262,7 +277,7 @@ protected:
}
EGLDisplay getDisplay() const { return display; }
- EGLDisplay getConfig() const { return config; }
+ EGLConfig getConfig() const { return config; }
EGLSurface getSurface() const { return surface; }
EGLContext getContext() const { return context; }
private:
@@ -532,10 +547,10 @@ TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle)
" gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
"}\n";
- GLuint program = createProgram(vs, fs);
+ const ProgramHandles ph = createProgram(vs, fs);
- glUseProgram(program);
- GLint location = glGetUniformLocation(program, "tex");
+ glUseProgram(ph.program);
+ GLint location = glGetUniformLocation(ph.program, "tex");
ASSERT_NE(-1, location);
glUniform1i(location, 0);
@@ -543,7 +558,9 @@ TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle)
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- drawQuad(program);
+ drawQuad(ph.program);
+
+ deleteProgram(ph);
compareColor(green);
@@ -584,9 +601,10 @@ TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3)
" fragColor = texture(tex, vec2(0, 0));\n"
"}\n";
- GLuint program = createProgram(vs, fs);
- glUseProgram(program);
- GLint location = glGetUniformLocation(program, "tex");
+ const ProgramHandles ph = createProgram(vs, fs);
+
+ glUseProgram(ph.program);
+ GLint location = glGetUniformLocation(ph.program, "tex");
ASSERT_NE(-1, location);
glUniform1i(location, 0);
@@ -594,7 +612,9 @@ TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3)
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_GLENUM_EQ(GL_NONE, glGetError());
- drawQuad(program);
+ drawQuad(ph.program);
+
+ deleteProgram(ph);
compareColor(green);
@@ -717,3 +737,743 @@ TEST_F(SwiftShaderTest, TextureRectangle_CopyTexSubImage)
Uninitialize();
}
+
+#ifndef EGL_ANGLE_iosurface_client_buffer
+#define EGL_ANGLE_iosurface_client_buffer 1
+#define EGL_IOSURFACE_ANGLE 0x3454
+#define EGL_IOSURFACE_PLANE_ANGLE 0x345A
+#define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
+#define EGL_TEXTURE_TYPE_ANGLE 0x345C
+#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
+#endif /* EGL_ANGLE_iosurface_client_buffer */
+
+#if defined(__APPLE__)
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOSurface/IOSurface.h>
+
+namespace
+{
+ void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
+ {
+ CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
+ CFDictionaryAddValue(dictionary, key, number);
+ CFRelease(number);
+ }
+} // anonymous namespace
+
+class EGLClientBufferWrapper
+{
+public:
+ EGLClientBufferWrapper(int width = 1, int height = 1)
+ {
+ // Create a 1 by 1 BGRA8888 IOSurface
+ ioSurface = nullptr;
+
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
+ kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ AddIntegerValue(dict, kIOSurfaceWidth, width);
+ AddIntegerValue(dict, kIOSurfaceHeight, height);
+ AddIntegerValue(dict, kIOSurfacePixelFormat, 'BGRA');
+ AddIntegerValue(dict, kIOSurfaceBytesPerElement, 4);
+
+ ioSurface = IOSurfaceCreate(dict);
+ CFRelease(dict);
+
+ EXPECT_NE(nullptr, ioSurface);
+ }
+
+ ~EGLClientBufferWrapper()
+ {
+ IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
+
+ CFRelease(ioSurface);
+ }
+
+ EGLClientBuffer getClientBuffer() const
+ {
+ return ioSurface;
+ }
+
+ const unsigned char* lockColor()
+ {
+ IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
+ return reinterpret_cast<const unsigned char*>(IOSurfaceGetBaseAddress(ioSurface));
+ }
+
+ void unlockColor()
+ {
+ IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
+ }
+
+ void writeColor(void* data, size_t dataSize)
+ {
+ // Write the data to the IOSurface
+ IOSurfaceLock(ioSurface, 0, nullptr);
+ memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize);
+ IOSurfaceUnlock(ioSurface, 0, nullptr);
+ }
+private:
+ IOSurfaceRef ioSurface;
+};
+
+#else // __APPLE__
+
+class EGLClientBufferWrapper
+{
+public:
+ EGLClientBufferWrapper(int width = 1, int height = 1)
+ {
+ clientBuffer = new unsigned char[4 * width * height];
+ }
+
+ ~EGLClientBufferWrapper()
+ {
+ delete[] clientBuffer;
+ }
+
+ EGLClientBuffer getClientBuffer() const
+ {
+ return clientBuffer;
+ }
+
+ const unsigned char* lockColor()
+ {
+ return clientBuffer;
+ }
+
+ void unlockColor()
+ {
+ }
+
+ void writeColor(void* data, size_t dataSize)
+ {
+ memcpy(clientBuffer, data, dataSize);
+ }
+private:
+ unsigned char* clientBuffer;
+};
+
+#endif
+
+class IOSurfaceClientBufferTest : public SwiftShaderTest
+{
+protected:
+ EGLSurface createIOSurfacePbuffer(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type) const
+ {
+ // Make a PBuffer from it using the EGL_ANGLE_iosurface_client_buffer extension
+ const EGLint attribs[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_IOSURFACE_PLANE_ANGLE, plane,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, (EGLint)internalFormat,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, (EGLint)type,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, buffer, getConfig(), attribs);
+ EXPECT_NE(EGL_NO_SURFACE, pbuffer);
+ return pbuffer;
+ }
+
+ void bindIOSurfaceToTexture(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type, EGLSurface *pbuffer, GLuint *texture) const
+ {
+ *pbuffer = createIOSurfacePbuffer(buffer, width, height, plane, internalFormat, type);
+
+ // Bind the pbuffer
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texture);
+ EGLBoolean result = eglBindTexImage(getDisplay(), *pbuffer, EGL_BACK_BUFFER);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+ }
+
+ void doClear(GLenum internalFormat, bool clearToZero)
+ {
+ if(internalFormat == GL_R16UI)
+ {
+ GLuint color = clearToZero ? 0 : 257;
+ glClearBufferuiv(GL_COLOR, 0, &color);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+ }
+ else
+ {
+ glClearColor(clearToZero ? 0.0f : 1.0f / 255.0f,
+ clearToZero ? 0.0f : 2.0f / 255.0f,
+ clearToZero ? 0.0f : 3.0f / 255.0f,
+ clearToZero ? 0.0f : 4.0f / 255.0f);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+ glClear(GL_COLOR_BUFFER_BIT);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+ }
+ }
+
+ void doClearTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
+ {
+ ASSERT_TRUE(dataSize <= 4);
+
+ // Bind the IOSurface to a texture and clear it.
+ GLuint texture = 1;
+ EGLSurface pbuffer;
+ bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
+
+ // glClear the pbuffer
+ GLuint fbo = 2;
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+ EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+
+ doClear(internalFormat, false);
+
+ // Unbind pbuffer and check content.
+ EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+ const unsigned char* color = clientBufferWrapper.lockColor();
+ for(size_t i = 0; i < dataSize; ++i)
+ {
+ EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
+ }
+
+ result = eglDestroySurface(getDisplay(), pbuffer);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+ }
+
+ void doSampleTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
+ {
+ ASSERT_TRUE(dataSize <= 4);
+
+ clientBufferWrapper.writeColor(data, dataSize);
+
+ // Bind the IOSurface to a texture and clear it.
+ GLuint texture = 1;
+ EGLSurface pbuffer;
+ bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
+
+ doClear(internalFormat, true);
+
+ // Create program and draw quad using it
+ const std::string vs =
+ "attribute vec4 position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
+ "}\n";
+
+ const std::string fs =
+ "#extension GL_ARB_texture_rectangle : require\n"
+ "precision mediump float;\n"
+ "uniform sampler2DRect tex;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
+ "}\n";
+
+ const ProgramHandles ph = createProgram(vs, fs);
+
+ drawQuad(ph.program);
+
+ deleteProgram(ph);
+
+ EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
+
+ // Unbind pbuffer and check content.
+ EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+
+ const unsigned char* color = clientBufferWrapper.lockColor();
+ for(size_t i = 0; i < dataSize; ++i)
+ {
+ EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
+ }
+ clientBufferWrapper.unlockColor();
+ }
+};
+
+// Tests for the EGL_ANGLE_iosurface_client_buffer extension
+TEST_F(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[4] = { 3, 2, 1, 4 };
+ doClearTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test reading from BGRA8888 IOSurfaces
+TEST_F(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[4] = { 3, 2, 1, 4 };
+ doSampleTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test using RG88 IOSurfaces for rendering
+TEST_F(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[2] = { 1, 2 };
+ doClearTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test reading from RG88 IOSurfaces
+TEST_F(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[2] = { 1, 2 };
+ doSampleTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test using R8 IOSurfaces for rendering
+TEST_F(IOSurfaceClientBufferTest, RenderToR8IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[1] = { 1 };
+ doClearTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test reading from R8 IOSurfaces
+TEST_F(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ unsigned char data[1] = { 1 };
+ doSampleTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test using R16 IOSurfaces for rendering
+TEST_F(IOSurfaceClientBufferTest, RenderToR16IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ uint16_t data[1] = { 257 };
+ doClearTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 2);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test reading from R8 IOSurfaces
+TEST_F(IOSurfaceClientBufferTest, ReadFromR16IOSurface)
+{
+ Initialize(3, false);
+
+ { // EGLClientBufferWrapper scope
+ EGLClientBufferWrapper clientBufferWrapper;
+ uint16_t data[1] = { 257 };
+ doSampleTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 1);
+ } // end of EGLClientBufferWrapper scope
+
+ Uninitialize();
+}
+
+// Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with
+// IOSurface
+TEST_F(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
+{
+ Initialize(3, false);
+
+ {
+ EGLClientBufferWrapper clientBufferWrapper(10, 10);
+
+ // Success case
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_NE(EGL_NO_SURFACE, pbuffer);
+
+ EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+ }
+
+ // Missing EGL_WIDTH
+ {
+ const EGLint attribs[] = {
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+ }
+
+ // Missing EGL_HEIGHT
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+ }
+
+ // Missing EGL_IOSURFACE_PLANE_ANGLE
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+ }
+
+ // Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of
+ // eglCreatePbufferFromClientBuffer
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
+ }
+
+ // Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+ }
+
+ // Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of
+ // eglCreatePbufferFromClientBuffer
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
+ }
+
+ // Missing EGL_TEXTURE_TYPE_ANGLE
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
+ }
+ }
+
+ Uninitialize();
+}
+
+// Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
+TEST_F(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
+{
+ Initialize(3, false);
+
+ {
+ EGLClientBufferWrapper clientBufferWrapper(10, 10);
+
+ // Success case
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_NE(EGL_NO_SURFACE, pbuffer);
+
+ EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
+ EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
+ EXPECT_EQ(EGL_SUCCESS, eglGetError());
+ }
+
+ // EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGB,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // EGL_WIDTH must be at least 1
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 0,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // EGL_HEIGHT must be at least 1
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 0,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+#if defined(__APPLE__)
+ // EGL_WIDTH must be at most the width of the IOSurface
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 11,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // EGL_HEIGHT must be at most the height of the IOSurface
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 11,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 1,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+#endif
+
+ // EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // EGL_IOSURFACE_PLANE_ANGLE must be at least 0
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, -1,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+
+ // The internal format / type most be listed in the table
+ {
+ const EGLint attribs[] = {
+ EGL_WIDTH, 10,
+ EGL_HEIGHT, 10,
+ EGL_IOSURFACE_PLANE_ANGLE, 0,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_RECTANGLE_ANGLE,
+ EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TYPE_ANGLE, GL_UNSIGNED_BYTE,
+ EGL_NONE, EGL_NONE,
+ };
+
+ EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
+ EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
+ EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
+ }
+ }
+
+ Uninitialize();
+}
+
+// Test IOSurface pbuffers cannot be made current
+TEST_F(IOSurfaceClientBufferTest, MakeCurrentDisallowed)
+{
+ Initialize(3, false);
+
+ {
+ EGLClientBufferWrapper clientBufferWrapper(10, 10);
+
+ EGLSurface pbuffer = createIOSurfacePbuffer(clientBufferWrapper.getClientBuffer(), 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE);
+
+ EGLBoolean result = eglMakeCurrent(getDisplay(), pbuffer, pbuffer, getContext());
+ EXPECT_EQ((EGLBoolean)EGL_FALSE, result);
+ EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
+ }
+
+ Uninitialize();
+}