Home | History | Annotate | Download | only in unittests
      1 // Copyright 2017 The SwiftShader Authors. All Rights Reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //    http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "gtest/gtest.h"
     16 #include "gmock/gmock.h"
     17 
     18 #include <EGL/egl.h>
     19 #include <GLES2/gl2.h>
     20 #include <GLES2/gl2ext.h>
     21 #include <GLES3/gl3.h>
     22 
     23 #if defined(_WIN32)
     24 #include <Windows.h>
     25 #endif
     26 
     27 #define EXPECT_GLENUM_EQ(expected, actual) EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
     28 
     29 class SwiftShaderTest : public testing::Test
     30 {
     31 protected:
     32 	void SetUp() override
     33 	{
     34 		#if defined(_WIN32) && !defined(STANDALONE)
     35 			// The DLLs are delay loaded (see BUILD.gn), so we can load
     36 			// the correct ones from Chrome's swiftshader subdirectory.
     37 			HMODULE libEGL = LoadLibraryA("swiftshader\\libEGL.dll");
     38 			EXPECT_NE((HMODULE)NULL, libEGL);
     39 
     40 			HMODULE libGLESv2 = LoadLibraryA("swiftshader\\libGLESv2.dll");
     41 			EXPECT_NE((HMODULE)NULL, libGLESv2);
     42 		#endif
     43 	}
     44 
     45 	void compareColor(unsigned char referenceColor[4])
     46 	{
     47 		unsigned char color[4] = { 0 };
     48 		glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
     49 		EXPECT_EQ(color[0], referenceColor[0]);
     50 		EXPECT_EQ(color[1], referenceColor[1]);
     51 		EXPECT_EQ(color[2], referenceColor[2]);
     52 		EXPECT_EQ(color[3], referenceColor[3]);
     53 	}
     54 
     55 	void Initialize(int version, bool withChecks)
     56 	{
     57 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
     58 
     59 		display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
     60 
     61 		if(withChecks)
     62 		{
     63 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
     64 			EXPECT_NE(EGL_NO_DISPLAY, display);
     65 
     66 			eglQueryString(display, EGL_VENDOR);
     67 			EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
     68 		}
     69 
     70 		EGLint major;
     71 		EGLint minor;
     72 		EGLBoolean initialized = eglInitialize(display, &major, &minor);
     73 
     74 		if(withChecks)
     75 		{
     76 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
     77 			EXPECT_EQ((EGLBoolean)EGL_TRUE, initialized);
     78 			EXPECT_EQ(1, major);
     79 			EXPECT_EQ(4, minor);
     80 
     81 			const char *eglVendor = eglQueryString(display, EGL_VENDOR);
     82 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
     83 			EXPECT_STREQ("Google Inc.", eglVendor);
     84 
     85 			const char *eglVersion = eglQueryString(display, EGL_VERSION);
     86 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
     87 			EXPECT_THAT(eglVersion, testing::HasSubstr("1.4 SwiftShader "));
     88 		}
     89 
     90 		eglBindAPI(EGL_OPENGL_ES_API);
     91 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
     92 
     93 		const EGLint configAttributes[] =
     94 		{
     95 			EGL_SURFACE_TYPE,		EGL_PBUFFER_BIT,
     96 			EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
     97 			EGL_ALPHA_SIZE,			8,
     98 			EGL_NONE
     99 		};
    100 
    101 		EGLint num_config = -1;
    102 		EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config);
    103 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    104 		EXPECT_EQ(num_config, 1);
    105 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    106 
    107 		if(withChecks)
    108 		{
    109 			EGLint conformant = 0;
    110 			eglGetConfigAttrib(display, config, EGL_CONFORMANT, &conformant);
    111 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    112 			EXPECT_TRUE(conformant & EGL_OPENGL_ES2_BIT);
    113 
    114 			EGLint renderableType = 0;
    115 			eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
    116 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    117 			EXPECT_TRUE(renderableType & EGL_OPENGL_ES2_BIT);
    118 
    119 			EGLint surfaceType = 0;
    120 			eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &surfaceType);
    121 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    122 			EXPECT_TRUE(surfaceType & EGL_WINDOW_BIT);
    123 		}
    124 
    125 		EGLint surfaceAttributes[] =
    126 		{
    127 			EGL_WIDTH, 1920,
    128 			EGL_HEIGHT, 1080,
    129 			EGL_NONE
    130 		};
    131 
    132 		surface = eglCreatePbufferSurface(display, config, surfaceAttributes);
    133 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    134 		EXPECT_NE(EGL_NO_SURFACE, surface);
    135 
    136 		EGLint contextAttributes[] =
    137 		{
    138 			EGL_CONTEXT_CLIENT_VERSION, version,
    139 			EGL_NONE
    140 		};
    141 
    142 		context = eglCreateContext(display, config, NULL, contextAttributes);
    143 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    144 		EXPECT_NE(EGL_NO_CONTEXT, context);
    145 
    146 		success = eglMakeCurrent(display, surface, surface, context);
    147 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    148 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    149 
    150 		if(withChecks)
    151 		{
    152 			EGLDisplay currentDisplay = eglGetCurrentDisplay();
    153 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    154 			EXPECT_EQ(display, currentDisplay);
    155 
    156 			EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
    157 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    158 			EXPECT_EQ(surface, currentDrawSurface);
    159 
    160 			EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
    161 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    162 			EXPECT_EQ(surface, currentReadSurface);
    163 
    164 			EGLContext currentContext = eglGetCurrentContext();
    165 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
    166 			EXPECT_EQ(context, currentContext);
    167 		}
    168 
    169 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    170 	}
    171 
    172 	void Uninitialize()
    173 	{
    174 		EGLBoolean success = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    175 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    176 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    177 
    178 		EGLDisplay currentDisplay = eglGetCurrentDisplay();
    179 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    180 		EXPECT_EQ(EGL_NO_DISPLAY, currentDisplay);
    181 
    182 		EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
    183 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    184 		EXPECT_EQ(EGL_NO_SURFACE, currentDrawSurface);
    185 
    186 		EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
    187 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    188 		EXPECT_EQ(EGL_NO_SURFACE, currentReadSurface);
    189 
    190 		EGLContext currentContext = eglGetCurrentContext();
    191 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    192 		EXPECT_EQ(EGL_NO_CONTEXT, currentContext);
    193 
    194 		success = eglDestroyContext(display, context);
    195 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    196 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    197 
    198 		success = eglDestroySurface(display, surface);
    199 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    200 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    201 
    202 		success = eglTerminate(display);
    203 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    204 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
    205 	}
    206 
    207 	struct ProgramHandles {
    208 		GLuint program;
    209 		GLuint vsShader;
    210 		GLuint fsShader;
    211 	};
    212 
    213 	ProgramHandles createProgram(const std::string& vs, const std::string& fs)
    214 	{
    215 		ProgramHandles ph;
    216 		ph.program = glCreateProgram();
    217 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    218 
    219 		ph.vsShader = glCreateShader(GL_VERTEX_SHADER);
    220 		const char* vsSource[1] = { vs.c_str() };
    221 		glShaderSource(ph.vsShader, 1, vsSource, nullptr);
    222 		glCompileShader(ph.vsShader);
    223 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    224 
    225 		ph.fsShader = glCreateShader(GL_FRAGMENT_SHADER);
    226 		const char* fsSource[1] = { fs.c_str() };
    227 		glShaderSource(ph.fsShader, 1, fsSource, nullptr);
    228 		glCompileShader(ph.fsShader);
    229 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    230 
    231 		glAttachShader(ph.program, ph.vsShader);
    232 		glAttachShader(ph.program, ph.fsShader);
    233 		glLinkProgram(ph.program);
    234 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    235 
    236 		return ph;
    237 	}
    238 
    239 	void deleteProgram(const ProgramHandles& ph)
    240 	{
    241 		glDeleteShader(ph.fsShader);
    242 		glDeleteShader(ph.vsShader);
    243 		glDeleteProgram(ph.program);
    244 	}
    245 
    246 	void drawQuad(GLuint program)
    247 	{
    248 		GLint prevProgram = 0;
    249 		glGetIntegerv(GL_CURRENT_PROGRAM, &prevProgram);
    250 
    251 		glUseProgram(program);
    252 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    253 
    254 		GLint posLoc = glGetAttribLocation(program, "position");
    255 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    256 
    257 		GLint location = glGetUniformLocation(program, "tex");
    258 		ASSERT_NE(-1, location);
    259 		glUniform1i(location, 0);
    260 
    261 		float vertices[18] = { -1.0f,  1.0f, 0.5f,
    262 		                       -1.0f, -1.0f, 0.5f,
    263 		                        1.0f, -1.0f, 0.5f,
    264 		                       -1.0f,  1.0f, 0.5f,
    265 		                        1.0f, -1.0f, 0.5f,
    266 		                        1.0f,  1.0f, 0.5f };
    267 
    268 		glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, vertices);
    269 		glEnableVertexAttribArray(posLoc);
    270 		glDrawArrays(GL_TRIANGLES, 0, 6);
    271 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    272 
    273 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
    274 		glDisableVertexAttribArray(posLoc);
    275 		glUseProgram(prevProgram);
    276 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    277 	}
    278 
    279 	EGLDisplay getDisplay() const { return display; }
    280 	EGLConfig getConfig() const { return config; }
    281 	EGLSurface getSurface() const { return surface; }
    282 	EGLContext getContext() const { return context; }
    283 private:
    284 	EGLDisplay display;
    285 	EGLConfig config;
    286 	EGLSurface surface;
    287 	EGLContext context;
    288 };
    289 
    290 TEST_F(SwiftShaderTest, Initalization)
    291 {
    292 	Initialize(2, true);
    293 
    294 	const GLubyte *glVendor = glGetString(GL_VENDOR);
    295 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    296 	EXPECT_STREQ("Google Inc.", (const char*)glVendor);
    297 
    298 	const GLubyte *glRenderer = glGetString(GL_RENDERER);
    299 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    300 	EXPECT_STREQ("Google SwiftShader", (const char*)glRenderer);
    301 
    302 	const GLubyte *glVersion = glGetString(GL_VERSION);
    303 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    304 	EXPECT_THAT((const char*)glVersion, testing::HasSubstr("OpenGL ES 2.0 SwiftShader "));
    305 
    306 	Uninitialize();
    307 }
    308 
    309 // Note: GL_ARB_texture_rectangle is part of gl2extchromium.h in the Chromium repo
    310 // GL_ARB_texture_rectangle
    311 #ifndef GL_ARB_texture_rectangle
    312 #define GL_ARB_texture_rectangle 1
    313 
    314 #ifndef GL_SAMPLER_2D_RECT_ARB
    315 #define GL_SAMPLER_2D_RECT_ARB 0x8B63
    316 #endif
    317 
    318 #ifndef GL_TEXTURE_BINDING_RECTANGLE_ARB
    319 #define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
    320 #endif
    321 
    322 #ifndef GL_TEXTURE_RECTANGLE_ARB
    323 #define GL_TEXTURE_RECTANGLE_ARB 0x84F5
    324 #endif
    325 
    326 #ifndef GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB
    327 #define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
    328 #endif
    329 
    330 #endif  // GL_ARB_texture_rectangle
    331 
    332 // Test using TexImage2D to define a rectangle texture
    333 
    334 TEST_F(SwiftShaderTest, TextureRectangle_TexImage2D)
    335 {
    336 	Initialize(2, false);
    337 
    338 	GLuint tex = 1;
    339 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    340 
    341 	// Defining level 0 is allowed
    342 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    343 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    344 
    345 	// Defining level other than 0 is not allowed
    346 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    347 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    348 
    349 	GLint maxSize = 0;
    350 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
    351 
    352 	// Defining a texture of the max size is allowed
    353 	{
    354 		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    355 		GLenum error = glGetError();
    356 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
    357 	}
    358 
    359 	// Defining a texture larger than the max size is disallowed
    360 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize + 1, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    361 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    362 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    363 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    364 
    365 	Uninitialize();
    366 }
    367 
    368 // Test using CompressedTexImage2D cannot be used on a retangle texture
    369 TEST_F(SwiftShaderTest, TextureRectangle_CompressedTexImage2DDisallowed)
    370 {
    371 	Initialize(2, false);
    372 
    373 	const char data[128] = { 0 };
    374 
    375 	// Control case: 2D texture
    376 	{
    377 		GLuint tex = 1;
    378 		glBindTexture(GL_TEXTURE_2D, tex);
    379 		glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
    380 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    381 	}
    382 
    383 	// Rectangle textures cannot be compressed
    384 	{
    385 		GLuint tex = 2;
    386 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    387 		glCompressedTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
    388 		EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    389 	}
    390 
    391 	Uninitialize();
    392 }
    393 
    394 // Test using TexStorage2D to define a rectangle texture (ES3)
    395 TEST_F(SwiftShaderTest, TextureRectangle_TexStorage2D)
    396 {
    397 	Initialize(3, false);
    398 
    399 	// Defining one level is allowed
    400 	{
    401 		GLuint tex = 1;
    402 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    403 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, 16, 16);
    404 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    405 	}
    406 
    407 	// Having more than one level is not allowed
    408 	{
    409 		GLuint tex = 2;
    410 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    411 		// Use 5 levels because the EXT_texture_storage extension requires a mip chain all the way
    412 		// to a 1x1 mip.
    413 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 5, GL_RGBA8UI, 16, 16);
    414 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    415 	}
    416 
    417 	GLint maxSize = 0;
    418 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
    419 
    420 	// Defining a texture of the max size is allowed but still allow for OOM
    421 	{
    422 		GLuint tex = 3;
    423 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    424 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize);
    425 		GLenum error = glGetError();
    426 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
    427 	}
    428 
    429 	// Defining a texture larger than the max size is disallowed
    430 	{
    431 		GLuint tex = 4;
    432 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    433 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize + 1, maxSize);
    434 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    435 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize + 1);
    436 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    437 	}
    438 
    439 	// Compressed formats are disallowed
    440 	GLuint tex = 5;
    441 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    442 	glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16);
    443 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    444 
    445 	Uninitialize();
    446 }
    447 
    448 // Test validation of disallowed texture parameters
    449 TEST_F(SwiftShaderTest, TextureRectangle_TexParameterRestriction)
    450 {
    451 	Initialize(3, false);
    452 
    453 	GLuint tex = 1;
    454 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    455 
    456 	// Only wrap mode CLAMP_TO_EDGE is supported
    457 	// Wrap S
    458 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    459 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    460 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT);
    461 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    462 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
    463 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    464 
    465 	// Wrap T
    466 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    467 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    468 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT);
    469 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    470 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
    471 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    472 
    473 	// Min filter has to be nearest or linear
    474 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    475 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    476 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    477 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    478 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    479 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    480 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
    481 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    482 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    483 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    484 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    485 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
    486 
    487 	// Base level has to be 0
    488 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0);
    489 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    490 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 1);
    491 	EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, glGetError());
    492 
    493 	Uninitialize();
    494 }
    495 
    496 // Test validation of "level" in FramebufferTexture2D
    497 TEST_F(SwiftShaderTest, TextureRectangle_FramebufferTexture2DLevel)
    498 {
    499 	Initialize(3, false);
    500 
    501 	GLuint tex = 1;
    502 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    503 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
    504 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    505 
    506 	GLuint fbo = 1;
    507 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    508 
    509 	// Using level 0 of a rectangle texture is valid.
    510 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
    511 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
    512 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    513 
    514 	// Setting level != 0 is invalid
    515 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 1);
    516 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    517 
    518 	Uninitialize();
    519 }
    520 
    521 // Test sampling from a rectangle texture
    522 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle)
    523 {
    524 	Initialize(3, false);
    525 
    526 	GLuint tex = 1;
    527 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    528 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    529 
    530 	unsigned char green[4] = { 0, 255, 0, 255 };
    531 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
    532 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    533 
    534 	const std::string vs =
    535 		"attribute vec4 position;\n"
    536 		"void main()\n"
    537 		"{\n"
    538 		"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
    539 		"}\n";
    540 
    541 	const std::string fs =
    542 		"#extension GL_ARB_texture_rectangle : require\n"
    543 		"precision mediump float;\n"
    544 		"uniform sampler2DRect tex;\n"
    545 		"void main()\n"
    546 		"{\n"
    547 		"    gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
    548 		"}\n";
    549 
    550 	const ProgramHandles ph = createProgram(vs, fs);
    551 
    552 	glUseProgram(ph.program);
    553 	GLint location = glGetUniformLocation(ph.program, "tex");
    554 	ASSERT_NE(-1, location);
    555 	glUniform1i(location, 0);
    556 
    557 	glClearColor(0.0, 0.0, 0.0, 0.0);
    558 	glClear(GL_COLOR_BUFFER_BIT);
    559 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    560 
    561 	drawQuad(ph.program);
    562 
    563 	deleteProgram(ph);
    564 
    565 	compareColor(green);
    566 
    567 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    568 
    569 	Uninitialize();
    570 }
    571 
    572 // Test sampling from a rectangle texture
    573 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3)
    574 {
    575 	Initialize(3, false);
    576 
    577 	GLuint tex = 1;
    578 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    579 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    580 
    581 	unsigned char green[4] = { 0, 255, 0, 255 };
    582 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
    583 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    584 
    585 	const std::string vs =
    586 		"#version 300 es\n"
    587 		"in vec4 position;\n"
    588 		"void main()\n"
    589 		"{\n"
    590 		"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
    591 		"}\n";
    592 
    593 	const std::string fs =
    594 		"#version 300 es\n"
    595 		"#extension GL_ARB_texture_rectangle : require\n"
    596 		"precision mediump float;\n"
    597 		"uniform sampler2DRect tex;\n"
    598 		"out vec4 fragColor;\n"
    599 		"void main()\n"
    600 		"{\n"
    601 		"    fragColor = texture(tex, vec2(0, 0));\n"
    602 		"}\n";
    603 
    604 	const ProgramHandles ph = createProgram(vs, fs);
    605 
    606 	glUseProgram(ph.program);
    607 	GLint location = glGetUniformLocation(ph.program, "tex");
    608 	ASSERT_NE(-1, location);
    609 	glUniform1i(location, 0);
    610 
    611 	glClearColor(0.0, 0.0, 0.0, 0.0);
    612 	glClear(GL_COLOR_BUFFER_BIT);
    613 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    614 
    615 	drawQuad(ph.program);
    616 
    617 	deleteProgram(ph);
    618 
    619 	compareColor(green);
    620 
    621 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    622 
    623 	Uninitialize();
    624 }
    625 
    626 // Test attaching a rectangle texture and rendering to it.
    627 TEST_F(SwiftShaderTest, TextureRectangle_RenderToRectangle)
    628 {
    629 	Initialize(3, false);
    630 
    631 	GLuint tex = 1;
    632 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    633 	unsigned char black[4] = { 0, 0, 0, 255 };
    634 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
    635 
    636 	GLuint fbo = 1;
    637 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    638 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
    639 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
    640 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    641 
    642 	// Clearing a texture is just as good as checking we can render to it, right?
    643 	glClearColor(0.0, 1.0, 0.0, 1.0);
    644 	glClear(GL_COLOR_BUFFER_BIT);
    645 
    646 	unsigned char green[4] = { 0, 255, 0, 255 };
    647 	compareColor(green);
    648 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    649 
    650 	Uninitialize();
    651 }
    652 
    653 TEST_F(SwiftShaderTest, TextureRectangle_DefaultSamplerParameters)
    654 {
    655 	Initialize(3, false);
    656 
    657 	GLuint tex = 1;
    658 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    659 
    660 	GLint minFilter = 0;
    661 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, &minFilter);
    662 	EXPECT_GLENUM_EQ(GL_LINEAR, minFilter);
    663 
    664 	GLint wrapS = 0;
    665 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, &wrapS);
    666 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapS);
    667 
    668 	GLint wrapT = 0;
    669 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, &wrapT);
    670 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapT);
    671 
    672 	Uninitialize();
    673 }
    674 
    675 // Test glCopyTexImage with rectangle textures (ES3)
    676 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexImage)
    677 {
    678 	Initialize(3, false);
    679 
    680 	GLuint tex = 1;
    681 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    682 
    683 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
    684 	glClearColor(0, 1, 0, 1);
    685 	glClear(GL_COLOR_BUFFER_BIT);
    686 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    687 
    688 	// Error case: level != 0
    689 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8, 0, 0, 1, 1, 0);
    690 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    691 
    692 	// level = 0 works and defines the texture.
    693 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 0, 0, 1, 1, 0);
    694 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    695 
    696 	GLuint fbo = 1;
    697 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    698 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
    699 
    700 	unsigned char green[4] = { 0, 255, 0, 255 };
    701 	compareColor(green);
    702 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    703 
    704 	Uninitialize();
    705 }
    706 
    707 // Test glCopyTexSubImage with rectangle textures (ES3)
    708 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexSubImage)
    709 {
    710 	Initialize(3, false);
    711 
    712 	GLuint tex = 1;
    713 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
    714 	unsigned char black[4] = { 0, 0, 0, 255 };
    715 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
    716 
    717 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
    718 	glClearColor(0, 1, 0, 1);
    719 	glClear(GL_COLOR_BUFFER_BIT);
    720 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    721 
    722 	// Error case: level != 0
    723 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, 0, 0, 0, 0, 1, 1);
    724 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
    725 
    726 	// level = 0 works and defines the texture.
    727 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 0, 0, 1, 1);
    728 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    729 
    730 	GLuint fbo = 1;
    731 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    732 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
    733 
    734 	unsigned char green[4] = { 0, 255, 0, 255 };
    735 	compareColor(green);
    736 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
    737 
    738 	Uninitialize();
    739 }
    740 
    741 #ifndef EGL_ANGLE_iosurface_client_buffer
    742 #define EGL_ANGLE_iosurface_client_buffer 1
    743 #define EGL_IOSURFACE_ANGLE 0x3454
    744 #define EGL_IOSURFACE_PLANE_ANGLE 0x345A
    745 #define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
    746 #define EGL_TEXTURE_TYPE_ANGLE 0x345C
    747 #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
    748 #endif /* EGL_ANGLE_iosurface_client_buffer */
    749 
    750 #if defined(__APPLE__)
    751 #include <CoreFoundation/CoreFoundation.h>
    752 #include <IOSurface/IOSurface.h>
    753 
    754 namespace
    755 {
    756 	void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
    757 	{
    758 		CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
    759 		CFDictionaryAddValue(dictionary, key, number);
    760 		CFRelease(number);
    761 	}
    762 }  // anonymous namespace
    763 
    764 class EGLClientBufferWrapper
    765 {
    766 public:
    767 	EGLClientBufferWrapper(int width = 1, int height = 1)
    768 	{
    769 		// Create a 1 by 1 BGRA8888 IOSurface
    770 		ioSurface = nullptr;
    771 
    772 		CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
    773 			kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    774 		AddIntegerValue(dict, kIOSurfaceWidth, width);
    775 		AddIntegerValue(dict, kIOSurfaceHeight, height);
    776 		AddIntegerValue(dict, kIOSurfacePixelFormat, 'BGRA');
    777 		AddIntegerValue(dict, kIOSurfaceBytesPerElement, 4);
    778 
    779 		ioSurface = IOSurfaceCreate(dict);
    780 		CFRelease(dict);
    781 
    782 		EXPECT_NE(nullptr, ioSurface);
    783 	}
    784 
    785 	~EGLClientBufferWrapper()
    786 	{
    787 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
    788 
    789 		CFRelease(ioSurface);
    790 	}
    791 
    792 	EGLClientBuffer getClientBuffer() const
    793 	{
    794 		return ioSurface;
    795 	}
    796 
    797 	const unsigned char* lockColor()
    798 	{
    799 		IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
    800 		return reinterpret_cast<const unsigned char*>(IOSurfaceGetBaseAddress(ioSurface));
    801 	}
    802 
    803 	void unlockColor()
    804 	{
    805 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
    806 	}
    807 
    808 	void writeColor(void* data, size_t dataSize)
    809 	{
    810 		// Write the data to the IOSurface
    811 		IOSurfaceLock(ioSurface, 0, nullptr);
    812 		memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize);
    813 		IOSurfaceUnlock(ioSurface, 0, nullptr);
    814 	}
    815 private:
    816 	IOSurfaceRef ioSurface;
    817 };
    818 
    819 #else // __APPLE__
    820 
    821 class EGLClientBufferWrapper
    822 {
    823 public:
    824 	EGLClientBufferWrapper(int width = 1, int height = 1)
    825 	{
    826 		clientBuffer = new unsigned char[4 * width * height];
    827 	}
    828 
    829 	~EGLClientBufferWrapper()
    830 	{
    831 		delete[] clientBuffer;
    832 	}
    833 
    834 	EGLClientBuffer getClientBuffer() const
    835 	{
    836 		return clientBuffer;
    837 	}
    838 
    839 	const unsigned char* lockColor()
    840 	{
    841 		return clientBuffer;
    842 	}
    843 
    844 	void unlockColor()
    845 	{
    846 	}
    847 
    848 	void writeColor(void* data, size_t dataSize)
    849 	{
    850 		memcpy(clientBuffer, data, dataSize);
    851 	}
    852 private:
    853 	unsigned char* clientBuffer;
    854 };
    855 
    856 #endif
    857 
    858 class IOSurfaceClientBufferTest : public SwiftShaderTest
    859 {
    860 protected:
    861 	EGLSurface createIOSurfacePbuffer(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type) const
    862 	{
    863 		// Make a PBuffer from it using the EGL_ANGLE_iosurface_client_buffer extension
    864 		const EGLint attribs[] = {
    865 			EGL_WIDTH,                         width,
    866 			EGL_HEIGHT,                        height,
    867 			EGL_IOSURFACE_PLANE_ANGLE,         plane,
    868 			EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
    869 			EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, (EGLint)internalFormat,
    870 			EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
    871 			EGL_TEXTURE_TYPE_ANGLE,            (EGLint)type,
    872 			EGL_NONE,                          EGL_NONE,
    873 		};
    874 
    875 		EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, buffer, getConfig(), attribs);
    876 		EXPECT_NE(EGL_NO_SURFACE, pbuffer);
    877 		return pbuffer;
    878 	}
    879 
    880 	void bindIOSurfaceToTexture(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type, EGLSurface *pbuffer, GLuint *texture) const
    881 	{
    882 		*pbuffer = createIOSurfacePbuffer(buffer, width, height, plane, internalFormat, type);
    883 
    884 		// Bind the pbuffer
    885 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texture);
    886 		EGLBoolean result = eglBindTexImage(getDisplay(), *pbuffer, EGL_BACK_BUFFER);
    887 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
    888 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    889 	}
    890 
    891 	void doClear(GLenum internalFormat, bool clearToZero)
    892 	{
    893 		if(internalFormat == GL_R16UI)
    894 		{
    895 			GLuint color = clearToZero ? 0 : 257;
    896 			glClearBufferuiv(GL_COLOR, 0, &color);
    897 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    898 		}
    899 		else
    900 		{
    901 			glClearColor(clearToZero ? 0.0f : 1.0f / 255.0f,
    902 				clearToZero ? 0.0f : 2.0f / 255.0f,
    903 				clearToZero ? 0.0f : 3.0f / 255.0f,
    904 				clearToZero ? 0.0f : 4.0f / 255.0f);
    905 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    906 			glClear(GL_COLOR_BUFFER_BIT);
    907 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    908 		}
    909 	}
    910 
    911 	void doClearTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
    912 	{
    913 		ASSERT_TRUE(dataSize <= 4);
    914 
    915 		// Bind the IOSurface to a texture and clear it.
    916 		GLuint texture = 1;
    917 		EGLSurface pbuffer;
    918 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
    919 
    920 		// glClear the pbuffer
    921 		GLuint fbo = 2;
    922 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    923 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    924 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
    925 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    926 		EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
    927 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    928 
    929 		doClear(internalFormat, false);
    930 
    931 		// Unbind pbuffer and check content.
    932 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
    933 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
    934 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    935 
    936 		const unsigned char* color = clientBufferWrapper.lockColor();
    937 		for(size_t i = 0; i < dataSize; ++i)
    938 		{
    939 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
    940 		}
    941 
    942 		result = eglDestroySurface(getDisplay(), pbuffer);
    943 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
    944 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    945 	}
    946 
    947 	void doSampleTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
    948 	{
    949 		ASSERT_TRUE(dataSize <= 4);
    950 
    951 		clientBufferWrapper.writeColor(data, dataSize);
    952 
    953 		// Bind the IOSurface to a texture and clear it.
    954 		GLuint texture = 1;
    955 		EGLSurface pbuffer;
    956 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
    957 
    958 		doClear(internalFormat, true);
    959 
    960 		// Create program and draw quad using it
    961 		const std::string vs =
    962 			"attribute vec4 position;\n"
    963 			"void main()\n"
    964 			"{\n"
    965 			"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
    966 			"}\n";
    967 
    968 		const std::string fs =
    969 			"#extension GL_ARB_texture_rectangle : require\n"
    970 			"precision mediump float;\n"
    971 			"uniform sampler2DRect tex;\n"
    972 			"void main()\n"
    973 			"{\n"
    974 			"    gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
    975 			"}\n";
    976 
    977 		const ProgramHandles ph = createProgram(vs, fs);
    978 
    979 		drawQuad(ph.program);
    980 
    981 		deleteProgram(ph);
    982 
    983 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
    984 
    985 		// Unbind pbuffer and check content.
    986 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
    987 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
    988 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
    989 
    990 		const unsigned char* color = clientBufferWrapper.lockColor();
    991 		for(size_t i = 0; i < dataSize; ++i)
    992 		{
    993 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
    994 		}
    995 		clientBufferWrapper.unlockColor();
    996 	}
    997 };
    998 
    999 // Tests for the EGL_ANGLE_iosurface_client_buffer extension
   1000 TEST_F(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
   1001 {
   1002 	Initialize(3, false);
   1003 
   1004 	{ // EGLClientBufferWrapper scope
   1005 		EGLClientBufferWrapper clientBufferWrapper;
   1006 		unsigned char data[4] = { 3, 2, 1, 4 };
   1007 		doClearTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
   1008 	} // end of EGLClientBufferWrapper scope
   1009 
   1010 	Uninitialize();
   1011 }
   1012 
   1013 // Test reading from BGRA8888 IOSurfaces
   1014 TEST_F(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
   1015 {
   1016 	Initialize(3, false);
   1017 
   1018 	{ // EGLClientBufferWrapper scope
   1019 		EGLClientBufferWrapper clientBufferWrapper;
   1020 		unsigned char data[4] = { 3, 2, 1, 4 };
   1021 		doSampleTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
   1022 	} // end of EGLClientBufferWrapper scope
   1023 
   1024 	Uninitialize();
   1025 }
   1026 
   1027 // Test using RG88 IOSurfaces for rendering
   1028 TEST_F(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
   1029 {
   1030 	Initialize(3, false);
   1031 
   1032 	{ // EGLClientBufferWrapper scope
   1033 		EGLClientBufferWrapper clientBufferWrapper;
   1034 		unsigned char data[2] = { 1, 2 };
   1035 		doClearTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
   1036 	} // end of EGLClientBufferWrapper scope
   1037 
   1038 	Uninitialize();
   1039 }
   1040 
   1041 // Test reading from RG88 IOSurfaces
   1042 TEST_F(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
   1043 {
   1044 	Initialize(3, false);
   1045 
   1046 	{ // EGLClientBufferWrapper scope
   1047 		EGLClientBufferWrapper clientBufferWrapper;
   1048 		unsigned char data[2] = { 1, 2 };
   1049 		doSampleTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
   1050 	} // end of EGLClientBufferWrapper scope
   1051 
   1052 	Uninitialize();
   1053 }
   1054 
   1055 // Test using R8 IOSurfaces for rendering
   1056 TEST_F(IOSurfaceClientBufferTest, RenderToR8IOSurface)
   1057 {
   1058 	Initialize(3, false);
   1059 
   1060 	{ // EGLClientBufferWrapper scope
   1061 		EGLClientBufferWrapper clientBufferWrapper;
   1062 		unsigned char data[1] = { 1 };
   1063 		doClearTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
   1064 	} // end of EGLClientBufferWrapper scope
   1065 
   1066 	Uninitialize();
   1067 }
   1068 
   1069 // Test reading from R8 IOSurfaces
   1070 TEST_F(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
   1071 {
   1072 	Initialize(3, false);
   1073 
   1074 	{ // EGLClientBufferWrapper scope
   1075 		EGLClientBufferWrapper clientBufferWrapper;
   1076 		unsigned char data[1] = { 1 };
   1077 		doSampleTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
   1078 	} // end of EGLClientBufferWrapper scope
   1079 
   1080 	Uninitialize();
   1081 }
   1082 
   1083 // Test using R16 IOSurfaces for rendering
   1084 TEST_F(IOSurfaceClientBufferTest, RenderToR16IOSurface)
   1085 {
   1086 	Initialize(3, false);
   1087 
   1088 	{ // EGLClientBufferWrapper scope
   1089 		EGLClientBufferWrapper clientBufferWrapper;
   1090 		uint16_t data[1] = { 257 };
   1091 		doClearTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 2);
   1092 	} // end of EGLClientBufferWrapper scope
   1093 
   1094 	Uninitialize();
   1095 }
   1096 
   1097 // Test reading from R8 IOSurfaces
   1098 TEST_F(IOSurfaceClientBufferTest, ReadFromR16IOSurface)
   1099 {
   1100 	Initialize(3, false);
   1101 
   1102 	{ // EGLClientBufferWrapper scope
   1103 		EGLClientBufferWrapper clientBufferWrapper;
   1104 		uint16_t data[1] = { 257 };
   1105 		doSampleTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 1);
   1106 	} // end of EGLClientBufferWrapper scope
   1107 
   1108 	Uninitialize();
   1109 }
   1110 
   1111 // Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with
   1112 // IOSurface
   1113 TEST_F(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
   1114 {
   1115 	Initialize(3, false);
   1116 
   1117 	{
   1118 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
   1119 
   1120 		// Success case
   1121 		{
   1122 			const EGLint attribs[] = {
   1123 				EGL_WIDTH,                         10,
   1124 				EGL_HEIGHT,                        10,
   1125 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1126 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1127 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1128 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1129 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1130 				EGL_NONE,                          EGL_NONE,
   1131 			};
   1132 
   1133 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1134 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
   1135 
   1136 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
   1137 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
   1138 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
   1139 		}
   1140 
   1141 		// Missing EGL_WIDTH
   1142 		{
   1143 			const EGLint attribs[] = {
   1144 				EGL_HEIGHT,                        10,
   1145 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1146 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1147 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1148 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1149 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1150 				EGL_NONE,                          EGL_NONE,
   1151 			};
   1152 
   1153 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1154 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1155 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
   1156 		}
   1157 
   1158 		// Missing EGL_HEIGHT
   1159 		{
   1160 			const EGLint attribs[] = {
   1161 				EGL_WIDTH,                         10,
   1162 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1163 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1164 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1165 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1166 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1167 				EGL_NONE,                          EGL_NONE,
   1168 			};
   1169 
   1170 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1171 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1172 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
   1173 		}
   1174 
   1175 		// Missing EGL_IOSURFACE_PLANE_ANGLE
   1176 		{
   1177 			const EGLint attribs[] = {
   1178 				EGL_WIDTH,                         10,
   1179 				EGL_HEIGHT,                        10,
   1180 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1181 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1182 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1183 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1184 				EGL_NONE,                          EGL_NONE,
   1185 			};
   1186 
   1187 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1188 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1189 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
   1190 		}
   1191 
   1192 		// Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of
   1193 		// eglCreatePbufferFromClientBuffer
   1194 		{
   1195 			const EGLint attribs[] = {
   1196 				EGL_WIDTH,                         10,
   1197 				EGL_HEIGHT,                        10,
   1198 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1199 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1200 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1201 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1202 				EGL_NONE,                          EGL_NONE,
   1203 			};
   1204 
   1205 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1206 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1207 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
   1208 		}
   1209 
   1210 		// Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE
   1211 		{
   1212 			const EGLint attribs[] = {
   1213 				EGL_WIDTH,                         10,
   1214 				EGL_HEIGHT,                        10,
   1215 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1216 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1217 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1218 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1219 				EGL_NONE,                          EGL_NONE,
   1220 			};
   1221 
   1222 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1223 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1224 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
   1225 		}
   1226 
   1227 		// Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of
   1228 		// eglCreatePbufferFromClientBuffer
   1229 		{
   1230 			const EGLint attribs[] = {
   1231 				EGL_WIDTH,                         10,
   1232 				EGL_HEIGHT,                        10,
   1233 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1234 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1235 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1236 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1237 				EGL_NONE,                          EGL_NONE,
   1238 			};
   1239 
   1240 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1241 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1242 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
   1243 		}
   1244 
   1245 		// Missing EGL_TEXTURE_TYPE_ANGLE
   1246 		{
   1247 			const EGLint attribs[] = {
   1248 				EGL_WIDTH,                         10,
   1249 				EGL_HEIGHT,                        10,
   1250 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1251 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1252 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1253 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1254 				EGL_NONE,                          EGL_NONE,
   1255 			};
   1256 
   1257 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1258 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1259 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
   1260 		}
   1261 	}
   1262 
   1263 	Uninitialize();
   1264 }
   1265 
   1266 // Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
   1267 TEST_F(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
   1268 {
   1269 	Initialize(3, false);
   1270 
   1271 	{
   1272 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
   1273 
   1274 		// Success case
   1275 		{
   1276 			const EGLint attribs[] = {
   1277 				EGL_WIDTH,                         10,
   1278 				EGL_HEIGHT,                        10,
   1279 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1280 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1281 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1282 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1283 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1284 				EGL_NONE,                          EGL_NONE,
   1285 			};
   1286 
   1287 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1288 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
   1289 
   1290 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
   1291 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
   1292 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
   1293 		}
   1294 
   1295 		// EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA
   1296 		{
   1297 			const EGLint attribs[] = {
   1298 				EGL_WIDTH,                         10,
   1299 				EGL_HEIGHT,                        10,
   1300 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1301 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1302 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1303 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGB,
   1304 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1305 				EGL_NONE,                          EGL_NONE,
   1306 			};
   1307 
   1308 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1309 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1310 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1311 		}
   1312 
   1313 		// EGL_WIDTH must be at least 1
   1314 		{
   1315 			const EGLint attribs[] = {
   1316 				EGL_WIDTH,                         0,
   1317 				EGL_HEIGHT,                        10,
   1318 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1319 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1320 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1321 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1322 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1323 				EGL_NONE,                          EGL_NONE,
   1324 			};
   1325 
   1326 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1327 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1328 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1329 		}
   1330 
   1331 		// EGL_HEIGHT must be at least 1
   1332 		{
   1333 			const EGLint attribs[] = {
   1334 				EGL_WIDTH,                         10,
   1335 				EGL_HEIGHT,                        0,
   1336 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1337 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1338 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1339 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1340 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1341 				EGL_NONE,                          EGL_NONE,
   1342 			};
   1343 
   1344 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1345 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1346 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1347 		}
   1348 
   1349 #if defined(__APPLE__)
   1350 		// EGL_WIDTH must be at most the width of the IOSurface
   1351 		{
   1352 			const EGLint attribs[] = {
   1353 				EGL_WIDTH,                         11,
   1354 				EGL_HEIGHT,                        10,
   1355 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1356 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1357 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1358 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1359 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1360 				EGL_NONE,                          EGL_NONE,
   1361 			};
   1362 
   1363 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1364 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1365 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1366 		}
   1367 
   1368 		// EGL_HEIGHT must be at most the height of the IOSurface
   1369 		{
   1370 			const EGLint attribs[] = {
   1371 				EGL_WIDTH,                         10,
   1372 				EGL_HEIGHT,                        11,
   1373 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1374 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1375 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1376 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1377 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1378 				EGL_NONE,                          EGL_NONE,
   1379 			};
   1380 
   1381 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1382 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1383 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1384 		}
   1385 
   1386 		// EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface
   1387 		{
   1388 			const EGLint attribs[] = {
   1389 				EGL_WIDTH,                         10,
   1390 				EGL_HEIGHT,                        10,
   1391 				EGL_IOSURFACE_PLANE_ANGLE,         1,
   1392 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1393 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1394 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1395 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1396 				EGL_NONE,                          EGL_NONE,
   1397 			};
   1398 
   1399 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1400 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1401 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1402 		}
   1403 #endif
   1404 
   1405 		// EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE
   1406 		{
   1407 			const EGLint attribs[] = {
   1408 				EGL_WIDTH,                         10,
   1409 				EGL_HEIGHT,                        10,
   1410 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1411 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_2D,
   1412 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1413 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1414 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1415 				EGL_NONE,                          EGL_NONE,
   1416 			};
   1417 
   1418 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1419 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1420 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1421 		}
   1422 
   1423 		// EGL_IOSURFACE_PLANE_ANGLE must be at least 0
   1424 		{
   1425 			const EGLint attribs[] = {
   1426 				EGL_WIDTH,                         10,
   1427 				EGL_HEIGHT,                        10,
   1428 				EGL_IOSURFACE_PLANE_ANGLE,         -1,
   1429 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1430 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
   1431 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1432 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1433 				EGL_NONE,                          EGL_NONE,
   1434 			};
   1435 
   1436 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1437 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1438 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1439 		}
   1440 
   1441 		// The internal format / type most be listed in the table
   1442 		{
   1443 			const EGLint attribs[] = {
   1444 				EGL_WIDTH,                         10,
   1445 				EGL_HEIGHT,                        10,
   1446 				EGL_IOSURFACE_PLANE_ANGLE,         0,
   1447 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
   1448 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA,
   1449 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
   1450 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
   1451 				EGL_NONE,                          EGL_NONE,
   1452 			};
   1453 
   1454 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
   1455 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
   1456 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
   1457 		}
   1458 	}
   1459 
   1460 	Uninitialize();
   1461 }
   1462 
   1463 // Test IOSurface pbuffers cannot be made current
   1464 TEST_F(IOSurfaceClientBufferTest, MakeCurrentDisallowed)
   1465 {
   1466 	Initialize(3, false);
   1467 
   1468 	{
   1469 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
   1470 
   1471 		EGLSurface pbuffer = createIOSurfacePbuffer(clientBufferWrapper.getClientBuffer(), 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE);
   1472 
   1473 		EGLBoolean result = eglMakeCurrent(getDisplay(), pbuffer, pbuffer, getContext());
   1474 		EXPECT_EQ((EGLBoolean)EGL_FALSE, result);
   1475 		EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
   1476 	}
   1477 
   1478 	Uninitialize();
   1479 }
   1480