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