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