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