1 //
2 // Copyright 2019 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "test_utils/ANGLETest.h"
8
9 #include "test_utils/gl_raii.h"
10
11 using namespace angle;
12
13 namespace
14 {
15
16 class WEBGLVideoTextureTest : public ANGLETest
17 {
18 protected:
WEBGLVideoTextureTest()19 WEBGLVideoTextureTest()
20 {
21 setWindowWidth(128);
22 setWindowHeight(128);
23 setConfigRedBits(8);
24 setConfigGreenBits(8);
25 setConfigBlueBits(8);
26 setConfigAlphaBits(8);
27 }
28 };
29
30 class WEBGLVideoTextureES300Test : public ANGLETest
31 {
32 protected:
WEBGLVideoTextureES300Test()33 WEBGLVideoTextureES300Test()
34 {
35 setWindowWidth(128);
36 setWindowHeight(128);
37 setConfigRedBits(8);
38 setConfigGreenBits(8);
39 setConfigBlueBits(8);
40 setConfigAlphaBits(8);
41 }
42 };
43
44 // Test to verify samplerVideoWEBGL works fine when extension is enabled.
TEST_P(WEBGLVideoTextureTest,VerifySamplerVideoWEBGL)45 TEST_P(WEBGLVideoTextureTest, VerifySamplerVideoWEBGL)
46 {
47 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture"));
48
49 constexpr char kVS[] = R"(
50 attribute vec2 position;
51 varying mediump vec2 texCoord;
52 void main()
53 {
54 gl_Position = vec4(position, 0, 1);
55 texCoord = position * 0.5 + vec2(0.5);
56 })";
57
58 constexpr char kFS[] = R"(
59
60 #extension GL_WEBGL_video_texture : require
61 precision mediump float;
62 varying mediump vec2 texCoord;
63 uniform mediump samplerVideoWEBGL s;
64 void main()
65 {
66 gl_FragColor = textureVideoWEBGL(s, texCoord);
67 })";
68
69 ANGLE_GL_PROGRAM(program, kVS, kFS);
70 // Initialize basic red texture.
71 const std::vector<GLColor> redColors(4, GLColor::red);
72 GLTexture texture;
73 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture);
74 glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
75 redColors.data());
76 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
77 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
78
79 ASSERT_GL_NO_ERROR();
80
81 drawQuad(program, "position", 0.0f);
82 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
83 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0);
84 ASSERT_GL_NO_ERROR();
85 }
86
87 // Test to verify samplerVideoWEBGL works fine as parameter of user defined function
88 // when extension is enabled.
TEST_P(WEBGLVideoTextureTest,VerifySamplerVideoWEBGLAsParameter)89 TEST_P(WEBGLVideoTextureTest, VerifySamplerVideoWEBGLAsParameter)
90 {
91 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture"));
92
93 constexpr char kVS[] = R"(
94 attribute vec2 position;
95 varying mediump vec2 texCoord;
96 void main()
97 {
98 gl_Position = vec4(position, 0, 1);
99 texCoord = position * 0.5 + vec2(0.5);
100 })";
101
102 constexpr char kFS[] = R"(
103
104 #extension GL_WEBGL_video_texture : require
105 precision mediump float;
106 varying mediump vec2 texCoord;
107 uniform mediump samplerVideoWEBGL s;
108
109 vec4 wrapTextureVideoWEBGL(samplerVideoWEBGL sampler, vec2 coord)
110 {
111 return textureVideoWEBGL(sampler, coord);
112 }
113
114 void main()
115 {
116 gl_FragColor = wrapTextureVideoWEBGL(s, texCoord);
117 })";
118
119 ANGLE_GL_PROGRAM(program, kVS, kFS);
120 // Initialize basic red texture.
121 const std::vector<GLColor> redColors(4, GLColor::red);
122 GLTexture texture;
123 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture);
124 glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
125 redColors.data());
126 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
127 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
128 ASSERT_GL_NO_ERROR();
129
130 drawQuad(program, "position", 0.0f);
131 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
132 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0);
133 ASSERT_GL_NO_ERROR();
134 }
135
136 // Test to ensure ANGLE state manager knows the change when binding VideoImage
137 // and can handle it correctly based on the program.
TEST_P(WEBGLVideoTextureTest,VerifyStateManagerKnowsBindingVideoImage)138 TEST_P(WEBGLVideoTextureTest, VerifyStateManagerKnowsBindingVideoImage)
139 {
140 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture"));
141
142 constexpr char kVS[] = R"(
143 attribute vec2 position;
144 varying mediump vec2 texCoord;
145 void main()
146 {
147 gl_Position = vec4(position, 0, 1);
148 texCoord = position * 0.5 + vec2(0.5);
149 })";
150
151 constexpr char kFS2D[] = R"(
152
153 precision mediump float;
154 varying mediump vec2 texCoord;
155 uniform mediump sampler2D s;
156
157 void main()
158 {
159 gl_FragColor = texture2D(s, texCoord);
160 })";
161
162 constexpr char kFSVideoImage[] = R"(
163
164 #extension GL_WEBGL_video_texture : require
165 precision mediump float;
166 varying mediump vec2 texCoord;
167 uniform mediump samplerVideoWEBGL s;
168
169 void main()
170 {
171 gl_FragColor = textureVideoWEBGL(s, texCoord);
172 })";
173
174 ANGLE_GL_PROGRAM(program2D, kVS, kFS2D);
175 ANGLE_GL_PROGRAM(programVideoImage, kVS, kFSVideoImage);
176 // Initialize basic red texture.
177 const std::vector<GLColor> redColors(4, GLColor::red);
178 const std::vector<GLColor> greenColors(4, GLColor::green);
179 GLTexture texture2D;
180 GLTexture textureVideoImage;
181 glBindTexture(GL_TEXTURE_2D, texture2D);
182 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, redColors.data());
183 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
185 ASSERT_GL_NO_ERROR();
186
187 // This should unbind the native TEXTURE_2D
188 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, textureVideoImage);
189 glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
190 greenColors.data());
191 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
192 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
193 ASSERT_GL_NO_ERROR();
194
195 // ANGLE will check state change and apply changes through state manager. If state manager
196 // is aware of the unbind, it will bind the correct texture back in native and the draw should
197 // work fine.
198 drawQuad(program2D, "position", 0.0f);
199 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
200 drawQuad(programVideoImage, "position", 0.0f);
201 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::green);
202 drawQuad(program2D, "position", 0.0f);
203 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
204
205 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0);
206 glBindTexture(GL_TEXTURE_2D, 0);
207 ASSERT_GL_NO_ERROR();
208 }
209
210 // Test to verify samplerVideoWEBGL works fine in ES300 when extension is enabled.
TEST_P(WEBGLVideoTextureES300Test,VerifySamplerVideoWEBGLInES300)211 TEST_P(WEBGLVideoTextureES300Test, VerifySamplerVideoWEBGLInES300)
212 {
213 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_WEBGL_video_texture"));
214
215 constexpr char kVS[] = R"(#version 300 es
216 in vec2 position;
217 out mediump vec2 texCoord;
218
219 void main()
220 {
221 gl_Position = vec4(position, 0, 1);
222 texCoord = position * 0.5 + vec2(0.5);
223 })";
224
225 constexpr char kFS[] = R"(#version 300 es
226 #extension GL_WEBGL_video_texture : require
227 precision mediump float;
228 in mediump vec2 texCoord;
229 uniform mediump samplerVideoWEBGL s;
230 out vec4 my_FragColor;
231 void main()
232 {
233 my_FragColor = texture(s, texCoord);
234 })";
235
236 ANGLE_GL_PROGRAM(program, kVS, kFS);
237 // Initialize basic red texture.
238 const std::vector<GLColor> redColors(4, GLColor::red);
239 GLTexture texture;
240 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, texture);
241 glTexImage2D(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
242 redColors.data());
243 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
244 glTexParameteri(GL_TEXTURE_VIDEO_IMAGE_WEBGL, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
245 ASSERT_GL_NO_ERROR();
246
247 drawQuad(program, "position", 0.0f);
248 EXPECT_PIXEL_RECT_EQ(0, 0, getWindowWidth(), getWindowHeight(), GLColor::red);
249 glBindTexture(GL_TEXTURE_VIDEO_IMAGE_WEBGL, 0);
250 ASSERT_GL_NO_ERROR();
251 }
252
253 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(WEBGLVideoTextureTest);
254
255 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WEBGLVideoTextureES300Test);
256 ANGLE_INSTANTIATE_TEST_ES3(WEBGLVideoTextureES300Test);
257 } // namespace
258