diff options
author | android-autoroll <android-autoroll@skia-public.iam.gserviceaccount.com> | 2022-04-14 21:30:23 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-04-14 21:30:23 +0000 |
commit | f5cad512395d01c28922d2cebe2840b02616051b (patch) | |
tree | c25526380ebd5c05000d9fd0ab9a25cbf56e248c | |
parent | 81a6937f61e959091cc3c975d07aad90c22870ee (diff) | |
parent | 9389240843c01a34e7b75e2ba2eb696b57805f96 (diff) | |
download | swiftshader-f5cad512395d01c28922d2cebe2840b02616051b.tar.gz |
Roll SwiftShader from 598c7cddf07f to 103a69bd6c82 (1 revision) am: 9389240843
Original change: https://android-review.googlesource.com/c/platform/external/swiftshader/+/2064810
Change-Id: I488fb5ae9f32b8679641c798611c6e85710e81db
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | tests/GLESUnitTests/main.cpp | 21 | ||||
-rw-r--r-- | tests/GLESUnitTests/unittests.cpp | 3047 |
2 files changed, 0 insertions, 3068 deletions
diff --git a/tests/GLESUnitTests/main.cpp b/tests/GLESUnitTests/main.cpp deleted file mode 100644 index 8f7e13f32..000000000 --- a/tests/GLESUnitTests/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2017 The SwiftShader Authors. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "gtest/gtest.h"
-
-int main(int argc, char **argv)
-{
- ::testing::InitGoogleTest(&argc, argv);
- return RUN_ALL_TESTS();
-}
diff --git a/tests/GLESUnitTests/unittests.cpp b/tests/GLESUnitTests/unittests.cpp deleted file mode 100644 index f9bea45ac..000000000 --- a/tests/GLESUnitTests/unittests.cpp +++ /dev/null @@ -1,3047 +0,0 @@ -// Copyright 2017 The SwiftShader Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// OpenGL ES unit tests that provide coverage for functionality not tested by -// the dEQP test suite. Also used as a smoke test. - -#include "gmock/gmock.h" -#include "gtest/gtest.h" - -#include <EGL/egl.h> -#include <GL/glcorearb.h> -#include <GL/glext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> -#include <GLES3/gl3.h> - -#if defined(_WIN32) -# include <Windows.h> -#endif - -#include <string.h> -#include <cstdint> - -#define EXPECT_GLENUM_EQ(expected, actual) EXPECT_EQ(static_cast<GLenum>(expected), static_cast<GLenum>(actual)) - -#define EXPECT_NO_GL_ERROR() EXPECT_GLENUM_EQ(GL_NO_ERROR, glGetError()) -#define EXPECT_NO_EGL_ERROR() EXPECT_EQ(EGL_SUCCESS, eglGetError()) - -class SwiftShaderTest : public testing::Test -{ -protected: - void SetUp() override - { -#if defined(_WIN32) && !defined(STANDALONE) - // The DLLs are delay loaded (see BUILD.gn), so we can load - // the correct ones from Chrome's swiftshader subdirectory. - HMODULE libEGL = LoadLibraryA("swiftshader\\libEGL.dll"); - EXPECT_NE((HMODULE)NULL, libEGL); - - HMODULE libGLESv2 = LoadLibraryA("swiftshader\\libGLESv2.dll"); - EXPECT_NE((HMODULE)NULL, libGLESv2); -#endif - } - - void expectFramebufferColor(const unsigned char referenceColor[4], GLint x = 0, GLint y = 0) - { - unsigned char color[4] = { 0 }; - glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(color[0], referenceColor[0]); - EXPECT_EQ(color[1], referenceColor[1]); - EXPECT_EQ(color[2], referenceColor[2]); - EXPECT_EQ(color[3], referenceColor[3]); - } - - void expectFramebufferColor(const float referenceColor[4], GLint x = 0, GLint y = 0) - { - float color[4] = { 0 }; - glReadPixels(x, y, 1, 1, GL_RGBA, GL_FLOAT, &color); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(color[0], referenceColor[0]); - EXPECT_EQ(color[1], referenceColor[1]); - EXPECT_EQ(color[2], referenceColor[2]); - EXPECT_EQ(color[3], referenceColor[3]); - } - - void Initialize(int version, bool withChecks) - { - EXPECT_NO_EGL_ERROR(); - - display = eglGetDisplay(EGL_DEFAULT_DISPLAY); - - if(withChecks) - { - EXPECT_NO_EGL_ERROR(); - EXPECT_NE(EGL_NO_DISPLAY, display); - - eglQueryString(display, EGL_VENDOR); - EXPECT_EQ(EGL_NOT_INITIALIZED, eglGetError()); - } - - EGLint major; - EGLint minor; - EGLBoolean initialized = eglInitialize(display, &major, &minor); - - if(withChecks) - { - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, initialized); - EXPECT_EQ(1, major); - EXPECT_EQ(4, minor); - - const char *eglVendor = eglQueryString(display, EGL_VENDOR); - EXPECT_NO_EGL_ERROR(); - EXPECT_STREQ("Google Inc.", eglVendor); - - const char *eglVersion = eglQueryString(display, EGL_VERSION); - EXPECT_NO_EGL_ERROR(); - EXPECT_THAT(eglVersion, testing::HasSubstr("1.4 SwiftShader ")); - } - - eglBindAPI(EGL_OPENGL_ES_API); - EXPECT_NO_EGL_ERROR(); - - const EGLint configAttributes[] = { - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_ALPHA_SIZE, 8, - EGL_NONE - }; - - EGLint num_config = -1; - EGLBoolean success = eglChooseConfig(display, configAttributes, &config, 1, &num_config); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(num_config, 1); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - - if(withChecks) - { - EGLint conformant = 0; - eglGetConfigAttrib(display, config, EGL_CONFORMANT, &conformant); - EXPECT_NO_EGL_ERROR(); - EXPECT_TRUE(conformant & EGL_OPENGL_ES2_BIT); - - EGLint renderableType = 0; - eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType); - EXPECT_NO_EGL_ERROR(); - EXPECT_TRUE(renderableType & EGL_OPENGL_ES2_BIT); - - EGLint surfaceType = 0; - eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType); - EXPECT_NO_EGL_ERROR(); - EXPECT_TRUE(surfaceType & EGL_WINDOW_BIT); - } - - EGLint surfaceAttributes[] = { - EGL_WIDTH, 1920, - EGL_HEIGHT, 1080, - EGL_NONE - }; - - surface = eglCreatePbufferSurface(display, config, surfaceAttributes); - EXPECT_NO_EGL_ERROR(); - EXPECT_NE(EGL_NO_SURFACE, surface); - - EGLint contextAttributes[] = { - EGL_CONTEXT_CLIENT_VERSION, version, - EGL_NONE - }; - - context = eglCreateContext(display, config, NULL, contextAttributes); - EXPECT_NO_EGL_ERROR(); - EXPECT_NE(EGL_NO_CONTEXT, context); - - success = eglMakeCurrent(display, surface, surface, context); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - - if(withChecks) - { - EGLDisplay currentDisplay = eglGetCurrentDisplay(); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(display, currentDisplay); - - EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(surface, currentDrawSurface); - - EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(surface, currentReadSurface); - - EGLContext currentContext = eglGetCurrentContext(); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(context, currentContext); - } - - EXPECT_NO_GL_ERROR(); - } - - void Uninitialize() - { - EXPECT_NO_GL_ERROR(); - - EGLBoolean success = eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - - EGLDisplay currentDisplay = eglGetCurrentDisplay(); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(EGL_NO_DISPLAY, currentDisplay); - - EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(EGL_NO_SURFACE, currentDrawSurface); - - EGLSurface currentReadSurface = eglGetCurrentSurface(EGL_READ); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(EGL_NO_SURFACE, currentReadSurface); - - EGLContext currentContext = eglGetCurrentContext(); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ(EGL_NO_CONTEXT, currentContext); - - success = eglDestroyContext(display, context); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - - success = eglDestroySurface(display, surface); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - - success = eglTerminate(display); - EXPECT_NO_EGL_ERROR(); - EXPECT_EQ((EGLBoolean)EGL_TRUE, success); - } - - struct ProgramHandles - { - GLuint program; - GLuint vertexShader; - GLuint fragmentShader; - }; - - GLuint MakeShader(const std::string &source, GLenum shaderType) - { - GLuint shader = glCreateShader(shaderType); - const char *c_source[1] = { source.c_str() }; - glShaderSource(shader, 1, c_source, nullptr); - glCompileShader(shader); - EXPECT_NO_GL_ERROR(); - - GLchar buf[1024]; - GLint compileStatus = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); - glGetShaderInfoLog(shader, sizeof(buf), nullptr, buf); - EXPECT_EQ(compileStatus, GL_TRUE) << "Compile status: " << std::endl - << buf; - - return shader; - } - - GLuint MakeProgram(GLuint vs, GLuint fs) - { - GLuint program; - - program = glCreateProgram(); - EXPECT_NO_GL_ERROR(); - - glAttachShader(program, vs); - glAttachShader(program, fs); - EXPECT_NO_GL_ERROR(); - - return program; - } - - void LinkProgram(GLuint program) - { - GLchar buf[1024]; - glLinkProgram(program); - - GLint linkStatus = 0; - glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); - glGetProgramInfoLog(program, sizeof(buf), nullptr, buf); - EXPECT_NE(linkStatus, 0) << "Link status: " << std::endl - << buf; - - EXPECT_NO_GL_ERROR(); - } - - ProgramHandles createProgram(const std::string &vs, const std::string &fs) - { - ProgramHandles ph; - ph.vertexShader = MakeShader(vs, GL_VERTEX_SHADER); - ph.fragmentShader = MakeShader(fs, GL_FRAGMENT_SHADER); - ph.program = MakeProgram(ph.vertexShader, ph.fragmentShader); - LinkProgram(ph.program); - - return ph; - } - - void deleteProgram(const ProgramHandles &ph) - { - glDeleteShader(ph.fragmentShader); - glDeleteShader(ph.vertexShader); - glDeleteProgram(ph.program); - - EXPECT_NO_GL_ERROR(); - } - - void drawQuad(GLuint program, const char *textureName = nullptr) - { - GLint prevProgram = 0; - glGetIntegerv(GL_CURRENT_PROGRAM, &prevProgram); - - glUseProgram(program); - EXPECT_NO_GL_ERROR(); - - GLint posLoc = glGetAttribLocation(program, "position"); - EXPECT_NO_GL_ERROR(); - - if(textureName) - { - GLint location = glGetUniformLocation(program, textureName); - ASSERT_NE(-1, location); - glUniform1i(location, 0); - } - - float vertices[18] = { -1.0f, 1.0f, 0.5f, - -1.0f, -1.0f, 0.5f, - 1.0f, -1.0f, 0.5f, - -1.0f, 1.0f, 0.5f, - 1.0f, -1.0f, 0.5f, - 1.0f, 1.0f, 0.5f }; - - glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, 0, vertices); - glEnableVertexAttribArray(posLoc); - glDrawArrays(GL_TRIANGLES, 0, 6); - EXPECT_NO_GL_ERROR(); - - glVertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, nullptr); - glDisableVertexAttribArray(posLoc); - glUseProgram(prevProgram); - EXPECT_NO_GL_ERROR(); - } - - std::string replace(std::string str, const std::string &substr, const std::string &replacement) - { - size_t pos = 0; - while((pos = str.find(substr, pos)) != std::string::npos) - { - str.replace(pos, substr.length(), replacement); - pos += replacement.length(); - } - return str; - } - - void checkCompiles(std::string v, std::string f) - { - Initialize(3, false); - - std::string vs = - R"(#version 300 es - in vec4 position; - out float unfoldable; - $INSERT - void main() - { - unfoldable = position.x; - gl_Position = vec4(position.xy, 0.0, 1.0); - gl_Position.x += F(unfoldable);\ - })"; - - std::string fs = - R"(#version 300 es - precision mediump float; - in float unfoldable; - out vec4 fragColor; - $INSERT - void main() - { - fragColor = vec4(1.0, 1.0, 1.0, 1.0); - fragColor.x += F(unfoldable); - })"; - - vs = replace(vs, "$INSERT", (v.length() > 0) ? v : "float F(float ignored) { return 0.0; }"); - fs = replace(fs, "$INSERT", (f.length() > 0) ? f : "float F(float ignored) { return 0.0; }"); - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - - drawQuad(ph.program); - - deleteProgram(ph); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); - } - - void checkCompiles(std::string s) - { - checkCompiles(s, ""); - checkCompiles("", s); - } - - std::string checkCompileFails(std::string source, GLenum glShaderType) - { - Initialize(3, false); - - GLint compileStatus = 0; - const char *c_source[1] = { source.c_str() }; - GLuint glShader = glCreateShader(glShaderType); - - glShaderSource(glShader, 1, c_source, nullptr); - glCompileShader(glShader); - EXPECT_NO_GL_ERROR(); - - std::string log; - char *buf; - GLsizei length = 0; - GLsizei written = 0; - - glGetShaderiv(glShader, GL_COMPILE_STATUS, &compileStatus); - EXPECT_EQ(compileStatus, GL_FALSE); - - glGetShaderiv(glShader, GL_INFO_LOG_LENGTH, &length); - EXPECT_NO_GL_ERROR(); - EXPECT_NE(length, 0); - buf = new char[length]; - - glGetShaderInfoLog(glShader, length, &written, buf); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(length, written + 1); - log.assign(buf, length); - delete[] buf; - - glDeleteShader(glShader); - - Uninitialize(); - - return log; - } - - void checkCompileFails(std::string s) - { - std::string vs = - R"(#version 300 es - in vec4 position; - out float unfoldable; - $INSERT - void main() - { - unfoldable = position.x; - gl_Position = vec4(position.xy, 0.0, 1.0); - gl_Position.x += F(unfoldable); - })"; - - std::string fs = - R"(#version 300 es - precision mediump float; - in float unfoldable; - out vec4 fragColor; - $INSERT - void main() - { - fragColor = vec4(1.0, 1.0, 1.0, 1.0); - fragColor.x += F(unfoldable); - })"; - - vs = replace(vs, "$INSERT", s); - fs = replace(fs, "$INSERT", s); - - checkCompileFails(vs, GL_VERTEX_SHADER); - checkCompileFails(fs, GL_FRAGMENT_SHADER); - } - - EGLDisplay getDisplay() const { return display; } - EGLConfig getConfig() const { return config; } - EGLSurface getSurface() const { return surface; } - EGLContext getContext() const { return context; } - -private: - EGLDisplay display; - EGLConfig config; - EGLSurface surface; - EGLContext context; -}; - -TEST_F(SwiftShaderTest, Initalization) -{ - Initialize(2, true); - - const GLubyte *glVendor = glGetString(GL_VENDOR); - EXPECT_NO_GL_ERROR(); - EXPECT_STREQ("Google Inc.", (const char *)glVendor); - - const GLubyte *glRenderer = glGetString(GL_RENDERER); - EXPECT_NO_GL_ERROR(); - EXPECT_STREQ("Google SwiftShader", (const char *)glRenderer); - - // SwiftShader return an OpenGL ES 3.0 context when a 2.0 context is requested, as allowed by the spec. - const GLubyte *glVersion = glGetString(GL_VERSION); - EXPECT_NO_GL_ERROR(); - EXPECT_THAT((const char *)glVersion, testing::HasSubstr("OpenGL ES 3.0 SwiftShader ")); - - Uninitialize(); -} - -// Test attempting to clear an incomplete framebuffer -TEST_F(SwiftShaderTest, ClearIncomplete) -{ - Initialize(3, false); - - GLfloat zero_float = 0; - GLuint renderbuffer; - glGenRenderbuffers(1, &renderbuffer); - GLuint framebuffer; - glGenFramebuffers(1, &framebuffer); - - glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer); - EXPECT_NO_GL_ERROR(); - glRenderbufferStorage(GL_RENDERBUFFER, GL_R8I, 43, 27); - EXPECT_NO_GL_ERROR(); - glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer); - EXPECT_NO_GL_ERROR(); - glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer); - EXPECT_NO_GL_ERROR(); - glBindFramebuffer(GL_FRAMEBUFFER, framebuffer); - EXPECT_NO_GL_ERROR(); - glClearBufferfv(GL_DEPTH, 0, &zero_float); - EXPECT_GLENUM_EQ(GL_INVALID_FRAMEBUFFER_OPERATION, glGetError()); - - Uninitialize(); -} - -// Test unrolling of a loop -TEST_F(SwiftShaderTest, UnrollLoop) -{ - Initialize(3, false); - - unsigned char green[4] = { 0, 255, 0, 255 }; - - const std::string vs = - R"(#version 300 es - in vec4 position; - out vec4 color; - void main() - { - for(int i = 0; i < 4; i++) - { - color[i] = (i % 2 == 0) ? 0.0 : 1.0; - } - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - in vec4 color; - out vec4 fragColor; - void main() - { - fragColor = color; - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - // Expect the info log to contain "unrolled". This is not a spec requirement. - GLsizei length = 0; - glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length); - EXPECT_NO_GL_ERROR(); - EXPECT_NE(length, 0); - char *log = new char[length]; - GLsizei written = 0; - glGetShaderInfoLog(ph.vertexShader, length, &written, log); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(length, written + 1); - EXPECT_NE(strstr(log, "unrolled"), nullptr); - delete[] log; - - glUseProgram(ph.program); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program); - - deleteProgram(ph); - - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test non-canonical or non-deterministic loops do not get unrolled -TEST_F(SwiftShaderTest, DynamicLoop) -{ - Initialize(3, false); - - const std::string vs = - R"(#version 300 es - in vec4 position; - out vec4 color; - void main() - { - for(int i = 0; i < 4; ) - { - color[i] = (i % 2 == 0) ? 0.0 : 1.0; - i++; - } - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - in vec4 color; - out vec4 fragColor; - void main() - { - vec4 temp; - for(int i = 0; i < 4; i++) - { - if(color.x < 0.0) return; - temp[i] = color[i]; - } - fragColor = vec4(temp[0], temp[1], temp[2], temp[3]); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - // Expect the info logs to be empty. This is not a spec requirement. - GLsizei length = 0; - glGetShaderiv(ph.vertexShader, GL_INFO_LOG_LENGTH, &length); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(length, 0); - glGetShaderiv(ph.fragmentShader, GL_INFO_LOG_LENGTH, &length); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(length, 0); - - glUseProgram(ph.program); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program); - - deleteProgram(ph); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test dynamic indexing -TEST_F(SwiftShaderTest, DynamicIndexing) -{ - Initialize(3, false); - - const std::string vs = - R"(#version 300 es - in vec4 position; - out float color[4]; - void main() - { - for(int i = 0; i < 4; ) - { - int j = (gl_VertexID + i) % 4; - color[j] = (j % 2 == 0) ? 0.0 : 1.0; - i++; - } - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - in float color[4]; - out vec4 fragColor; - void main() - { - float temp[4]; - for(int i = 0; i < 4; ) - { - temp[i] = color[i]; - i++; - } - fragColor = vec4(temp[0], temp[1], temp[2], temp[3]); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program); - - deleteProgram(ph); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test vertex attribute location linking -TEST_F(SwiftShaderTest, AttributeLocation) -{ - Initialize(3, false); - - const std::string vs = - R"(#version 300 es - layout(location = 0) in vec4 a0; // Explicitly bound in GLSL - layout(location = 2) in vec4 a2; // Explicitly bound in GLSL - in vec4 a5; // Bound to location 5 by API - in mat2 a3; // Implicit location - in vec4 a1; // Implicit location - in vec4 a6; // Implicit location - out vec4 color; - void main() - { - vec4 a34 = vec4(a3[0], a3[1]); - gl_Position = a0; - color = (a2 == vec4(1.0, 2.0, 3.0, 4.0) && - a34 == vec4(5.0, 6.0, 7.0, 8.0) && - a5 == vec4(9.0, 10.0, 11.0, 12.0) && - a1 == vec4(13.0, 14.0, 15.0, 16.0) && - a6 == vec4(17.0, 18.0, 19.0, 20.0)) ? - vec4(0.0, 1.0, 0.0, 1.0) : - vec4(1.0, 0.0, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - in vec4 color; - out vec4 fragColor; - void main() - { - fragColor = color; - })"; - - ProgramHandles ph; - ph.vertexShader = MakeShader(vs, GL_VERTEX_SHADER); - ph.fragmentShader = MakeShader(fs, GL_FRAGMENT_SHADER); - ph.program = glCreateProgram(); - EXPECT_NO_GL_ERROR(); - - // Not assigned a layout location in GLSL. Bind it explicitly with the API. - glBindAttribLocation(ph.program, 5, "a5"); - EXPECT_NO_GL_ERROR(); - - // Should not override GLSL layout location qualifier - glBindAttribLocation(ph.program, 8, "a2"); - EXPECT_NO_GL_ERROR(); - - glAttachShader(ph.program, ph.vertexShader); - glAttachShader(ph.program, ph.fragmentShader); - glLinkProgram(ph.program); - EXPECT_NO_GL_ERROR(); - - // Changes after linking should have no effect - glBindAttribLocation(ph.program, 0, "a1"); - glBindAttribLocation(ph.program, 6, "a2"); - glBindAttribLocation(ph.program, 2, "a6"); - - GLint linkStatus = 0; - glGetProgramiv(ph.program, GL_LINK_STATUS, &linkStatus); - EXPECT_NE(linkStatus, 0); - EXPECT_NO_GL_ERROR(); - - float vertices[6][3] = { { -1.0f, 1.0f, 0.5f }, - { -1.0f, -1.0f, 0.5f }, - { 1.0f, -1.0f, 0.5f }, - { -1.0f, 1.0f, 0.5f }, - { 1.0f, -1.0f, 0.5f }, - { 1.0f, 1.0f, 0.5f } }; - - float attributes[5][4] = { { 1.0f, 2.0f, 3.0f, 4.0f }, - { 5.0f, 6.0f, 7.0f, 8.0f }, - { 9.0f, 10.0f, 11.0f, 12.0f }, - { 13.0f, 14.0f, 15.0f, 16.0f }, - { 17.0f, 18.0f, 19.0f, 20.0f } }; - - GLint a0 = glGetAttribLocation(ph.program, "a0"); - EXPECT_EQ(a0, 0); - glVertexAttribPointer(a0, 3, GL_FLOAT, GL_FALSE, 0, vertices); - glEnableVertexAttribArray(a0); - EXPECT_NO_GL_ERROR(); - - GLint a2 = glGetAttribLocation(ph.program, "a2"); - EXPECT_EQ(a2, 2); - glVertexAttribPointer(a2, 4, GL_FLOAT, GL_FALSE, 0, attributes[0]); - glVertexAttribDivisor(a2, 1); - glEnableVertexAttribArray(a2); - EXPECT_NO_GL_ERROR(); - - GLint a3 = glGetAttribLocation(ph.program, "a3"); - EXPECT_EQ(a3, 3); // Note: implementation specific - glVertexAttribPointer(a3 + 0, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][0]); - glVertexAttribPointer(a3 + 1, 2, GL_FLOAT, GL_FALSE, 0, &attributes[1][2]); - glVertexAttribDivisor(a3 + 0, 1); - glVertexAttribDivisor(a3 + 1, 1); - glEnableVertexAttribArray(a3 + 0); - glEnableVertexAttribArray(a3 + 1); - EXPECT_NO_GL_ERROR(); - - GLint a5 = glGetAttribLocation(ph.program, "a5"); - EXPECT_EQ(a5, 5); - glVertexAttribPointer(a5, 4, GL_FLOAT, GL_FALSE, 0, attributes[2]); - glVertexAttribDivisor(a5, 1); - glEnableVertexAttribArray(a5); - EXPECT_NO_GL_ERROR(); - - GLint a1 = glGetAttribLocation(ph.program, "a1"); - EXPECT_EQ(a1, 1); // Note: implementation specific - glVertexAttribPointer(a1, 4, GL_FLOAT, GL_FALSE, 0, attributes[3]); - glVertexAttribDivisor(a1, 1); - glEnableVertexAttribArray(a1); - EXPECT_NO_GL_ERROR(); - - GLint a6 = glGetAttribLocation(ph.program, "a6"); - EXPECT_EQ(a6, 6); // Note: implementation specific - glVertexAttribPointer(a6, 4, GL_FLOAT, GL_FALSE, 0, attributes[4]); - glVertexAttribDivisor(a6, 1); - glEnableVertexAttribArray(a6); - EXPECT_NO_GL_ERROR(); - - glUseProgram(ph.program); - glDrawArrays(GL_TRIANGLES, 0, 6); - EXPECT_NO_GL_ERROR(); - - deleteProgram(ph); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test negative layout locations -TEST_F(SwiftShaderTest, NegativeLocation) -{ - const std::string vs = - R"(#version 300 es - layout(location = 0x86868686u) in vec4 a0; // Explicitly bound in GLSL - layout(location = 0x96969696u) in vec4 a2; // Explicitly bound in GLSL - in vec4 a5; // Bound to location 5 by API - in mat2 a3; // Implicit location - in vec4 a1; // Implicit location - in vec4 a6; // Implicit location - out vec4 color; - float F(float f) - { - vec4 a34 = vec4(a3[0], a3[1]);\n" - gl_Position = a0;\n" - color = (a2 == vec4(1.0, 2.0, 3.0, 4.0) && - a34 == vec4(5.0, 6.0, 7.0, 8.0) && - a5 == vec4(9.0, 10.0, 11.0, 12.0) && - a1 == vec4(13.0, 14.0, 15.0, 16.0) && - a6 == vec4(17.0, 18.0, 19.0, 20.0)) ? - vec4(0.0, 1.0, 0.0, 1.0) : - vec4(1.0, 0.0, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - in vec4 color; - layout(location = 0xA6A6A6A6u) out vec4 fragColor; - float F main() - { - fragColor = color; - })"; - - { - std::string log = checkCompileFails(vs, GL_VERTEX_SHADER); - EXPECT_NE(strstr(log.c_str(), "out of range: location must be non-negative"), nullptr); - } - - { - std::string log = checkCompileFails(fs, GL_FRAGMENT_SHADER); - EXPECT_NE(strstr(log.c_str(), "out of range: location must be non-negative"), nullptr); - } -} - -// Tests clearing of a texture with 'dirty' content. -TEST_F(SwiftShaderTest, ClearDirtyTexture) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_R11F_G11F_B10F, 256, 256, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, nullptr); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); - EXPECT_NO_GL_ERROR(); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); - - float dirty_color[3] = { 128 / 255.0f, 64 / 255.0f, 192 / 255.0f }; - GLint dirty_x = 8; - GLint dirty_y = 12; - glTexSubImage2D(GL_TEXTURE_2D, 0, dirty_x, dirty_y, 1, 1, GL_RGB, GL_FLOAT, dirty_color); - - const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f }; - glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - expectFramebufferColor(clear_color, dirty_x, dirty_y); - - Uninitialize(); -} - -// Tests copying between textures of different floating-point formats using a framebuffer object. -TEST_F(SwiftShaderTest, CopyTexImage) -{ - Initialize(3, false); - - GLuint tex1 = 1; - float green[4] = { 0.0f, 1.0f, 0.0f, 1.0f }; - glBindTexture(GL_TEXTURE_2D, tex1); - glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, 16, 16); - glTexSubImage2D(GL_TEXTURE_2D, 0, 5, 10, 1, 1, GL_RGBA, GL_FLOAT, &green); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0); - EXPECT_NO_GL_ERROR(); - - GLuint tex2 = 2; - glBindTexture(GL_TEXTURE_2D, tex2); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 6, 8, 8, 0); - EXPECT_NO_GL_ERROR(); - - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex2, 0); - expectFramebufferColor(green, 3, 4); - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Tests copying to a texture from a pixel buffer object -TEST_F(SwiftShaderTest, CopyTexImageFromPixelBuffer) -{ - Initialize(3, false); - const GLuint red = 0xff0000ff; - const GLuint green = 0x00ff00ff; - const GLuint blue = 0x0000ffff; - // Set up texture - GLuint texture = 0; - glGenTextures(1, &texture); - EXPECT_NO_GL_ERROR(); - GLuint tex_data[4][4] = { - { red, red, red, red }, - { red, red, red, red }, - { red, red, red, red }, - { red, red, red, red } - }; - glBindTexture(GL_TEXTURE_2D, texture); - EXPECT_NO_GL_ERROR(); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void *)tex_data[0]); - EXPECT_NO_GL_ERROR(); - // Set up Pixel Buffer Object - GLuint pixelBuffer = 0; - glGenBuffers(1, &pixelBuffer); - glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pixelBuffer); - EXPECT_NO_GL_ERROR(); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 4); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - EXPECT_NO_GL_ERROR(); - GLuint pixel_data[4][4] = { - { blue, blue, green, green }, - { blue, blue, green, green }, - { blue, blue, green, green }, - { blue, blue, green, green }, - }; - glBufferData(GL_PIXEL_UNPACK_BUFFER, sizeof(pixel_data), (void *)pixel_data, GL_STREAM_DRAW); - // Should set the 2-rightmost columns of the currently bound texture to the - // 2-rightmost columns of the PBO; - GLintptr offset = 2 * sizeof(GLuint); - glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 0, 2, 4, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(offset)); - EXPECT_NO_GL_ERROR(); - // Create an off-screen framebuffer to render the texture data to. - GLuint fbo = 0; - glGenFramebuffers(1, &fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); - EXPECT_NO_GL_ERROR(); - unsigned int color[4][4] = { - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 }, - { 0, 0, 0, 0 } - }; - glReadPixels(0, 0, 4, 4, GL_RGBA, GL_UNSIGNED_BYTE, &color); - EXPECT_NO_GL_ERROR(); - bool allEqual = true; - for(int i = 0; i < 4; i++) - { - for(int j = 0; j < 2; j++) - { - allEqual = allEqual && (color[i][j] == tex_data[i][j]); - allEqual = allEqual && (color[i][j + 2] == pixel_data[i][j + 2]); - if(!allEqual) - break; - } - if(!allEqual) - break; - } - EXPECT_EQ(allEqual, true); - // We can't use an offset of 3 GLuints or more, because the PBO is not large - // enough to satisfy such a request with the current GL_UNPACK_ROW_LENGTH. - offset = 3 * sizeof(GLuint); - glTexSubImage2D(GL_TEXTURE_2D, 0, 2, 0, 2, 4, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(offset)); - GLenum error = glGetError(); - EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, error); - Uninitialize(); -} - -// Tests reading of half-float textures. -TEST_F(SwiftShaderTest, ReadHalfFloat) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_2D, tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, 256, 256, 0, GL_RGB, GL_HALF_FLOAT, nullptr); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); - EXPECT_NO_GL_ERROR(); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); - - const float clear_color[4] = { 1.0f, 32.0f, 0.5f, 1.0f }; - glClearColor(clear_color[0], clear_color[1], clear_color[2], 1.0f); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - uint16_t pixel[3] = { 0x1234, 0x3F80, 0xAAAA }; - GLint x = 6; - GLint y = 3; - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, pixel); - - // This relies on GL_HALF_FLOAT being a valid type for read-back, - // which isn't guaranteed by the spec but is supported by SwiftShader. - uint16_t read_color[3] = { 0, 0, 0 }; - glReadPixels(x, y, 1, 1, GL_RGB, GL_HALF_FLOAT, &read_color); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(read_color[0], pixel[0]); - EXPECT_EQ(read_color[1], pixel[1]); - EXPECT_EQ(read_color[2], pixel[2]); - - Uninitialize(); -} - -// Tests construction of a structure containing a single matrix -TEST_F(SwiftShaderTest, MatrixInStruct) -{ - Initialize(2, false); - - const std::string fs = - R"(#version 100 - precision mediump float; - struct S - { - mat2 rotation; - }; - void main(void) - { - float angle = 1.0; - S(mat2(1.0, angle, 1.0, 1.0)); - })"; - - MakeShader(fs, GL_FRAGMENT_SHADER); - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, TestMat4Uniform) -{ - Initialize(3, false); - const std::string vs = R"(#version 300 es - precision highp float; - uniform mat4 UniformMatrix; - out vec4 color; - void main() - { - const vec4 pos[] = vec4[]( - vec4( 1., 1., .0, 1.), - vec4(-1., 1., .0, 1.), - vec4(-1., -1., .0, 1.), - vec4( 1., 1., .0, 1.), - vec4(-1., -1., .0, 1.), - vec4( 1., -1., .0, 1.)); - gl_Position = pos[gl_VertexID]; - color = vec4(vec3(UniformMatrix[0].xyz), 1.); - } - )"; - const std::string ps = R"(#version 300 es - precision highp float; - in vec4 color; - out vec4 fragColor; - void main() - { - fragColor = color; - })"; - const ProgramHandles ph = createProgram(vs, ps); - - glUseProgram(ph.program); - GLint location = glGetUniformLocation(ph.program, "UniformMatrix"); - ASSERT_NE(-1, location); - constexpr float unit_mat[] = { - 1., 0., 0., 0., - 0., 1., 0., 0., - 0., 0., 1., 0., - 0., 0., 0., 1. - }; - glUniformMatrix4fv(location, 1, GL_FALSE, unit_mat); - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - GLuint dummyvao = GL_NONE; - glGenVertexArrays(1, &dummyvao); - glBindVertexArray(dummyvao); - glDrawArrays(GL_TRIANGLES, 0, 6); - - EXPECT_NO_GL_ERROR(); - - unsigned char red[4] = { 255, 0, 0, 255 }; - expectFramebufferColor(red); - - Uninitialize(); -} - -// Test sampling from a sampler in a struct as a function argument -TEST_F(SwiftShaderTest, SamplerArrayInStructArrayAsFunctionArg) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_2D, tex); - EXPECT_NO_GL_ERROR(); - - unsigned char green[4] = { 0, 255, 0, 255 }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green); - EXPECT_NO_GL_ERROR(); - - const std::string vs = - R"(#version 300 es - in vec4 position; - void main() - { - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - struct SamplerStruct{ sampler2D tex[2]; }; - vec4 doSample(in SamplerStruct s[2]) - { - return texture(s[1].tex[1], vec2(0.0)); - } - uniform SamplerStruct samplerStruct[2]; - out vec4 fragColor; - void main() - { - fragColor = doSample(samplerStruct); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - GLint location = glGetUniformLocation(ph.program, "samplerStruct[1].tex[1]"); - ASSERT_NE(-1, location); - glUniform1i(location, 0); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program, "samplerStruct[1].tex[1]"); - - deleteProgram(ph); - - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test sampling from a sampler in a struct as a function argument -TEST_F(SwiftShaderTest, AtanCornerCases) -{ - Initialize(3, false); - - const std::string vs = - R"(#version 300 es - in vec4 position; - void main() - { - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - precision mediump float; - const float kPI = 3.14159265358979323846; - uniform float positive_value; - uniform float negative_value; - out vec4 fragColor; - void main() - { - // Should yield vec4(0, pi, pi/2, -pi/2) - vec4 result = atan(vec4(0.0, 0.0, positive_value, negative_value), - vec4(positive_value, negative_value, 0.0, 0.0)); - fragColor = (result / vec4(kPI)) + vec4(0.5, -0.5, 0.0, 1.0) + vec4(0.5 / 255.0); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - GLint positive_value = glGetUniformLocation(ph.program, "positive_value"); - ASSERT_NE(-1, positive_value); - GLint negative_value = glGetUniformLocation(ph.program, "negative_value"); - ASSERT_NE(-1, negative_value); - - float value = 1.0f; - glUniform1fv(positive_value, 1, &value); - value = -1.0f; - glUniform1fv(negative_value, 1, &value); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program, nullptr); - - deleteProgram(ph); - - unsigned char grey[4] = { 128, 128, 128, 128 }; - expectFramebufferColor(grey); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, TransformFeedback_DrawArraysInstanced) -{ - Initialize(3, false); - - std::string fs = - R"(#version 300 es - in mediump vec2 vary; - out mediump vec4 color; - void main() - { - color = vec4(vary, 0.0, 1.0); - })"; - std::string vs = - R"(#version 300 es - layout(location=0) in mediump vec2 pos; - out mediump vec2 vary; - void main() - { - vary = pos; - gl_Position = vec4(pos, 0.0, 1.0); - })"; - - GLuint vert = MakeShader(vs, GL_VERTEX_SHADER); - GLuint frag = MakeShader(fs, GL_FRAGMENT_SHADER); - GLuint program = MakeProgram(vert, frag); - LinkProgram(program); - glBeginTransformFeedback(GL_POINTS); - glDrawArraysInstanced(GL_POINTS, 0, 1, 1); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, TransformFeedback_BadViewport) -{ - Initialize(3, false); - - GLuint tfBuffer; - glGenBuffers(1, &tfBuffer); - glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfBuffer); - glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1 << 12, nullptr, GL_STATIC_DRAW); - - std::string vsSource = - R"(#version 300 es - in vec4 a_position; - void main() - { - gl_Position = a_position; - })"; - std::string fsSource = - R"(#version 300 es - precision highp float; - out vec4 my_FragColor; - void main() - { - my_FragColor = vec4(1.0, 0.0, 0.0, 1.0); - })"; - - const char *varyings[] = { "gl_Position" }; - - GLuint vs = MakeShader(vsSource, GL_VERTEX_SHADER); - GLuint fs = MakeShader(fsSource, GL_FRAGMENT_SHADER); - GLuint program = MakeProgram(vs, fs); - - glTransformFeedbackVaryings(program, 1, - &varyings[0], GL_INTERLEAVED_ATTRIBS); - LinkProgram(program); - glUseProgram(program); - - glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfBuffer); - glBeginTransformFeedback(GL_TRIANGLES); - - GLuint primitivesWrittenQuery = 0; - glGenQueries(1, &primitivesWrittenQuery); - glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, primitivesWrittenQuery); - - glViewport(0, 10000000, 300, 300); - - GLint positionLocation = glGetAttribLocation(program, "a_position"); - GLfloat quadVertices[] = { - -1.0f, - 1.0f, - 0.5f, - -1.0f, - -1.0f, - 0.5f, - 1.0f, - -1.0f, - 0.5f, - -1.0f, - 1.0f, - 0.5f, - 1.0f, - -1.0f, - 0.5f, - 1.0f, - 1.0f, - 0.5f, - }; - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, &quadVertices[0]); - - glDrawArrays(GL_TRIANGLES, 0, 6); - glDisableVertexAttribArray(positionLocation); - glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr); - - glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); - glEndTransformFeedback(); - - GLuint primitivesWritten = 0; - glGetQueryObjectuiv(primitivesWrittenQuery, GL_QUERY_RESULT_EXT, &primitivesWritten); - EXPECT_NO_GL_ERROR(); - - EXPECT_EQ(2u, primitivesWritten); - - Uninitialize(); -} - -// Test conditions that should result in a GL_OUT_OF_MEMORY and not crash -TEST_F(SwiftShaderTest, OutOfMemory) -{ - // Image sizes are assumed to fit in a 32-bit signed integer by the renderer, - // so test that we can't create a 2+ GiB image. - { - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_3D, tex); - - const int width = 0xC2; - const int height = 0x541; - const int depth = 0x404; - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, width, height, depth, 0, GL_RGBA, GL_FLOAT, nullptr); - EXPECT_GLENUM_EQ(GL_OUT_OF_MEMORY, glGetError()); - - // b/145229887: Allocating an image of exactly 1 GiB should succeed. - const int width8k = 8192; - const int height8k = 8192; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width8k, height8k, 0, GL_RGBA, GL_FLOAT, nullptr); - EXPECT_NO_GL_ERROR(); - - // The spec states that the GL is in an undefined state when GL_OUT_OF_MEMORY - // is returned, and the context must be recreated before attempting more rendering. - Uninitialize(); - } -} - -TEST_F(SwiftShaderTest, ViewportBounds) -{ - auto doRenderWithViewportSettings = [&](GLint x, GLint y, GLsizei w, GLsizei h) { - Initialize(3, false); - - std::string vs = - R"(#version 300 es - in vec4 position; - out float unfoldable; - void main() - { - unfoldable = position.x; - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - std::string fs = - R"(#version 300 es - precision mediump float; - in float unfoldable; - out vec4 fragColor; - void main() - { - fragColor = vec4(1.0, 1.0, 1.0, 1.0); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - - glViewport(x, y, w, h); - - drawQuad(ph.program); - EXPECT_NO_GL_ERROR(); - - deleteProgram(ph); - Uninitialize(); - }; - - GLsizei w = 100; - GLsizei h = 100; - GLint minPos = -2000; - - doRenderWithViewportSettings(0, 0, 0, 0); - doRenderWithViewportSettings(0, 0, w, h); - - // Negative positions - doRenderWithViewportSettings(minPos, 0, w, h); - doRenderWithViewportSettings(0, minPos, w, h); - doRenderWithViewportSettings(minPos, minPos, w, h); -} - -// Test using TexImage2D to define a rectangle texture - -TEST_F(SwiftShaderTest, TextureRectangle_TexImage2D) -{ - Initialize(2, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - - // Defining level 0 is allowed - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_NO_GL_ERROR(); - - // Defining level other than 0 is not allowed - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - - GLint maxSize = 0; - glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize); - - // Defining a texture of the max size is allowed - { - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - GLenum error = glGetError(); - ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY); - } - - // Defining a texture larger than the max size is disallowed - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize + 1, maxSize, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, maxSize, maxSize + 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - - Uninitialize(); -} - -// Test using CompressedTexImage2D cannot be used on a retangle texture -TEST_F(SwiftShaderTest, TextureRectangle_CompressedTexImage2DDisallowed) -{ - Initialize(2, false); - - const char data[128] = { 0 }; - - // Control case: 2D texture - { - GLuint tex = 1; - glBindTexture(GL_TEXTURE_2D, tex); - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data); - EXPECT_NO_GL_ERROR(); - } - - // Rectangle textures cannot be compressed - { - GLuint tex = 2; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glCompressedTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - } - - Uninitialize(); -} - -// Test using TexStorage2D to define a rectangle texture (ES3) -TEST_F(SwiftShaderTest, TextureRectangle_TexStorage2D) -{ - Initialize(3, false); - - // Defining one level is allowed - { - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, 16, 16); - EXPECT_NO_GL_ERROR(); - } - - // Having more than one level is not allowed - { - GLuint tex = 2; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - // Use 5 levels because the EXT_texture_storage extension requires a mip chain all the way - // to a 1x1 mip. - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 5, GL_RGBA8UI, 16, 16); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - } - - GLint maxSize = 0; - glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &maxSize); - - // Defining a texture of the max size is allowed but still allow for OOM - { - GLuint tex = 3; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize); - GLenum error = glGetError(); - ASSERT_TRUE(error == GL_NO_ERROR || error == GL_OUT_OF_MEMORY); - } - - // Defining a texture larger than the max size is disallowed - { - GLuint tex = 4; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize + 1, maxSize); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8UI, maxSize, maxSize + 1); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - } - - // Compressed formats are disallowed - GLuint tex = 5; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glTexStorage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - Uninitialize(); -} - -// Test validation of disallowed texture parameters -TEST_F(SwiftShaderTest, TextureRectangle_TexParameterRestriction) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - - // Only wrap mode CLAMP_TO_EDGE is supported - // Wrap S - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - EXPECT_NO_GL_ERROR(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_REPEAT); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - // Wrap T - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - EXPECT_NO_GL_ERROR(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_REPEAT); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - // Min filter has to be nearest or linear - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - EXPECT_NO_GL_ERROR(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - EXPECT_NO_GL_ERROR(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - // Base level has to be 0 - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 0); - EXPECT_NO_GL_ERROR(); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_BASE_LEVEL, 1); - EXPECT_GLENUM_EQ(GL_INVALID_OPERATION, glGetError()); - - Uninitialize(); -} - -// Test validation of "level" in FramebufferTexture2D -TEST_F(SwiftShaderTest, TextureRectangle_FramebufferTexture2DLevel) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - - // Using level 0 of a rectangle texture is valid. - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); - EXPECT_NO_GL_ERROR(); - - // Setting level != 0 is invalid - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 1); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - - Uninitialize(); -} - -// Test sampling from a rectangle texture -TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangle) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - EXPECT_NO_GL_ERROR(); - - unsigned char green[4] = { 0, 255, 0, 255 }; - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green); - EXPECT_NO_GL_ERROR(); - - const std::string vs = - R"(attribute vec4 position; - void main() - { - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#extension GL_ARB_texture_rectangle : require - precision mediump float; - uniform sampler2DRect tex; - void main() - { - gl_FragColor = texture2DRect(tex, vec2(0, 0)); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - GLint location = glGetUniformLocation(ph.program, "tex"); - ASSERT_NE(-1, location); - glUniform1i(location, 0); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program, "tex"); - - deleteProgram(ph); - - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test sampling from a rectangle texture -TEST_F(SwiftShaderTest, TextureRectangle_SamplingFromRectangleESSL3) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - EXPECT_NO_GL_ERROR(); - - unsigned char green[4] = { 0, 255, 0, 255 }; - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, green); - EXPECT_NO_GL_ERROR(); - - const std::string vs = - R"(#version 300 es - in vec4 position; - void main() - { - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#version 300 es - #extension GL_ARB_texture_rectangle : require - precision mediump float; - uniform sampler2DRect tex; - out vec4 fragColor; - void main() - { - fragColor = texture(tex, vec2(0, 0)); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - glUseProgram(ph.program); - GLint location = glGetUniformLocation(ph.program, "tex"); - ASSERT_NE(-1, location); - glUniform1i(location, 0); - - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - drawQuad(ph.program, "tex"); - - deleteProgram(ph); - - expectFramebufferColor(green); - - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test attaching a rectangle texture and rendering to it. -TEST_F(SwiftShaderTest, TextureRectangle_RenderToRectangle) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - unsigned char black[4] = { 0, 0, 0, 255 }; - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0); - EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); - EXPECT_NO_GL_ERROR(); - - // Clearing a texture is just as good as checking we can render to it, right? - glClearColor(0.0, 1.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, TextureRectangle_DefaultSamplerParameters) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - - GLint minFilter = 0; - glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, &minFilter); - EXPECT_GLENUM_EQ(GL_LINEAR, minFilter); - - GLint wrapS = 0; - glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, &wrapS); - EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapS); - - GLint wrapT = 0; - glGetTexParameteriv(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, &wrapT); - EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, wrapT); - - Uninitialize(); -} - -// Test glCopyTexImage with rectangle textures (ES3) -TEST_F(SwiftShaderTest, TextureRectangle_CopyTexImage) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - // Error case: level != 0 - glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, GL_RGBA8, 0, 0, 1, 1, 0); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - - // level = 0 works and defines the texture. - glCopyTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, 0, 0, 1, 1, 0); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -// Test glCopyTexSubImage with rectangle textures (ES3) -TEST_F(SwiftShaderTest, TextureRectangle_CopyTexSubImage) -{ - Initialize(3, false); - - GLuint tex = 1; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, tex); - unsigned char black[4] = { 0, 0, 0, 255 }; - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - - // Error case: level != 0 - glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 1, 0, 0, 0, 0, 1, 1); - EXPECT_GLENUM_EQ(GL_INVALID_VALUE, glGetError()); - - // level = 0 works and defines the texture. - glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 0, 0, 1, 1); - EXPECT_NO_GL_ERROR(); - - GLuint fbo = 1; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, tex, 0); - - unsigned char green[4] = { 0, 255, 0, 255 }; - expectFramebufferColor(green); - EXPECT_NO_GL_ERROR(); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, BlitTest) -{ - Initialize(3, false); - - GLuint fbos[] = { 0, 0 }; - glGenFramebuffers(2, fbos); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, fbos[0]); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); - - GLuint textures[] = { 0, 0 }; - glGenTextures(2, textures); - - glBindTexture(GL_TEXTURE_2D, textures[0]); - unsigned char red[4][4] = { - { 255, 0, 0, 255 }, - { 255, 0, 0, 255 }, - { 255, 0, 0, 255 }, - { 255, 0, 0, 255 } - }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, red); - EXPECT_NO_GL_ERROR(); - - glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0); - EXPECT_NO_GL_ERROR(); - - glBindTexture(GL_TEXTURE_2D, textures[1]); - unsigned char black[4][4] = { - { 0, 0, 0, 255 }, - { 0, 0, 0, 255 }, - { 0, 0, 0, 255 }, - { 0, 0, 0, 255 } - }; - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, black); - EXPECT_NO_GL_ERROR(); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0); - - // Test that glBlitFramebuffer works as expected for the normal case. - glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST); - EXPECT_NO_GL_ERROR(); - EXPECT_EQ(red[0][1], black[0][1]); - - // Check that glBlitFramebuffer doesn't crash with ugly input. - const int big = (int)2e9; - const int small = 200; - const int neg_small = -small; - const int neg_big = -big; - int max = 0x7fffffff; - int data[][8] = { - // sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 - { 0, 0, 0, 0, 0, 0, 0, 0 }, - { -1, -1, -1, -1, -1, -1, -1, -1 }, - { 1, 1, 1, 1, 1, 1, 1, 1 }, - { -1, -1, 1, 1, -1, -1, 1, 1 }, - { 0, 0, 127, (int)2e9, 10, 10, 200, 200 }, - { -2, -2, 127, 2147483470, 10, 10, 200, 200 }, - { big, small, small, big, big, big, small, small }, - { neg_small, small, neg_small, neg_small, neg_small, big, small }, - { big, big - 1, big - 2, big - 3, big - 4, big - 5, big - 6, big - 7 }, - { big, neg_big, neg_big, big, small, big, 0, neg_small }, - { 323479648, 21931, 1769809195, 32733, 0, 0, -161640504, 32766 }, - { 0, 0, max, max, 0, 0, 8, 8 }, - { 0, 0, 8, 8, 0, 0, max, max }, - { 0, 0, max, max, 0, 0, max, max }, - { -1, -1, max, max, 0, 0, 8, 8 }, - { 0, 0, 8, 8, -1, -1, max, max }, - { -1, -1, max, max, -1, -1, max, max }, - { -max - 1, -max - 1, max, max, -max - 1, -max - 1, max, max } - }; - - for(int i = 0; i < (int)(sizeof(data) / sizeof(data[0])); i++) - { - glBlitFramebuffer( - data[i][0], data[i][1], data[i][2], data[i][3], - data[i][4], data[i][5], data[i][6], data[i][7], - GL_COLOR_BUFFER_BIT, GL_NEAREST); - // Ignore error state, just make sure that we don't crash on these inputs. - } - - // Clear the error state before uninitializing test. - glGetError(); - - glDeleteFramebuffers(2, fbos); - glDeleteTextures(2, textures); - Uninitialize(); -} - -TEST_F(SwiftShaderTest, InvalidEnum_TexImage2D) -{ - Initialize(3, false); - - const GLenum invalidTarget = GL_TEXTURE_3D; - - glTexImage2D(invalidTarget, 0, GL_R11F_G11F_B10F, 256, 256, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, nullptr); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - float pixels[3] = { 0.0f, 0.0f, 0.0f }; - glTexSubImage2D(invalidTarget, 0, 0, 0, 1, 1, GL_RGB, GL_FLOAT, pixels); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - glCopyTexImage2D(invalidTarget, 0, GL_RGB, 2, 6, 8, 8, 0); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - glCopyTexSubImage2D(invalidTarget, 0, 0, 0, 0, 0, 1, 1); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - const char data[128] = { 0 }; - glCompressedTexImage2D(invalidTarget, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 16, 16, 0, 128, data); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - glCompressedTexSubImage2D(invalidTarget, 0, 0, 0, 0, 0, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 0, 0); - EXPECT_GLENUM_EQ(GL_INVALID_ENUM, glGetError()); - - Uninitialize(); -} - -TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedIfs) -{ - std::string body = "return 1.0;"; - for(int i = 0; i < 16; i++) - { - body = " if (f > " + std::to_string(i * 0.1f) + ") {\n" + body + "}\n"; - } - - checkCompiles( - "float F(float f) {\n" + body + " return 0.0f;\n}\n"); -} - -TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedSwitches) -{ - std::string body = "return 1.0;"; - for(int i = 0; i < 16; i++) - { - body = " switch (int(f)) {\n case 1:\n f *= 2.0;\n" + body + "}\n"; - } - - checkCompiles("float F(float f) {\n" + body + " return 0.0f;\n}\n"); -} - -TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedLoops) -{ - std::string loops = "f = f + f * 2.0;"; - for(int i = 0; i < 16; i++) - { - auto it = "l" + std::to_string(i); - loops = " for (int " + it + " = 0; " + it + " < i; " + it + "++) {\n" + loops + "}\n"; - } - - checkCompiles( - "float F(float f) {\n" - " int i = (f > 0.0) ? 1 : 0;\n" + - loops + - " return f;\n" - "}\n"); -} - -TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedCalls) -{ - std::string funcs = "float E(float f) { return f * 2.0f; }\n"; - std::string last = "E"; - for(int i = 0; i < 16; i++) - { - std::string f = "C" + std::to_string(i); - funcs += "float " + f + "(float f) { return " + last + "(f) + 1.0f; }\n"; - last = f; - } - - checkCompiles(funcs + - "float F(float f) { return " + last + "(f); }\n"); -} - -TEST_F(SwiftShaderTest, CompilerLimits_ManyCallSites) -{ - std::string calls; - for(int i = 0; i < 256; i++) - { - calls += " f += C(f);\n"; - } - - checkCompiles( - "float C(float f) { return f * 2.0f; }\n" - "float F(float f) {\n" + - calls + " return f;\n}\n"); -} - -TEST_F(SwiftShaderTest, CompilerLimits_DeepNestedCallsInUnusedFunction) -{ - std::string funcs = "float E(float f) { return f * 2.0f; }\n"; - std::string last = "E"; - for(int i = 0; i < 16; i++) - { - std::string f = "C" + std::to_string(i); - funcs += "float " + f + "(float f) { return " + last + "(f) + 1.0f; }\n"; - last = f; - } - - checkCompiles(funcs + - "float F(float f) { return f; }\n"); -} - -// Test that the compiler correctly handles functions being stripped. -// The frontend will strip the Dead functions, but may keep the their function -// labels reserved. This produces labels that are greater than the number of -// live functions. -TEST_F(SwiftShaderTest, CompilerLimits_SparseLabels) -{ - checkCompiles( - R"(void Dead1() {} - void Dead2() {} - void Dead3() {} - void Dead4() {} - void Dead5() { Dead1(); Dead2(); Dead3(); Dead4(); } - float F(float f) { for(int i = 0; i < -1; ++i) { Dead5(); } return f; })"); -} - -// Test that the compiler doesn't compile arrays larger than -// GL_MAX_{VERTEX/FRAGMENT}_UNIFORM_VECTOR. -TEST_F(SwiftShaderTest, CompilerLimits_ArraySize) -{ - checkCompileFails( - R"(uniform float u_var[100000000]; - float F(float f) { return u_var[2]; })"); - checkCompileFails( - R"(struct structType { mediump sampler2D m0; mediump samplerCube m1; }; - uniform structType u_var[100000000]; - float F(float f) { return texture(u_var[2].m1, vec3(0.0)), vec4(0.26, 1.72, 0.60, 0.12).x; })"); -} - -// Test that the compiler rejects negations of things that can't be negated. -TEST_F(SwiftShaderTest, BadNegation) -{ - checkCompileFails( - R"(uniform samplerCube m; - float F (float f) { vec4 ret = texture(-m, vec3(f)); return ret.x; })"); - checkCompileFails( - R"(uniform sampler2D m[9]; - vec4 G (sampler2D X[9]) { return texture(X[0], vec2(0.0f)); } - float F (float f) { vec4 ret = G(-m); return ret.x; })"); - checkCompileFails( - R"(struct structType { int a; float b; }; - uniform structType m; - float F (float f) { structType n = -m; return f; })"); - checkCompileFails( - R"(struct structType { int a; float b; }; - uniform structType m[4]; - float F (float f) { structType n[4] = -m; return f; })"); - checkCompileFails( - R"(uniform float m[4]; - float G (float f[4]) { return f[0]; } - float F (float f) { return G(-m); })"); -} - -TEST_F(SwiftShaderTest, SwitchDefaultOnly) -{ - checkCompiles(R"( - float F (float f) { - switch (0u) { - default: - return -f; - } - return f; - })"); -} - -#ifndef EGL_ANGLE_iosurface_client_buffer -# define EGL_ANGLE_iosurface_client_buffer 1 -# define EGL_IOSURFACE_ANGLE 0x3454 -# define EGL_IOSURFACE_PLANE_ANGLE 0x345A -# define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B -# define EGL_TEXTURE_TYPE_ANGLE 0x345C -# define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D -#endif /* EGL_ANGLE_iosurface_client_buffer */ - -#if defined(__APPLE__) -# include <CoreFoundation/CoreFoundation.h> -# include <IOSurface/IOSurface.h> - -namespace { -void AddIntegerValue(CFMutableDictionaryRef dictionary, const CFStringRef key, int32_t value) -{ - CFNumberRef number = CFNumberCreate(nullptr, kCFNumberSInt32Type, &value); - CFDictionaryAddValue(dictionary, key, number); - CFRelease(number); -} -} // anonymous namespace - -class EGLClientBufferWrapper -{ -public: - EGLClientBufferWrapper(int width = 1, int height = 1) - { - // Create a 1 by 1 BGRA8888 IOSurface - ioSurface = nullptr; - - CFMutableDictionaryRef dict = CFDictionaryCreateMutable( - kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - AddIntegerValue(dict, kIOSurfaceWidth, width); - AddIntegerValue(dict, kIOSurfaceHeight, height); - AddIntegerValue(dict, kIOSurfacePixelFormat, 'BGRA'); - AddIntegerValue(dict, kIOSurfaceBytesPerElement, 4); - - ioSurface = IOSurfaceCreate(dict); - CFRelease(dict); - - EXPECT_NE(nullptr, ioSurface); - } - - ~EGLClientBufferWrapper() - { - IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr); - - CFRelease(ioSurface); - } - - EGLClientBuffer getClientBuffer() const - { - return ioSurface; - } - - const unsigned char *lockColor() - { - IOSurfaceLock(ioSurface, kIOSurfaceLockReadOnly, nullptr); - return reinterpret_cast<const unsigned char *>(IOSurfaceGetBaseAddress(ioSurface)); - } - - void unlockColor() - { - IOSurfaceUnlock(ioSurface, kIOSurfaceLockReadOnly, nullptr); - } - - void writeColor(void *data, size_t dataSize) - { - // Write the data to the IOSurface - IOSurfaceLock(ioSurface, 0, nullptr); - memcpy(IOSurfaceGetBaseAddress(ioSurface), data, dataSize); - IOSurfaceUnlock(ioSurface, 0, nullptr); - } - -private: - IOSurfaceRef ioSurface; -}; - -#else // __APPLE__ - -class EGLClientBufferWrapper -{ -public: - EGLClientBufferWrapper(int width = 1, int height = 1) - { - clientBuffer = new unsigned char[4 * width * height]; - } - - ~EGLClientBufferWrapper() - { - delete[] clientBuffer; - } - - EGLClientBuffer getClientBuffer() const - { - return clientBuffer; - } - - const unsigned char *lockColor() - { - return clientBuffer; - } - - void unlockColor() - { - } - - void writeColor(void *data, size_t dataSize) - { - memcpy(clientBuffer, data, dataSize); - } - -private: - unsigned char *clientBuffer; -}; - -#endif - -class IOSurfaceClientBufferTest : public SwiftShaderTest -{ -protected: - EGLSurface createIOSurfacePbuffer(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type) const - { - // Make a PBuffer from it using the EGL_ANGLE_iosurface_client_buffer extension - const EGLint attribs[] = { - EGL_WIDTH, - width, - EGL_HEIGHT, - height, - EGL_IOSURFACE_PLANE_ANGLE, - plane, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - (EGLint)internalFormat, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - (EGLint)type, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, buffer, getConfig(), attribs); - EXPECT_NE(EGL_NO_SURFACE, pbuffer); - return pbuffer; - } - - void bindIOSurfaceToTexture(EGLClientBuffer buffer, EGLint width, EGLint height, EGLint plane, GLenum internalFormat, GLenum type, EGLSurface *pbuffer, GLuint *texture) const - { - *pbuffer = createIOSurfacePbuffer(buffer, width, height, plane, internalFormat, type); - - // Bind the pbuffer - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, *texture); - EGLBoolean result = eglBindTexImage(getDisplay(), *pbuffer, EGL_BACK_BUFFER); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - } - - void doClear(GLenum internalFormat, bool clearToZero) - { - if(internalFormat == GL_R16UI) - { - GLuint color = clearToZero ? 0 : 257; - glClearBufferuiv(GL_COLOR, 0, &color); - EXPECT_NO_GL_ERROR(); - } - else - { - glClearColor(clearToZero ? 0.0f : 1.0f / 255.0f, - clearToZero ? 0.0f : 2.0f / 255.0f, - clearToZero ? 0.0f : 3.0f / 255.0f, - clearToZero ? 0.0f : 4.0f / 255.0f); - EXPECT_NO_GL_ERROR(); - glClear(GL_COLOR_BUFFER_BIT); - EXPECT_NO_GL_ERROR(); - } - } - - void doClearTest(EGLClientBufferWrapper &clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize) - { - ASSERT_TRUE(dataSize <= 4); - - // Bind the IOSurface to a texture and clear it. - GLuint texture = 1; - EGLSurface pbuffer; - bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture); - - // glClear the pbuffer - GLuint fbo = 2; - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - EXPECT_NO_GL_ERROR(); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_RECTANGLE_ARB, texture, 0); - EXPECT_NO_GL_ERROR(); - EXPECT_GLENUM_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER), GL_FRAMEBUFFER_COMPLETE); - EXPECT_NO_GL_ERROR(); - - doClear(internalFormat, false); - - // Unbind pbuffer and check content. - EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - - const unsigned char *color = clientBufferWrapper.lockColor(); - for(size_t i = 0; i < dataSize; ++i) - { - EXPECT_EQ(color[i], reinterpret_cast<unsigned char *>(data)[i]); - } - - result = eglDestroySurface(getDisplay(), pbuffer); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - } - - void doSampleTest(EGLClientBufferWrapper &clientBufferWrapper, GLenum internalFormat, GLenum type, void *data, size_t dataSize) - { - ASSERT_TRUE(dataSize <= 4); - - clientBufferWrapper.writeColor(data, dataSize); - - // Bind the IOSurface to a texture and clear it. - GLuint texture = 1; - EGLSurface pbuffer; - bindIOSurfaceToTexture(clientBufferWrapper.getClientBuffer(), 1, 1, 0, internalFormat, type, &pbuffer, &texture); - - doClear(internalFormat, true); - - // Create program and draw quad using it - const std::string vs = - R"(attribute vec4 position; - void main() - { - gl_Position = vec4(position.xy, 0.0, 1.0); - })"; - - const std::string fs = - R"(#extension GL_ARB_texture_rectangle : require - precision mediump float; - uniform sampler2DRect tex; - void main() - { - gl_FragColor = texture2DRect(tex, vec2(0, 0)); - })"; - - const ProgramHandles ph = createProgram(vs, fs); - - drawQuad(ph.program, "tex"); - - deleteProgram(ph); - EXPECT_NO_GL_ERROR(); - - // Unbind pbuffer and check content. - EGLBoolean result = eglReleaseTexImage(getDisplay(), pbuffer, EGL_BACK_BUFFER); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - - const unsigned char *color = clientBufferWrapper.lockColor(); - for(size_t i = 0; i < dataSize; ++i) - { - EXPECT_EQ(color[i], reinterpret_cast<unsigned char *>(data)[i]); - } - clientBufferWrapper.unlockColor(); - } -}; - -// Tests for the EGL_ANGLE_iosurface_client_buffer extension -TEST_F(IOSurfaceClientBufferTest, RenderToBGRA8888IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[4] = { 3, 2, 1, 4 }; - doClearTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test reading from BGRA8888 IOSurfaces -TEST_F(IOSurfaceClientBufferTest, ReadFromBGRA8888IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[4] = { 3, 2, 1, 4 }; - doSampleTest(clientBufferWrapper, GL_BGRA_EXT, GL_UNSIGNED_BYTE, data, 4); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test using RGBX8888 IOSurfaces for rendering -TEST_F(IOSurfaceClientBufferTest, RenderToRGBX8888IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[3] = { 1, 2, 3 }; - doClearTest(clientBufferWrapper, GL_RGB, GL_UNSIGNED_BYTE, data, 3); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test reading from RGBX8888 IOSurfaces -TEST_F(IOSurfaceClientBufferTest, ReadFromRGBX8888IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[3] = { 1, 2, 3 }; - doSampleTest(clientBufferWrapper, GL_RGB, GL_UNSIGNED_BYTE, data, 3); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test using RG88 IOSurfaces for rendering -TEST_F(IOSurfaceClientBufferTest, RenderToRG88IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[2] = { 1, 2 }; - doClearTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test reading from RG88 IOSurfaces -TEST_F(IOSurfaceClientBufferTest, ReadFromRG88IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[2] = { 1, 2 }; - doSampleTest(clientBufferWrapper, GL_RG, GL_UNSIGNED_BYTE, data, 2); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test using R8 IOSurfaces for rendering -TEST_F(IOSurfaceClientBufferTest, RenderToR8IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[1] = { 1 }; - doClearTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test reading from R8 IOSurfaces -TEST_F(IOSurfaceClientBufferTest, ReadFromR8IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - unsigned char data[1] = { 1 }; - doSampleTest(clientBufferWrapper, GL_RED, GL_UNSIGNED_BYTE, data, 1); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test using R16 IOSurfaces for rendering -TEST_F(IOSurfaceClientBufferTest, RenderToR16IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - uint16_t data[1] = { 257 }; - doClearTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 2); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test reading from R8 IOSurfaces -TEST_F(IOSurfaceClientBufferTest, ReadFromR16IOSurface) -{ - Initialize(3, false); - - { // EGLClientBufferWrapper scope - EGLClientBufferWrapper clientBufferWrapper; - uint16_t data[1] = { 257 }; - doSampleTest(clientBufferWrapper, GL_R16UI, GL_UNSIGNED_SHORT, data, 1); - } // end of EGLClientBufferWrapper scope - - Uninitialize(); -} - -// Test the validation errors for missing attributes for eglCreatePbufferFromClientBuffer with -// IOSurface -TEST_F(IOSurfaceClientBufferTest, NegativeValidationMissingAttributes) -{ - Initialize(3, false); - - { - EGLClientBufferWrapper clientBufferWrapper(10, 10); - - // Success case - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_NE(EGL_NO_SURFACE, pbuffer); - - EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - } - - // Missing EGL_WIDTH - { - const EGLint attribs[] = { - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError()); - } - - // Missing EGL_HEIGHT - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError()); - } - - // Missing EGL_IOSURFACE_PLANE_ANGLE - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError()); - } - - // Missing EGL_TEXTURE_TARGET - EGL_BAD_MATCH from the base spec of - // eglCreatePbufferFromClientBuffer - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_MATCH, eglGetError()); - } - - // Missing EGL_TEXTURE_INTERNAL_FORMAT_ANGLE - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError()); - } - - // Missing EGL_TEXTURE_FORMAT - EGL_BAD_MATCH from the base spec of - // eglCreatePbufferFromClientBuffer - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_MATCH, eglGetError()); - } - - // Missing EGL_TEXTURE_TYPE_ANGLE - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_PARAMETER, eglGetError()); - } - } - - Uninitialize(); -} - -// Test the validation errors for bad parameters for eglCreatePbufferFromClientBuffer with IOSurface -TEST_F(IOSurfaceClientBufferTest, NegativeValidationBadAttributes) -{ - Initialize(3, false); - - { - EGLClientBufferWrapper clientBufferWrapper(10, 10); - - // Success case - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_NE(EGL_NO_SURFACE, pbuffer); - - EGLBoolean result = eglDestroySurface(getDisplay(), pbuffer); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - } - - // EGL_TEXTURE_FORMAT must be EGL_TEXTURE_RGBA - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGB, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // EGL_WIDTH must be at least 1 - { - const EGLint attribs[] = { - EGL_WIDTH, - 0, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // EGL_HEIGHT must be at least 1 - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 0, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - -#if defined(__APPLE__) - // EGL_WIDTH must be at most the width of the IOSurface - { - const EGLint attribs[] = { - EGL_WIDTH, - 11, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // EGL_HEIGHT must be at most the height of the IOSurface - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 11, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // EGL_IOSURFACE_PLANE_ANGLE must less than the number of planes of the IOSurface - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 1, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } -#endif - - // EGL_TEXTURE_FORMAT must be at EGL_TEXTURE_RECTANGLE_ANGLE - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_2D, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // EGL_IOSURFACE_PLANE_ANGLE must be at least 0 - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - -1, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_BGRA_EXT, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - - // The internal format / type most be listed in the table - { - const EGLint attribs[] = { - EGL_WIDTH, - 10, - EGL_HEIGHT, - 10, - EGL_IOSURFACE_PLANE_ANGLE, - 0, - EGL_TEXTURE_TARGET, - EGL_TEXTURE_RECTANGLE_ANGLE, - EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, - GL_RGBA, - EGL_TEXTURE_FORMAT, - EGL_TEXTURE_RGBA, - EGL_TEXTURE_TYPE_ANGLE, - GL_UNSIGNED_BYTE, - EGL_NONE, - EGL_NONE, - }; - - EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(getDisplay(), EGL_IOSURFACE_ANGLE, clientBufferWrapper.getClientBuffer(), getConfig(), attribs); - EXPECT_EQ(EGL_NO_SURFACE, pbuffer); - EXPECT_EQ(EGL_BAD_ATTRIBUTE, eglGetError()); - } - } - - Uninitialize(); -} - -// Test IOSurface pbuffers can be made current -TEST_F(IOSurfaceClientBufferTest, MakeCurrentAllowed) -{ - Initialize(3, false); - - { - EGLClientBufferWrapper clientBufferWrapper(10, 10); - - EGLSurface pbuffer = createIOSurfacePbuffer(clientBufferWrapper.getClientBuffer(), 10, 10, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE); - - EGLBoolean result = eglMakeCurrent(getDisplay(), pbuffer, pbuffer, getContext()); - EXPECT_EQ((EGLBoolean)EGL_TRUE, result); - EXPECT_NO_EGL_ERROR(); - } - - Uninitialize(); -} |