Edit

kc3-lang/angle/src/tests/gl_tests/WEBGLVideoTextureTest.cpp

Branch :

  • Show log

    Commit

  • Author : Yan
    Date : 2019-10-14 14:13:59
    Hash : 17b3c2f3
    Message : Implement SamplerVideoWEBGL for WEBGL_video_texture extension on desktop WEBGL_video_texture is an extension that will improve uploading video frame to WebGL performance. (https://www.khronos.org/registry/webgl/extensions/proposals/WEBGL_video_texture/) This extension introduced a new texture type TEXTURE_VIDEO_IMAGE_WEBGL and a new sampler type samplerVideoWEBGL to sample it. In chromium implementation, TEXTURE_VIDEO_IMAGE_WEBGL maps to different native texture type based on platform. On desktop, it maps to GL_TEXTURE2D(Currently supported). On Android, it should map to GL_TEXTURE_EXTERNAL(TODO). SamplerVideoWEBGL needs to be mapped to sampler2D or samplerExternalOES according to TEXTURE_VIDEO_IMAGE_WEBGL implementation. This patch implements samplerVideoWEBGL in Angle to support WEBGL_video_texture on desktop. In this case, samplerVideoWEBGL should map to sampler2D. Bug: chromium:776222, angleproject:3889 Change-Id: Idb0a5fcde37ca75ccc1181226b91f257212e7500 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1866274 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/tests/gl_tests/WEBGLVideoTextureTest.cpp
  • //
    // 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<GLColor> 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(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<GLColor> 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<GLColor> redColors(4, GLColor::red);
        const std::vector<GLColor> 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<GLColor> 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);
    ANGLE_INSTANTIATE_TEST_ES3(WEBGLVideoTextureES300Test);
    }  // namespace