TEST_F(CollectVertexVariablesTest, VaryingInterpolation) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "centroid out float vary;\n" "void main() {\n" " gl_Position = vec4(1.0);\n" " vary = 1.0;\n" "}\n"; const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::Varying> &varyings = mTranslator->getVaryings(); ASSERT_EQ(2u, varyings.size()); const sh::Varying *varying = &varyings[0]; if (varying->name == "gl_Position") { varying = &varyings[1]; } EXPECT_EQ(0u, varying->arraySize); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, varying->precision); EXPECT_TRUE(varying->staticUse); EXPECT_GLENUM_EQ(GL_FLOAT, varying->type); EXPECT_EQ("vary", varying->name); EXPECT_EQ(sh::INTERPOLATION_CENTROID, varying->interpolation); }
TEST_F(CollectFragmentVariablesTest, LocationOutputVar) { const std::string &shaderString = "#version 300 es\n" "precision mediump float;\n" "layout(location=5) out vec4 out_fragColor;\n" "void main() {\n" " out_fragColor = vec4(1.0);\n" "}\n"; const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::Attribute> &outputVariables = mTranslator->getOutputVariables(); ASSERT_EQ(1u, outputVariables.size()); const sh::Attribute &outputVariable = outputVariables[0]; EXPECT_EQ(0u, outputVariable.arraySize); EXPECT_EQ(5, outputVariable.location); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable.precision); EXPECT_TRUE(outputVariable.staticUse); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable.type); EXPECT_EQ("out_fragColor", outputVariable.name); }
// Test that gl_FragColor built-in usage in ESSL1 fragment shader is reflected in the output // variables list. TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragColor) { const std::string &fragColorShader = "precision mediump float;\n" "void main() {\n" " gl_FragColor = vec4(1.0);\n" "}\n"; const sh::Attribute *outputVariable = nullptr; validateOutputVariableForShader(fragColorShader, "gl_FragColor", &outputVariable); ASSERT_NE(outputVariable, nullptr); EXPECT_EQ(0u, outputVariable->arraySize); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); }
// Test that unmultipying and premultiplying the alpha is the same as doing neither TEST_P(CopyTextureTest, UnmultiplyAndPremultplyAlpha) { if (!checkExtensions()) { return; } GLColor rgbaPixels[4] = {GLColor(255u, 255u, 255u, 255u), GLColor(127u, 127u, 127u, 127u), GLColor(63u, 63u, 63u, 127u), GLColor(255u, 255u, 255u, 0u)}; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels); glCopyTextureCHROMIUM(mTextures[0], mTextures[1], GL_RGBA, GL_UNSIGNED_BYTE, GL_FALSE, GL_TRUE, GL_TRUE); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 255, 255, 255), 1.0); EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(127, 127, 127, 127), 1.0); EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(63, 63, 63, 127), 1.0); EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(255, 255, 255, 0), 1.0); EXPECT_GL_NO_ERROR(); }
// Test that using an offset in CopySubTexture works correctly TEST_P(CopyTextureTest, CopySubTextureOffset) { if (!checkExtensions()) { return; } GLColor rgbaPixels[4 * 4] = {GLColor::red, GLColor::green, GLColor::blue, GLColor::black}; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgbaPixels); GLColor transparentPixels[4 * 4] = {GLColor::transparentBlack, GLColor::transparentBlack, GLColor::transparentBlack, GLColor::transparentBlack}; glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, transparentPixels); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 1, 1, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 1, 0, 1, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 1, 0, 1, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::transparentBlack); EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::red); EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green); EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::blue); EXPECT_GL_NO_ERROR(); }
// Test to ensure that the basic functionality of the extension works. TEST_P(CopyTextureTest, BasicCopySubTexture) { if (!checkExtensions()) { return; } GLColor pixels = GLColor::red; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixels); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 0, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(0, 0, pixels); EXPECT_GL_NO_ERROR(); }
// For use in the gl_DepthRange tests. void validateDepthRangeShader(const std::string &shaderString) { const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::Uniform> &uniforms = mTranslator->getUniforms(); ASSERT_EQ(1u, uniforms.size()); const sh::Uniform &uniform = uniforms[0]; EXPECT_EQ("gl_DepthRange", uniform.name); ASSERT_TRUE(uniform.isStruct()); ASSERT_EQ(3u, uniform.fields.size()); bool foundNear = false; bool foundFar = false; bool foundDiff = false; for (const auto &field : uniform.fields) { if (field.name == "near") { EXPECT_FALSE(foundNear); foundNear = true; } else if (field.name == "far") { EXPECT_FALSE(foundFar); foundFar = true; } else { ASSERT_EQ("diff", field.name); EXPECT_FALSE(foundDiff); foundDiff = true; } EXPECT_EQ(0u, field.arraySize); EXPECT_FALSE(field.isStruct()); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision); EXPECT_TRUE(field.staticUse); EXPECT_GLENUM_EQ(GL_FLOAT, field.type); } EXPECT_TRUE(foundNear && foundFar && foundDiff); }
TEST_F(CollectVertexVariablesTest, NestedStructRowMajorInterfaceBlock) { const std::string &shaderString = "#version 300 es\n" "struct st { mat2 m; };" "layout(row_major) uniform b {\n" " st s;\n" "};" "void main() {\n" " gl_Position = vec4(s.m);\n" "}\n"; const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); ASSERT_EQ(1u, interfaceBlocks.size()); const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_TRUE(interfaceBlock.isRowMajorLayout); EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ("b", interfaceBlock.name); EXPECT_TRUE(interfaceBlock.staticUse); ASSERT_EQ(1u, interfaceBlock.fields.size()); const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; EXPECT_TRUE(field.isStruct()); EXPECT_TRUE(field.staticUse); EXPECT_EQ("s", field.name); EXPECT_TRUE(field.isRowMajorLayout); const sh::ShaderVariable &member = field.fields[0]; // NOTE: we don't currently mark struct members as statically used or not EXPECT_FALSE(member.isStruct()); EXPECT_EQ("m", member.name); EXPECT_GLENUM_EQ(GL_FLOAT_MAT2, member.type); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, member.precision); }
// Test that gl_FragDataEXT built-in usage in ESSL1 fragment shader is reflected in the output // variables list. Also test that the precision is highp if user requests it. TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragDepthHighp) { const std::string &fragDepthHighShader = "#extension GL_EXT_frag_depth : require\n" "void main() {\n" " gl_FragDepthEXT = 0.7;" "}\n"; ShBuiltInResources resources = mTranslator->getResources(); resources.EXT_frag_depth = 1; resources.FragmentPrecisionHigh = 1; initTranslator(resources); const sh::Attribute *outputVariable = nullptr; validateOutputVariableForShader(fragDepthHighShader, "gl_FragDepthEXT", &outputVariable); ASSERT_NE(outputVariable, nullptr); EXPECT_EQ(0u, outputVariable->arraySize); EXPECT_GLENUM_EQ(GL_FLOAT, outputVariable->type); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, outputVariable->precision); }
// Test that gl_FragData built-in usage in ESSL1 fragment shader is reflected in the output // variables list. TEST_F(CollectFragmentVariablesTest, OutputVarESSL1FragData) { const std::string &fragDataShader = "#extension GL_EXT_draw_buffers : require\n" "precision mediump float;\n" "void main() {\n" " gl_FragData[0] = vec4(1.0);\n" " gl_FragData[1] = vec4(0.5);\n" "}\n"; ShBuiltInResources resources = mTranslator->getResources(); resources.EXT_draw_buffers = 1; const unsigned int kMaxDrawBuffers = 3u; resources.MaxDrawBuffers = kMaxDrawBuffers; initTranslator(resources); const sh::Attribute *outputVariable = nullptr; validateOutputVariableForShader(fragDataShader, "gl_FragData", &outputVariable); ASSERT_NE(outputVariable, nullptr); EXPECT_EQ(kMaxDrawBuffers, outputVariable->arraySize); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, outputVariable->type); EXPECT_GLENUM_EQ(GL_MEDIUM_FLOAT, outputVariable->precision); }
TEST_F(CollectVertexVariablesTest, SimpleInstancedInterfaceBlock) { const std::string &shaderString = "#version 300 es\n" "uniform b {\n" " float f;\n" "} blockInstance;" "void main() {\n" " gl_Position = vec4(blockInstance.f, 0.0, 0.0, 1.0);\n" "}\n"; const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::InterfaceBlock> &interfaceBlocks = mTranslator->getInterfaceBlocks(); ASSERT_EQ(1u, interfaceBlocks.size()); const sh::InterfaceBlock &interfaceBlock = interfaceBlocks[0]; EXPECT_EQ(0u, interfaceBlock.arraySize); EXPECT_FALSE(interfaceBlock.isRowMajorLayout); EXPECT_EQ(sh::BLOCKLAYOUT_SHARED, interfaceBlock.layout); EXPECT_EQ("b", interfaceBlock.name); EXPECT_TRUE(interfaceBlock.staticUse); ASSERT_EQ(1u, interfaceBlock.fields.size()); const sh::InterfaceBlockField &field = interfaceBlock.fields[0]; EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, field.precision); EXPECT_TRUE(field.staticUse); EXPECT_GLENUM_EQ(GL_FLOAT, field.type); EXPECT_EQ("b.f", field.name); EXPECT_FALSE(field.isRowMajorLayout); EXPECT_TRUE(field.fields.empty()); }
TEST_F(CollectVertexVariablesTest, LocationAttribute) { const std::string &shaderString = "#version 300 es\n" "layout(location=5) in vec4 in_Position;\n" "void main() {\n" " gl_Position = in_Position;\n" "}\n"; const char *shaderStrings[] = { shaderString.c_str() }; ASSERT_TRUE(mTranslator->compile(shaderStrings, 1, SH_VARIABLES)); const std::vector<sh::Attribute> &attributes = mTranslator->getAttributes(); ASSERT_EQ(1u, attributes.size()); const sh::Attribute &attribute = attributes[0]; EXPECT_EQ(0u, attribute.arraySize); EXPECT_EQ(5, attribute.location); EXPECT_GLENUM_EQ(GL_HIGH_FLOAT, attribute.precision); EXPECT_TRUE(attribute.staticUse); EXPECT_GLENUM_EQ(GL_FLOAT_VEC4, attribute.type); EXPECT_EQ("in_Position", attribute.name); }
// Test that CopyTexture cannot redefine an immutable texture and CopySubTexture can copy data to // immutable textures TEST_P(CopyTextureTest, ImmutableTexture) { if (!checkExtensions()) { return; } if (getClientMajorVersion() < 3 && (!extensionEnabled("GL_EXT_texture_storage") || !extensionEnabled("GL_OES_rgb8_rgba8"))) { std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage or GL_OES_rgb8_rgba8" << std::endl; return; } GLColor pixels = GLColor::red; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixels); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8_OES, 1, 1); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[1], 0); EXPECT_GL_NO_ERROR(); // Should generate an error when the texture is redefined glCopyTextureCHROMIUM(mTextures[0], mTextures[1], GL_RGBA, GL_UNSIGNED_BYTE, false, false, false); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // Should succeed when using CopySubTexture glCopySubTextureCHROMIUM(mTextures[0], mTextures[1], 0, 0, 0, 0, 1, 1, false, false, false); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(0, 0, pixels); EXPECT_GL_NO_ERROR(); }
// Test to ensure that the destination texture is redefined if the properties are different. TEST_P(CopyTextureTest, RedefineDestinationTexture) { if (!checkExtensions()) { return; } GLColor pixels[4] = {GLColor::red, GLColor::red, GLColor::red, GLColor::red}; glBindTexture(GL_TEXTURE_2D, mTextures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, 1, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_NO_ERROR(); // GL_INVALID_OPERATION due to "intrinsic format" != "internal format". glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_ERROR(GL_INVALID_OPERATION); // GL_INVALID_VALUE due to bad dimensions. glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_ERROR(GL_INVALID_VALUE); // If the dest texture has different properties, glCopyTextureCHROMIUM() // redefines them. glCopyTextureCHROMIUM(mTextures[0], mTextures[1], GL_RGBA, GL_UNSIGNED_BYTE, false, false, false); EXPECT_GL_NO_ERROR(); // glTexSubImage2D() succeeds because mTextures[1] is redefined into 2x2 // dimension and GL_RGBA format. glBindTexture(GL_TEXTURE_2D, mTextures[1]); glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels); EXPECT_GL_NO_ERROR(); // Check that FB is complete. EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); EXPECT_PIXEL_COLOR_EQ(1, 1, pixels[3]); EXPECT_GL_NO_ERROR(); }