Changeset 252741 in webkit


Ignore:
Timestamp:
Nov 21, 2019 10:53:59 AM (4 years ago)
Author:
dino@apple.com
Message:

Implement accelerated video-to-texture upload path for ANGLE backend for WebGL on desktop
https://bugs.webkit.org/show_bug.cgi?id=200904

Support GPU-accelerated video uploads to WebGL textures with ANGLE.

Uses the IOSurface path, as the CVOpenGLTextureCache seems to have
been disabled at the OS level, even on top-of-tree WebKit without
using ANGLE.

Uses the EGL_ANGLE_iosurface_client_buffer extension to import
IOSurfaces; reuses all of the existing shader and OpenGL code.

Necessary other fixes to GraphicsContext3D's ANGLE backend: supporting
context sharing, and querying the selected EGLConfig.

Covered by WebGL conformance tests. Verified speedup with
"Animating textures in WebGL" MDN article.

Patch by Kenneth Russell <kbr@chromium.org> on 2019-11-21
Reviewed by Dean Jackson.

  • platform/graphics/GraphicsContext3D.h:

(WebCore::GraphicsContext3D::platformDisplay const):
(WebCore::GraphicsContext3D::platformConfig const):

  • platform/graphics/cocoa/GraphicsContext3DCocoa.mm:

(WebCore::GraphicsContext3D::GraphicsContext3D):

  • platform/graphics/cv/VideoTextureCopierCV.cpp:

(WebCore::VideoTextureCopierCV::initializeContextObjects):
(WebCore::VideoTextureCopierCV::initializeUVContextObjects):
(WebCore::VideoTextureCopierCV::attachIOSurfaceToTexture):
(WebCore::VideoTextureCopierCV::detachIOSurfaceFromTexture):
(WebCore::VideoTextureCopierCV::copyImageToPlatformTexture):
(WebCore::VideoTextureCopierCV::copyVideoTextureToPlatformTexture):

  • platform/graphics/cv/VideoTextureCopierCV.h:
Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252737 r252741  
     12019-11-21  Kenneth Russell  <kbr@chromium.org>
     2
     3        Implement accelerated video-to-texture upload path for ANGLE backend for WebGL on desktop
     4        https://bugs.webkit.org/show_bug.cgi?id=200904
     5
     6        Support GPU-accelerated video uploads to WebGL textures with ANGLE.
     7
     8        Uses the IOSurface path, as the CVOpenGLTextureCache seems to have
     9        been disabled at the OS level, even on top-of-tree WebKit without
     10        using ANGLE.
     11
     12        Uses the EGL_ANGLE_iosurface_client_buffer extension to import
     13        IOSurfaces; reuses all of the existing shader and OpenGL code.
     14
     15        Necessary other fixes to GraphicsContext3D's ANGLE backend: supporting
     16        context sharing, and querying the selected EGLConfig.
     17
     18        Covered by WebGL conformance tests. Verified speedup with
     19        "Animating textures in WebGL" MDN article.
     20
     21        Reviewed by Dean Jackson.
     22
     23        * platform/graphics/GraphicsContext3D.h:
     24        (WebCore::GraphicsContext3D::platformDisplay const):
     25        (WebCore::GraphicsContext3D::platformConfig const):
     26        * platform/graphics/cocoa/GraphicsContext3DCocoa.mm:
     27        (WebCore::GraphicsContext3D::GraphicsContext3D):
     28        * platform/graphics/cv/VideoTextureCopierCV.cpp:
     29        (WebCore::VideoTextureCopierCV::initializeContextObjects):
     30        (WebCore::VideoTextureCopierCV::initializeUVContextObjects):
     31        (WebCore::VideoTextureCopierCV::attachIOSurfaceToTexture):
     32        (WebCore::VideoTextureCopierCV::detachIOSurfaceFromTexture):
     33        (WebCore::VideoTextureCopierCV::copyImageToPlatformTexture):
     34        (WebCore::VideoTextureCopierCV::copyVideoTextureToPlatformTexture):
     35        * platform/graphics/cv/VideoTextureCopierCV.h:
     36
    1372019-11-21  Youenn Fablet  <youenn@apple.com>
    238
  • trunk/Source/WebCore/platform/graphics/GraphicsContext3D.h

    r252717 r252741  
    743743        PRIMITIVE_RESTART = 0x8F9D,
    744744
    745         // OpenGL ES 3 constants
    746         MAP_READ_BIT = 0x0001
     745        // OpenGL ES 3 constants.
     746        MAP_READ_BIT = 0x0001,
     747
     748        // Necessary desktop OpenGL constants.
     749        TEXTURE_RECTANGLE_ARB = 0x84F5
    747750    };
    748751
     
    778781    Platform3DObject platformTexture() const { return m_texture; }
    779782    CALayer* platformLayer() const { return reinterpret_cast<CALayer*>(m_webGLLayer.get()); }
     783#if USE(ANGLE)
     784    PlatformGraphicsContext3DDisplay platformDisplay() const { return m_displayObj; }
     785    PlatformGraphicsContext3DConfig platformConfig() const { return m_configObj; }
     786#endif // USE(ANGLE)
    780787#else
    781788    PlatformGraphicsContext3D platformGraphicsContext3D();
     
    13811388#if USE(ANGLE)
    13821389    PlatformGraphicsContext3DDisplay m_displayObj { nullptr };
     1390    PlatformGraphicsContext3DConfig m_configObj { nullptr };
    13831391#endif // USE(ANGLE)
    13841392#endif // PLATFORM(COCOA)
  • trunk/Source/WebCore/platform/graphics/cocoa/GraphicsContext3DCocoa.mm

    r252245 r252741  
    291291
    292292    UNUSED_PARAM(hostWindow);
    293     UNUSED_PARAM(sharedContext);
    294293
    295294    m_displayObj = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
     
    305304    LOG(WebGL, "Extensions: %s", displayExtensions);
    306305
    307     EGLConfig config;
    308306    EGLint configAttributes[] = {
    309307        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
     
    315313    };
    316314    EGLint numberConfigsReturned = 0;
    317     EGL_ChooseConfig(m_displayObj, configAttributes, &config, 1, &numberConfigsReturned);
     315    EGL_ChooseConfig(m_displayObj, configAttributes, &m_configObj, 1, &numberConfigsReturned);
    318316    if (numberConfigsReturned != 1) {
    319317        LOG(WebGL, "EGLConfig Initialization failed.");
     
    350348    contextAttributes.push_back(EGL_NONE);
    351349
    352     m_contextObj = EGL_CreateContext(m_displayObj, config, EGL_NO_CONTEXT, contextAttributes.data());
     350    m_contextObj = EGL_CreateContext(m_displayObj, m_configObj, sharedContext ? static_cast<EGLContext>(sharedContext->m_contextObj) : EGL_NO_CONTEXT, contextAttributes.data());
    353351    if (m_contextObj == EGL_NO_CONTEXT) {
    354352        LOG(WebGL, "EGLContext Initialization failed.");
     
    388386#endif
    389387#if USE(ANGLE)
    390         [m_webGLLayer setEGLDisplay:m_displayObj config:config];
     388        [m_webGLLayer setEGLDisplay:m_displayObj config:m_configObj];
    391389#endif
    392390    END_BLOCK_OBJC_EXCEPTIONS
  • trunk/Source/WebCore/platform/graphics/cv/VideoTextureCopierCV.cpp

    r252245 r252741  
    3939#if USE(OPENGL_ES)
    4040#include <OpenGLES/ES3/glext.h>
     41#endif
     42
     43#if USE(ANGLE)
     44#define EGL_EGL_PROTOTYPES 0
     45#include <ANGLE/egl.h>
     46#include <ANGLE/eglext.h>
     47#include <ANGLE/eglext_angle.h>
     48#include <ANGLE/entry_points_egl.h>
     49#include <ANGLE/entry_points_gles_2_0_autogen.h>
     50// Skip the inclusion of ANGLE's explicit context entry points for now.
     51#define GL_ANGLE_explicit_context
     52#include <ANGLE/gl2ext.h>
     53#include <ANGLE/gl2ext_angle.h>
    4154#endif
    4255
     
    516529    StringBuilder fragmentShaderSource;
    517530
    518 #if USE(OPENGL_ES)
     531#if USE(OPENGL_ES) || USE(ANGLE)
    519532    fragmentShaderSource.appendLiteral("precision mediump float;\n");
     533#endif
     534#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    520535    fragmentShaderSource.appendLiteral("uniform sampler2D u_texture;\n");
    521 #elif USE(OPENGL)
     536#elif USE(OPENGL) || (USE(ANGLE) && !PLATFORM(IOS_FAMILY))
    522537    fragmentShaderSource.appendLiteral("uniform sampler2DRect u_texture;\n");
    523 #elif USE(ANGLE)
    524     // FIXME: determine how to access rectangular textures via ANGLE.
    525     ASSERT_NOT_REACHED();
    526538#else
    527539#error Unsupported configuration
     
    533545    fragmentShaderSource.appendLiteral("void main() {\n");
    534546    fragmentShaderSource.appendLiteral("    vec2 texPos = vec2(v_texturePosition.x * u_textureDimensions.x, v_texturePosition.y * u_textureDimensions.y);\n");
    535 #if USE(OPENGL_ES)
     547#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    536548    fragmentShaderSource.appendLiteral("    vec4 color = texture2D(u_texture, texPos);\n");
    537 #elif USE(OPENGL)
     549#elif USE(OPENGL) || (USE(ANGLE) && !PLATFORM(IOS_FAMILY))
    538550    fragmentShaderSource.appendLiteral("    vec4 color = texture2DRect(u_texture, texPos);\n");
    539 #elif USE(ANGLE)
    540     // FIXME: determine how to access rectangular textures via ANGLE.
    541     ASSERT_NOT_REACHED();
    542551#else
    543552#error Unsupported configuration
     
    619628        "       normalizedPosition.y = 1.0 - normalizedPosition.y;\n"
    620629        "   }\n"
    621 #if USE(OPENGL_ES)
     630#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    622631        "   v_yTextureCoordinate = normalizedPosition;\n"
    623632        "   v_uvTextureCoordinate = normalizedPosition;\n"
    624 #elif USE(OPENGL)
     633#elif USE(OPENGL) || (USE(ANGLE) && !PLATFORM(IOS_FAMILY))
    625634        "   v_yTextureCoordinate = normalizedPosition * u_yTextureSize;\n"
    626635        "   v_uvTextureCoordinate = normalizedPosition * u_uvTextureSize;\n"
    627 #elif USE(ANGLE)
    628         // FIXME: determine how to access rectangular textures via ANGLE.
    629636#else
    630637#error Unsupported configuration
     
    646653
    647654    String fragmentShaderSource {
    648 #if USE(OPENGL_ES)
     655#if USE(OPENGL_ES) || USE(ANGLE)
    649656        "precision mediump float;\n"
     657#endif
     658#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    650659        "#define SAMPLERTYPE sampler2D\n"
    651660        "#define TEXTUREFUNC texture2D\n"
    652 #elif USE(OPENGL)
     661#elif USE(OPENGL) || (USE(ANGLE) && !PLATFORM(IOS_FAMILY))
    653662        "#define SAMPLERTYPE sampler2DRect\n"
    654663        "#define TEXTUREFUNC texture2DRect\n"
    655 #elif USE(ANGLE)
    656         // FIXME: determine how to access rectangular textures via ANGLE.
    657664#else
    658665#error Unsupported configuration
     
    723730}
    724731
     732#if USE(ANGLE)
     733void* VideoTextureCopierCV::attachIOSurfaceToTexture(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type, IOSurfaceRef surface, GC3Duint plane)
     734{
     735    auto display = m_context->platformDisplay();
     736    EGLint eglTextureTarget = 0;
     737
     738    if (target == GraphicsContext3D::TEXTURE_RECTANGLE_ARB)
     739        eglTextureTarget = EGL_TEXTURE_RECTANGLE_ANGLE;
     740    else if (target == GraphicsContext3D::TEXTURE_2D)
     741        eglTextureTarget = EGL_TEXTURE_2D;
     742    else {
     743        LOG(WebGL, "Unknown texture target %d.", static_cast<int>(target));
     744        return nullptr;
     745    }
     746
     747    const EGLint surfaceAttributes[] = {
     748        EGL_WIDTH, width,
     749        EGL_HEIGHT, height,
     750        EGL_IOSURFACE_PLANE_ANGLE, static_cast<EGLint>(plane),
     751        EGL_TEXTURE_TARGET, static_cast<EGLint>(eglTextureTarget),
     752        EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, static_cast<EGLint>(internalFormat),
     753        EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
     754        EGL_TEXTURE_TYPE_ANGLE, static_cast<EGLint>(type),
     755        EGL_NONE, EGL_NONE
     756    };
     757    EGLSurface pbuffer = EGL_CreatePbufferFromClientBuffer(display, EGL_IOSURFACE_ANGLE, surface, m_context->platformConfig(), surfaceAttributes);
     758    if (!pbuffer)
     759        return nullptr;
     760    if (!EGL_BindTexImage(display, pbuffer, EGL_BACK_BUFFER)) {
     761        EGL_DestroySurface(display, pbuffer);
     762        return nullptr;
     763    }
     764    return pbuffer;
     765}
     766
     767void VideoTextureCopierCV::detachIOSurfaceFromTexture(void* handle)
     768{
     769    auto display = m_context->platformDisplay();
     770    EGL_ReleaseTexImage(display, handle, EGL_BACK_BUFFER);
     771    EGL_DestroySurface(display, handle);
     772}
     773#endif
     774
    725775bool VideoTextureCopierCV::copyImageToPlatformTexture(CVPixelBufferRef image, size_t width, size_t height, Platform3DObject outputTexture, GC3Denum outputTarget, GC3Dint level, GC3Denum internalFormat, GC3Denum format, GC3Denum type, bool premultiplyAlpha, bool flipY)
    726776{
     777    // CVOpenGLTextureCache seems to be disabled since the deprecation of
     778    // OpenGL. To avoid porting unused code to the ANGLE code paths, remove it.
     779#if USE(ANGLE)
     780    UNUSED_PARAM(outputTarget);
     781    UNUSED_PARAM(premultiplyAlpha);
     782#else
    727783    if (!m_textureCache) {
    728784        m_textureCache = TextureCacheCV::create(m_context);
     
    739795        return copyVideoTextureToPlatformTexture(texture.get(), width, height, outputTexture, outputTarget, level, internalFormat, format, type, premultiplyAlpha, flipY, swapColorChannels);
    740796    }
     797#endif // USE(ANGLE)
    741798
    742799#if HAVE(IOSURFACE)
     
    795852    auto uvPlaneHeight = IOSurfaceGetHeightOfPlane(surface, 1);
    796853
    797 #if USE(OPENGL_ES)
     854#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    798855    GC3Denum videoTextureTarget = GraphicsContext3D::TEXTURE_2D;
    799 #elif USE(OPENGL)
    800     GC3Denum videoTextureTarget = GL_TEXTURE_RECTANGLE_ARB;
    801 #elif USE(ANGLE)
    802     // FIXME: determine how to access rectangular textures via ANGLE.
    803     GC3Denum videoTextureTarget = GraphicsContext3D::TEXTURE_2D;
     856#elif USE(OPENGL) || (USE(ANGLE) && !PLATFORM(IOS_FAMILY))
     857    GC3Denum videoTextureTarget = GraphicsContext3D::TEXTURE_RECTANGLE_ARB;
    804858#else
    805859#error Unsupported configuration
     
    812866    m_context->texParameteri(videoTextureTarget, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
    813867    m_context->texParameteri(videoTextureTarget, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
     868#if USE(ANGLE)
     869    auto uvHandle = attachIOSurfaceToTexture(videoTextureTarget, GraphicsContext3D::RG, uvPlaneWidth, uvPlaneHeight, GraphicsContext3D::UNSIGNED_BYTE, surface, 1);
     870    if (!uvHandle) {
     871        m_context->deleteTexture(uvTexture);
     872        return false;
     873    }
     874#else
    814875    if (!m_context->texImageIOSurface2D(videoTextureTarget, GraphicsContext3D::RG, uvPlaneWidth, uvPlaneHeight, GraphicsContext3D::RG, GraphicsContext3D::UNSIGNED_BYTE, surface, 1)) {
    815876        m_context->deleteTexture(uvTexture);
    816877        return false;
    817878    }
     879#endif // USE(ANGLE)
    818880
    819881    auto yTexture = m_context->createTexture();
     
    824886    m_context->texParameteri(videoTextureTarget, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
    825887    m_context->texParameteri(videoTextureTarget, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
     888#if USE(ANGLE)
     889    auto yHandle = attachIOSurfaceToTexture(videoTextureTarget, GraphicsContext3D::RED, yPlaneWidth, yPlaneHeight, GraphicsContext3D::UNSIGNED_BYTE, surface, 0);
     890    if (!yHandle) {
     891        m_context->deleteTexture(yTexture);
     892        m_context->deleteTexture(uvTexture);
     893        return false;
     894    }
     895#else
    826896    if (!m_context->texImageIOSurface2D(videoTextureTarget, GraphicsContext3D::LUMINANCE, yPlaneWidth, yPlaneHeight, GraphicsContext3D::LUMINANCE, GraphicsContext3D::UNSIGNED_BYTE, surface, 0)) {
    827897        m_context->deleteTexture(yTexture);
     
    829899        return false;
    830900    }
     901#endif // USE(ANGLE)
    831902
    832903    // Configure the drawing parameters.
     
    845916    m_context->drawArrays(GraphicsContext3D::TRIANGLES, 0, 6);
    846917
    847 #if USE(OPENGL_ES)
     918#if USE(OPENGL_ES) || (USE(ANGLE) && PLATFORM(IOS_FAMILY))
    848919    // flush() must be called here in order to re-synchronize the output texture's contents across the
    849920    // two EAGL contexts.
     
    854925    m_context->deleteTexture(yTexture);
    855926    m_context->deleteTexture(uvTexture);
     927#if USE(ANGLE)
     928    detachIOSurfaceFromTexture(yHandle);
     929    detachIOSurfaceFromTexture(uvHandle);
     930#endif
    856931
    857932    m_lastSurface = surface;
     
    887962    CVOpenGLTextureGetCleanTexCoords(inputVideoTexture, lowerLeft, lowerRight, upperRight, upperLeft);
    888963#elif USE(ANGLE)
     964    // CVOpenGLTextureCacheCreateTextureFromImage seems to always return
     965    // kCVReturnPixelBufferNotOpenGLCompatible on desktop macOS now, so this
     966    // entire code path seems to be unused. Assume the IOSurface path will be
     967    // taken when using ANGLE.
    889968    UNUSED_PARAM(lowerLeft);
    890969    UNUSED_PARAM(lowerRight);
  • trunk/Source/WebCore/platform/graphics/cv/VideoTextureCopierCV.h

    r248762 r252741  
    7171#endif
    7272
     73#if USE(ANGLE)
     74#if !HAVE(IOSURFACE)
     75#error USE(ANGLE) requires HAVE(IOSURFACE)
     76#endif // !HAVE(IOSURFACE)
     77
     78    // Returns a handle which, if non-null, must be released via the
     79    // detach call below.
     80    void* attachIOSurfaceToTexture(GC3Denum target, GC3Denum internalFormat, GC3Dsizei width, GC3Dsizei height, GC3Denum type, IOSurfaceRef, GC3Duint plane);
     81    void detachIOSurfaceFromTexture(void* handle);
     82#endif
     83
    7384    Ref<GraphicsContext3D> m_sharedContext;
    7485    Ref<GraphicsContext3D> m_context;
     86#if !USE(ANGLE)
    7587    std::unique_ptr<TextureCacheCV> m_textureCache;
     88#endif
    7689    Platform3DObject m_framebuffer { 0 };
    7790    Platform3DObject m_program { 0 };
Note: See TracChangeset for help on using the changeset viewer.