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 // OpenGL ES unit tests that provide coverage for functionality not tested by
16 // the dEQP test suite. Also used as a smoke test.
17 
18 #include "gtest/gtest.h"
19 #include "gmock/gmock.h"
20 
21 #include <EGL/egl.h>
22 #include <GLES2/gl2.h>
23 #include <GLES2/gl2ext.h>
24 #include <GLES3/gl3.h>
25 #include <GL/glcorearb.h>
26 #include <GL/glext.h>
27 
28 #if defined(_WIN32)
29 #include <Windows.h>
30 #endif
31 
32 #include <string.h>
33 #include <cstdint>
34 
35 #define EXPECT_GLENUM_EQ(expected, actual) EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual))
36 
37 class SwiftShaderTest : public testing::Test
38 {
39 protected:
SetUp()40 	void SetUp() override
41 	{
42 		#if defined(_WIN32) && !defined(STANDALONE)
43 			// The DLLs are delay loaded (see BUILD.gn), so we can load
44 			// the correct ones from Chrome's swiftshader subdirectory.
45 			HMODULE libEGL = LoadLibraryA("swiftshader\\libEGL.dll");
46 			EXPECT_NE((HMODULE)NULL, libEGL);
47 
48 			HMODULE libGLESv2 = LoadLibraryA("swiftshader\\libGLESv2.dll");
49 			EXPECT_NE((HMODULE)NULL, libGLESv2);
50 		#endif
51 	}
52 
expectFramebufferColor(const unsigned char referenceColor[4],GLint x=0,GLint y=0)53 	void expectFramebufferColor(const unsigned char referenceColor[4], GLint x = 0, GLint y = 0)
54 	{
55 		unsigned char color[4] = { 0 };
56 		glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
57 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
58 		EXPECT_EQ(color[0], referenceColor[0]);
59 		EXPECT_EQ(color[1], referenceColor[1]);
60 		EXPECT_EQ(color[2], referenceColor[2]);
61 		EXPECT_EQ(color[3], referenceColor[3]);
62 	}
63 
expectFramebufferColor(const float referenceColor[4],GLint x=0,GLint y=0)64 	void expectFramebufferColor(const float referenceColor[4], GLint x = 0, GLint y = 0)
65 	{
66 		float color[4] = { 0 };
67 		glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &color);
68 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
69 		EXPECT_EQ(color[0], referenceColor[0]);
70 		EXPECT_EQ(color[1], referenceColor[1]);
71 		EXPECT_EQ(color[2], referenceColor[2]);
72 		EXPECT_EQ(color[3], referenceColor[3]);
73 	}
74 
Initialize(int version,bool withChecks)75 	void Initialize(int version, bool withChecks)
76 	{
77 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
78 
79 		display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
80 
81 		if(withChecks)
82 		{
83 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
84 			EXPECT_NE(EGL_NO_DISPLAY, display);
85 
86 			eglQueryString(display, EGL_VENDOR);
87 			EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
88 		}
89 
90 		EGLint major;
91 		EGLint minor;
92 		EGLBoolean initialized = eglInitialize(display, &major, &minor);
93 
94 		if(withChecks)
95 		{
96 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
97 			EXPECT_EQ((EGLBoolean)EGL_TRUE, initialized);
98 			EXPECT_EQ(1, major);
99 			EXPECT_EQ(4, minor);
100 
101 			const char *eglVendor = eglQueryString(display, EGL_VENDOR);
102 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
103 			EXPECT_STREQ("Google Inc.", eglVendor);
104 
105 			const char *eglVersion = eglQueryString(display, EGL_VERSION);
106 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
107 			EXPECT_THAT(eglVersion, testing::HasSubstr("1.4 SwiftShader "));
108 		}
109 
110 		eglBindAPI(EGL_OPENGL_ES_API);
111 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
112 
113 		const EGLint configAttributes[] =
114 		{
115 			EGL_SURFACE_TYPE,		EGL_PBUFFER_BIT,
116 			EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
117 			EGL_ALPHA_SIZE,			8,
118 			EGL_NONE
119 		};
120 
121 		EGLint num_config = -1;
122 		EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config);
123 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
124 		EXPECT_EQ(num_config, 1);
125 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
126 
127 		if(withChecks)
128 		{
129 			EGLint conformant = 0;
130 			eglGetConfigAttrib(display, config, EGL_CONFORMANT, &conformant);
131 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
132 			EXPECT_TRUE(conformant & EGL_OPENGL_ES2_BIT);
133 
134 			EGLint renderableType = 0;
135 			eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
136 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
137 			EXPECT_TRUE(renderableType & EGL_OPENGL_ES2_BIT);
138 
139 			EGLint surfaceType = 0;
140 			eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
141 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
142 			EXPECT_TRUE(surfaceType & EGL_WINDOW_BIT);
143 		}
144 
145 		EGLint surfaceAttributes[] =
146 		{
147 			EGL_WIDTH, 1920,
148 			EGL_HEIGHT, 1080,
149 			EGL_NONE
150 		};
151 
152 		surface = eglCreatePbufferSurface(display, config, surfaceAttributes);
153 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
154 		EXPECT_NE(EGL_NO_SURFACE, surface);
155 
156 		EGLint contextAttributes[] =
157 		{
158 			EGL_CONTEXT_CLIENT_VERSION, version,
159 			EGL_NONE
160 		};
161 
162 		context = eglCreateContext(display, config, NULL, contextAttributes);
163 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
164 		EXPECT_NE(EGL_NO_CONTEXT, context);
165 
166 		success = eglMakeCurrent(display, surface, surface, context);
167 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
168 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
169 
170 		if(withChecks)
171 		{
172 			EGLDisplay currentDisplay = eglGetCurrentDisplay();
173 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
174 			EXPECT_EQ(display, currentDisplay);
175 
176 			EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
177 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
178 			EXPECT_EQ(surface, currentDrawSurface);
179 
180 			EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
181 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
182 			EXPECT_EQ(surface, currentReadSurface);
183 
184 			EGLContext currentContext = eglGetCurrentContext();
185 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
186 			EXPECT_EQ(context, currentContext);
187 		}
188 
189 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
190 	}
191 
Uninitialize()192 	void Uninitialize()
193 	{
194 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
195 
196 		EGLBoolean success = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
197 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
198 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
199 
200 		EGLDisplay currentDisplay = eglGetCurrentDisplay();
201 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
202 		EXPECT_EQ(EGL_NO_DISPLAY, currentDisplay);
203 
204 		EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
205 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
206 		EXPECT_EQ(EGL_NO_SURFACE, currentDrawSurface);
207 
208 		EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
209 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
210 		EXPECT_EQ(EGL_NO_SURFACE, currentReadSurface);
211 
212 		EGLContext currentContext = eglGetCurrentContext();
213 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
214 		EXPECT_EQ(EGL_NO_CONTEXT, currentContext);
215 
216 		success = eglDestroyContext(display, context);
217 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
218 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
219 
220 		success = eglDestroySurface(display, surface);
221 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
222 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
223 
224 		success = eglTerminate(display);
225 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
226 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
227 	}
228 
229 	struct ProgramHandles
230 	{
231 		GLuint program;
232 		GLuint vertexShader;
233 		GLuint fragmentShader;
234 	};
235 
createProgram(const std::string & vs,const std::string & fs)236 	ProgramHandles createProgram(const std::string& vs, const std::string& fs)
237 	{
238 		ProgramHandles ph;
239 		ph.program = glCreateProgram();
240 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
241 
242 		ph.vertexShader = glCreateShader(GL_VERTEX_SHADER);
243 		const char* vsSource[1] = { vs.c_str() };
244 		glShaderSource(ph.vertexShader, 1, vsSource, nullptr);
245 		glCompileShader(ph.vertexShader);
246 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
247 		GLint vsCompileStatus = 0;
248 		glGetShaderiv(ph.vertexShader, GL_COMPILE_STATUS, &vsCompileStatus);
249 		EXPECT_EQ(vsCompileStatus, GL_TRUE);
250 
251 		ph.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
252 		const char* fsSource[1] = { fs.c_str() };
253 		glShaderSource(ph.fragmentShader, 1, fsSource, nullptr);
254 		glCompileShader(ph.fragmentShader);
255 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
256 		GLint fsCompileStatus = 0;
257 		glGetShaderiv(ph.fragmentShader, GL_COMPILE_STATUS, &fsCompileStatus);
258 		EXPECT_EQ(fsCompileStatus, GL_TRUE);
259 
260 		glAttachShader(ph.program, ph.vertexShader);
261 		glAttachShader(ph.program, ph.fragmentShader);
262 		glLinkProgram(ph.program);
263 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
264 
265 		GLint linkStatus = 0;
266 		glGetProgramiv(ph.program, GL_LINK_STATUS, &linkStatus);
267 		EXPECT_NE(linkStatus, 0);
268 
269 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
270 
271 		return ph;
272 	}
273 
deleteProgram(const ProgramHandles & ph)274 	void deleteProgram(const ProgramHandles& ph)
275 	{
276 		glDeleteShader(ph.fragmentShader);
277 		glDeleteShader(ph.vertexShader);
278 		glDeleteProgram(ph.program);
279 
280 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
281 	}
282 
drawQuad(GLuint program,const char * textureName=nullptr)283 	void drawQuad(GLuint program, const char* textureName = nullptr)
284 	{
285 		GLint prevProgram = 0;
286 		glGetIntegerv(GL_CURRENT_PROGRAM, &prevProgram);
287 
288 		glUseProgram(program);
289 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
290 
291 		GLint posLoc = glGetAttribLocation(program, "position");
292 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
293 
294 		if(textureName)
295 		{
296 			GLint location = glGetUniformLocation(program, textureName);
297 			ASSERT_NE(-1, location);
298 			glUniform1i(location, 0);
299 		}
300 
301 		float vertices[18] = { -1.0f,  1.0f, 0.5f,
302 		                       -1.0f, -1.0f, 0.5f,
303 		                        1.0f, -1.0f, 0.5f,
304 		                       -1.0f,  1.0f, 0.5f,
305 		                        1.0f, -1.0f, 0.5f,
306 		                        1.0f,  1.0f, 0.5f };
307 
308 		glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, vertices);
309 		glEnableVertexAttribArray(posLoc);
310 		glDrawArrays(GL_TRIANGLES, 0, 6);
311 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
312 
313 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
314 		glDisableVertexAttribArray(posLoc);
315 		glUseProgram(prevProgram);
316 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
317 	}
318 
getDisplay() const319 	EGLDisplay getDisplay() const { return display; }
getConfig() const320 	EGLConfig getConfig() const { return config; }
getSurface() const321 	EGLSurface getSurface() const { return surface; }
getContext() const322 	EGLContext getContext() const { return context; }
323 
324 private:
325 	EGLDisplay display;
326 	EGLConfig config;
327 	EGLSurface surface;
328 	EGLContext context;
329 };
330 
TEST_F(SwiftShaderTest,Initalization)331 TEST_F(SwiftShaderTest, Initalization)
332 {
333 	Initialize(2, true);
334 
335 	const GLubyte *glVendor = glGetString(GL_VENDOR);
336 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
337 	EXPECT_STREQ("Google Inc.", (const char*)glVendor);
338 
339 	const GLubyte *glRenderer = glGetString(GL_RENDERER);
340 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
341 	EXPECT_STREQ("Google SwiftShader", (const char*)glRenderer);
342 
343 	// SwiftShader return an OpenGL ES 3.0 context when a 2.0 context is requested, as allowed by the spec.
344 	const GLubyte *glVersion = glGetString(GL_VERSION);
345 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
346 	EXPECT_THAT((const char*)glVersion, testing::HasSubstr("OpenGL ES 3.0 SwiftShader "));
347 
348 	Uninitialize();
349 }
350 
351 // Test attempting to clear an incomplete framebuffer
TEST_F(SwiftShaderTest,ClearIncomplete)352 TEST_F(SwiftShaderTest, ClearIncomplete)
353 {
354 	Initialize(3, false);
355 
356 	GLfloat zero_float = 0;
357 	GLuint renderbuffer;
358 	glGenRenderbuffers(1, &renderbuffer);
359 	GLuint framebuffer;
360 	glGenFramebuffers(1, &framebuffer);
361 
362 	glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
363 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
364 	glRenderbufferStorage(GL_RENDERBUFFER, GL_R8I, 43, 27);
365 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
366 	glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
367 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
368 	glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
369 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
370 	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
371 	EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
372 	glClearBufferfv(GL_DEPTH, 0, &zero_float);
373 	EXPECT_GLENUM_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, glGetError());
374 
375 	Uninitialize();
376 }
377 
378 // Test unrolling of a loop
TEST_F(SwiftShaderTest,UnrollLoop)379 TEST_F(SwiftShaderTest, UnrollLoop)
380 {
381 	Initialize(3, false);
382 
383 	unsigned char green[4] = { 0, 255, 0, 255 };
384 
385 	const std::string vs =
386 		"#version 300 es\n"
387 		"in vec4 position;\n"
388 		"out vec4 color;\n"
389 		"void main()\n"
390 		"{\n"
391 		"   for(int i = 0; i < 4; i++)\n"
392 		"   {\n"
393 		"       color[i] = (i % 2 == 0) ? 0.0 : 1.0;\n"
394 		"   }\n"
395 		"	gl_Position = vec4(position.xy, 0.0, 1.0);\n"
396 		"}\n";
397 
398 	const std::string fs =
399 		"#version 300 es\n"
400 		"precision mediump float;\n"
401 		"in vec4 color;\n"
402 		"out vec4 fragColor;\n"
403 		"void main()\n"
404 		"{\n"
405 		"	fragColor = color;\n"
406 		"}\n";
407 
408 	const ProgramHandles ph = createProgram(vs, fs);
409 
410 	// Expect the info log to contain "unrolled". This is not a spec requirement.
411 	GLsizei length = 0;
412 	glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length);
413 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
414 	EXPECT_NE(length, 0);
415 	char *log = new char[length];
416 	GLsizei written = 0;
417 	glGetShaderInfoLog(ph.vertexShader, length, &written, log);
418 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
419 	EXPECT_EQ(length, written + 1);
420 	EXPECT_NE(strstr(log, "unrolled"), nullptr);
421 	delete[] log;
422 
423 	glUseProgram(ph.program);
424 
425 	glClearColor(0.0, 0.0, 0.0, 0.0);
426 	glClear(GL_COLOR_BUFFER_BIT);
427 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
428 
429 	drawQuad(ph.program);
430 
431 	deleteProgram(ph);
432 
433 	expectFramebufferColor(green);
434 
435 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
436 
437 	Uninitialize();
438 }
439 
440 // Test non-canonical or non-deterministic loops do not get unrolled
TEST_F(SwiftShaderTest,DynamicLoop)441 TEST_F(SwiftShaderTest, DynamicLoop)
442 {
443 	Initialize(3, false);
444 
445 	const std::string vs =
446 		"#version 300 es\n"
447 		"in vec4 position;\n"
448 		"out vec4 color;\n"
449 		"void main()\n"
450 		"{\n"
451 		"   for(int i = 0; i < 4; )\n"
452 		"   {\n"
453 		"       color[i] = (i % 2 == 0) ? 0.0 : 1.0;\n"
454 		"       i++;"
455 		"   }\n"
456 		"	gl_Position = vec4(position.xy, 0.0, 1.0);\n"
457 		"}\n";
458 
459 	const std::string fs =
460 		"#version 300 es\n"
461 		"precision mediump float;\n"
462 		"in vec4 color;\n"
463 		"out vec4 fragColor;\n"
464 		"void main()\n"
465 		"{\n"
466 		"   vec4 temp;"
467 		"   for(int i = 0; i < 4; i++)\n"
468 		"   {\n"
469 		"       if(color.x < 0.0) return;"
470 		"       temp[i] = color[i];\n"
471 		"   }\n"
472 		"	fragColor = vec4(temp[0], temp[1], temp[2], temp[3]);\n"
473 		"}\n";
474 
475 	const ProgramHandles ph = createProgram(vs, fs);
476 
477 	// Expect the info logs to be empty. This is not a spec requirement.
478 	GLsizei length = 0;
479 	glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length);
480 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
481 	EXPECT_EQ(length, 0);
482 	glGetShaderiv(ph.fragmentShader, GL_INFO_LOG_LENGTH, &length);
483 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
484 	EXPECT_EQ(length, 0);
485 
486 	glUseProgram(ph.program);
487 
488 	glClearColor(0.0, 0.0, 0.0, 0.0);
489 	glClear(GL_COLOR_BUFFER_BIT);
490 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
491 
492 	drawQuad(ph.program);
493 
494 	deleteProgram(ph);
495 
496 	unsigned char green[4] = { 0, 255, 0, 255 };
497 	expectFramebufferColor(green);
498 
499 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
500 
501 	Uninitialize();
502 }
503 
504 // Test dynamic indexing
TEST_F(SwiftShaderTest,DynamicIndexing)505 TEST_F(SwiftShaderTest, DynamicIndexing)
506 {
507 	Initialize(3, false);
508 
509 	const std::string vs =
510 		"#version 300 es\n"
511 		"in vec4 position;\n"
512 		"out float color[4];\n"
513 		"void main()\n"
514 		"{\n"
515 		"   for(int i = 0; i < 4; )\n"
516 		"   {\n"
517 		"       int j = (gl_VertexID + i) % 4;\n"
518 		"       color[j] = (j % 2 == 0) ? 0.0 : 1.0;\n"
519 		"       i++;"
520 		"   }\n"
521 		"	gl_Position = vec4(position.xy, 0.0, 1.0);\n"
522 		"}\n";
523 
524 	const std::string fs =
525 		"#version 300 es\n"
526 		"precision mediump float;\n"
527 		"in float color[4];\n"
528 		"out vec4 fragColor;\n"
529 		"void main()\n"
530 		"{\n"
531 		"   float temp[4];"
532 		"   for(int i = 0; i < 4; )\n"
533 		"   {\n"
534 		"       temp[i] = color[i];\n"
535 		"       i++;"
536 		"   }\n"
537 		"	fragColor = vec4(temp[0], temp[1], temp[2], temp[3]);\n"
538 		"}\n";
539 
540 	const ProgramHandles ph = createProgram(vs, fs);
541 
542 	glUseProgram(ph.program);
543 
544 	glClearColor(0.0, 0.0, 0.0, 0.0);
545 	glClear(GL_COLOR_BUFFER_BIT);
546 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
547 
548 	drawQuad(ph.program);
549 
550 	deleteProgram(ph);
551 
552 	unsigned char green[4] = { 0, 255, 0, 255 };
553 	expectFramebufferColor(green);
554 
555 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
556 
557 	Uninitialize();
558 }
559 
560 // Test vertex attribute location linking
TEST_F(SwiftShaderTest,AttributeLocation)561 TEST_F(SwiftShaderTest, AttributeLocation)
562 {
563 	Initialize(3, false);
564 
565 	const std::string vs =
566 		"#version 300 es\n"
567 		"layout(location = 0) in vec4 a0;\n"   // Explicitly bound in GLSL
568 		"layout(location = 2) in vec4 a2;\n"   // Explicitly bound in GLSL
569 		"in vec4 a5;\n"                        // Bound to location 5 by API
570 		"in mat2 a3;\n"                        // Implicit location
571 		"in vec4 a1;\n"                        // Implicit location
572 		"in vec4 a6;\n"                        // Implicit location
573 		"out vec4 color;\n"
574 		"void main()\n"
575 		"{\n"
576 		"   vec4 a34 = vec4(a3[0], a3[1]);\n"
577 		"	gl_Position = a0;\n"
578 		"   color = (a2 == vec4(1.0, 2.0, 3.0, 4.0) &&\n"
579 		"            a34 == vec4(5.0, 6.0, 7.0, 8.0) &&\n"
580 		"            a5 == vec4(9.0, 10.0, 11.0, 12.0) &&\n"
581 		"            a1 == vec4(13.0, 14.0, 15.0, 16.0) &&\n"
582 		"            a6 == vec4(17.0, 18.0, 19.0, 20.0)) ?\n"
583 		"           vec4(0.0, 1.0, 0.0, 1.0) :\n"
584 		"           vec4(1.0, 0.0, 0.0, 1.0);"
585 		"}\n";
586 
587 	const std::string fs =
588 		"#version 300 es\n"
589 		"precision mediump float;\n"
590 		"in vec4 color;\n"
591 		"out vec4 fragColor;\n"
592 		"void main()\n"
593 		"{\n"
594 		"	fragColor = color;\n"
595 		"}\n";
596 
597 	ProgramHandles ph;
598 	ph.program = glCreateProgram();
599 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
600 
601 	ph.vertexShader = glCreateShader(GL_VERTEX_SHADER);
602 	const char* vsSource[1] = { vs.c_str() };
603 	glShaderSource(ph.vertexShader, 1, vsSource, nullptr);
604 	glCompileShader(ph.vertexShader);
605 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
606 	GLint vsCompileStatus = 0;
607 	glGetShaderiv(ph.vertexShader, GL_COMPILE_STATUS, &vsCompileStatus);
608 	EXPECT_EQ(vsCompileStatus, GL_TRUE);
609 
610 	ph.fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
611 	const char* fsSource[1] = { fs.c_str() };
612 	glShaderSource(ph.fragmentShader, 1, fsSource, nullptr);
613 	glCompileShader(ph.fragmentShader);
614 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
615 	GLint fsCompileStatus = 0;
616 	glGetShaderiv(ph.fragmentShader, GL_COMPILE_STATUS, &fsCompileStatus);
617 	EXPECT_EQ(fsCompileStatus, GL_TRUE);
618 
619 	// Not assigned a layout location in GLSL. Bind it explicitly with the API.
620 	glBindAttribLocation(ph.program, 5, "a5");
621 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
622 
623 	// Should not override GLSL layout location qualifier
624 	glBindAttribLocation(ph.program, 8, "a2");
625 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
626 
627 	glAttachShader(ph.program, ph.vertexShader);
628 	glAttachShader(ph.program, ph.fragmentShader);
629 	glLinkProgram(ph.program);
630 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
631 
632 	// Changes after linking should have no effect
633 	glBindAttribLocation(ph.program, 0, "a1");
634 	glBindAttribLocation(ph.program, 6, "a2");
635 	glBindAttribLocation(ph.program, 2, "a6");
636 
637 	GLint linkStatus = 0;
638 	glGetProgramiv(ph.program, GL_LINK_STATUS, &linkStatus);
639 	EXPECT_NE(linkStatus, 0);
640 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
641 
642 	float vertices[6][3] = { { -1.0f,  1.0f, 0.5f },
643 	                         { -1.0f, -1.0f, 0.5f },
644 	                         {  1.0f, -1.0f, 0.5f },
645 	                         { -1.0f,  1.0f, 0.5f },
646 	                         {  1.0f, -1.0f, 0.5f },
647 	                         {  1.0f,  1.0f, 0.5f } };
648 
649 	float attributes[5][4] = { { 1.0f, 2.0f, 3.0f, 4.0f },
650 	                           { 5.0f, 6.0f, 7.0f, 8.0f },
651 	                           { 9.0f, 10.0f, 11.0f, 12.0f },
652 	                           { 13.0f, 14.0f, 15.0f, 16.0f },
653 	                           { 17.0f, 18.0f, 19.0f, 20.0f } };
654 
655 	GLint a0 = glGetAttribLocation(ph.program, "a0");
656 	EXPECT_EQ(a0, 0);
657 	glVertexAttribPointer(a0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
658 	glEnableVertexAttribArray(a0);
659 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
660 
661 	GLint a2 = glGetAttribLocation(ph.program, "a2");
662 	EXPECT_EQ(a2, 2);
663 	glVertexAttribPointer(a2, 4, GL_FLOAT, GL_FALSE, 0, attributes[0]);
664 	glVertexAttribDivisor(a2, 1);
665 	glEnableVertexAttribArray(a2);
666 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
667 
668 	GLint a3 = glGetAttribLocation(ph.program, "a3");
669 	EXPECT_EQ(a3, 3);   // Note: implementation specific
670 	glVertexAttribPointer(a3 + 0, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][0]);
671 	glVertexAttribPointer(a3 + 1, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][2]);
672 	glVertexAttribDivisor(a3 + 0, 1);
673 	glVertexAttribDivisor(a3 + 1, 1);
674 	glEnableVertexAttribArray(a3 + 0);
675 	glEnableVertexAttribArray(a3 + 1);
676 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
677 
678 	GLint a5 = glGetAttribLocation(ph.program, "a5");
679 	EXPECT_EQ(a5, 5);
680 	glVertexAttribPointer(a5, 4, GL_FLOAT, GL_FALSE, 0, attributes[2]);
681 	glVertexAttribDivisor(a5, 1);
682 	glEnableVertexAttribArray(a5);
683 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
684 
685 	GLint a1 = glGetAttribLocation(ph.program, "a1");
686 	EXPECT_EQ(a1, 1);   // Note: implementation specific
687 	glVertexAttribPointer(a1, 4, GL_FLOAT, GL_FALSE, 0, attributes[3]);
688 	glVertexAttribDivisor(a1, 1);
689 	glEnableVertexAttribArray(a1);
690 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
691 
692 	GLint a6 = glGetAttribLocation(ph.program, "a6");
693 	EXPECT_EQ(a6, 6);   // Note: implementation specific
694 	glVertexAttribPointer(a6, 4, GL_FLOAT, GL_FALSE, 0, attributes[4]);
695 	glVertexAttribDivisor(a6, 1);
696 	glEnableVertexAttribArray(a6);
697 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
698 
699 	glUseProgram(ph.program);
700 	glDrawArrays(GL_TRIANGLES, 0, 6);
701 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
702 
703 	deleteProgram(ph);
704 
705 	unsigned char green[4] = { 0, 255, 0, 255 };
706 	expectFramebufferColor(green);
707 
708 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
709 
710 	Uninitialize();
711 }
712 
713 // Tests clearing of a texture with 'dirty' content.
TEST_F(SwiftShaderTest,ClearDirtyTexture)714 TEST_F(SwiftShaderTest, ClearDirtyTexture)
715 {
716 	Initialize(3, false);
717 
718 	GLuint tex = 1;
719 	glBindTexture(GL_TEXTURE_2D, tex);
720 	glTexImage2D(GL_TEXTURE_2D, 0, GL_R11F_G11F_B10F, 256, 256, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, nullptr);
721 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
722 
723 	GLuint fbo = 1;
724 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
725 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
726 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
727 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
728 
729 	float dirty_color[3] = { 128 / 255.0f, 64 / 255.0f, 192 / 255.0f };
730 	GLint dirty_x = 8;
731 	GLint dirty_y = 12;
732 	glTexSubImage2D(GL_TEXTURE_2D, 0, dirty_x, dirty_y, 1, 1, GL_RGB, GL_FLOAT, dirty_color);
733 
734 	const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f };
735 	glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f);
736 	glClear(GL_COLOR_BUFFER_BIT);
737 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
738 
739 	expectFramebufferColor(clear_color, dirty_x, dirty_y);
740 
741 	Uninitialize();
742 }
743 
744 // Tests copying between textures of different floating-point formats using a framebuffer object.
TEST_F(SwiftShaderTest,CopyTexImage)745 TEST_F(SwiftShaderTest, CopyTexImage)
746 {
747 	Initialize(3, false);
748 
749 	GLuint tex1 = 1;
750 	float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
751 	glBindTexture(GL_TEXTURE_2D, tex1);
752 	glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16);
753 	glTexSubImage2D(GL_TEXTURE_2D, 0, 5, 10, 1, 1, GL_RGBA, GL_FLOAT, &green);
754 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
755 
756 	GLuint fbo = 1;
757 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
758 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
759 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
760 
761 	GLuint tex2 = 2;
762 	glBindTexture(GL_TEXTURE_2D, tex2);
763 	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 6, 8, 8, 0);
764 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
765 
766 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
767 	expectFramebufferColor(green, 3, 4);
768 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
769 
770 	Uninitialize();
771 }
772 
773 // Tests reading of half-float textures.
TEST_F(SwiftShaderTest,ReadHalfFloat)774 TEST_F(SwiftShaderTest, ReadHalfFloat)
775 {
776 	Initialize(3, false);
777 
778 	GLuint tex = 1;
779 	glBindTexture(GL_TEXTURE_2D, tex);
780 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 256, 256, 0, GL_RGB, GL_HALF_FLOAT, nullptr);
781 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
782 
783 	GLuint fbo = 1;
784 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
785 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
786 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
787 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
788 
789 	const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f };
790 	glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f);
791 	glClear(GL_COLOR_BUFFER_BIT);
792 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
793 
794 	uint16_t pixel[3] = { 0x1234, 0x3F80, 0xAAAA };
795 	GLint x = 6;
796 	GLint y = 3;
797 	glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, pixel);
798 
799 	// This relies on GL_HALF_FLOAT being a valid type for read-back,
800 	// which isn't guaranteed by the spec but is supported by SwiftShader.
801 	uint16_t read_color[3] = { 0, 0, 0 };
802 	glReadPixels(x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, &read_color);
803 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
804 	EXPECT_EQ(read_color[0], pixel[0]);
805 	EXPECT_EQ(read_color[1], pixel[1]);
806 	EXPECT_EQ(read_color[2], pixel[2]);
807 
808 	Uninitialize();
809 }
810 
811 // Tests construction of a structure containing a single matrix
TEST_F(SwiftShaderTest,MatrixInStruct)812 TEST_F(SwiftShaderTest, MatrixInStruct)
813 {
814 	Initialize(2, false);
815 
816 	const std::string fs =
817 		"#version 100\n"
818 		"precision mediump float;\n"
819 		"struct S\n"
820 		"{\n"
821 		"	mat2 rotation;\n"
822 		"};\n"
823 		"void main(void)\n"
824 		"{\n"
825 		"	float angle = 1.0;\n"
826 		"	S(mat2(1.0, angle, 1.0, 1.0));\n"
827 		"}\n";
828 
829 	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
830 	const char *fsSource[1] = { fs.c_str() };
831 	glShaderSource(fragmentShader, 1, fsSource, nullptr);
832 	glCompileShader(fragmentShader);
833 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
834 	GLint compileStatus = 0;
835 	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &compileStatus);
836 	EXPECT_NE(compileStatus, 0);
837 
838 	Uninitialize();
839 }
840 
841 // Test sampling from a sampler in a struct as a function argument
TEST_F(SwiftShaderTest,SamplerArrayInStructArrayAsFunctionArg)842 TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg)
843 {
844 	Initialize(3, false);
845 
846 	GLuint tex = 1;
847 	glBindTexture(GL_TEXTURE_2D, tex);
848 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
849 
850 	unsigned char green[4] = { 0, 255, 0, 255 };
851 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
852 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
853 
854 	const std::string vs =
855 		"#version 300 es\n"
856 		"in vec4 position;\n"
857 		"void main()\n"
858 		"{\n"
859 		"	gl_Position = vec4(position.xy, 0.0, 1.0);\n"
860 		"}\n";
861 
862 	const std::string fs =
863 		"#version 300 es\n"
864 		"precision mediump float;\n"
865 		"struct SamplerStruct{ sampler2D tex[2]; };\n"
866 		"vec4 doSample(in SamplerStruct s[2])\n"
867 		"{\n"
868 		"	return texture(s[1].tex[1], vec2(0.0));\n"
869 		"}\n"
870 		"uniform SamplerStruct samplerStruct[2];\n"
871 		"out vec4 fragColor;\n"
872 		"void main()\n"
873 		"{\n"
874 		"	fragColor = doSample(samplerStruct);\n"
875 		"}\n";
876 
877 	const ProgramHandles ph = createProgram(vs, fs);
878 
879 	glUseProgram(ph.program);
880 	GLint location = glGetUniformLocation(ph.program, "samplerStruct[1].tex[1]");
881 	ASSERT_NE(-1, location);
882 	glUniform1i(location, 0);
883 
884 	glClearColor(0.0, 0.0, 0.0, 0.0);
885 	glClear(GL_COLOR_BUFFER_BIT);
886 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
887 
888 	drawQuad(ph.program, "samplerStruct[1].tex[1]");
889 
890 	deleteProgram(ph);
891 
892 	expectFramebufferColor(green);
893 
894 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
895 
896 	Uninitialize();
897 }
898 
899 // Test sampling from a sampler in a struct as a function argument
TEST_F(SwiftShaderTest,AtanCornerCases)900 TEST_F(SwiftShaderTest, AtanCornerCases)
901 {
902 	Initialize(3, false);
903 
904 	const std::string vs =
905 		"#version 300 es\n"
906 		"in vec4 position;\n"
907 		"void main()\n"
908 		"{\n"
909 		"	gl_Position = vec4(position.xy, 0.0, 1.0);\n"
910 		"}\n";
911 
912 	const std::string fs =
913 		"#version 300 es\n"
914 		"precision mediump float;\n"
915 		"const float kPI = 3.14159265358979323846;"
916 		"uniform float positive_value;\n"
917 		"uniform float negative_value;\n"
918 		"out vec4 fragColor;\n"
919 		"void main()\n"
920 		"{\n"
921 		"	// Should yield vec4(0, pi, pi/2, -pi/2)\n"
922 		"	vec4 result = atan(vec4(0.0, 0.0, positive_value, negative_value),\n"
923 		"	                   vec4(positive_value, negative_value, 0.0, 0.0));\n"
924 		"	fragColor = (result / vec4(kPI)) + vec4(0.5, -0.5, 0.0, 1.0) + vec4(0.5 / 255.0);\n"
925 		"}\n";
926 
927 	const ProgramHandles ph = createProgram(vs, fs);
928 
929 	glUseProgram(ph.program);
930 	GLint positive_value = glGetUniformLocation(ph.program, "positive_value");
931 	ASSERT_NE(-1, positive_value);
932 	GLint negative_value = glGetUniformLocation(ph.program, "negative_value");
933 	ASSERT_NE(-1, negative_value);
934 	glUniform1f(positive_value,  1.0);
935 	glUniform1f(negative_value, -1.0);
936 
937 	glClearColor(0.0, 0.0, 0.0, 0.0);
938 	glClear(GL_COLOR_BUFFER_BIT);
939 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
940 
941 	drawQuad(ph.program, nullptr);
942 
943 	deleteProgram(ph);
944 
945 	unsigned char grey[4] = { 128, 128, 128, 128 };
946 	expectFramebufferColor(grey);
947 
948 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
949 
950 	Uninitialize();
951 }
952 
TEST_F(SwiftShaderTest,TransformFeedback_DrawArraysInstanced)953 TEST_F(SwiftShaderTest, TransformFeedback_DrawArraysInstanced)
954 {
955 	Initialize(3, false);
956 
957 	const char * data0[] =
958 	{
959 		"#version 300 es\n"
960 		"in mediump vec2 vary;"
961 		"out mediump vec4 color;"
962 		"void main()"
963 		"{\t"
964 			"color = vec4(vary, 0.0, 1.0);"
965 		"}"
966 	};
967 	const char * data1[] =
968 	{
969 		"#version 300 es\n"
970 		"layout(location=0) in mediump vec2 pos;"
971 		"out mediump vec2 vary;"
972 		"void main()"
973 		"{\t"
974 			"vary = pos;\t"
975 			"gl_Position = vec4(pos, 0.0, 1.0);"
976 		"}"
977 	};
978 
979 	GLuint vert = glCreateShader(GL_VERTEX_SHADER);
980 	GLuint frag = glCreateShader(GL_FRAGMENT_SHADER);
981 	GLuint program = glCreateProgram();
982 
983 	glShaderSource(frag, 1, data0, (const GLint *)0);
984 	glAttachShader(program, vert);
985 	glCompileShader(frag);
986 	glAttachShader(program, frag);
987 	glShaderSource(vert, 1, data1, (const GLint *)0);
988 	glCompileShader(vert);
989 	glLinkProgram(program);
990 	glUseProgram(program);
991 	glBeginTransformFeedback(GL_POINTS);
992 	glDrawArraysInstanced(GL_POINTS, 0, 1, 1);
993 
994 	Uninitialize();
995 }
996 
997 // Test conditions that should result in a GL_OUT_OF_MEMORY and not crash
TEST_F(SwiftShaderTest,OutOfMemory)998 TEST_F(SwiftShaderTest, OutOfMemory)
999 {
1000 	// Image sizes are assumed to fit in a 32-bit signed integer by the renderer,
1001 	// so test that we can't create a 2+ GiB image.
1002 	{
1003 		Initialize(3, false);
1004 
1005 		GLuint tex = 1;
1006 		glBindTexture(GL_TEXTURE_3D, tex);
1007 
1008 		const int width = 0xC2;
1009 		const int height = 0x541;
1010 		const int depth = 0x404;
1011 		glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA, GL_FLOAT, nullptr);
1012 		EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, glGetError());
1013 
1014 		// The spec states that the GL is in an undefined state when GL_OUT_OF_MEMORY
1015 		// is returned, and the context must be recreated before attempting more rendering.
1016 		Uninitialize();
1017 	}
1018 }
1019 
1020 // Test using TexImage2D to define a rectangle texture
1021 
TEST_F(SwiftShaderTest,TextureRectangle_TexImage2D)1022 TEST_F(SwiftShaderTest, TextureRectangle_TexImage2D)
1023 {
1024 	Initialize(2, false);
1025 
1026 	GLuint tex = 1;
1027 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1028 
1029 	// Defining level 0 is allowed
1030 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1031 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1032 
1033 	// Defining level other than 0 is not allowed
1034 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1035 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1036 
1037 	GLint maxSize = 0;
1038 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
1039 
1040 	// Defining a texture of the max size is allowed
1041 	{
1042 		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1043 		GLenum error = glGetError();
1044 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
1045 	}
1046 
1047 	// Defining a texture larger than the max size is disallowed
1048 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize + 1, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1049 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1050 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1051 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1052 
1053 	Uninitialize();
1054 }
1055 
1056 // Test using CompressedTexImage2D cannot be used on a retangle texture
TEST_F(SwiftShaderTest,TextureRectangle_CompressedTexImage2DDisallowed)1057 TEST_F(SwiftShaderTest, TextureRectangle_CompressedTexImage2DDisallowed)
1058 {
1059 	Initialize(2, false);
1060 
1061 	const char data[128] = { 0 };
1062 
1063 	// Control case: 2D texture
1064 	{
1065 		GLuint tex = 1;
1066 		glBindTexture(GL_TEXTURE_2D, tex);
1067 		glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
1068 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1069 	}
1070 
1071 	// Rectangle textures cannot be compressed
1072 	{
1073 		GLuint tex = 2;
1074 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1075 		glCompressedTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
1076 		EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1077 	}
1078 
1079 	Uninitialize();
1080 }
1081 
1082 // Test using TexStorage2D to define a rectangle texture (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_TexStorage2D)1083 TEST_F(SwiftShaderTest, TextureRectangle_TexStorage2D)
1084 {
1085 	Initialize(3, false);
1086 
1087 	// Defining one level is allowed
1088 	{
1089 		GLuint tex = 1;
1090 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1091 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, 16, 16);
1092 		EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1093 	}
1094 
1095 	// Having more than one level is not allowed
1096 	{
1097 		GLuint tex = 2;
1098 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1099 		// Use 5 levels because the EXT_texture_storage extension requires a mip chain all the way
1100 		// to a 1x1 mip.
1101 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 5, GL_RGBA8UI, 16, 16);
1102 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1103 	}
1104 
1105 	GLint maxSize = 0;
1106 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
1107 
1108 	// Defining a texture of the max size is allowed but still allow for OOM
1109 	{
1110 		GLuint tex = 3;
1111 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1112 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize);
1113 		GLenum error = glGetError();
1114 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
1115 	}
1116 
1117 	// Defining a texture larger than the max size is disallowed
1118 	{
1119 		GLuint tex = 4;
1120 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1121 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize + 1, maxSize);
1122 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1123 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize + 1);
1124 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1125 	}
1126 
1127 	// Compressed formats are disallowed
1128 	GLuint tex = 5;
1129 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1130 	glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16);
1131 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1132 
1133 	Uninitialize();
1134 }
1135 
1136 // Test validation of disallowed texture parameters
TEST_F(SwiftShaderTest,TextureRectangle_TexParameterRestriction)1137 TEST_F(SwiftShaderTest, TextureRectangle_TexParameterRestriction)
1138 {
1139 	Initialize(3, false);
1140 
1141 	GLuint tex = 1;
1142 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1143 
1144 	// Only wrap mode CLAMP_TO_EDGE is supported
1145 	// Wrap S
1146 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1147 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1148 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT);
1149 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1150 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
1151 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1152 
1153 	// Wrap T
1154 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1155 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1156 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT);
1157 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1158 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
1159 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1160 
1161 	// Min filter has to be nearest or linear
1162 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1163 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1164 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1165 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1166 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1167 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1168 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
1169 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1170 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1171 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1172 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1173 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1174 
1175 	// Base level has to be 0
1176 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0);
1177 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1178 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 1);
1179 	EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, glGetError());
1180 
1181 	Uninitialize();
1182 }
1183 
1184 // Test validation of "level" in FramebufferTexture2D
TEST_F(SwiftShaderTest,TextureRectangle_FramebufferTexture2DLevel)1185 TEST_F(SwiftShaderTest, TextureRectangle_FramebufferTexture2DLevel)
1186 {
1187 	Initialize(3, false);
1188 
1189 	GLuint tex = 1;
1190 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1191 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1192 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1193 
1194 	GLuint fbo = 1;
1195 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1196 
1197 	// Using level 0 of a rectangle texture is valid.
1198 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1199 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1200 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1201 
1202 	// Setting level != 0 is invalid
1203 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 1);
1204 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1205 
1206 	Uninitialize();
1207 }
1208 
1209 // Test sampling from a rectangle texture
TEST_F(SwiftShaderTest,TextureRectangle_SamplingFromRectangle)1210 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle)
1211 {
1212 	Initialize(3, false);
1213 
1214 	GLuint tex = 1;
1215 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1216 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1217 
1218 	unsigned char green[4] = { 0, 255, 0, 255 };
1219 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
1220 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1221 
1222 	const std::string vs =
1223 		"attribute vec4 position;\n"
1224 		"void main()\n"
1225 		"{\n"
1226 		"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1227 		"}\n";
1228 
1229 	const std::string fs =
1230 		"#extension GL_ARB_texture_rectangle : require\n"
1231 		"precision mediump float;\n"
1232 		"uniform sampler2DRect tex;\n"
1233 		"void main()\n"
1234 		"{\n"
1235 		"    gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
1236 		"}\n";
1237 
1238 	const ProgramHandles ph = createProgram(vs, fs);
1239 
1240 	glUseProgram(ph.program);
1241 	GLint location = glGetUniformLocation(ph.program, "tex");
1242 	ASSERT_NE(-1, location);
1243 	glUniform1i(location, 0);
1244 
1245 	glClearColor(0.0, 0.0, 0.0, 0.0);
1246 	glClear(GL_COLOR_BUFFER_BIT);
1247 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1248 
1249 	drawQuad(ph.program, "tex");
1250 
1251 	deleteProgram(ph);
1252 
1253 	expectFramebufferColor(green);
1254 
1255 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1256 
1257 	Uninitialize();
1258 }
1259 
1260 // Test sampling from a rectangle texture
TEST_F(SwiftShaderTest,TextureRectangle_SamplingFromRectangleESSL3)1261 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3)
1262 {
1263 	Initialize(3, false);
1264 
1265 	GLuint tex = 1;
1266 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1267 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1268 
1269 	unsigned char green[4] = { 0, 255, 0, 255 };
1270 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
1271 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1272 
1273 	const std::string vs =
1274 		"#version 300 es\n"
1275 		"in vec4 position;\n"
1276 		"void main()\n"
1277 		"{\n"
1278 		"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1279 		"}\n";
1280 
1281 	const std::string fs =
1282 		"#version 300 es\n"
1283 		"#extension GL_ARB_texture_rectangle : require\n"
1284 		"precision mediump float;\n"
1285 		"uniform sampler2DRect tex;\n"
1286 		"out vec4 fragColor;\n"
1287 		"void main()\n"
1288 		"{\n"
1289 		"    fragColor = texture(tex, vec2(0, 0));\n"
1290 		"}\n";
1291 
1292 	const ProgramHandles ph = createProgram(vs, fs);
1293 
1294 	glUseProgram(ph.program);
1295 	GLint location = glGetUniformLocation(ph.program, "tex");
1296 	ASSERT_NE(-1, location);
1297 	glUniform1i(location, 0);
1298 
1299 	glClearColor(0.0, 0.0, 0.0, 0.0);
1300 	glClear(GL_COLOR_BUFFER_BIT);
1301 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1302 
1303 	drawQuad(ph.program, "tex");
1304 
1305 	deleteProgram(ph);
1306 
1307 	expectFramebufferColor(green);
1308 
1309 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1310 
1311 	Uninitialize();
1312 }
1313 
1314 // Test attaching a rectangle texture and rendering to it.
TEST_F(SwiftShaderTest,TextureRectangle_RenderToRectangle)1315 TEST_F(SwiftShaderTest, TextureRectangle_RenderToRectangle)
1316 {
1317 	Initialize(3, false);
1318 
1319 	GLuint tex = 1;
1320 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1321 	unsigned char black[4] = { 0, 0, 0, 255 };
1322 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
1323 
1324 	GLuint fbo = 1;
1325 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1326 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1327 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1328 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1329 
1330 	// Clearing a texture is just as good as checking we can render to it, right?
1331 	glClearColor(0.0, 1.0, 0.0, 1.0);
1332 	glClear(GL_COLOR_BUFFER_BIT);
1333 
1334 	unsigned char green[4] = { 0, 255, 0, 255 };
1335 	expectFramebufferColor(green);
1336 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1337 
1338 	Uninitialize();
1339 }
1340 
TEST_F(SwiftShaderTest,TextureRectangle_DefaultSamplerParameters)1341 TEST_F(SwiftShaderTest, TextureRectangle_DefaultSamplerParameters)
1342 {
1343 	Initialize(3, false);
1344 
1345 	GLuint tex = 1;
1346 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1347 
1348 	GLint minFilter = 0;
1349 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, &minFilter);
1350 	EXPECT_GLENUM_EQ(GL_LINEAR, minFilter);
1351 
1352 	GLint wrapS = 0;
1353 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, &wrapS);
1354 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapS);
1355 
1356 	GLint wrapT = 0;
1357 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, &wrapT);
1358 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapT);
1359 
1360 	Uninitialize();
1361 }
1362 
1363 // Test glCopyTexImage with rectangle textures (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_CopyTexImage)1364 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexImage)
1365 {
1366 	Initialize(3, false);
1367 
1368 	GLuint tex = 1;
1369 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1370 
1371 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1372 	glClearColor(0, 1, 0, 1);
1373 	glClear(GL_COLOR_BUFFER_BIT);
1374 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1375 
1376 	// Error case: level != 0
1377 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8, 0, 0, 1, 1, 0);
1378 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1379 
1380 	// level = 0 works and defines the texture.
1381 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 0, 0, 1, 1, 0);
1382 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1383 
1384 	GLuint fbo = 1;
1385 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1386 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1387 
1388 	unsigned char green[4] = { 0, 255, 0, 255 };
1389 	expectFramebufferColor(green);
1390 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1391 
1392 	Uninitialize();
1393 }
1394 
1395 // Test glCopyTexSubImage with rectangle textures (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_CopyTexSubImage)1396 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexSubImage)
1397 {
1398 	Initialize(3, false);
1399 
1400 	GLuint tex = 1;
1401 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1402 	unsigned char black[4] = { 0, 0, 0, 255 };
1403 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
1404 
1405 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1406 	glClearColor(0, 1, 0, 1);
1407 	glClear(GL_COLOR_BUFFER_BIT);
1408 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1409 
1410 	// Error case: level != 0
1411 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, 0, 0, 0, 0, 1, 1);
1412 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1413 
1414 	// level = 0 works and defines the texture.
1415 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 0, 0, 1, 1);
1416 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1417 
1418 	GLuint fbo = 1;
1419 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1420 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1421 
1422 	unsigned char green[4] = { 0, 255, 0, 255 };
1423 	expectFramebufferColor(green);
1424 	EXPECT_GLENUM_EQ(GL_NONE, glGetError());
1425 
1426 	Uninitialize();
1427 }
1428 
1429 #ifndef EGL_ANGLE_iosurface_client_buffer
1430 #define EGL_ANGLE_iosurface_client_buffer 1
1431 #define EGL_IOSURFACE_ANGLE 0x3454
1432 #define EGL_IOSURFACE_PLANE_ANGLE 0x345A
1433 #define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
1434 #define EGL_TEXTURE_TYPE_ANGLE 0x345C
1435 #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
1436 #endif /* EGL_ANGLE_iosurface_client_buffer */
1437 
1438 #if defined(__APPLE__)
1439 #include <CoreFoundation/CoreFoundation.h>
1440 #include <IOSurface/IOSurface.h>
1441 
1442 namespace
1443 {
AddIntegerValue(CFMutableDictionaryRef dictionary,const CFStringRef key,int32_t value)1444 	void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
1445 	{
1446 		CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
1447 		CFDictionaryAddValue(dictionary, key, number);
1448 		CFRelease(number);
1449 	}
1450 }  // anonymous namespace
1451 
1452 class EGLClientBufferWrapper
1453 {
1454 public:
EGLClientBufferWrapper(int width=1,int height=1)1455 	EGLClientBufferWrapper(int width = 1, int height = 1)
1456 	{
1457 		// Create a 1 by 1 BGRA8888 IOSurface
1458 		ioSurface = nullptr;
1459 
1460 		CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
1461 			kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1462 		AddIntegerValue(dict, kIOSurfaceWidth, width);
1463 		AddIntegerValue(dict, kIOSurfaceHeight, height);
1464 		AddIntegerValue(dict, kIOSurfacePixelFormat, 'BGRA');
1465 		AddIntegerValue(dict, kIOSurfaceBytesPerElement, 4);
1466 
1467 		ioSurface = IOSurfaceCreate(dict);
1468 		CFRelease(dict);
1469 
1470 		EXPECT_NE(nullptr, ioSurface);
1471 	}
1472 
~EGLClientBufferWrapper()1473 	~EGLClientBufferWrapper()
1474 	{
1475 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
1476 
1477 		CFRelease(ioSurface);
1478 	}
1479 
getClientBuffer() const1480 	EGLClientBuffer getClientBuffer() const
1481 	{
1482 		return ioSurface;
1483 	}
1484 
lockColor()1485 	const unsigned char* lockColor()
1486 	{
1487 		IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
1488 		return reinterpret_cast<const unsigned char*>(IOSurfaceGetBaseAddress(ioSurface));
1489 	}
1490 
unlockColor()1491 	void unlockColor()
1492 	{
1493 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
1494 	}
1495 
writeColor(void * data,size_t dataSize)1496 	void writeColor(void* data, size_t dataSize)
1497 	{
1498 		// Write the data to the IOSurface
1499 		IOSurfaceLock(ioSurface, 0, nullptr);
1500 		memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize);
1501 		IOSurfaceUnlock(ioSurface, 0, nullptr);
1502 	}
1503 private:
1504 	IOSurfaceRef ioSurface;
1505 };
1506 
1507 #else // __APPLE__
1508 
1509 class EGLClientBufferWrapper
1510 {
1511 public:
EGLClientBufferWrapper(int width=1,int height=1)1512 	EGLClientBufferWrapper(int width = 1, int height = 1)
1513 	{
1514 		clientBuffer = new unsigned char[4 * width * height];
1515 	}
1516 
~EGLClientBufferWrapper()1517 	~EGLClientBufferWrapper()
1518 	{
1519 		delete[] clientBuffer;
1520 	}
1521 
getClientBuffer() const1522 	EGLClientBuffer getClientBuffer() const
1523 	{
1524 		return clientBuffer;
1525 	}
1526 
lockColor()1527 	const unsigned char* lockColor()
1528 	{
1529 		return clientBuffer;
1530 	}
1531 
unlockColor()1532 	void unlockColor()
1533 	{
1534 	}
1535 
writeColor(void * data,size_t dataSize)1536 	void writeColor(void* data, size_t dataSize)
1537 	{
1538 		memcpy(clientBuffer, data, dataSize);
1539 	}
1540 private:
1541 	unsigned char* clientBuffer;
1542 };
1543 
1544 #endif
1545 
1546 class IOSurfaceClientBufferTest : public SwiftShaderTest
1547 {
1548 protected:
createIOSurfacePbuffer(EGLClientBuffer buffer,EGLint width,EGLint height,EGLint plane,GLenum internalFormat,GLenum type) const1549 	EGLSurface createIOSurfacePbuffer(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type) const
1550 	{
1551 		// Make a PBuffer from it using the EGL_ANGLE_iosurface_client_buffer extension
1552 		const EGLint attribs[] = {
1553 			EGL_WIDTH,                         width,
1554 			EGL_HEIGHT,                        height,
1555 			EGL_IOSURFACE_PLANE_ANGLE,         plane,
1556 			EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1557 			EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, (EGLint)internalFormat,
1558 			EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1559 			EGL_TEXTURE_TYPE_ANGLE,            (EGLint)type,
1560 			EGL_NONE,                          EGL_NONE,
1561 		};
1562 
1563 		EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, buffer, getConfig(), attribs);
1564 		EXPECT_NE(EGL_NO_SURFACE, pbuffer);
1565 		return pbuffer;
1566 	}
1567 
bindIOSurfaceToTexture(EGLClientBuffer buffer,EGLint width,EGLint height,EGLint plane,GLenum internalFormat,GLenum type,EGLSurface * pbuffer,GLuint * texture) const1568 	void bindIOSurfaceToTexture(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type, EGLSurface *pbuffer, GLuint *texture) const
1569 	{
1570 		*pbuffer = createIOSurfacePbuffer(buffer, width, height, plane, internalFormat, type);
1571 
1572 		// Bind the pbuffer
1573 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texture);
1574 		EGLBoolean result = eglBindTexImage(getDisplay(), *pbuffer, EGL_BACK_BUFFER);
1575 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1576 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
1577 	}
1578 
doClear(GLenum internalFormat,bool clearToZero)1579 	void doClear(GLenum internalFormat, bool clearToZero)
1580 	{
1581 		if(internalFormat == GL_R16UI)
1582 		{
1583 			GLuint color = clearToZero ? 0 : 257;
1584 			glClearBufferuiv(GL_COLOR, 0, &color);
1585 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1586 		}
1587 		else
1588 		{
1589 			glClearColor(clearToZero ? 0.0f : 1.0f / 255.0f,
1590 				clearToZero ? 0.0f : 2.0f / 255.0f,
1591 				clearToZero ? 0.0f : 3.0f / 255.0f,
1592 				clearToZero ? 0.0f : 4.0f / 255.0f);
1593 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1594 			glClear(GL_COLOR_BUFFER_BIT);
1595 			EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1596 		}
1597 	}
1598 
doClearTest(EGLClientBufferWrapper & clientBufferWrapper,GLenum internalFormat,GLenum type,void * data,size_t dataSize)1599 	void doClearTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
1600 	{
1601 		ASSERT_TRUE(dataSize <= 4);
1602 
1603 		// Bind the IOSurface to a texture and clear it.
1604 		GLuint texture = 1;
1605 		EGLSurface pbuffer;
1606 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
1607 
1608 		// glClear the pbuffer
1609 		GLuint fbo = 2;
1610 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1611 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1612 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
1613 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1614 		EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
1615 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1616 
1617 		doClear(internalFormat, false);
1618 
1619 		// Unbind pbuffer and check content.
1620 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
1621 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1622 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
1623 
1624 		const unsigned char* color = clientBufferWrapper.lockColor();
1625 		for(size_t i = 0; i < dataSize; ++i)
1626 		{
1627 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
1628 		}
1629 
1630 		result = eglDestroySurface(getDisplay(), pbuffer);
1631 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1632 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
1633 	}
1634 
doSampleTest(EGLClientBufferWrapper & clientBufferWrapper,GLenum internalFormat,GLenum type,void * data,size_t dataSize)1635 	void doSampleTest(EGLClientBufferWrapper& clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
1636 	{
1637 		ASSERT_TRUE(dataSize <= 4);
1638 
1639 		clientBufferWrapper.writeColor(data, dataSize);
1640 
1641 		// Bind the IOSurface to a texture and clear it.
1642 		GLuint texture = 1;
1643 		EGLSurface pbuffer;
1644 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
1645 
1646 		doClear(internalFormat, true);
1647 
1648 		// Create program and draw quad using it
1649 		const std::string vs =
1650 			"attribute vec4 position;\n"
1651 			"void main()\n"
1652 			"{\n"
1653 			"    gl_Position = vec4(position.xy, 0.0, 1.0);\n"
1654 			"}\n";
1655 
1656 		const std::string fs =
1657 			"#extension GL_ARB_texture_rectangle : require\n"
1658 			"precision mediump float;\n"
1659 			"uniform sampler2DRect tex;\n"
1660 			"void main()\n"
1661 			"{\n"
1662 			"    gl_FragColor = texture2DRect(tex, vec2(0, 0));\n"
1663 			"}\n";
1664 
1665 		const ProgramHandles ph = createProgram(vs, fs);
1666 
1667 		drawQuad(ph.program, "tex");
1668 
1669 		deleteProgram(ph);
1670 
1671 		EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError());
1672 
1673 		// Unbind pbuffer and check content.
1674 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
1675 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1676 		EXPECT_EQ(EGL_SUCCESS, eglGetError());
1677 
1678 		const unsigned char* color = clientBufferWrapper.lockColor();
1679 		for(size_t i = 0; i < dataSize; ++i)
1680 		{
1681 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char*>(data)[i]);
1682 		}
1683 		clientBufferWrapper.unlockColor();
1684 	}
1685 };
1686 
1687 // Tests for the EGL_ANGLE_iosurface_client_buffer extension
TEST_F(IOSurfaceClientBufferTest,RenderToBGRA8888IOSurface)1688 TEST_F(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
1689 {
1690 	Initialize(3, false);
1691 
1692 	{ // EGLClientBufferWrapper scope
1693 		EGLClientBufferWrapper clientBufferWrapper;
1694 		unsigned char data[4] = { 3, 2, 1, 4 };
1695 		doClearTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
1696 	} // end of EGLClientBufferWrapper scope
1697 
1698 	Uninitialize();
1699 }
1700 
1701 // Test reading from BGRA8888 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromBGRA8888IOSurface)1702 TEST_F(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
1703 {
1704 	Initialize(3, false);
1705 
1706 	{ // EGLClientBufferWrapper scope
1707 		EGLClientBufferWrapper clientBufferWrapper;
1708 		unsigned char data[4] = { 3, 2, 1, 4 };
1709 		doSampleTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
1710 	} // end of EGLClientBufferWrapper scope
1711 
1712 	Uninitialize();
1713 }
1714 
1715 // Test using RG88 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToRG88IOSurface)1716 TEST_F(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
1717 {
1718 	Initialize(3, false);
1719 
1720 	{ // EGLClientBufferWrapper scope
1721 		EGLClientBufferWrapper clientBufferWrapper;
1722 		unsigned char data[2] = { 1, 2 };
1723 		doClearTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
1724 	} // end of EGLClientBufferWrapper scope
1725 
1726 	Uninitialize();
1727 }
1728 
1729 // Test reading from RG88 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromRG88IOSurface)1730 TEST_F(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
1731 {
1732 	Initialize(3, false);
1733 
1734 	{ // EGLClientBufferWrapper scope
1735 		EGLClientBufferWrapper clientBufferWrapper;
1736 		unsigned char data[2] = { 1, 2 };
1737 		doSampleTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
1738 	} // end of EGLClientBufferWrapper scope
1739 
1740 	Uninitialize();
1741 }
1742 
1743 // Test using R8 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToR8IOSurface)1744 TEST_F(IOSurfaceClientBufferTest, RenderToR8IOSurface)
1745 {
1746 	Initialize(3, false);
1747 
1748 	{ // EGLClientBufferWrapper scope
1749 		EGLClientBufferWrapper clientBufferWrapper;
1750 		unsigned char data[1] = { 1 };
1751 		doClearTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
1752 	} // end of EGLClientBufferWrapper scope
1753 
1754 	Uninitialize();
1755 }
1756 
1757 // Test reading from R8 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromR8IOSurface)1758 TEST_F(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
1759 {
1760 	Initialize(3, false);
1761 
1762 	{ // EGLClientBufferWrapper scope
1763 		EGLClientBufferWrapper clientBufferWrapper;
1764 		unsigned char data[1] = { 1 };
1765 		doSampleTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
1766 	} // end of EGLClientBufferWrapper scope
1767 
1768 	Uninitialize();
1769 }
1770 
1771 // Test using R16 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToR16IOSurface)1772 TEST_F(IOSurfaceClientBufferTest, RenderToR16IOSurface)
1773 {
1774 	Initialize(3, false);
1775 
1776 	{ // EGLClientBufferWrapper scope
1777 		EGLClientBufferWrapper clientBufferWrapper;
1778 		uint16_t data[1] = { 257 };
1779 		doClearTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 2);
1780 	} // end of EGLClientBufferWrapper scope
1781 
1782 	Uninitialize();
1783 }
1784 
1785 // Test reading from R8 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromR16IOSurface)1786 TEST_F(IOSurfaceClientBufferTest, ReadFromR16IOSurface)
1787 {
1788 	Initialize(3, false);
1789 
1790 	{ // EGLClientBufferWrapper scope
1791 		EGLClientBufferWrapper clientBufferWrapper;
1792 		uint16_t data[1] = { 257 };
1793 		doSampleTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 1);
1794 	} // end of EGLClientBufferWrapper scope
1795 
1796 	Uninitialize();
1797 }
1798 
1799 // Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with
1800 // IOSurface
TEST_F(IOSurfaceClientBufferTest,NegativeValidationMissingAttributes)1801 TEST_F(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
1802 {
1803 	Initialize(3, false);
1804 
1805 	{
1806 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
1807 
1808 		// Success case
1809 		{
1810 			const EGLint attribs[] = {
1811 				EGL_WIDTH,                         10,
1812 				EGL_HEIGHT,                        10,
1813 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1814 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1815 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1816 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1817 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1818 				EGL_NONE,                          EGL_NONE,
1819 			};
1820 
1821 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1822 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
1823 
1824 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
1825 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1826 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
1827 		}
1828 
1829 		// Missing EGL_WIDTH
1830 		{
1831 			const EGLint attribs[] = {
1832 				EGL_HEIGHT,                        10,
1833 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1834 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1835 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1836 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1837 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1838 				EGL_NONE,                          EGL_NONE,
1839 			};
1840 
1841 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1842 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1843 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
1844 		}
1845 
1846 		// Missing EGL_HEIGHT
1847 		{
1848 			const EGLint attribs[] = {
1849 				EGL_WIDTH,                         10,
1850 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1851 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1852 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1853 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1854 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1855 				EGL_NONE,                          EGL_NONE,
1856 			};
1857 
1858 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1859 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1860 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
1861 		}
1862 
1863 		// Missing EGL_IOSURFACE_PLANE_ANGLE
1864 		{
1865 			const EGLint attribs[] = {
1866 				EGL_WIDTH,                         10,
1867 				EGL_HEIGHT,                        10,
1868 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1869 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1870 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1871 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1872 				EGL_NONE,                          EGL_NONE,
1873 			};
1874 
1875 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1876 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1877 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
1878 		}
1879 
1880 		// Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of
1881 		// eglCreatePbufferFromClientBuffer
1882 		{
1883 			const EGLint attribs[] = {
1884 				EGL_WIDTH,                         10,
1885 				EGL_HEIGHT,                        10,
1886 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1887 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1888 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1889 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1890 				EGL_NONE,                          EGL_NONE,
1891 			};
1892 
1893 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1894 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1895 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
1896 		}
1897 
1898 		// Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE
1899 		{
1900 			const EGLint attribs[] = {
1901 				EGL_WIDTH,                         10,
1902 				EGL_HEIGHT,                        10,
1903 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1904 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1905 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1906 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1907 				EGL_NONE,                          EGL_NONE,
1908 			};
1909 
1910 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1911 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1912 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
1913 		}
1914 
1915 		// Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of
1916 		// eglCreatePbufferFromClientBuffer
1917 		{
1918 			const EGLint attribs[] = {
1919 				EGL_WIDTH,                         10,
1920 				EGL_HEIGHT,                        10,
1921 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1922 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1923 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1924 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1925 				EGL_NONE,                          EGL_NONE,
1926 			};
1927 
1928 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1929 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1930 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
1931 		}
1932 
1933 		// Missing EGL_TEXTURE_TYPE_ANGLE
1934 		{
1935 			const EGLint attribs[] = {
1936 				EGL_WIDTH,                         10,
1937 				EGL_HEIGHT,                        10,
1938 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1939 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1940 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1941 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1942 				EGL_NONE,                          EGL_NONE,
1943 			};
1944 
1945 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1946 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1947 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
1948 		}
1949 	}
1950 
1951 	Uninitialize();
1952 }
1953 
1954 // Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
TEST_F(IOSurfaceClientBufferTest,NegativeValidationBadAttributes)1955 TEST_F(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
1956 {
1957 	Initialize(3, false);
1958 
1959 	{
1960 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
1961 
1962 		// Success case
1963 		{
1964 			const EGLint attribs[] = {
1965 				EGL_WIDTH,                         10,
1966 				EGL_HEIGHT,                        10,
1967 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1968 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1969 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1970 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
1971 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1972 				EGL_NONE,                          EGL_NONE,
1973 			};
1974 
1975 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1976 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
1977 
1978 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
1979 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
1980 			EXPECT_EQ(EGL_SUCCESS, eglGetError());
1981 		}
1982 
1983 		// EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA
1984 		{
1985 			const EGLint attribs[] = {
1986 				EGL_WIDTH,                         10,
1987 				EGL_HEIGHT,                        10,
1988 				EGL_IOSURFACE_PLANE_ANGLE,         0,
1989 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
1990 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
1991 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGB,
1992 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
1993 				EGL_NONE,                          EGL_NONE,
1994 			};
1995 
1996 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
1997 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
1998 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
1999 		}
2000 
2001 		// EGL_WIDTH must be at least 1
2002 		{
2003 			const EGLint attribs[] = {
2004 				EGL_WIDTH,                         0,
2005 				EGL_HEIGHT,                        10,
2006 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2007 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2008 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2009 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2010 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2011 				EGL_NONE,                          EGL_NONE,
2012 			};
2013 
2014 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2015 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2016 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2017 		}
2018 
2019 		// EGL_HEIGHT must be at least 1
2020 		{
2021 			const EGLint attribs[] = {
2022 				EGL_WIDTH,                         10,
2023 				EGL_HEIGHT,                        0,
2024 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2025 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2026 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2027 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2028 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2029 				EGL_NONE,                          EGL_NONE,
2030 			};
2031 
2032 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2033 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2034 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2035 		}
2036 
2037 #if defined(__APPLE__)
2038 		// EGL_WIDTH must be at most the width of the IOSurface
2039 		{
2040 			const EGLint attribs[] = {
2041 				EGL_WIDTH,                         11,
2042 				EGL_HEIGHT,                        10,
2043 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2044 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2045 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2046 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2047 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2048 				EGL_NONE,                          EGL_NONE,
2049 			};
2050 
2051 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2052 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2053 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2054 		}
2055 
2056 		// EGL_HEIGHT must be at most the height of the IOSurface
2057 		{
2058 			const EGLint attribs[] = {
2059 				EGL_WIDTH,                         10,
2060 				EGL_HEIGHT,                        11,
2061 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2062 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2063 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2064 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2065 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2066 				EGL_NONE,                          EGL_NONE,
2067 			};
2068 
2069 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2070 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2071 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2072 		}
2073 
2074 		// EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface
2075 		{
2076 			const EGLint attribs[] = {
2077 				EGL_WIDTH,                         10,
2078 				EGL_HEIGHT,                        10,
2079 				EGL_IOSURFACE_PLANE_ANGLE,         1,
2080 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2081 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2082 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2083 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2084 				EGL_NONE,                          EGL_NONE,
2085 			};
2086 
2087 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2088 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2089 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2090 		}
2091 #endif
2092 
2093 		// EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE
2094 		{
2095 			const EGLint attribs[] = {
2096 				EGL_WIDTH,                         10,
2097 				EGL_HEIGHT,                        10,
2098 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2099 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_2D,
2100 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2101 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2102 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2103 				EGL_NONE,                          EGL_NONE,
2104 			};
2105 
2106 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2107 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2108 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2109 		}
2110 
2111 		// EGL_IOSURFACE_PLANE_ANGLE must be at least 0
2112 		{
2113 			const EGLint attribs[] = {
2114 				EGL_WIDTH,                         10,
2115 				EGL_HEIGHT,                        10,
2116 				EGL_IOSURFACE_PLANE_ANGLE,         -1,
2117 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2118 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_BGRA_EXT,
2119 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2120 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2121 				EGL_NONE,                          EGL_NONE,
2122 			};
2123 
2124 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2125 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2126 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2127 		}
2128 
2129 		// The internal format / type most be listed in the table
2130 		{
2131 			const EGLint attribs[] = {
2132 				EGL_WIDTH,                         10,
2133 				EGL_HEIGHT,                        10,
2134 				EGL_IOSURFACE_PLANE_ANGLE,         0,
2135 				EGL_TEXTURE_TARGET,                EGL_TEXTURE_RECTANGLE_ANGLE,
2136 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGBA,
2137 				EGL_TEXTURE_FORMAT,                EGL_TEXTURE_RGBA,
2138 				EGL_TEXTURE_TYPE_ANGLE,            GL_UNSIGNED_BYTE,
2139 				EGL_NONE,                          EGL_NONE,
2140 			};
2141 
2142 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2143 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2144 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2145 		}
2146 	}
2147 
2148 	Uninitialize();
2149 }
2150 
2151 // Test IOSurface pbuffers cannot be made current
TEST_F(IOSurfaceClientBufferTest,MakeCurrentDisallowed)2152 TEST_F(IOSurfaceClientBufferTest, MakeCurrentDisallowed)
2153 {
2154 	Initialize(3, false);
2155 
2156 	{
2157 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
2158 
2159 		EGLSurface pbuffer = createIOSurfacePbuffer(clientBufferWrapper.getClientBuffer(), 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE);
2160 
2161 		EGLBoolean result = eglMakeCurrent(getDisplay(), pbuffer, pbuffer, getContext());
2162 		EXPECT_EQ((EGLBoolean)EGL_FALSE, result);
2163 		EXPECT_EQ(EGL_BAD_SURFACE, eglGetError());
2164 	}
2165 
2166 	Uninitialize();
2167 }
2168