• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 
21 #include <EGL/egl.h>
22 #include <GL/glcorearb.h>
23 #include <GL/glext.h>
24 #include <GLES2/gl2.h>
25 #include <GLES2/gl2ext.h>
26 #include <GLES3/gl3.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 #define EXPECT_NO_GL_ERROR() EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError())
38 #define EXPECT_NO_EGL_ERROR() EXPECT_EQ(EGL_SUCCESS, eglGetError())
39 
40 class SwiftShaderTest : public testing::Test
41 {
42 protected:
SetUp()43 	void SetUp() override
44 	{
45 #if defined(_WIN32) && !defined(STANDALONE)
46 		// The DLLs are delay loaded (see BUILD.gn), so we can load
47 		// the correct ones from Chrome's swiftshader subdirectory.
48 		HMODULE libEGL = LoadLibraryA("swiftshader\\libEGL.dll");
49 		EXPECT_NE((HMODULE)NULL, libEGL);
50 
51 		HMODULE libGLESv2 = LoadLibraryA("swiftshader\\libGLESv2.dll");
52 		EXPECT_NE((HMODULE)NULL, libGLESv2);
53 #endif
54 	}
55 
expectFramebufferColor(const unsigned char referenceColor[4],GLint x=0,GLint y=0)56 	void expectFramebufferColor(const unsigned char referenceColor[4], GLint x = 0, GLint y = 0)
57 	{
58 		unsigned char color[4] = { 0 };
59 		glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
60 		EXPECT_NO_GL_ERROR();
61 		EXPECT_EQ(color[0], referenceColor[0]);
62 		EXPECT_EQ(color[1], referenceColor[1]);
63 		EXPECT_EQ(color[2], referenceColor[2]);
64 		EXPECT_EQ(color[3], referenceColor[3]);
65 	}
66 
expectFramebufferColor(const float referenceColor[4],GLint x=0,GLint y=0)67 	void expectFramebufferColor(const float referenceColor[4], GLint x = 0, GLint y = 0)
68 	{
69 		float color[4] = { 0 };
70 		glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &color);
71 		EXPECT_NO_GL_ERROR();
72 		EXPECT_EQ(color[0], referenceColor[0]);
73 		EXPECT_EQ(color[1], referenceColor[1]);
74 		EXPECT_EQ(color[2], referenceColor[2]);
75 		EXPECT_EQ(color[3], referenceColor[3]);
76 	}
77 
Initialize(int version,bool withChecks)78 	void Initialize(int version, bool withChecks)
79 	{
80 		EXPECT_NO_EGL_ERROR();
81 
82 		display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
83 
84 		if(withChecks)
85 		{
86 			EXPECT_NO_EGL_ERROR();
87 			EXPECT_NE(EGL_NO_DISPLAY, display);
88 
89 			eglQueryString(display, EGL_VENDOR);
90 			EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError());
91 		}
92 
93 		EGLint major;
94 		EGLint minor;
95 		EGLBoolean initialized = eglInitialize(display, &major, &minor);
96 
97 		if(withChecks)
98 		{
99 			EXPECT_NO_EGL_ERROR();
100 			EXPECT_EQ((EGLBoolean)EGL_TRUE, initialized);
101 			EXPECT_EQ(1, major);
102 			EXPECT_EQ(4, minor);
103 
104 			const char *eglVendor = eglQueryString(display, EGL_VENDOR);
105 			EXPECT_NO_EGL_ERROR();
106 			EXPECT_STREQ("Google Inc.", eglVendor);
107 
108 			const char *eglVersion = eglQueryString(display, EGL_VERSION);
109 			EXPECT_NO_EGL_ERROR();
110 			EXPECT_THAT(eglVersion, testing::HasSubstr("1.4 SwiftShader "));
111 		}
112 
113 		eglBindAPI(EGL_OPENGL_ES_API);
114 		EXPECT_NO_EGL_ERROR();
115 
116 		const EGLint configAttributes[] = {
117 			EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
118 			EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
119 			EGL_ALPHA_SIZE, 8,
120 			EGL_NONE
121 		};
122 
123 		EGLint num_config = -1;
124 		EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config);
125 		EXPECT_NO_EGL_ERROR();
126 		EXPECT_EQ(num_config, 1);
127 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
128 
129 		if(withChecks)
130 		{
131 			EGLint conformant = 0;
132 			eglGetConfigAttrib(display, config, EGL_CONFORMANT, &conformant);
133 			EXPECT_NO_EGL_ERROR();
134 			EXPECT_TRUE(conformant & EGL_OPENGL_ES2_BIT);
135 
136 			EGLint renderableType = 0;
137 			eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType);
138 			EXPECT_NO_EGL_ERROR();
139 			EXPECT_TRUE(renderableType & EGL_OPENGL_ES2_BIT);
140 
141 			EGLint surfaceType = 0;
142 			eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
143 			EXPECT_NO_EGL_ERROR();
144 			EXPECT_TRUE(surfaceType & EGL_WINDOW_BIT);
145 		}
146 
147 		EGLint surfaceAttributes[] = {
148 			EGL_WIDTH, 1920,
149 			EGL_HEIGHT, 1080,
150 			EGL_NONE
151 		};
152 
153 		surface = eglCreatePbufferSurface(display, config, surfaceAttributes);
154 		EXPECT_NO_EGL_ERROR();
155 		EXPECT_NE(EGL_NO_SURFACE, surface);
156 
157 		EGLint contextAttributes[] = {
158 			EGL_CONTEXT_CLIENT_VERSION, version,
159 			EGL_NONE
160 		};
161 
162 		context = eglCreateContext(display, config, NULL, contextAttributes);
163 		EXPECT_NO_EGL_ERROR();
164 		EXPECT_NE(EGL_NO_CONTEXT, context);
165 
166 		success = eglMakeCurrent(display, surface, surface, context);
167 		EXPECT_NO_EGL_ERROR();
168 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
169 
170 		if(withChecks)
171 		{
172 			EGLDisplay currentDisplay = eglGetCurrentDisplay();
173 			EXPECT_NO_EGL_ERROR();
174 			EXPECT_EQ(display, currentDisplay);
175 
176 			EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
177 			EXPECT_NO_EGL_ERROR();
178 			EXPECT_EQ(surface, currentDrawSurface);
179 
180 			EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
181 			EXPECT_NO_EGL_ERROR();
182 			EXPECT_EQ(surface, currentReadSurface);
183 
184 			EGLContext currentContext = eglGetCurrentContext();
185 			EXPECT_NO_EGL_ERROR();
186 			EXPECT_EQ(context, currentContext);
187 		}
188 
189 		EXPECT_NO_GL_ERROR();
190 	}
191 
Uninitialize()192 	void Uninitialize()
193 	{
194 		EXPECT_NO_GL_ERROR();
195 
196 		EGLBoolean success = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
197 		EXPECT_NO_EGL_ERROR();
198 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
199 
200 		EGLDisplay currentDisplay = eglGetCurrentDisplay();
201 		EXPECT_NO_EGL_ERROR();
202 		EXPECT_EQ(EGL_NO_DISPLAY, currentDisplay);
203 
204 		EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
205 		EXPECT_NO_EGL_ERROR();
206 		EXPECT_EQ(EGL_NO_SURFACE, currentDrawSurface);
207 
208 		EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ);
209 		EXPECT_NO_EGL_ERROR();
210 		EXPECT_EQ(EGL_NO_SURFACE, currentReadSurface);
211 
212 		EGLContext currentContext = eglGetCurrentContext();
213 		EXPECT_NO_EGL_ERROR();
214 		EXPECT_EQ(EGL_NO_CONTEXT, currentContext);
215 
216 		success = eglDestroyContext(display, context);
217 		EXPECT_NO_EGL_ERROR();
218 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
219 
220 		success = eglDestroySurface(display, surface);
221 		EXPECT_NO_EGL_ERROR();
222 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
223 
224 		success = eglTerminate(display);
225 		EXPECT_NO_EGL_ERROR();
226 		EXPECT_EQ((EGLBoolean)EGL_TRUE, success);
227 	}
228 
229 	struct ProgramHandles
230 	{
231 		GLuint program;
232 		GLuint vertexShader;
233 		GLuint fragmentShader;
234 	};
235 
MakeShader(const std::string & source,GLenum shaderType)236 	GLuint MakeShader(const std::string &source, GLenum shaderType)
237 	{
238 		GLuint shader = glCreateShader(shaderType);
239 		const char *c_source[1] = { source.c_str() };
240 		glShaderSource(shader, 1, c_source, nullptr);
241 		glCompileShader(shader);
242 		EXPECT_NO_GL_ERROR();
243 
244 		GLchar buf[1024];
245 		GLint compileStatus = 0;
246 		glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
247 		glGetShaderInfoLog(shader, sizeof(buf), nullptr, buf);
248 		EXPECT_EQ(compileStatus, GL_TRUE) << "Compile status: " << std::endl
249 		                                  << buf;
250 
251 		return shader;
252 	}
253 
MakeProgram(GLuint vs,GLuint fs)254 	GLuint MakeProgram(GLuint vs, GLuint fs)
255 	{
256 		GLuint program;
257 
258 		program = glCreateProgram();
259 		EXPECT_NO_GL_ERROR();
260 
261 		glAttachShader(program, vs);
262 		glAttachShader(program, fs);
263 		EXPECT_NO_GL_ERROR();
264 
265 		return program;
266 	}
267 
LinkProgram(GLuint program)268 	void LinkProgram(GLuint program)
269 	{
270 		GLchar buf[1024];
271 		glLinkProgram(program);
272 
273 		GLint linkStatus = 0;
274 		glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
275 		glGetProgramInfoLog(program, sizeof(buf), nullptr, buf);
276 		EXPECT_NE(linkStatus, 0) << "Link status: " << std::endl
277 		                         << buf;
278 
279 		EXPECT_NO_GL_ERROR();
280 	}
281 
createProgram(const std::string & vs,const std::string & fs)282 	ProgramHandles createProgram(const std::string &vs, const std::string &fs)
283 	{
284 		ProgramHandles ph;
285 		ph.vertexShader = MakeShader(vs, GL_VERTEX_SHADER);
286 		ph.fragmentShader = MakeShader(fs, GL_FRAGMENT_SHADER);
287 		ph.program = MakeProgram(ph.vertexShader, ph.fragmentShader);
288 		LinkProgram(ph.program);
289 
290 		return ph;
291 	}
292 
deleteProgram(const ProgramHandles & ph)293 	void deleteProgram(const ProgramHandles &ph)
294 	{
295 		glDeleteShader(ph.fragmentShader);
296 		glDeleteShader(ph.vertexShader);
297 		glDeleteProgram(ph.program);
298 
299 		EXPECT_NO_GL_ERROR();
300 	}
301 
drawQuad(GLuint program,const char * textureName=nullptr)302 	void drawQuad(GLuint program, const char *textureName = nullptr)
303 	{
304 		GLint prevProgram = 0;
305 		glGetIntegerv(GL_CURRENT_PROGRAM, &prevProgram);
306 
307 		glUseProgram(program);
308 		EXPECT_NO_GL_ERROR();
309 
310 		GLint posLoc = glGetAttribLocation(program, "position");
311 		EXPECT_NO_GL_ERROR();
312 
313 		if(textureName)
314 		{
315 			GLint location = glGetUniformLocation(program, textureName);
316 			ASSERT_NE(-1, location);
317 			glUniform1i(location, 0);
318 		}
319 
320 		float vertices[18] = { -1.0f, 1.0f, 0.5f,
321 			                   -1.0f, -1.0f, 0.5f,
322 			                   1.0f, -1.0f, 0.5f,
323 			                   -1.0f, 1.0f, 0.5f,
324 			                   1.0f, -1.0f, 0.5f,
325 			                   1.0f, 1.0f, 0.5f };
326 
327 		glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, vertices);
328 		glEnableVertexAttribArray(posLoc);
329 		glDrawArrays(GL_TRIANGLES, 0, 6);
330 		EXPECT_NO_GL_ERROR();
331 
332 		glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
333 		glDisableVertexAttribArray(posLoc);
334 		glUseProgram(prevProgram);
335 		EXPECT_NO_GL_ERROR();
336 	}
337 
replace(std::string str,const std::string & substr,const std::string & replacement)338 	std::string replace(std::string str, const std::string &substr, const std::string &replacement)
339 	{
340 		size_t pos = 0;
341 		while((pos = str.find(substr, pos)) != std::string::npos)
342 		{
343 			str.replace(pos, substr.length(), replacement);
344 			pos += replacement.length();
345 		}
346 		return str;
347 	}
348 
checkCompiles(std::string v,std::string f)349 	void checkCompiles(std::string v, std::string f)
350 	{
351 		Initialize(3, false);
352 
353 		std::string vs =
354 		    R"(#version 300 es
355 			in vec4 position;
356 			out float unfoldable;
357 			$INSERT
358 			void main()
359 			{
360 			    unfoldable = position.x;
361 			    gl_Position = vec4(position.xy, 0.0, 1.0);
362 			    gl_Position.x += F(unfoldable);\
363 			})";
364 
365 		std::string fs =
366 		    R"(#version 300 es
367 			precision mediump float;
368 			in float unfoldable;
369 			out vec4 fragColor;
370 			$INSERT
371 			void main()
372 			{
373 			    fragColor = vec4(1.0, 1.0, 1.0, 1.0);
374 			    fragColor.x += F(unfoldable);
375 			})";
376 
377 		vs = replace(vs, "$INSERT", (v.length() > 0) ? v : "float F(float ignored) { return 0.0; }");
378 		fs = replace(fs, "$INSERT", (f.length() > 0) ? f : "float F(float ignored) { return 0.0; }");
379 
380 		const ProgramHandles ph = createProgram(vs, fs);
381 
382 		glUseProgram(ph.program);
383 
384 		drawQuad(ph.program);
385 
386 		deleteProgram(ph);
387 
388 		EXPECT_NO_GL_ERROR();
389 
390 		Uninitialize();
391 	}
392 
checkCompiles(std::string s)393 	void checkCompiles(std::string s)
394 	{
395 		checkCompiles(s, "");
396 		checkCompiles("", s);
397 	}
398 
checkCompileFails(std::string source,GLenum glShaderType)399 	std::string checkCompileFails(std::string source, GLenum glShaderType)
400 	{
401 		Initialize(3, false);
402 
403 		GLint compileStatus = 0;
404 		const char *c_source[1] = { source.c_str() };
405 		GLuint glShader = glCreateShader(glShaderType);
406 
407 		glShaderSource(glShader, 1, c_source, nullptr);
408 		glCompileShader(glShader);
409 		EXPECT_NO_GL_ERROR();
410 
411 		std::string log;
412 		char *buf;
413 		GLsizei length = 0;
414 		GLsizei written = 0;
415 
416 		glGetShaderiv(glShader, GL_COMPILE_STATUS, &compileStatus);
417 		EXPECT_EQ(compileStatus, GL_FALSE);
418 
419 		glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &length);
420 		EXPECT_NO_GL_ERROR();
421 		EXPECT_NE(length, 0);
422 		buf = new char[length];
423 
424 		glGetShaderInfoLog(glShader, length, &written, buf);
425 		EXPECT_NO_GL_ERROR();
426 		EXPECT_EQ(length, written + 1);
427 		log.assign(buf, length);
428 		delete[] buf;
429 
430 		glDeleteShader(glShader);
431 
432 		Uninitialize();
433 
434 		return log;
435 	}
436 
checkCompileFails(std::string s)437 	void checkCompileFails(std::string s)
438 	{
439 		std::string vs =
440 		    R"(#version 300 es
441 			in vec4 position;
442 			out float unfoldable;
443 			$INSERT
444 			void main()
445 			{
446 			    unfoldable = position.x;
447 			    gl_Position = vec4(position.xy, 0.0, 1.0);
448 			    gl_Position.x += F(unfoldable);
449 			})";
450 
451 		std::string fs =
452 		    R"(#version 300 es
453 			precision mediump float;
454 			in float unfoldable;
455 			out vec4 fragColor;
456 			$INSERT
457 			void main()
458 			{
459 			    fragColor = vec4(1.0, 1.0, 1.0, 1.0);
460 			    fragColor.x += F(unfoldable);
461 			})";
462 
463 		vs = replace(vs, "$INSERT", s);
464 		fs = replace(fs, "$INSERT", s);
465 
466 		checkCompileFails(vs, GL_VERTEX_SHADER);
467 		checkCompileFails(fs, GL_FRAGMENT_SHADER);
468 	}
469 
getDisplay() const470 	EGLDisplay getDisplay() const { return display; }
getConfig() const471 	EGLConfig getConfig() const { return config; }
getSurface() const472 	EGLSurface getSurface() const { return surface; }
getContext() const473 	EGLContext getContext() const { return context; }
474 
475 private:
476 	EGLDisplay display;
477 	EGLConfig config;
478 	EGLSurface surface;
479 	EGLContext context;
480 };
481 
TEST_F(SwiftShaderTest,Initalization)482 TEST_F(SwiftShaderTest, Initalization)
483 {
484 	Initialize(2, true);
485 
486 	const GLubyte *glVendor = glGetString(GL_VENDOR);
487 	EXPECT_NO_GL_ERROR();
488 	EXPECT_STREQ("Google Inc.", (const char *)glVendor);
489 
490 	const GLubyte *glRenderer = glGetString(GL_RENDERER);
491 	EXPECT_NO_GL_ERROR();
492 	EXPECT_STREQ("Google SwiftShader", (const char *)glRenderer);
493 
494 	// SwiftShader return an OpenGL ES 3.0 context when a 2.0 context is requested, as allowed by the spec.
495 	const GLubyte *glVersion = glGetString(GL_VERSION);
496 	EXPECT_NO_GL_ERROR();
497 	EXPECT_THAT((const char *)glVersion, testing::HasSubstr("OpenGL ES 3.0 SwiftShader "));
498 
499 	Uninitialize();
500 }
501 
502 // Test attempting to clear an incomplete framebuffer
TEST_F(SwiftShaderTest,ClearIncomplete)503 TEST_F(SwiftShaderTest, ClearIncomplete)
504 {
505 	Initialize(3, false);
506 
507 	GLfloat zero_float = 0;
508 	GLuint renderbuffer;
509 	glGenRenderbuffers(1, &renderbuffer);
510 	GLuint framebuffer;
511 	glGenFramebuffers(1, &framebuffer);
512 
513 	glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
514 	EXPECT_NO_GL_ERROR();
515 	glRenderbufferStorage(GL_RENDERBUFFER, GL_R8I, 43, 27);
516 	EXPECT_NO_GL_ERROR();
517 	glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
518 	EXPECT_NO_GL_ERROR();
519 	glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);
520 	EXPECT_NO_GL_ERROR();
521 	glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
522 	EXPECT_NO_GL_ERROR();
523 	glClearBufferfv(GL_DEPTH, 0, &zero_float);
524 	EXPECT_GLENUM_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, glGetError());
525 
526 	Uninitialize();
527 }
528 
529 // Test unrolling of a loop
TEST_F(SwiftShaderTest,UnrollLoop)530 TEST_F(SwiftShaderTest, UnrollLoop)
531 {
532 	Initialize(3, false);
533 
534 	unsigned char green[4] = { 0, 255, 0, 255 };
535 
536 	const std::string vs =
537 	    R"(#version 300 es
538 		in vec4 position;
539 		out vec4 color;
540 		void main()
541 		{
542 		   for(int i = 0; i < 4; i++)
543 		   {
544 		       color[i] = (i % 2 == 0) ? 0.0 : 1.0;
545 		   }
546 			gl_Position = vec4(position.xy, 0.0, 1.0);
547 		})";
548 
549 	const std::string fs =
550 	    R"(#version 300 es
551 		precision mediump float;
552 		in vec4 color;
553 		out vec4 fragColor;
554 		void main()
555 		{
556 			fragColor = color;
557 		})";
558 
559 	const ProgramHandles ph = createProgram(vs, fs);
560 
561 	// Expect the info log to contain "unrolled". This is not a spec requirement.
562 	GLsizei length = 0;
563 	glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length);
564 	EXPECT_NO_GL_ERROR();
565 	EXPECT_NE(length, 0);
566 	char *log = new char[length];
567 	GLsizei written = 0;
568 	glGetShaderInfoLog(ph.vertexShader, length, &written, log);
569 	EXPECT_NO_GL_ERROR();
570 	EXPECT_EQ(length, written + 1);
571 	EXPECT_NE(strstr(log, "unrolled"), nullptr);
572 	delete[] log;
573 
574 	glUseProgram(ph.program);
575 
576 	glClearColor(0.0, 0.0, 0.0, 0.0);
577 	glClear(GL_COLOR_BUFFER_BIT);
578 	EXPECT_NO_GL_ERROR();
579 
580 	drawQuad(ph.program);
581 
582 	deleteProgram(ph);
583 
584 	expectFramebufferColor(green);
585 
586 	EXPECT_NO_GL_ERROR();
587 
588 	Uninitialize();
589 }
590 
591 // Test non-canonical or non-deterministic loops do not get unrolled
TEST_F(SwiftShaderTest,DynamicLoop)592 TEST_F(SwiftShaderTest, DynamicLoop)
593 {
594 	Initialize(3, false);
595 
596 	const std::string vs =
597 	    R"(#version 300 es
598 		in vec4 position;
599 		out vec4 color;
600 		void main()
601 		{
602 		   for(int i = 0; i < 4; )
603 		   {
604 		       color[i] = (i % 2 == 0) ? 0.0 : 1.0;
605 		       i++;
606 		   }
607 			gl_Position = vec4(position.xy, 0.0, 1.0);
608 		})";
609 
610 	const std::string fs =
611 	    R"(#version 300 es
612 		precision mediump float;
613 		in vec4 color;
614 		out vec4 fragColor;
615 		void main()
616 		{
617 		   vec4 temp;
618 		   for(int i = 0; i < 4; i++)
619 		   {
620 		       if(color.x < 0.0) return;
621 		       temp[i] = color[i];
622 		   }
623 			fragColor = vec4(temp[0], temp[1], temp[2], temp[3]);
624 		})";
625 
626 	const ProgramHandles ph = createProgram(vs, fs);
627 
628 	// Expect the info logs to be empty. This is not a spec requirement.
629 	GLsizei length = 0;
630 	glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length);
631 	EXPECT_NO_GL_ERROR();
632 	EXPECT_EQ(length, 0);
633 	glGetShaderiv(ph.fragmentShader, GL_INFO_LOG_LENGTH, &length);
634 	EXPECT_NO_GL_ERROR();
635 	EXPECT_EQ(length, 0);
636 
637 	glUseProgram(ph.program);
638 
639 	glClearColor(0.0, 0.0, 0.0, 0.0);
640 	glClear(GL_COLOR_BUFFER_BIT);
641 	EXPECT_NO_GL_ERROR();
642 
643 	drawQuad(ph.program);
644 
645 	deleteProgram(ph);
646 
647 	unsigned char green[4] = { 0, 255, 0, 255 };
648 	expectFramebufferColor(green);
649 
650 	EXPECT_NO_GL_ERROR();
651 
652 	Uninitialize();
653 }
654 
655 // Test dynamic indexing
TEST_F(SwiftShaderTest,DynamicIndexing)656 TEST_F(SwiftShaderTest, DynamicIndexing)
657 {
658 	Initialize(3, false);
659 
660 	const std::string vs =
661 	    R"(#version 300 es
662 		in vec4 position;
663 		out float color[4];
664 		void main()
665 		{
666 		   for(int i = 0; i < 4; )
667 		   {
668 		       int j = (gl_VertexID + i) % 4;
669 		       color[j] = (j % 2 == 0) ? 0.0 : 1.0;
670 		       i++;
671 		   }
672 			gl_Position = vec4(position.xy, 0.0, 1.0);
673 		})";
674 
675 	const std::string fs =
676 	    R"(#version 300 es
677 		precision mediump float;
678 		in float color[4];
679 		out vec4 fragColor;
680 		void main()
681 		{
682 		   float temp[4];
683 		   for(int i = 0; i < 4; )
684 		   {
685 		       temp[i] = color[i];
686 		       i++;
687 		   }
688 			fragColor = vec4(temp[0], temp[1], temp[2], temp[3]);
689 		})";
690 
691 	const ProgramHandles ph = createProgram(vs, fs);
692 
693 	glUseProgram(ph.program);
694 
695 	glClearColor(0.0, 0.0, 0.0, 0.0);
696 	glClear(GL_COLOR_BUFFER_BIT);
697 	EXPECT_NO_GL_ERROR();
698 
699 	drawQuad(ph.program);
700 
701 	deleteProgram(ph);
702 
703 	unsigned char green[4] = { 0, 255, 0, 255 };
704 	expectFramebufferColor(green);
705 
706 	EXPECT_NO_GL_ERROR();
707 
708 	Uninitialize();
709 }
710 
711 // Test vertex attribute location linking
TEST_F(SwiftShaderTest,AttributeLocation)712 TEST_F(SwiftShaderTest, AttributeLocation)
713 {
714 	Initialize(3, false);
715 
716 	const std::string vs =
717 	    R"(#version 300 es
718 		layout(location = 0) in vec4 a0;   // Explicitly bound in GLSL
719 		layout(location = 2) in vec4 a2;   // Explicitly bound in GLSL
720 		in vec4 a5;                        // Bound to location 5 by API
721 		in mat2 a3;                        // Implicit location
722 		in vec4 a1;                        // Implicit location
723 		in vec4 a6;                        // Implicit location
724 		out vec4 color;
725 		void main()
726 		{
727 		   vec4 a34 = vec4(a3[0], a3[1]);
728 			gl_Position = a0;
729 		   color = (a2 == vec4(1.0, 2.0, 3.0, 4.0) &&
730 		            a34 == vec4(5.0, 6.0, 7.0, 8.0) &&
731 		            a5 == vec4(9.0, 10.0, 11.0, 12.0) &&
732 		            a1 == vec4(13.0, 14.0, 15.0, 16.0) &&
733 		            a6 == vec4(17.0, 18.0, 19.0, 20.0)) ?
734 		           vec4(0.0, 1.0, 0.0, 1.0) :
735 		           vec4(1.0, 0.0, 0.0, 1.0);
736 		})";
737 
738 	const std::string fs =
739 	    R"(#version 300 es
740 		precision mediump float;
741 		in vec4 color;
742 		out vec4 fragColor;
743 		void main()
744 		{
745 			fragColor = color;
746 		})";
747 
748 	ProgramHandles ph;
749 	ph.vertexShader = MakeShader(vs, GL_VERTEX_SHADER);
750 	ph.fragmentShader = MakeShader(fs, GL_FRAGMENT_SHADER);
751 	ph.program = glCreateProgram();
752 	EXPECT_NO_GL_ERROR();
753 
754 	// Not assigned a layout location in GLSL. Bind it explicitly with the API.
755 	glBindAttribLocation(ph.program, 5, "a5");
756 	EXPECT_NO_GL_ERROR();
757 
758 	// Should not override GLSL layout location qualifier
759 	glBindAttribLocation(ph.program, 8, "a2");
760 	EXPECT_NO_GL_ERROR();
761 
762 	glAttachShader(ph.program, ph.vertexShader);
763 	glAttachShader(ph.program, ph.fragmentShader);
764 	glLinkProgram(ph.program);
765 	EXPECT_NO_GL_ERROR();
766 
767 	// Changes after linking should have no effect
768 	glBindAttribLocation(ph.program, 0, "a1");
769 	glBindAttribLocation(ph.program, 6, "a2");
770 	glBindAttribLocation(ph.program, 2, "a6");
771 
772 	GLint linkStatus = 0;
773 	glGetProgramiv(ph.program, GL_LINK_STATUS, &linkStatus);
774 	EXPECT_NE(linkStatus, 0);
775 	EXPECT_NO_GL_ERROR();
776 
777 	float vertices[6][3] = { { -1.0f, 1.0f, 0.5f },
778 		                     { -1.0f, -1.0f, 0.5f },
779 		                     { 1.0f, -1.0f, 0.5f },
780 		                     { -1.0f, 1.0f, 0.5f },
781 		                     { 1.0f, -1.0f, 0.5f },
782 		                     { 1.0f, 1.0f, 0.5f } };
783 
784 	float attributes[5][4] = { { 1.0f, 2.0f, 3.0f, 4.0f },
785 		                       { 5.0f, 6.0f, 7.0f, 8.0f },
786 		                       { 9.0f, 10.0f, 11.0f, 12.0f },
787 		                       { 13.0f, 14.0f, 15.0f, 16.0f },
788 		                       { 17.0f, 18.0f, 19.0f, 20.0f } };
789 
790 	GLint a0 = glGetAttribLocation(ph.program, "a0");
791 	EXPECT_EQ(a0, 0);
792 	glVertexAttribPointer(a0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
793 	glEnableVertexAttribArray(a0);
794 	EXPECT_NO_GL_ERROR();
795 
796 	GLint a2 = glGetAttribLocation(ph.program, "a2");
797 	EXPECT_EQ(a2, 2);
798 	glVertexAttribPointer(a2, 4, GL_FLOAT, GL_FALSE, 0, attributes[0]);
799 	glVertexAttribDivisor(a2, 1);
800 	glEnableVertexAttribArray(a2);
801 	EXPECT_NO_GL_ERROR();
802 
803 	GLint a3 = glGetAttribLocation(ph.program, "a3");
804 	EXPECT_EQ(a3, 3);  // Note: implementation specific
805 	glVertexAttribPointer(a3 + 0, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][0]);
806 	glVertexAttribPointer(a3 + 1, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][2]);
807 	glVertexAttribDivisor(a3 + 0, 1);
808 	glVertexAttribDivisor(a3 + 1, 1);
809 	glEnableVertexAttribArray(a3 + 0);
810 	glEnableVertexAttribArray(a3 + 1);
811 	EXPECT_NO_GL_ERROR();
812 
813 	GLint a5 = glGetAttribLocation(ph.program, "a5");
814 	EXPECT_EQ(a5, 5);
815 	glVertexAttribPointer(a5, 4, GL_FLOAT, GL_FALSE, 0, attributes[2]);
816 	glVertexAttribDivisor(a5, 1);
817 	glEnableVertexAttribArray(a5);
818 	EXPECT_NO_GL_ERROR();
819 
820 	GLint a1 = glGetAttribLocation(ph.program, "a1");
821 	EXPECT_EQ(a1, 1);  // Note: implementation specific
822 	glVertexAttribPointer(a1, 4, GL_FLOAT, GL_FALSE, 0, attributes[3]);
823 	glVertexAttribDivisor(a1, 1);
824 	glEnableVertexAttribArray(a1);
825 	EXPECT_NO_GL_ERROR();
826 
827 	GLint a6 = glGetAttribLocation(ph.program, "a6");
828 	EXPECT_EQ(a6, 6);  // Note: implementation specific
829 	glVertexAttribPointer(a6, 4, GL_FLOAT, GL_FALSE, 0, attributes[4]);
830 	glVertexAttribDivisor(a6, 1);
831 	glEnableVertexAttribArray(a6);
832 	EXPECT_NO_GL_ERROR();
833 
834 	glUseProgram(ph.program);
835 	glDrawArrays(GL_TRIANGLES, 0, 6);
836 	EXPECT_NO_GL_ERROR();
837 
838 	deleteProgram(ph);
839 
840 	unsigned char green[4] = { 0, 255, 0, 255 };
841 	expectFramebufferColor(green);
842 
843 	EXPECT_NO_GL_ERROR();
844 
845 	Uninitialize();
846 }
847 
848 // Test negative layout locations
TEST_F(SwiftShaderTest,NegativeLocation)849 TEST_F(SwiftShaderTest, NegativeLocation)
850 {
851 	const std::string vs =
852 	    R"(#version 300 es
853 		layout(location = 0x86868686u) in vec4 a0;   // Explicitly bound in GLSL
854 		layout(location = 0x96969696u) in vec4 a2;   // Explicitly bound in GLSL
855 		in vec4 a5;                        // Bound to location 5 by API
856 		in mat2 a3;                        // Implicit location
857 		in vec4 a1;                        // Implicit location
858 		in vec4 a6;                        // Implicit location
859 		out vec4 color;
860 		float F(float f)
861 		{
862 		   vec4 a34 = vec4(a3[0], a3[1]);\n"
863 			gl_Position = a0;\n"
864 		   color = (a2 == vec4(1.0, 2.0, 3.0, 4.0) &&
865 		            a34 == vec4(5.0, 6.0, 7.0, 8.0) &&
866 		            a5 == vec4(9.0, 10.0, 11.0, 12.0) &&
867 		            a1 == vec4(13.0, 14.0, 15.0, 16.0) &&
868 		            a6 == vec4(17.0, 18.0, 19.0, 20.0)) ?
869 		           vec4(0.0, 1.0, 0.0, 1.0) :
870 		           vec4(1.0, 0.0, 0.0, 1.0);
871 		})";
872 
873 	const std::string fs =
874 	    R"(#version 300 es
875 		precision mediump float;
876 		in vec4 color;
877 		layout(location = 0xA6A6A6A6u) out vec4 fragColor;
878 		float F main()
879 		{
880 			fragColor = color;
881 		})";
882 
883 	{
884 		std::string log = checkCompileFails(vs, GL_VERTEX_SHADER);
885 		EXPECT_NE(strstr(log.c_str(), "out of range: location must be non-negative"), nullptr);
886 	}
887 
888 	{
889 		std::string log = checkCompileFails(fs, GL_FRAGMENT_SHADER);
890 		EXPECT_NE(strstr(log.c_str(), "out of range: location must be non-negative"), nullptr);
891 	}
892 }
893 
894 // Tests clearing of a texture with 'dirty' content.
TEST_F(SwiftShaderTest,ClearDirtyTexture)895 TEST_F(SwiftShaderTest, ClearDirtyTexture)
896 {
897 	Initialize(3, false);
898 
899 	GLuint tex = 1;
900 	glBindTexture(GL_TEXTURE_2D, tex);
901 	glTexImage2D(GL_TEXTURE_2D, 0, GL_R11F_G11F_B10F, 256, 256, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, nullptr);
902 	EXPECT_NO_GL_ERROR();
903 
904 	GLuint fbo = 1;
905 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
906 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
907 	EXPECT_NO_GL_ERROR();
908 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
909 
910 	float dirty_color[3] = { 128 / 255.0f, 64 / 255.0f, 192 / 255.0f };
911 	GLint dirty_x = 8;
912 	GLint dirty_y = 12;
913 	glTexSubImage2D(GL_TEXTURE_2D, 0, dirty_x, dirty_y, 1, 1, GL_RGB, GL_FLOAT, dirty_color);
914 
915 	const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f };
916 	glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f);
917 	glClear(GL_COLOR_BUFFER_BIT);
918 	EXPECT_NO_GL_ERROR();
919 
920 	expectFramebufferColor(clear_color, dirty_x, dirty_y);
921 
922 	Uninitialize();
923 }
924 
925 // Tests copying between textures of different floating-point formats using a framebuffer object.
TEST_F(SwiftShaderTest,CopyTexImage)926 TEST_F(SwiftShaderTest, CopyTexImage)
927 {
928 	Initialize(3, false);
929 
930 	GLuint tex1 = 1;
931 	float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
932 	glBindTexture(GL_TEXTURE_2D, tex1);
933 	glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16);
934 	glTexSubImage2D(GL_TEXTURE_2D, 0, 5, 10, 1, 1, GL_RGBA, GL_FLOAT, &green);
935 	EXPECT_NO_GL_ERROR();
936 
937 	GLuint fbo = 1;
938 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
939 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
940 	EXPECT_NO_GL_ERROR();
941 
942 	GLuint tex2 = 2;
943 	glBindTexture(GL_TEXTURE_2D, tex2);
944 	glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 6, 8, 8, 0);
945 	EXPECT_NO_GL_ERROR();
946 
947 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0);
948 	expectFramebufferColor(green, 3, 4);
949 	EXPECT_NO_GL_ERROR();
950 
951 	Uninitialize();
952 }
953 
954 // Tests copying to a texture from a pixel buffer object
TEST_F(SwiftShaderTest,CopyTexImageFromPixelBuffer)955 TEST_F(SwiftShaderTest, CopyTexImageFromPixelBuffer)
956 {
957 	Initialize(3, false);
958 	const GLuint red = 0xff0000ff;
959 	const GLuint green = 0x00ff00ff;
960 	const GLuint blue = 0x0000ffff;
961 	// Set up texture
962 	GLuint texture = 0;
963 	glGenTextures(1, &texture);
964 	EXPECT_NO_GL_ERROR();
965 	GLuint tex_data[4][4] = {
966 		{ red, red, red, red },
967 		{ red, red, red, red },
968 		{ red, red, red, red },
969 		{ red, red, red, red }
970 	};
971 	glBindTexture(GL_TEXTURE_2D, texture);
972 	EXPECT_NO_GL_ERROR();
973 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void *)tex_data[0]);
974 	EXPECT_NO_GL_ERROR();
975 	// Set up Pixel Buffer Object
976 	GLuint pixelBuffer = 0;
977 	glGenBuffers(1, &pixelBuffer);
978 	glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBuffer);
979 	EXPECT_NO_GL_ERROR();
980 	glPixelStorei(GL_UNPACK_ROW_LENGTH, 4);
981 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
982 	EXPECT_NO_GL_ERROR();
983 	GLuint pixel_data[4][4] = {
984 		{ blue, blue, green, green },
985 		{ blue, blue, green, green },
986 		{ blue, blue, green, green },
987 		{ blue, blue, green, green },
988 	};
989 	glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pixel_data), (void *)pixel_data, GL_STREAM_DRAW);
990 	// Should set the 2-rightmost columns of the currently bound texture to the
991 	// 2-rightmost columns of the PBO;
992 	GLintptr offset = 2 * sizeof(GLuint);
993 	glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 0, 2, 4, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(offset));
994 	EXPECT_NO_GL_ERROR();
995 	// Create an off-screen framebuffer to render the texture data to.
996 	GLuint fbo = 0;
997 	glGenFramebuffers(1, &fbo);
998 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
999 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
1000 	EXPECT_NO_GL_ERROR();
1001 	unsigned int color[4][4] = {
1002 		{ 0, 0, 0, 0 },
1003 		{ 0, 0, 0, 0 },
1004 		{ 0, 0, 0, 0 },
1005 		{ 0, 0, 0, 0 }
1006 	};
1007 	glReadPixels(0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, &color);
1008 	EXPECT_NO_GL_ERROR();
1009 	bool allEqual = true;
1010 	for(int i = 0; i < 4; i++)
1011 	{
1012 		for(int j = 0; j < 2; j++)
1013 		{
1014 			allEqual = allEqual && (color[i][j] == tex_data[i][j]);
1015 			allEqual = allEqual && (color[i][j + 2] == pixel_data[i][j + 2]);
1016 			if(!allEqual)
1017 				break;
1018 		}
1019 		if(!allEqual)
1020 			break;
1021 	}
1022 	EXPECT_EQ(allEqual, true);
1023 	// We can't use an offset of 3 GLuints or more, because the PBO is not large
1024 	// enough to satisfy such a request with the current GL_UNPACK_ROW_LENGTH.
1025 	offset = 3 * sizeof(GLuint);
1026 	glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 0, 2, 4, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(offset));
1027 	GLenum error = glGetError();
1028 	EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, error);
1029 	Uninitialize();
1030 }
1031 
1032 // Tests reading of half-float textures.
TEST_F(SwiftShaderTest,ReadHalfFloat)1033 TEST_F(SwiftShaderTest, ReadHalfFloat)
1034 {
1035 	Initialize(3, false);
1036 
1037 	GLuint tex = 1;
1038 	glBindTexture(GL_TEXTURE_2D, tex);
1039 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 256, 256, 0, GL_RGB, GL_HALF_FLOAT, nullptr);
1040 	EXPECT_NO_GL_ERROR();
1041 
1042 	GLuint fbo = 1;
1043 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1044 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1045 	EXPECT_NO_GL_ERROR();
1046 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1047 
1048 	const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f };
1049 	glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f);
1050 	glClear(GL_COLOR_BUFFER_BIT);
1051 	EXPECT_NO_GL_ERROR();
1052 
1053 	uint16_t pixel[3] = { 0x1234, 0x3F80, 0xAAAA };
1054 	GLint x = 6;
1055 	GLint y = 3;
1056 	glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, pixel);
1057 
1058 	// This relies on GL_HALF_FLOAT being a valid type for read-back,
1059 	// which isn't guaranteed by the spec but is supported by SwiftShader.
1060 	uint16_t read_color[3] = { 0, 0, 0 };
1061 	glReadPixels(x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, &read_color);
1062 	EXPECT_NO_GL_ERROR();
1063 	EXPECT_EQ(read_color[0], pixel[0]);
1064 	EXPECT_EQ(read_color[1], pixel[1]);
1065 	EXPECT_EQ(read_color[2], pixel[2]);
1066 
1067 	Uninitialize();
1068 }
1069 
1070 // Tests construction of a structure containing a single matrix
TEST_F(SwiftShaderTest,MatrixInStruct)1071 TEST_F(SwiftShaderTest, MatrixInStruct)
1072 {
1073 	Initialize(2, false);
1074 
1075 	const std::string fs =
1076 	    R"(#version 100
1077 		precision mediump float;
1078 		struct S
1079 		{
1080 			mat2 rotation;
1081 		};
1082 		void main(void)
1083 		{
1084 			float angle = 1.0;
1085 			S(mat2(1.0, angle, 1.0, 1.0));
1086 		})";
1087 
1088 	MakeShader(fs, GL_FRAGMENT_SHADER);
1089 	EXPECT_NO_GL_ERROR();
1090 
1091 	Uninitialize();
1092 }
1093 
TEST_F(SwiftShaderTest,TestMat4Uniform)1094 TEST_F(SwiftShaderTest, TestMat4Uniform)
1095 {
1096 	Initialize(3, false);
1097 	const std::string vs = R"(#version 300 es
1098 	    precision highp float;
1099 	    uniform mat4 UniformMatrix;
1100 	    out vec4 color;
1101 	    void main()
1102         {
1103 		    const vec4 pos[] = vec4[](
1104 		        vec4( 1.,  1., .0, 1.),
1105 		        vec4(-1.,  1., .0, 1.),
1106 		        vec4(-1., -1., .0, 1.),
1107 		        vec4( 1.,  1., .0, 1.),
1108 		        vec4(-1., -1., .0, 1.),
1109 		        vec4( 1., -1., .0, 1.));
1110 		        gl_Position = pos[gl_VertexID];
1111 		      color = vec4(vec3(UniformMatrix[0].xyz), 1.);
1112 	    }
1113 	)";
1114 	const std::string ps = R"(#version 300 es
1115 	    precision  highp float;
1116 	    in vec4 color;
1117 	    out vec4 fragColor;
1118 	    void main()
1119         {
1120 		    fragColor = color;
1121 	    })";
1122 	const ProgramHandles ph = createProgram(vs, ps);
1123 
1124 	glUseProgram(ph.program);
1125 	GLint location = glGetUniformLocation(ph.program, "UniformMatrix");
1126 	ASSERT_NE(-1, location);
1127 	constexpr float unit_mat[] = {
1128 		1., 0., 0., 0.,
1129 		0., 1., 0., 0.,
1130 		0., 0., 1., 0.,
1131 		0., 0., 0., 1.
1132 	};
1133 	glUniformMatrix4fv(location, 1, GL_FALSE, unit_mat);
1134 	glClearColor(0.0, 0.0, 0.0, 1.0);
1135 	glClear(GL_COLOR_BUFFER_BIT);
1136 	GLuint dummyvao = GL_NONE;
1137 	glGenVertexArrays(1, &dummyvao);
1138 	glBindVertexArray(dummyvao);
1139 	glDrawArrays(GL_TRIANGLES, 0, 6);
1140 
1141 	EXPECT_NO_GL_ERROR();
1142 
1143 	unsigned char red[4] = { 255, 0, 0, 255 };
1144 	expectFramebufferColor(red);
1145 
1146 	Uninitialize();
1147 }
1148 
1149 // Test sampling from a sampler in a struct as a function argument
TEST_F(SwiftShaderTest,SamplerArrayInStructArrayAsFunctionArg)1150 TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg)
1151 {
1152 	Initialize(3, false);
1153 
1154 	GLuint tex = 1;
1155 	glBindTexture(GL_TEXTURE_2D, tex);
1156 	EXPECT_NO_GL_ERROR();
1157 
1158 	unsigned char green[4] = { 0, 255, 0, 255 };
1159 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
1160 	EXPECT_NO_GL_ERROR();
1161 
1162 	const std::string vs =
1163 	    R"(#version 300 es
1164 		in vec4 position;
1165 		void main()
1166 		{
1167 			gl_Position = vec4(position.xy, 0.0, 1.0);
1168 		})";
1169 
1170 	const std::string fs =
1171 	    R"(#version 300 es
1172 		precision mediump float;
1173 		struct SamplerStruct{ sampler2D tex[2]; };
1174 		vec4 doSample(in SamplerStruct s[2])
1175 		{
1176 			return texture(s[1].tex[1], vec2(0.0));
1177 		}
1178 		uniform SamplerStruct samplerStruct[2];
1179 		out vec4 fragColor;
1180 		void main()
1181 		{
1182 			fragColor = doSample(samplerStruct);
1183 		})";
1184 
1185 	const ProgramHandles ph = createProgram(vs, fs);
1186 
1187 	glUseProgram(ph.program);
1188 	GLint location = glGetUniformLocation(ph.program, "samplerStruct[1].tex[1]");
1189 	ASSERT_NE(-1, location);
1190 	glUniform1i(location, 0);
1191 
1192 	glClearColor(0.0, 0.0, 0.0, 0.0);
1193 	glClear(GL_COLOR_BUFFER_BIT);
1194 	EXPECT_NO_GL_ERROR();
1195 
1196 	drawQuad(ph.program, "samplerStruct[1].tex[1]");
1197 
1198 	deleteProgram(ph);
1199 
1200 	expectFramebufferColor(green);
1201 
1202 	EXPECT_NO_GL_ERROR();
1203 
1204 	Uninitialize();
1205 }
1206 
1207 // Test sampling from a sampler in a struct as a function argument
TEST_F(SwiftShaderTest,AtanCornerCases)1208 TEST_F(SwiftShaderTest, AtanCornerCases)
1209 {
1210 	Initialize(3, false);
1211 
1212 	const std::string vs =
1213 	    R"(#version 300 es
1214 		in vec4 position;
1215 		void main()
1216 		{
1217 			gl_Position = vec4(position.xy, 0.0, 1.0);
1218 		})";
1219 
1220 	const std::string fs =
1221 	    R"(#version 300 es
1222 		precision mediump float;
1223 		const float kPI = 3.14159265358979323846;
1224 		uniform float positive_value;
1225 		uniform float negative_value;
1226 		out vec4 fragColor;
1227 		void main()
1228 		{
1229 			// Should yield vec4(0, pi, pi/2, -pi/2)
1230 			vec4 result = atan(vec4(0.0, 0.0, positive_value, negative_value),
1231 			                   vec4(positive_value, negative_value, 0.0, 0.0));
1232 			fragColor = (result / vec4(kPI)) + vec4(0.5, -0.5, 0.0, 1.0) + vec4(0.5 / 255.0);
1233 		})";
1234 
1235 	const ProgramHandles ph = createProgram(vs, fs);
1236 
1237 	glUseProgram(ph.program);
1238 	GLint positive_value = glGetUniformLocation(ph.program, "positive_value");
1239 	ASSERT_NE(-1, positive_value);
1240 	GLint negative_value = glGetUniformLocation(ph.program, "negative_value");
1241 	ASSERT_NE(-1, negative_value);
1242 
1243 	float value = 1.0f;
1244 	glUniform1fv(positive_value, 1, &value);
1245 	value = -1.0f;
1246 	glUniform1fv(negative_value, 1, &value);
1247 
1248 	glClearColor(0.0, 0.0, 0.0, 0.0);
1249 	glClear(GL_COLOR_BUFFER_BIT);
1250 	EXPECT_NO_GL_ERROR();
1251 
1252 	drawQuad(ph.program, nullptr);
1253 
1254 	deleteProgram(ph);
1255 
1256 	unsigned char grey[4] = { 128, 128, 128, 128 };
1257 	expectFramebufferColor(grey);
1258 
1259 	EXPECT_NO_GL_ERROR();
1260 
1261 	Uninitialize();
1262 }
1263 
TEST_F(SwiftShaderTest,TransformFeedback_DrawArraysInstanced)1264 TEST_F(SwiftShaderTest, TransformFeedback_DrawArraysInstanced)
1265 {
1266 	Initialize(3, false);
1267 
1268 	std::string fs =
1269 	    R"(#version 300 es
1270 		in mediump vec2 vary;
1271 		out mediump vec4 color;
1272 		void main()
1273 		{
1274 			color = vec4(vary, 0.0, 1.0);
1275 		})";
1276 	std::string vs =
1277 	    R"(#version 300 es
1278 		layout(location=0) in mediump vec2 pos;
1279 		out mediump vec2 vary;
1280 		void main()
1281 		{
1282 			vary = pos;
1283 			gl_Position = vec4(pos, 0.0, 1.0);
1284 		})";
1285 
1286 	GLuint vert = MakeShader(vs, GL_VERTEX_SHADER);
1287 	GLuint frag = MakeShader(fs, GL_FRAGMENT_SHADER);
1288 	GLuint program = MakeProgram(vert, frag);
1289 	LinkProgram(program);
1290 	glBeginTransformFeedback(GL_POINTS);
1291 	glDrawArraysInstanced(GL_POINTS, 0, 1, 1);
1292 
1293 	Uninitialize();
1294 }
1295 
TEST_F(SwiftShaderTest,TransformFeedback_BadViewport)1296 TEST_F(SwiftShaderTest, TransformFeedback_BadViewport)
1297 {
1298 	Initialize(3, false);
1299 
1300 	GLuint tfBuffer;
1301 	glGenBuffers(1, &tfBuffer);
1302 	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfBuffer);
1303 	glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1 << 12, nullptr, GL_STATIC_DRAW);
1304 
1305 	std::string vsSource =
1306 	    R"(#version 300 es
1307 		in vec4 a_position;
1308 		void main()
1309 		{
1310 			gl_Position = a_position;
1311 		})";
1312 	std::string fsSource =
1313 	    R"(#version 300 es
1314 		precision highp float;
1315 		out vec4 my_FragColor;
1316 		void main()
1317 		{
1318 			my_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
1319 		})";
1320 
1321 	const char *varyings[] = { "gl_Position" };
1322 
1323 	GLuint vs = MakeShader(vsSource, GL_VERTEX_SHADER);
1324 	GLuint fs = MakeShader(fsSource, GL_FRAGMENT_SHADER);
1325 	GLuint program = MakeProgram(vs, fs);
1326 
1327 	glTransformFeedbackVaryings(program, 1,
1328 	                            &varyings[0], GL_INTERLEAVED_ATTRIBS);
1329 	LinkProgram(program);
1330 	glUseProgram(program);
1331 
1332 	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer);
1333 	glBeginTransformFeedback(GL_TRIANGLES);
1334 
1335 	GLuint primitivesWrittenQuery = 0;
1336 	glGenQueries(1, &primitivesWrittenQuery);
1337 	glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery);
1338 
1339 	glViewport(0, 10000000, 300, 300);
1340 
1341 	GLint positionLocation = glGetAttribLocation(program, "a_position");
1342 	GLfloat quadVertices[] = {
1343 		-1.0f,
1344 		1.0f,
1345 		0.5f,
1346 		-1.0f,
1347 		-1.0f,
1348 		0.5f,
1349 		1.0f,
1350 		-1.0f,
1351 		0.5f,
1352 		-1.0f,
1353 		1.0f,
1354 		0.5f,
1355 		1.0f,
1356 		-1.0f,
1357 		0.5f,
1358 		1.0f,
1359 		1.0f,
1360 		0.5f,
1361 	};
1362 
1363 	glBindBuffer(GL_ARRAY_BUFFER, 0);
1364 
1365 	glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, &quadVertices[0]);
1366 
1367 	glDrawArrays(GL_TRIANGLES, 0, 6);
1368 	glDisableVertexAttribArray(positionLocation);
1369 	glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
1370 
1371 	glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
1372 	glEndTransformFeedback();
1373 
1374 	GLuint primitivesWritten = 0;
1375 	glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten);
1376 	EXPECT_NO_GL_ERROR();
1377 
1378 	EXPECT_EQ(2u, primitivesWritten);
1379 
1380 	Uninitialize();
1381 }
1382 
1383 // Test conditions that should result in a GL_OUT_OF_MEMORY and not crash
TEST_F(SwiftShaderTest,OutOfMemory)1384 TEST_F(SwiftShaderTest, OutOfMemory)
1385 {
1386 	// Image sizes are assumed to fit in a 32-bit signed integer by the renderer,
1387 	// so test that we can't create a 2+ GiB image.
1388 	{
1389 		Initialize(3, false);
1390 
1391 		GLuint tex = 1;
1392 		glBindTexture(GL_TEXTURE_3D, tex);
1393 
1394 		const int width = 0xC2;
1395 		const int height = 0x541;
1396 		const int depth = 0x404;
1397 		glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA, GL_FLOAT, nullptr);
1398 		EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, glGetError());
1399 
1400 		// b/145229887: Allocating an image of exactly 1 GiB should succeed.
1401 		const int width8k = 8192;
1402 		const int height8k = 8192;
1403 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width8k, height8k, 0, GL_RGBA, GL_FLOAT, nullptr);
1404 		EXPECT_NO_GL_ERROR();
1405 
1406 		// The spec states that the GL is in an undefined state when GL_OUT_OF_MEMORY
1407 		// is returned, and the context must be recreated before attempting more rendering.
1408 		Uninitialize();
1409 	}
1410 }
1411 
TEST_F(SwiftShaderTest,ViewportBounds)1412 TEST_F(SwiftShaderTest, ViewportBounds)
1413 {
1414 	auto doRenderWithViewportSettings = [&](GLint x, GLint y, GLsizei w, GLsizei h) {
1415 		Initialize(3, false);
1416 
1417 		std::string vs =
1418 		    R"(#version 300 es
1419 			in vec4 position;
1420 			out float unfoldable;
1421 			void main()
1422 			{
1423 			    unfoldable = position.x;
1424 			    gl_Position = vec4(position.xy, 0.0, 1.0);
1425 			})";
1426 
1427 		std::string fs =
1428 		    R"(#version 300 es
1429 			precision mediump float;
1430 			in float unfoldable;
1431 			out vec4 fragColor;
1432 			void main()
1433 			{
1434 			    fragColor = vec4(1.0, 1.0, 1.0, 1.0);
1435 			})";
1436 
1437 		const ProgramHandles ph = createProgram(vs, fs);
1438 
1439 		glUseProgram(ph.program);
1440 
1441 		glViewport(x, y, w, h);
1442 
1443 		drawQuad(ph.program);
1444 		EXPECT_NO_GL_ERROR();
1445 
1446 		deleteProgram(ph);
1447 		Uninitialize();
1448 	};
1449 
1450 	GLsizei w = 100;
1451 	GLsizei h = 100;
1452 	GLint minPos = -2000;
1453 
1454 	doRenderWithViewportSettings(0, 0, 0, 0);
1455 	doRenderWithViewportSettings(0, 0, w, h);
1456 
1457 	// Negative positions
1458 	doRenderWithViewportSettings(minPos, 0, w, h);
1459 	doRenderWithViewportSettings(0, minPos, w, h);
1460 	doRenderWithViewportSettings(minPos, minPos, w, h);
1461 }
1462 
1463 // Test using TexImage2D to define a rectangle texture
1464 
TEST_F(SwiftShaderTest,TextureRectangle_TexImage2D)1465 TEST_F(SwiftShaderTest, TextureRectangle_TexImage2D)
1466 {
1467 	Initialize(2, false);
1468 
1469 	GLuint tex = 1;
1470 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1471 
1472 	// Defining level 0 is allowed
1473 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1474 	EXPECT_NO_GL_ERROR();
1475 
1476 	// Defining level other than 0 is not allowed
1477 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1478 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1479 
1480 	GLint maxSize = 0;
1481 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
1482 
1483 	// Defining a texture of the max size is allowed
1484 	{
1485 		glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1486 		GLenum error = glGetError();
1487 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
1488 	}
1489 
1490 	// Defining a texture larger than the max size is disallowed
1491 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize + 1, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1492 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1493 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1494 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1495 
1496 	Uninitialize();
1497 }
1498 
1499 // Test using CompressedTexImage2D cannot be used on a retangle texture
TEST_F(SwiftShaderTest,TextureRectangle_CompressedTexImage2DDisallowed)1500 TEST_F(SwiftShaderTest, TextureRectangle_CompressedTexImage2DDisallowed)
1501 {
1502 	Initialize(2, false);
1503 
1504 	const char data[128] = { 0 };
1505 
1506 	// Control case: 2D texture
1507 	{
1508 		GLuint tex = 1;
1509 		glBindTexture(GL_TEXTURE_2D, tex);
1510 		glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
1511 		EXPECT_NO_GL_ERROR();
1512 	}
1513 
1514 	// Rectangle textures cannot be compressed
1515 	{
1516 		GLuint tex = 2;
1517 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1518 		glCompressedTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
1519 		EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1520 	}
1521 
1522 	Uninitialize();
1523 }
1524 
1525 // Test using TexStorage2D to define a rectangle texture (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_TexStorage2D)1526 TEST_F(SwiftShaderTest, TextureRectangle_TexStorage2D)
1527 {
1528 	Initialize(3, false);
1529 
1530 	// Defining one level is allowed
1531 	{
1532 		GLuint tex = 1;
1533 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1534 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, 16, 16);
1535 		EXPECT_NO_GL_ERROR();
1536 	}
1537 
1538 	// Having more than one level is not allowed
1539 	{
1540 		GLuint tex = 2;
1541 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1542 		// Use 5 levels because the EXT_texture_storage extension requires a mip chain all the way
1543 		// to a 1x1 mip.
1544 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 5, GL_RGBA8UI, 16, 16);
1545 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1546 	}
1547 
1548 	GLint maxSize = 0;
1549 	glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize);
1550 
1551 	// Defining a texture of the max size is allowed but still allow for OOM
1552 	{
1553 		GLuint tex = 3;
1554 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1555 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize);
1556 		GLenum error = glGetError();
1557 		ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY);
1558 	}
1559 
1560 	// Defining a texture larger than the max size is disallowed
1561 	{
1562 		GLuint tex = 4;
1563 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1564 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize + 1, maxSize);
1565 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1566 		glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize + 1);
1567 		EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1568 	}
1569 
1570 	// Compressed formats are disallowed
1571 	GLuint tex = 5;
1572 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1573 	glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16);
1574 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1575 
1576 	Uninitialize();
1577 }
1578 
1579 // Test validation of disallowed texture parameters
TEST_F(SwiftShaderTest,TextureRectangle_TexParameterRestriction)1580 TEST_F(SwiftShaderTest, TextureRectangle_TexParameterRestriction)
1581 {
1582 	Initialize(3, false);
1583 
1584 	GLuint tex = 1;
1585 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1586 
1587 	// Only wrap mode CLAMP_TO_EDGE is supported
1588 	// Wrap S
1589 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1590 	EXPECT_NO_GL_ERROR();
1591 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT);
1592 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1593 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
1594 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1595 
1596 	// Wrap T
1597 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1598 	EXPECT_NO_GL_ERROR();
1599 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT);
1600 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1601 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
1602 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1603 
1604 	// Min filter has to be nearest or linear
1605 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1606 	EXPECT_NO_GL_ERROR();
1607 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1608 	EXPECT_NO_GL_ERROR();
1609 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1610 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1611 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
1612 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1613 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1614 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1615 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
1616 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1617 
1618 	// Base level has to be 0
1619 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0);
1620 	EXPECT_NO_GL_ERROR();
1621 	glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 1);
1622 	EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, glGetError());
1623 
1624 	Uninitialize();
1625 }
1626 
1627 // Test validation of "level" in FramebufferTexture2D
TEST_F(SwiftShaderTest,TextureRectangle_FramebufferTexture2DLevel)1628 TEST_F(SwiftShaderTest, TextureRectangle_FramebufferTexture2DLevel)
1629 {
1630 	Initialize(3, false);
1631 
1632 	GLuint tex = 1;
1633 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1634 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1635 	EXPECT_NO_GL_ERROR();
1636 
1637 	GLuint fbo = 1;
1638 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1639 
1640 	// Using level 0 of a rectangle texture is valid.
1641 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1642 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1643 	EXPECT_NO_GL_ERROR();
1644 
1645 	// Setting level != 0 is invalid
1646 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 1);
1647 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1648 
1649 	Uninitialize();
1650 }
1651 
1652 // Test sampling from a rectangle texture
TEST_F(SwiftShaderTest,TextureRectangle_SamplingFromRectangle)1653 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle)
1654 {
1655 	Initialize(3, false);
1656 
1657 	GLuint tex = 1;
1658 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1659 	EXPECT_NO_GL_ERROR();
1660 
1661 	unsigned char green[4] = { 0, 255, 0, 255 };
1662 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
1663 	EXPECT_NO_GL_ERROR();
1664 
1665 	const std::string vs =
1666 	    R"(attribute vec4 position;
1667 		void main()
1668 		{
1669 		    gl_Position = vec4(position.xy, 0.0, 1.0);
1670 		})";
1671 
1672 	const std::string fs =
1673 	    R"(#extension GL_ARB_texture_rectangle : require
1674 		precision mediump float;
1675 		uniform sampler2DRect tex;
1676 		void main()
1677 		{
1678 		    gl_FragColor = texture2DRect(tex, vec2(0, 0));
1679 		})";
1680 
1681 	const ProgramHandles ph = createProgram(vs, fs);
1682 
1683 	glUseProgram(ph.program);
1684 	GLint location = glGetUniformLocation(ph.program, "tex");
1685 	ASSERT_NE(-1, location);
1686 	glUniform1i(location, 0);
1687 
1688 	glClearColor(0.0, 0.0, 0.0, 0.0);
1689 	glClear(GL_COLOR_BUFFER_BIT);
1690 	EXPECT_NO_GL_ERROR();
1691 
1692 	drawQuad(ph.program, "tex");
1693 
1694 	deleteProgram(ph);
1695 
1696 	expectFramebufferColor(green);
1697 
1698 	EXPECT_NO_GL_ERROR();
1699 
1700 	Uninitialize();
1701 }
1702 
1703 // Test sampling from a rectangle texture
TEST_F(SwiftShaderTest,TextureRectangle_SamplingFromRectangleESSL3)1704 TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3)
1705 {
1706 	Initialize(3, false);
1707 
1708 	GLuint tex = 1;
1709 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1710 	EXPECT_NO_GL_ERROR();
1711 
1712 	unsigned char green[4] = { 0, 255, 0, 255 };
1713 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green);
1714 	EXPECT_NO_GL_ERROR();
1715 
1716 	const std::string vs =
1717 	    R"(#version 300 es
1718 		in vec4 position;
1719 		void main()
1720 		{
1721 		    gl_Position = vec4(position.xy, 0.0, 1.0);
1722 		})";
1723 
1724 	const std::string fs =
1725 	    R"(#version 300 es
1726 		#extension GL_ARB_texture_rectangle : require
1727 		precision mediump float;
1728 		uniform sampler2DRect tex;
1729 		out vec4 fragColor;
1730 		void main()
1731 		{
1732 		    fragColor = texture(tex, vec2(0, 0));
1733 		})";
1734 
1735 	const ProgramHandles ph = createProgram(vs, fs);
1736 
1737 	glUseProgram(ph.program);
1738 	GLint location = glGetUniformLocation(ph.program, "tex");
1739 	ASSERT_NE(-1, location);
1740 	glUniform1i(location, 0);
1741 
1742 	glClearColor(0.0, 0.0, 0.0, 0.0);
1743 	glClear(GL_COLOR_BUFFER_BIT);
1744 	EXPECT_NO_GL_ERROR();
1745 
1746 	drawQuad(ph.program, "tex");
1747 
1748 	deleteProgram(ph);
1749 
1750 	expectFramebufferColor(green);
1751 
1752 	EXPECT_NO_GL_ERROR();
1753 
1754 	Uninitialize();
1755 }
1756 
1757 // Test attaching a rectangle texture and rendering to it.
TEST_F(SwiftShaderTest,TextureRectangle_RenderToRectangle)1758 TEST_F(SwiftShaderTest, TextureRectangle_RenderToRectangle)
1759 {
1760 	Initialize(3, false);
1761 
1762 	GLuint tex = 1;
1763 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1764 	unsigned char black[4] = { 0, 0, 0, 255 };
1765 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
1766 
1767 	GLuint fbo = 1;
1768 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1769 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1770 	EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1771 	EXPECT_NO_GL_ERROR();
1772 
1773 	// Clearing a texture is just as good as checking we can render to it, right?
1774 	glClearColor(0.0, 1.0, 0.0, 1.0);
1775 	glClear(GL_COLOR_BUFFER_BIT);
1776 
1777 	unsigned char green[4] = { 0, 255, 0, 255 };
1778 	expectFramebufferColor(green);
1779 	EXPECT_NO_GL_ERROR();
1780 
1781 	Uninitialize();
1782 }
1783 
TEST_F(SwiftShaderTest,TextureRectangle_DefaultSamplerParameters)1784 TEST_F(SwiftShaderTest, TextureRectangle_DefaultSamplerParameters)
1785 {
1786 	Initialize(3, false);
1787 
1788 	GLuint tex = 1;
1789 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1790 
1791 	GLint minFilter = 0;
1792 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, &minFilter);
1793 	EXPECT_GLENUM_EQ(GL_LINEAR, minFilter);
1794 
1795 	GLint wrapS = 0;
1796 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, &wrapS);
1797 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapS);
1798 
1799 	GLint wrapT = 0;
1800 	glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, &wrapT);
1801 	EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapT);
1802 
1803 	Uninitialize();
1804 }
1805 
1806 // Test glCopyTexImage with rectangle textures (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_CopyTexImage)1807 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexImage)
1808 {
1809 	Initialize(3, false);
1810 
1811 	GLuint tex = 1;
1812 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1813 
1814 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1815 	glClearColor(0, 1, 0, 1);
1816 	glClear(GL_COLOR_BUFFER_BIT);
1817 	EXPECT_NO_GL_ERROR();
1818 
1819 	// Error case: level != 0
1820 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8, 0, 0, 1, 1, 0);
1821 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1822 
1823 	// level = 0 works and defines the texture.
1824 	glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 0, 0, 1, 1, 0);
1825 	EXPECT_NO_GL_ERROR();
1826 
1827 	GLuint fbo = 1;
1828 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1829 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1830 
1831 	unsigned char green[4] = { 0, 255, 0, 255 };
1832 	expectFramebufferColor(green);
1833 	EXPECT_NO_GL_ERROR();
1834 
1835 	Uninitialize();
1836 }
1837 
1838 // Test glCopyTexSubImage with rectangle textures (ES3)
TEST_F(SwiftShaderTest,TextureRectangle_CopyTexSubImage)1839 TEST_F(SwiftShaderTest, TextureRectangle_CopyTexSubImage)
1840 {
1841 	Initialize(3, false);
1842 
1843 	GLuint tex = 1;
1844 	glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex);
1845 	unsigned char black[4] = { 0, 0, 0, 255 };
1846 	glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
1847 
1848 	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1849 	glClearColor(0, 1, 0, 1);
1850 	glClear(GL_COLOR_BUFFER_BIT);
1851 	EXPECT_NO_GL_ERROR();
1852 
1853 	// Error case: level != 0
1854 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, 0, 0, 0, 0, 1, 1);
1855 	EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError());
1856 
1857 	// level = 0 works and defines the texture.
1858 	glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 0, 0, 1, 1);
1859 	EXPECT_NO_GL_ERROR();
1860 
1861 	GLuint fbo = 1;
1862 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1863 	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0);
1864 
1865 	unsigned char green[4] = { 0, 255, 0, 255 };
1866 	expectFramebufferColor(green);
1867 	EXPECT_NO_GL_ERROR();
1868 
1869 	Uninitialize();
1870 }
1871 
TEST_F(SwiftShaderTest,BlitTest)1872 TEST_F(SwiftShaderTest, BlitTest)
1873 {
1874 	Initialize(3, false);
1875 
1876 	GLuint fbos[] = { 0, 0 };
1877 	glGenFramebuffers(2, fbos);
1878 
1879 	glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]);
1880 	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]);
1881 
1882 	GLuint textures[] = { 0, 0 };
1883 	glGenTextures(2, textures);
1884 
1885 	glBindTexture(GL_TEXTURE_2D, textures[0]);
1886 	unsigned char red[4][4] = {
1887 		{ 255, 0, 0, 255 },
1888 		{ 255, 0, 0, 255 },
1889 		{ 255, 0, 0, 255 },
1890 		{ 255, 0, 0, 255 }
1891 	};
1892 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red);
1893 	EXPECT_NO_GL_ERROR();
1894 
1895 	glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
1896 	EXPECT_NO_GL_ERROR();
1897 
1898 	glBindTexture(GL_TEXTURE_2D, textures[1]);
1899 	unsigned char black[4][4] = {
1900 		{ 0, 0, 0, 255 },
1901 		{ 0, 0, 0, 255 },
1902 		{ 0, 0, 0, 255 },
1903 		{ 0, 0, 0, 255 }
1904 	};
1905 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, black);
1906 	EXPECT_NO_GL_ERROR();
1907 	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
1908 
1909 	// Test that glBlitFramebuffer works as expected for the normal case.
1910 	glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1911 	EXPECT_NO_GL_ERROR();
1912 	EXPECT_EQ(red[0][1], black[0][1]);
1913 
1914 	// Check that glBlitFramebuffer doesn't crash with ugly input.
1915 	const int big = (int)2e9;
1916 	const int small = 200;
1917 	const int neg_small = -small;
1918 	const int neg_big = -big;
1919 	int max = 0x7fffffff;
1920 	int data[][8] = {
1921 		// sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1
1922 		{ 0, 0, 0, 0, 0, 0, 0, 0 },
1923 		{ -1, -1, -1, -1, -1, -1, -1, -1 },
1924 		{ 1, 1, 1, 1, 1, 1, 1, 1 },
1925 		{ -1, -1, 1, 1, -1, -1, 1, 1 },
1926 		{ 0, 0, 127, (int)2e9, 10, 10, 200, 200 },
1927 		{ -2, -2, 127, 2147483470, 10, 10, 200, 200 },
1928 		{ big, small, small, big, big, big, small, small },
1929 		{ neg_small, small, neg_small, neg_small, neg_small, big, small },
1930 		{ big, big - 1, big - 2, big - 3, big - 4, big - 5, big - 6, big - 7 },
1931 		{ big, neg_big, neg_big, big, small, big, 0, neg_small },
1932 		{ 323479648, 21931, 1769809195, 32733, 0, 0, -161640504, 32766 },
1933 		{ 0, 0, max, max, 0, 0, 8, 8 },
1934 		{ 0, 0, 8, 8, 0, 0, max, max },
1935 		{ 0, 0, max, max, 0, 0, max, max },
1936 		{ -1, -1, max, max, 0, 0, 8, 8 },
1937 		{ 0, 0, 8, 8, -1, -1, max, max },
1938 		{ -1, -1, max, max, -1, -1, max, max },
1939 		{ -max - 1, -max - 1, max, max, -max - 1, -max - 1, max, max }
1940 	};
1941 
1942 	for(int i = 0; i < (int)(sizeof(data) / sizeof(data[0])); i++)
1943 	{
1944 		glBlitFramebuffer(
1945 		    data[i][0], data[i][1], data[i][2], data[i][3],
1946 		    data[i][4], data[i][5], data[i][6], data[i][7],
1947 		    GL_COLOR_BUFFER_BIT, GL_NEAREST);
1948 		// Ignore error state, just make sure that we don't crash on these inputs.
1949 	}
1950 
1951 	// Clear the error state before uninitializing test.
1952 	glGetError();
1953 
1954 	glDeleteFramebuffers(2, fbos);
1955 	glDeleteTextures(2, textures);
1956 	Uninitialize();
1957 }
1958 
TEST_F(SwiftShaderTest,InvalidEnum_TexImage2D)1959 TEST_F(SwiftShaderTest, InvalidEnum_TexImage2D)
1960 {
1961 	Initialize(3, false);
1962 
1963 	const GLenum invalidTarget = GL_TEXTURE_3D;
1964 
1965 	glTexImage2D(invalidTarget, 0, GL_R11F_G11F_B10F, 256, 256, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, nullptr);
1966 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1967 
1968 	float pixels[3] = { 0.0f, 0.0f, 0.0f };
1969 	glTexSubImage2D(invalidTarget, 0, 0, 0, 1, 1, GL_RGB, GL_FLOAT, pixels);
1970 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1971 
1972 	glCopyTexImage2D(invalidTarget, 0, GL_RGB, 2, 6, 8, 8, 0);
1973 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1974 
1975 	glCopyTexSubImage2D(invalidTarget, 0, 0, 0, 0, 0, 1, 1);
1976 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1977 
1978 	const char data[128] = { 0 };
1979 	glCompressedTexImage2D(invalidTarget, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data);
1980 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1981 
1982 	glCompressedTexSubImage2D(invalidTarget, 0, 0, 0, 0, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0);
1983 	EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError());
1984 
1985 	Uninitialize();
1986 }
1987 
TEST_F(SwiftShaderTest,CompilerLimits_DeepNestedIfs)1988 TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedIfs)
1989 {
1990 	std::string body = "return 1.0;";
1991 	for(int i = 0; i < 16; i++)
1992 	{
1993 		body = "  if (f > " + std::to_string(i * 0.1f) + ") {\n" + body + "}\n";
1994 	}
1995 
1996 	checkCompiles(
1997 	    "float F(float f) {\n" + body + "  return 0.0f;\n}\n");
1998 }
1999 
TEST_F(SwiftShaderTest,CompilerLimits_DeepNestedSwitches)2000 TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedSwitches)
2001 {
2002 	std::string body = "return 1.0;";
2003 	for(int i = 0; i < 16; i++)
2004 	{
2005 		body = "  switch (int(f)) {\n case 1:\n  f *= 2.0;\n" + body + "}\n";
2006 	}
2007 
2008 	checkCompiles("float F(float f) {\n" + body + "  return 0.0f;\n}\n");
2009 }
2010 
TEST_F(SwiftShaderTest,CompilerLimits_DeepNestedLoops)2011 TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedLoops)
2012 {
2013 	std::string loops = "f = f + f * 2.0;";
2014 	for(int i = 0; i < 16; i++)
2015 	{
2016 		auto it = "l" + std::to_string(i);
2017 		loops = "  for (int " + it + " = 0; " + it + " < i; " + it + "++) {\n" + loops + "}\n";
2018 	}
2019 
2020 	checkCompiles(
2021 	    "float F(float f) {\n"
2022 	    "  int i = (f > 0.0) ? 1 : 0;\n" +
2023 	    loops +
2024 	    "  return f;\n"
2025 	    "}\n");
2026 }
2027 
TEST_F(SwiftShaderTest,CompilerLimits_DeepNestedCalls)2028 TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedCalls)
2029 {
2030 	std::string funcs = "float E(float f) { return f * 2.0f; }\n";
2031 	std::string last = "E";
2032 	for(int i = 0; i < 16; i++)
2033 	{
2034 		std::string f = "C" + std::to_string(i);
2035 		funcs += "float " + f + "(float f) { return " + last + "(f) + 1.0f; }\n";
2036 		last = f;
2037 	}
2038 
2039 	checkCompiles(funcs +
2040 	              "float F(float f) { return " + last + "(f); }\n");
2041 }
2042 
TEST_F(SwiftShaderTest,CompilerLimits_ManyCallSites)2043 TEST_F(SwiftShaderTest, CompilerLimits_ManyCallSites)
2044 {
2045 	std::string calls;
2046 	for(int i = 0; i < 256; i++)
2047 	{
2048 		calls += "  f += C(f);\n";
2049 	}
2050 
2051 	checkCompiles(
2052 	    "float C(float f) { return f * 2.0f; }\n"
2053 	    "float F(float f) {\n" +
2054 	    calls + "  return f;\n}\n");
2055 }
2056 
TEST_F(SwiftShaderTest,CompilerLimits_DeepNestedCallsInUnusedFunction)2057 TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedCallsInUnusedFunction)
2058 {
2059 	std::string funcs = "float E(float f) { return f * 2.0f; }\n";
2060 	std::string last = "E";
2061 	for(int i = 0; i < 16; i++)
2062 	{
2063 		std::string f = "C" + std::to_string(i);
2064 		funcs += "float " + f + "(float f) { return " + last + "(f) + 1.0f; }\n";
2065 		last = f;
2066 	}
2067 
2068 	checkCompiles(funcs +
2069 	              "float F(float f) { return f; }\n");
2070 }
2071 
2072 // Test that the compiler correctly handles functions being stripped.
2073 // The frontend will strip the Dead functions, but may keep the their function
2074 // labels reserved. This produces labels that are greater than the number of
2075 // live functions.
TEST_F(SwiftShaderTest,CompilerLimits_SparseLabels)2076 TEST_F(SwiftShaderTest, CompilerLimits_SparseLabels)
2077 {
2078 	checkCompiles(
2079 	    R"(void Dead1() {}
2080 		void Dead2() {}
2081 		void Dead3() {}
2082 		void Dead4() {}
2083 		void Dead5() { Dead1(); Dead2(); Dead3(); Dead4(); }
2084 		float F(float f) { for(int i = 0; i < -1; ++i) { Dead5(); } return f; })");
2085 }
2086 
2087 // Test that the compiler doesn't compile arrays larger than
2088 // GL_MAX_{VERTEX/FRAGMENT}_UNIFORM_VECTOR.
TEST_F(SwiftShaderTest,CompilerLimits_ArraySize)2089 TEST_F(SwiftShaderTest, CompilerLimits_ArraySize)
2090 {
2091 	checkCompileFails(
2092 	    R"(uniform float u_var[100000000];
2093 		float F(float f) { return u_var[2]; })");
2094 	checkCompileFails(
2095 	    R"(struct structType { mediump sampler2D m0; mediump samplerCube m1; };
2096 		uniform structType u_var[100000000];
2097 		float F(float f) { return texture(u_var[2].m1, vec3(0.0)), vec4(0.26, 1.72, 0.60, 0.12).x; })");
2098 }
2099 
2100 // Test that the compiler rejects negations of things that can't be negated.
TEST_F(SwiftShaderTest,BadNegation)2101 TEST_F(SwiftShaderTest, BadNegation)
2102 {
2103 	checkCompileFails(
2104 	    R"(uniform samplerCube m;
2105 		float F (float f) { vec4 ret = texture(-m, vec3(f)); return ret.x; })");
2106 	checkCompileFails(
2107 	    R"(uniform sampler2D m[9];
2108 		vec4 G (sampler2D X[9]) { return texture(X[0], vec2(0.0f)); }
2109 		float F (float f) { vec4 ret = G(-m); return ret.x; })");
2110 	checkCompileFails(
2111 	    R"(struct structType { int a; float b; };
2112 		uniform structType m;
2113 		float F (float f) { structType n = -m; return f; })");
2114 	checkCompileFails(
2115 	    R"(struct structType { int a; float b; };
2116 		uniform structType m[4];
2117 		float F (float f) { structType n[4] = -m; return f; })");
2118 	checkCompileFails(
2119 	    R"(uniform float m[4];
2120 		float G (float f[4]) { return f[0]; }
2121 		float F (float f) { return G(-m); })");
2122 }
2123 
TEST_F(SwiftShaderTest,SwitchDefaultOnly)2124 TEST_F(SwiftShaderTest, SwitchDefaultOnly)
2125 {
2126 	checkCompiles(R"(
2127 		float F (float f) {
2128 			switch (0u) {
2129 			default:
2130 				return -f;
2131 			}
2132 			return f;
2133 		})");
2134 }
2135 
2136 #ifndef EGL_ANGLE_iosurface_client_buffer
2137 #	define EGL_ANGLE_iosurface_client_buffer 1
2138 #	define EGL_IOSURFACE_ANGLE 0x3454
2139 #	define EGL_IOSURFACE_PLANE_ANGLE 0x345A
2140 #	define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
2141 #	define EGL_TEXTURE_TYPE_ANGLE 0x345C
2142 #	define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
2143 #endif /* EGL_ANGLE_iosurface_client_buffer */
2144 
2145 #if defined(__APPLE__)
2146 #	include <CoreFoundation/CoreFoundation.h>
2147 #	include <IOSurface/IOSurface.h>
2148 
2149 namespace {
AddIntegerValue(CFMutableDictionaryRef dictionary,const CFStringRef key,int32_t value)2150 void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value)
2151 {
2152 	CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value);
2153 	CFDictionaryAddValue(dictionary, key, number);
2154 	CFRelease(number);
2155 }
2156 }  // anonymous namespace
2157 
2158 class EGLClientBufferWrapper
2159 {
2160 public:
EGLClientBufferWrapper(int width=1,int height=1)2161 	EGLClientBufferWrapper(int width = 1, int height = 1)
2162 	{
2163 		// Create a 1 by 1 BGRA8888 IOSurface
2164 		ioSurface = nullptr;
2165 
2166 		CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
2167 		    kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
2168 		AddIntegerValue(dict, kIOSurfaceWidth, width);
2169 		AddIntegerValue(dict, kIOSurfaceHeight, height);
2170 		AddIntegerValue(dict, kIOSurfacePixelFormat, 'BGRA');
2171 		AddIntegerValue(dict, kIOSurfaceBytesPerElement, 4);
2172 
2173 		ioSurface = IOSurfaceCreate(dict);
2174 		CFRelease(dict);
2175 
2176 		EXPECT_NE(nullptr, ioSurface);
2177 	}
2178 
~EGLClientBufferWrapper()2179 	~EGLClientBufferWrapper()
2180 	{
2181 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
2182 
2183 		CFRelease(ioSurface);
2184 	}
2185 
getClientBuffer() const2186 	EGLClientBuffer getClientBuffer() const
2187 	{
2188 		return ioSurface;
2189 	}
2190 
lockColor()2191 	const unsigned char *lockColor()
2192 	{
2193 		IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
2194 		return reinterpret_cast<const unsigned char *>(IOSurfaceGetBaseAddress(ioSurface));
2195 	}
2196 
unlockColor()2197 	void unlockColor()
2198 	{
2199 		IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr);
2200 	}
2201 
writeColor(void * data,size_t dataSize)2202 	void writeColor(void *data, size_t dataSize)
2203 	{
2204 		// Write the data to the IOSurface
2205 		IOSurfaceLock(ioSurface, 0, nullptr);
2206 		memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize);
2207 		IOSurfaceUnlock(ioSurface, 0, nullptr);
2208 	}
2209 
2210 private:
2211 	IOSurfaceRef ioSurface;
2212 };
2213 
2214 #else  // __APPLE__
2215 
2216 class EGLClientBufferWrapper
2217 {
2218 public:
EGLClientBufferWrapper(int width=1,int height=1)2219 	EGLClientBufferWrapper(int width = 1, int height = 1)
2220 	{
2221 		clientBuffer = new unsigned char[4 * width * height];
2222 	}
2223 
~EGLClientBufferWrapper()2224 	~EGLClientBufferWrapper()
2225 	{
2226 		delete[] clientBuffer;
2227 	}
2228 
getClientBuffer() const2229 	EGLClientBuffer getClientBuffer() const
2230 	{
2231 		return clientBuffer;
2232 	}
2233 
lockColor()2234 	const unsigned char *lockColor()
2235 	{
2236 		return clientBuffer;
2237 	}
2238 
unlockColor()2239 	void unlockColor()
2240 	{
2241 	}
2242 
writeColor(void * data,size_t dataSize)2243 	void writeColor(void *data, size_t dataSize)
2244 	{
2245 		memcpy(clientBuffer, data, dataSize);
2246 	}
2247 
2248 private:
2249 	unsigned char *clientBuffer;
2250 };
2251 
2252 #endif
2253 
2254 class IOSurfaceClientBufferTest : public SwiftShaderTest
2255 {
2256 protected:
createIOSurfacePbuffer(EGLClientBuffer buffer,EGLint width,EGLint height,EGLint plane,GLenum internalFormat,GLenum type) const2257 	EGLSurface createIOSurfacePbuffer(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type) const
2258 	{
2259 		// Make a PBuffer from it using the EGL_ANGLE_iosurface_client_buffer extension
2260 		const EGLint attribs[] = {
2261 			EGL_WIDTH,
2262 			width,
2263 			EGL_HEIGHT,
2264 			height,
2265 			EGL_IOSURFACE_PLANE_ANGLE,
2266 			plane,
2267 			EGL_TEXTURE_TARGET,
2268 			EGL_TEXTURE_RECTANGLE_ANGLE,
2269 			EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2270 			(EGLint)internalFormat,
2271 			EGL_TEXTURE_FORMAT,
2272 			EGL_TEXTURE_RGBA,
2273 			EGL_TEXTURE_TYPE_ANGLE,
2274 			(EGLint)type,
2275 			EGL_NONE,
2276 			EGL_NONE,
2277 		};
2278 
2279 		EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, buffer, getConfig(), attribs);
2280 		EXPECT_NE(EGL_NO_SURFACE, pbuffer);
2281 		return pbuffer;
2282 	}
2283 
bindIOSurfaceToTexture(EGLClientBuffer buffer,EGLint width,EGLint height,EGLint plane,GLenum internalFormat,GLenum type,EGLSurface * pbuffer,GLuint * texture) const2284 	void bindIOSurfaceToTexture(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type, EGLSurface *pbuffer, GLuint *texture) const
2285 	{
2286 		*pbuffer = createIOSurfacePbuffer(buffer, width, height, plane, internalFormat, type);
2287 
2288 		// Bind the pbuffer
2289 		glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texture);
2290 		EGLBoolean result = eglBindTexImage(getDisplay(), *pbuffer, EGL_BACK_BUFFER);
2291 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2292 		EXPECT_NO_EGL_ERROR();
2293 	}
2294 
doClear(GLenum internalFormat,bool clearToZero)2295 	void doClear(GLenum internalFormat, bool clearToZero)
2296 	{
2297 		if(internalFormat == GL_R16UI)
2298 		{
2299 			GLuint color = clearToZero ? 0 : 257;
2300 			glClearBufferuiv(GL_COLOR, 0, &color);
2301 			EXPECT_NO_GL_ERROR();
2302 		}
2303 		else
2304 		{
2305 			glClearColor(clearToZero ? 0.0f : 1.0f / 255.0f,
2306 			             clearToZero ? 0.0f : 2.0f / 255.0f,
2307 			             clearToZero ? 0.0f : 3.0f / 255.0f,
2308 			             clearToZero ? 0.0f : 4.0f / 255.0f);
2309 			EXPECT_NO_GL_ERROR();
2310 			glClear(GL_COLOR_BUFFER_BIT);
2311 			EXPECT_NO_GL_ERROR();
2312 		}
2313 	}
2314 
doClearTest(EGLClientBufferWrapper & clientBufferWrapper,GLenum internalFormat,GLenum type,void * data,size_t dataSize)2315 	void doClearTest(EGLClientBufferWrapper &clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
2316 	{
2317 		ASSERT_TRUE(dataSize <= 4);
2318 
2319 		// Bind the IOSurface to a texture and clear it.
2320 		GLuint texture = 1;
2321 		EGLSurface pbuffer;
2322 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
2323 
2324 		// glClear the pbuffer
2325 		GLuint fbo = 2;
2326 		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2327 		EXPECT_NO_GL_ERROR();
2328 		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, 0);
2329 		EXPECT_NO_GL_ERROR();
2330 		EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE);
2331 		EXPECT_NO_GL_ERROR();
2332 
2333 		doClear(internalFormat, false);
2334 
2335 		// Unbind pbuffer and check content.
2336 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
2337 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2338 		EXPECT_NO_EGL_ERROR();
2339 
2340 		const unsigned char *color = clientBufferWrapper.lockColor();
2341 		for(size_t i = 0; i < dataSize; ++i)
2342 		{
2343 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char *>(data)[i]);
2344 		}
2345 
2346 		result = eglDestroySurface(getDisplay(), pbuffer);
2347 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2348 		EXPECT_NO_EGL_ERROR();
2349 	}
2350 
doSampleTest(EGLClientBufferWrapper & clientBufferWrapper,GLenum internalFormat,GLenum type,void * data,size_t dataSize)2351 	void doSampleTest(EGLClientBufferWrapper &clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize)
2352 	{
2353 		ASSERT_TRUE(dataSize <= 4);
2354 
2355 		clientBufferWrapper.writeColor(data, dataSize);
2356 
2357 		// Bind the IOSurface to a texture and clear it.
2358 		GLuint texture = 1;
2359 		EGLSurface pbuffer;
2360 		bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture);
2361 
2362 		doClear(internalFormat, true);
2363 
2364 		// Create program and draw quad using it
2365 		const std::string vs =
2366 		    R"(attribute vec4 position;
2367 			void main()
2368 			{
2369 			    gl_Position = vec4(position.xy, 0.0, 1.0);
2370 			})";
2371 
2372 		const std::string fs =
2373 		    R"(#extension GL_ARB_texture_rectangle : require
2374 			precision mediump float;
2375 			uniform sampler2DRect tex;
2376 			void main()
2377 			{
2378 			    gl_FragColor = texture2DRect(tex, vec2(0, 0));
2379 			})";
2380 
2381 		const ProgramHandles ph = createProgram(vs, fs);
2382 
2383 		drawQuad(ph.program, "tex");
2384 
2385 		deleteProgram(ph);
2386 		EXPECT_NO_GL_ERROR();
2387 
2388 		// Unbind pbuffer and check content.
2389 		EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER);
2390 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2391 		EXPECT_NO_EGL_ERROR();
2392 
2393 		const unsigned char *color = clientBufferWrapper.lockColor();
2394 		for(size_t i = 0; i < dataSize; ++i)
2395 		{
2396 			EXPECT_EQ(color[i], reinterpret_cast<unsigned char *>(data)[i]);
2397 		}
2398 		clientBufferWrapper.unlockColor();
2399 	}
2400 };
2401 
2402 // Tests for the EGL_ANGLE_iosurface_client_buffer extension
TEST_F(IOSurfaceClientBufferTest,RenderToBGRA8888IOSurface)2403 TEST_F(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface)
2404 {
2405 	Initialize(3, false);
2406 
2407 	{  // EGLClientBufferWrapper scope
2408 		EGLClientBufferWrapper clientBufferWrapper;
2409 		unsigned char data[4] = { 3, 2, 1, 4 };
2410 		doClearTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
2411 	}  // end of EGLClientBufferWrapper scope
2412 
2413 	Uninitialize();
2414 }
2415 
2416 // Test reading from BGRA8888 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromBGRA8888IOSurface)2417 TEST_F(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface)
2418 {
2419 	Initialize(3, false);
2420 
2421 	{  // EGLClientBufferWrapper scope
2422 		EGLClientBufferWrapper clientBufferWrapper;
2423 		unsigned char data[4] = { 3, 2, 1, 4 };
2424 		doSampleTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4);
2425 	}  // end of EGLClientBufferWrapper scope
2426 
2427 	Uninitialize();
2428 }
2429 
2430 // Test using RGBX8888 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToRGBX8888IOSurface)2431 TEST_F(IOSurfaceClientBufferTest, RenderToRGBX8888IOSurface)
2432 {
2433 	Initialize(3, false);
2434 
2435 	{  // EGLClientBufferWrapper scope
2436 		EGLClientBufferWrapper clientBufferWrapper;
2437 		unsigned char data[3] = { 1, 2, 3 };
2438 		doClearTest(clientBufferWrapper, GL_RGB, GL_UNSIGNED_BYTE, data, 3);
2439 	}  // end of EGLClientBufferWrapper scope
2440 
2441 	Uninitialize();
2442 }
2443 
2444 // Test reading from RGBX8888 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromRGBX8888IOSurface)2445 TEST_F(IOSurfaceClientBufferTest, ReadFromRGBX8888IOSurface)
2446 {
2447 	Initialize(3, false);
2448 
2449 	{  // EGLClientBufferWrapper scope
2450 		EGLClientBufferWrapper clientBufferWrapper;
2451 		unsigned char data[3] = { 1, 2, 3 };
2452 		doSampleTest(clientBufferWrapper, GL_RGB, GL_UNSIGNED_BYTE, data, 3);
2453 	}  // end of EGLClientBufferWrapper scope
2454 
2455 	Uninitialize();
2456 }
2457 
2458 // Test using RG88 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToRG88IOSurface)2459 TEST_F(IOSurfaceClientBufferTest, RenderToRG88IOSurface)
2460 {
2461 	Initialize(3, false);
2462 
2463 	{  // EGLClientBufferWrapper scope
2464 		EGLClientBufferWrapper clientBufferWrapper;
2465 		unsigned char data[2] = { 1, 2 };
2466 		doClearTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
2467 	}  // end of EGLClientBufferWrapper scope
2468 
2469 	Uninitialize();
2470 }
2471 
2472 // Test reading from RG88 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromRG88IOSurface)2473 TEST_F(IOSurfaceClientBufferTest, ReadFromRG88IOSurface)
2474 {
2475 	Initialize(3, false);
2476 
2477 	{  // EGLClientBufferWrapper scope
2478 		EGLClientBufferWrapper clientBufferWrapper;
2479 		unsigned char data[2] = { 1, 2 };
2480 		doSampleTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2);
2481 	}  // end of EGLClientBufferWrapper scope
2482 
2483 	Uninitialize();
2484 }
2485 
2486 // Test using R8 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToR8IOSurface)2487 TEST_F(IOSurfaceClientBufferTest, RenderToR8IOSurface)
2488 {
2489 	Initialize(3, false);
2490 
2491 	{  // EGLClientBufferWrapper scope
2492 		EGLClientBufferWrapper clientBufferWrapper;
2493 		unsigned char data[1] = { 1 };
2494 		doClearTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
2495 	}  // end of EGLClientBufferWrapper scope
2496 
2497 	Uninitialize();
2498 }
2499 
2500 // Test reading from R8 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromR8IOSurface)2501 TEST_F(IOSurfaceClientBufferTest, ReadFromR8IOSurface)
2502 {
2503 	Initialize(3, false);
2504 
2505 	{  // EGLClientBufferWrapper scope
2506 		EGLClientBufferWrapper clientBufferWrapper;
2507 		unsigned char data[1] = { 1 };
2508 		doSampleTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1);
2509 	}  // end of EGLClientBufferWrapper scope
2510 
2511 	Uninitialize();
2512 }
2513 
2514 // Test using R16 IOSurfaces for rendering
TEST_F(IOSurfaceClientBufferTest,RenderToR16IOSurface)2515 TEST_F(IOSurfaceClientBufferTest, RenderToR16IOSurface)
2516 {
2517 	Initialize(3, false);
2518 
2519 	{  // EGLClientBufferWrapper scope
2520 		EGLClientBufferWrapper clientBufferWrapper;
2521 		uint16_t data[1] = { 257 };
2522 		doClearTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 2);
2523 	}  // end of EGLClientBufferWrapper scope
2524 
2525 	Uninitialize();
2526 }
2527 
2528 // Test reading from R8 IOSurfaces
TEST_F(IOSurfaceClientBufferTest,ReadFromR16IOSurface)2529 TEST_F(IOSurfaceClientBufferTest, ReadFromR16IOSurface)
2530 {
2531 	Initialize(3, false);
2532 
2533 	{  // EGLClientBufferWrapper scope
2534 		EGLClientBufferWrapper clientBufferWrapper;
2535 		uint16_t data[1] = { 257 };
2536 		doSampleTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 1);
2537 	}  // end of EGLClientBufferWrapper scope
2538 
2539 	Uninitialize();
2540 }
2541 
2542 // Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with
2543 // IOSurface
TEST_F(IOSurfaceClientBufferTest,NegativeValidationMissingAttributes)2544 TEST_F(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes)
2545 {
2546 	Initialize(3, false);
2547 
2548 	{
2549 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
2550 
2551 		// Success case
2552 		{
2553 			const EGLint attribs[] = {
2554 				EGL_WIDTH,
2555 				10,
2556 				EGL_HEIGHT,
2557 				10,
2558 				EGL_IOSURFACE_PLANE_ANGLE,
2559 				0,
2560 				EGL_TEXTURE_TARGET,
2561 				EGL_TEXTURE_RECTANGLE_ANGLE,
2562 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2563 				GL_BGRA_EXT,
2564 				EGL_TEXTURE_FORMAT,
2565 				EGL_TEXTURE_RGBA,
2566 				EGL_TEXTURE_TYPE_ANGLE,
2567 				GL_UNSIGNED_BYTE,
2568 				EGL_NONE,
2569 				EGL_NONE,
2570 			};
2571 
2572 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2573 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
2574 
2575 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
2576 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2577 			EXPECT_NO_EGL_ERROR();
2578 		}
2579 
2580 		// Missing EGL_WIDTH
2581 		{
2582 			const EGLint attribs[] = {
2583 				EGL_HEIGHT,
2584 				10,
2585 				EGL_IOSURFACE_PLANE_ANGLE,
2586 				0,
2587 				EGL_TEXTURE_TARGET,
2588 				EGL_TEXTURE_RECTANGLE_ANGLE,
2589 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2590 				GL_BGRA_EXT,
2591 				EGL_TEXTURE_FORMAT,
2592 				EGL_TEXTURE_RGBA,
2593 				EGL_TEXTURE_TYPE_ANGLE,
2594 				GL_UNSIGNED_BYTE,
2595 				EGL_NONE,
2596 				EGL_NONE,
2597 			};
2598 
2599 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2600 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2601 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
2602 		}
2603 
2604 		// Missing EGL_HEIGHT
2605 		{
2606 			const EGLint attribs[] = {
2607 				EGL_WIDTH,
2608 				10,
2609 				EGL_IOSURFACE_PLANE_ANGLE,
2610 				0,
2611 				EGL_TEXTURE_TARGET,
2612 				EGL_TEXTURE_RECTANGLE_ANGLE,
2613 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2614 				GL_BGRA_EXT,
2615 				EGL_TEXTURE_FORMAT,
2616 				EGL_TEXTURE_RGBA,
2617 				EGL_TEXTURE_TYPE_ANGLE,
2618 				GL_UNSIGNED_BYTE,
2619 				EGL_NONE,
2620 				EGL_NONE,
2621 			};
2622 
2623 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2624 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2625 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
2626 		}
2627 
2628 		// Missing EGL_IOSURFACE_PLANE_ANGLE
2629 		{
2630 			const EGLint attribs[] = {
2631 				EGL_WIDTH,
2632 				10,
2633 				EGL_HEIGHT,
2634 				10,
2635 				EGL_TEXTURE_TARGET,
2636 				EGL_TEXTURE_RECTANGLE_ANGLE,
2637 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2638 				GL_BGRA_EXT,
2639 				EGL_TEXTURE_FORMAT,
2640 				EGL_TEXTURE_RGBA,
2641 				EGL_TEXTURE_TYPE_ANGLE,
2642 				GL_UNSIGNED_BYTE,
2643 				EGL_NONE,
2644 				EGL_NONE,
2645 			};
2646 
2647 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2648 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2649 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
2650 		}
2651 
2652 		// Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of
2653 		// eglCreatePbufferFromClientBuffer
2654 		{
2655 			const EGLint attribs[] = {
2656 				EGL_WIDTH,
2657 				10,
2658 				EGL_HEIGHT,
2659 				10,
2660 				EGL_IOSURFACE_PLANE_ANGLE,
2661 				0,
2662 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2663 				GL_BGRA_EXT,
2664 				EGL_TEXTURE_FORMAT,
2665 				EGL_TEXTURE_RGBA,
2666 				EGL_TEXTURE_TYPE_ANGLE,
2667 				GL_UNSIGNED_BYTE,
2668 				EGL_NONE,
2669 				EGL_NONE,
2670 			};
2671 
2672 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2673 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2674 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
2675 		}
2676 
2677 		// Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE
2678 		{
2679 			const EGLint attribs[] = {
2680 				EGL_WIDTH,
2681 				10,
2682 				EGL_HEIGHT,
2683 				10,
2684 				EGL_IOSURFACE_PLANE_ANGLE,
2685 				0,
2686 				EGL_TEXTURE_TARGET,
2687 				EGL_TEXTURE_RECTANGLE_ANGLE,
2688 				EGL_TEXTURE_FORMAT,
2689 				EGL_TEXTURE_RGBA,
2690 				EGL_TEXTURE_TYPE_ANGLE,
2691 				GL_UNSIGNED_BYTE,
2692 				EGL_NONE,
2693 				EGL_NONE,
2694 			};
2695 
2696 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2697 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2698 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
2699 		}
2700 
2701 		// Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of
2702 		// eglCreatePbufferFromClientBuffer
2703 		{
2704 			const EGLint attribs[] = {
2705 				EGL_WIDTH,
2706 				10,
2707 				EGL_HEIGHT,
2708 				10,
2709 				EGL_IOSURFACE_PLANE_ANGLE,
2710 				0,
2711 				EGL_TEXTURE_TARGET,
2712 				EGL_TEXTURE_RECTANGLE_ANGLE,
2713 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2714 				GL_BGRA_EXT,
2715 				EGL_TEXTURE_TYPE_ANGLE,
2716 				GL_UNSIGNED_BYTE,
2717 				EGL_NONE,
2718 				EGL_NONE,
2719 			};
2720 
2721 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2722 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2723 			EXPECT_EQ(EGL_BAD_MATCH, eglGetError());
2724 		}
2725 
2726 		// Missing EGL_TEXTURE_TYPE_ANGLE
2727 		{
2728 			const EGLint attribs[] = {
2729 				EGL_WIDTH,
2730 				10,
2731 				EGL_HEIGHT,
2732 				10,
2733 				EGL_IOSURFACE_PLANE_ANGLE,
2734 				0,
2735 				EGL_TEXTURE_TARGET,
2736 				EGL_TEXTURE_RECTANGLE_ANGLE,
2737 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2738 				GL_BGRA_EXT,
2739 				EGL_TEXTURE_FORMAT,
2740 				EGL_TEXTURE_RGBA,
2741 				EGL_NONE,
2742 				EGL_NONE,
2743 			};
2744 
2745 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2746 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2747 			EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError());
2748 		}
2749 	}
2750 
2751 	Uninitialize();
2752 }
2753 
2754 // Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface
TEST_F(IOSurfaceClientBufferTest,NegativeValidationBadAttributes)2755 TEST_F(IOSurfaceClientBufferTest, NegativeValidationBadAttributes)
2756 {
2757 	Initialize(3, false);
2758 
2759 	{
2760 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
2761 
2762 		// Success case
2763 		{
2764 			const EGLint attribs[] = {
2765 				EGL_WIDTH,
2766 				10,
2767 				EGL_HEIGHT,
2768 				10,
2769 				EGL_IOSURFACE_PLANE_ANGLE,
2770 				0,
2771 				EGL_TEXTURE_TARGET,
2772 				EGL_TEXTURE_RECTANGLE_ANGLE,
2773 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2774 				GL_BGRA_EXT,
2775 				EGL_TEXTURE_FORMAT,
2776 				EGL_TEXTURE_RGBA,
2777 				EGL_TEXTURE_TYPE_ANGLE,
2778 				GL_UNSIGNED_BYTE,
2779 				EGL_NONE,
2780 				EGL_NONE,
2781 			};
2782 
2783 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2784 			EXPECT_NE(EGL_NO_SURFACE, pbuffer);
2785 
2786 			EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer);
2787 			EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
2788 			EXPECT_NO_EGL_ERROR();
2789 		}
2790 
2791 		// EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA
2792 		{
2793 			const EGLint attribs[] = {
2794 				EGL_WIDTH,
2795 				10,
2796 				EGL_HEIGHT,
2797 				10,
2798 				EGL_IOSURFACE_PLANE_ANGLE,
2799 				0,
2800 				EGL_TEXTURE_TARGET,
2801 				EGL_TEXTURE_RECTANGLE_ANGLE,
2802 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2803 				GL_BGRA_EXT,
2804 				EGL_TEXTURE_FORMAT,
2805 				EGL_TEXTURE_RGB,
2806 				EGL_TEXTURE_TYPE_ANGLE,
2807 				GL_UNSIGNED_BYTE,
2808 				EGL_NONE,
2809 				EGL_NONE,
2810 			};
2811 
2812 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2813 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2814 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2815 		}
2816 
2817 		// EGL_WIDTH must be at least 1
2818 		{
2819 			const EGLint attribs[] = {
2820 				EGL_WIDTH,
2821 				0,
2822 				EGL_HEIGHT,
2823 				10,
2824 				EGL_IOSURFACE_PLANE_ANGLE,
2825 				0,
2826 				EGL_TEXTURE_TARGET,
2827 				EGL_TEXTURE_RECTANGLE_ANGLE,
2828 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2829 				GL_BGRA_EXT,
2830 				EGL_TEXTURE_FORMAT,
2831 				EGL_TEXTURE_RGBA,
2832 				EGL_TEXTURE_TYPE_ANGLE,
2833 				GL_UNSIGNED_BYTE,
2834 				EGL_NONE,
2835 				EGL_NONE,
2836 			};
2837 
2838 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2839 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2840 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2841 		}
2842 
2843 		// EGL_HEIGHT must be at least 1
2844 		{
2845 			const EGLint attribs[] = {
2846 				EGL_WIDTH,
2847 				10,
2848 				EGL_HEIGHT,
2849 				0,
2850 				EGL_IOSURFACE_PLANE_ANGLE,
2851 				0,
2852 				EGL_TEXTURE_TARGET,
2853 				EGL_TEXTURE_RECTANGLE_ANGLE,
2854 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2855 				GL_BGRA_EXT,
2856 				EGL_TEXTURE_FORMAT,
2857 				EGL_TEXTURE_RGBA,
2858 				EGL_TEXTURE_TYPE_ANGLE,
2859 				GL_UNSIGNED_BYTE,
2860 				EGL_NONE,
2861 				EGL_NONE,
2862 			};
2863 
2864 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2865 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2866 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2867 		}
2868 
2869 #if defined(__APPLE__)
2870 		// EGL_WIDTH must be at most the width of the IOSurface
2871 		{
2872 			const EGLint attribs[] = {
2873 				EGL_WIDTH,
2874 				11,
2875 				EGL_HEIGHT,
2876 				10,
2877 				EGL_IOSURFACE_PLANE_ANGLE,
2878 				0,
2879 				EGL_TEXTURE_TARGET,
2880 				EGL_TEXTURE_RECTANGLE_ANGLE,
2881 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2882 				GL_BGRA_EXT,
2883 				EGL_TEXTURE_FORMAT,
2884 				EGL_TEXTURE_RGBA,
2885 				EGL_TEXTURE_TYPE_ANGLE,
2886 				GL_UNSIGNED_BYTE,
2887 				EGL_NONE,
2888 				EGL_NONE,
2889 			};
2890 
2891 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2892 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2893 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2894 		}
2895 
2896 		// EGL_HEIGHT must be at most the height of the IOSurface
2897 		{
2898 			const EGLint attribs[] = {
2899 				EGL_WIDTH,
2900 				10,
2901 				EGL_HEIGHT,
2902 				11,
2903 				EGL_IOSURFACE_PLANE_ANGLE,
2904 				0,
2905 				EGL_TEXTURE_TARGET,
2906 				EGL_TEXTURE_RECTANGLE_ANGLE,
2907 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2908 				GL_BGRA_EXT,
2909 				EGL_TEXTURE_FORMAT,
2910 				EGL_TEXTURE_RGBA,
2911 				EGL_TEXTURE_TYPE_ANGLE,
2912 				GL_UNSIGNED_BYTE,
2913 				EGL_NONE,
2914 				EGL_NONE,
2915 			};
2916 
2917 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2918 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2919 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2920 		}
2921 
2922 		// EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface
2923 		{
2924 			const EGLint attribs[] = {
2925 				EGL_WIDTH,
2926 				10,
2927 				EGL_HEIGHT,
2928 				10,
2929 				EGL_IOSURFACE_PLANE_ANGLE,
2930 				1,
2931 				EGL_TEXTURE_TARGET,
2932 				EGL_TEXTURE_RECTANGLE_ANGLE,
2933 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2934 				GL_BGRA_EXT,
2935 				EGL_TEXTURE_FORMAT,
2936 				EGL_TEXTURE_RGBA,
2937 				EGL_TEXTURE_TYPE_ANGLE,
2938 				GL_UNSIGNED_BYTE,
2939 				EGL_NONE,
2940 				EGL_NONE,
2941 			};
2942 
2943 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2944 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2945 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2946 		}
2947 #endif
2948 
2949 		// EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE
2950 		{
2951 			const EGLint attribs[] = {
2952 				EGL_WIDTH,
2953 				10,
2954 				EGL_HEIGHT,
2955 				10,
2956 				EGL_IOSURFACE_PLANE_ANGLE,
2957 				0,
2958 				EGL_TEXTURE_TARGET,
2959 				EGL_TEXTURE_2D,
2960 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2961 				GL_BGRA_EXT,
2962 				EGL_TEXTURE_FORMAT,
2963 				EGL_TEXTURE_RGBA,
2964 				EGL_TEXTURE_TYPE_ANGLE,
2965 				GL_UNSIGNED_BYTE,
2966 				EGL_NONE,
2967 				EGL_NONE,
2968 			};
2969 
2970 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2971 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2972 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2973 		}
2974 
2975 		// EGL_IOSURFACE_PLANE_ANGLE must be at least 0
2976 		{
2977 			const EGLint attribs[] = {
2978 				EGL_WIDTH,
2979 				10,
2980 				EGL_HEIGHT,
2981 				10,
2982 				EGL_IOSURFACE_PLANE_ANGLE,
2983 				-1,
2984 				EGL_TEXTURE_TARGET,
2985 				EGL_TEXTURE_RECTANGLE_ANGLE,
2986 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
2987 				GL_BGRA_EXT,
2988 				EGL_TEXTURE_FORMAT,
2989 				EGL_TEXTURE_RGBA,
2990 				EGL_TEXTURE_TYPE_ANGLE,
2991 				GL_UNSIGNED_BYTE,
2992 				EGL_NONE,
2993 				EGL_NONE,
2994 			};
2995 
2996 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
2997 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
2998 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
2999 		}
3000 
3001 		// The internal format / type most be listed in the table
3002 		{
3003 			const EGLint attribs[] = {
3004 				EGL_WIDTH,
3005 				10,
3006 				EGL_HEIGHT,
3007 				10,
3008 				EGL_IOSURFACE_PLANE_ANGLE,
3009 				0,
3010 				EGL_TEXTURE_TARGET,
3011 				EGL_TEXTURE_RECTANGLE_ANGLE,
3012 				EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
3013 				GL_RGBA,
3014 				EGL_TEXTURE_FORMAT,
3015 				EGL_TEXTURE_RGBA,
3016 				EGL_TEXTURE_TYPE_ANGLE,
3017 				GL_UNSIGNED_BYTE,
3018 				EGL_NONE,
3019 				EGL_NONE,
3020 			};
3021 
3022 			EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs);
3023 			EXPECT_EQ(EGL_NO_SURFACE, pbuffer);
3024 			EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError());
3025 		}
3026 	}
3027 
3028 	Uninitialize();
3029 }
3030 
3031 // Test IOSurface pbuffers can be made current
TEST_F(IOSurfaceClientBufferTest,MakeCurrentAllowed)3032 TEST_F(IOSurfaceClientBufferTest, MakeCurrentAllowed)
3033 {
3034 	Initialize(3, false);
3035 
3036 	{
3037 		EGLClientBufferWrapper clientBufferWrapper(10, 10);
3038 
3039 		EGLSurface pbuffer = createIOSurfacePbuffer(clientBufferWrapper.getClientBuffer(), 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE);
3040 
3041 		EGLBoolean result = eglMakeCurrent(getDisplay(), pbuffer, pbuffer, getContext());
3042 		EXPECT_EQ((EGLBoolean)EGL_TRUE, result);
3043 		EXPECT_NO_EGL_ERROR();
3044 	}
3045 
3046 	Uninitialize();
3047 }
3048