// // Copyright 2019 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // #include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" using namespace angle; namespace { class WEBGLVideoTextureTest : public ANGLETest<> { protected: WEBGLVideoTextureTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); } }; class WEBGLVideoTextureES300Test : public ANGLETest<> { protected: WEBGLVideoTextureES300Test() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); } }; // Test to verify samplerVideoWEBGL works fine when extension is enabled. TEST_P(WEBGLVideoTextureTest, VerifySamplerVideoWEBGL) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture")); constexpr char kVS[] = R"( attribute vec2 position; varying mediump vec2 texCoord; void main() { gl_Position = vec4(position, 0, 1); texCoord = position * 0.5 + vec2(0.5); })"; constexpr char kFS[] = R"( #extension GL_WEBGL_video_texture : require precision mediump float; varying mediump vec2 texCoord; uniform mediump samplerVideoWEBGL s; void main() { gl_FragColor = textureVideoWEBGL(s, texCoord); })"; ANGLE_GL_PROGRAM(program, kVS, kFS); // Initialize basic red texture. const std::vector redColors(4, GLColor::red); GLTexture texture; glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture); glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data()); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); drawQuad(program, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0); ASSERT_GL_NO_ERROR(); } // Test to verify samplerVideoWEBGL works fine as parameter of user defined function // when extension is enabled. TEST_P(WEBGLVideoTextureTest, VerifySamplerVideoWEBGLAsParameter) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture")); constexpr char kVS[] = R"( attribute vec2 position; varying mediump vec2 texCoord; void main() { gl_Position = vec4(position, 0, 1); texCoord = position * 0.5 + vec2(0.5); })"; constexpr char kFS[] = R"( #extension GL_WEBGL_video_texture : require precision mediump float; varying mediump vec2 texCoord; uniform mediump samplerVideoWEBGL s; vec4 wrapTextureVideoWEBGL(mediump samplerVideoWEBGL sampler, vec2 coord) { return textureVideoWEBGL(sampler, coord); } void main() { gl_FragColor = wrapTextureVideoWEBGL(s, texCoord); })"; ANGLE_GL_PROGRAM(program, kVS, kFS); // Initialize basic red texture. const std::vector redColors(4, GLColor::red); GLTexture texture; glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture); glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data()); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); drawQuad(program, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0); ASSERT_GL_NO_ERROR(); } // Test to ensure ANGLE state manager knows the change when binding VideoImage // and can handle it correctly based on the program. TEST_P(WEBGLVideoTextureTest, VerifyStateManagerKnowsBindingVideoImage) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture")); constexpr char kVS[] = R"( attribute vec2 position; varying mediump vec2 texCoord; void main() { gl_Position = vec4(position, 0, 1); texCoord = position * 0.5 + vec2(0.5); })"; constexpr char kFS2D[] = R"( precision mediump float; varying mediump vec2 texCoord; uniform mediump sampler2D s; void main() { gl_FragColor = texture2D(s, texCoord); })"; constexpr char kFSVideoImage[] = R"( #extension GL_WEBGL_video_texture : require precision mediump float; varying mediump vec2 texCoord; uniform mediump samplerVideoWEBGL s; void main() { gl_FragColor = textureVideoWEBGL(s, texCoord); })"; ANGLE_GL_PROGRAM(program2D, kVS, kFS2D); ANGLE_GL_PROGRAM(programVideoImage, kVS, kFSVideoImage); // Initialize basic red texture. const std::vector redColors(4, GLColor::red); const std::vector greenColors(4, GLColor::green); GLTexture texture2D; GLTexture textureVideoImage; glBindTexture(GL_TEXTURE_2D, texture2D); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); // This should unbind the native TEXTURE_2D glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, textureVideoImage); glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, greenColors.data()); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); // ANGLE will check state change and apply changes through state manager. If state manager // is aware of the unbind, it will bind the correct texture back in native and the draw should // work fine. drawQuad(program2D, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); drawQuad(programVideoImage, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green); drawQuad(program2D, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0); glBindTexture(GL_TEXTURE_2D, 0); ASSERT_GL_NO_ERROR(); } // Test to verify samplerVideoWEBGL works fine in ES300 when extension is enabled. TEST_P(WEBGLVideoTextureES300Test, VerifySamplerVideoWEBGLInES300) { ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture")); constexpr char kVS[] = R"(#version 300 es in vec2 position; out mediump vec2 texCoord; void main() { gl_Position = vec4(position, 0, 1); texCoord = position * 0.5 + vec2(0.5); })"; constexpr char kFS[] = R"(#version 300 es #extension GL_WEBGL_video_texture : require precision mediump float; in mediump vec2 texCoord; uniform mediump samplerVideoWEBGL s; out vec4 my_FragColor; void main() { my_FragColor = texture(s, texCoord); })"; ANGLE_GL_PROGRAM(program, kVS, kFS); // Initialize basic red texture. const std::vector redColors(4, GLColor::red); GLTexture texture; glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture); glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data()); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ASSERT_GL_NO_ERROR(); drawQuad(program, "position", 0.0f); EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red); glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0); ASSERT_GL_NO_ERROR(); } ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WEBGLVideoTextureTest); GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WEBGLVideoTextureES300Test); ANGLE_INSTANTIATE_TEST_ES3(WEBGLVideoTextureES300Test); } // namespace