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