gfx/gl/EGLUtils.cpp
author yulia <ystartsev@mozilla.com>
Thu, 18 Oct 2018 14:34:33 +0000
changeset 490315 a6b4461eadf0622f4d4f6ea1ee8389d1c655b336
parent 469224 db10936e9f8dc579e104cc6ca8e718e7e8dd4499
permissions -rw-r--r--
Bug 1495387 - introduce async front instantiation; r=ochameau Depends on D8989 Differential Revision: https://phabricator.services.mozilla.com/D8990

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "EGLUtils.h"

#include "GLContextEGL.h"
#include "GLLibraryEGL.h"

namespace mozilla {
namespace gl {

bool
DoesEGLContextSupportSharingWithEGLImage(GLContext* gl)
{
    auto* egl = gl::GLLibraryEGL::Get();

    return egl->HasKHRImageBase() &&
           egl->HasKHRImageTexture2D() &&
           gl->IsExtensionSupported(GLContext::OES_EGL_image);
}

EGLImage
CreateEGLImage(GLContext* gl, GLuint tex)
{
    MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));

    auto* egl = gl::GLLibraryEGL::Get();

    EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
    EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
    EGLImage image = egl->fCreateImage(EGL_DISPLAY(),
                                       eglContext,
                                       LOCAL_EGL_GL_TEXTURE_2D,
                                       clientBuffer,
                                       nullptr);
    return image;
}

////////////////////////////////////////////////////////////////////////
// EGLImageWrapper

/*static*/ EGLImageWrapper*
EGLImageWrapper::Create(GLContext* gl, GLuint tex)
{
    MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));

    auto* egl = gl::GLLibraryEGL::Get();

    EGLDisplay display = EGL_DISPLAY();
    EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
    EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
    EGLImage image = egl->fCreateImage(display,
                                       eglContext,
                                       LOCAL_EGL_GL_TEXTURE_2D,
                                       clientBuffer,
                                       nullptr);
    if (!image) {
#ifdef DEBUG
        printf_stderr("Could not create EGL images: ERROR (0x%04x)\n",
                      egl->fGetError());
#endif
        return nullptr;
    }

    return new EGLImageWrapper(egl, display, image);
}

EGLImageWrapper::EGLImageWrapper(GLLibraryEGL* library,
                                 EGLDisplay display,
                                 EGLImage image)
    : mLibrary(library)
    , mDisplay(display)
    , mImage(image)
    , mSync(0)
{
    MOZ_ASSERT(mImage);
}

EGLImageWrapper::~EGLImageWrapper()
{
    mLibrary->fDestroyImage(mDisplay, mImage);
}

bool
EGLImageWrapper::FenceSync(GLContext* gl)
{
    MOZ_ASSERT(!mSync);

    if (mLibrary->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
        mSync = mLibrary->fCreateSync(mDisplay,
                                      LOCAL_EGL_SYNC_FENCE,
                                      nullptr);
        // We need to flush to make sure the sync object enters the command stream;
        // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
        // happens on a different thread/context.
        gl->fFlush();
    }

    if (!mSync) {
        // we failed to create one, so just do a finish
        gl->fFinish();
    }

    return true;
}

bool
EGLImageWrapper::ClientWaitSync()
{
    if (!mSync) {
        // if we have no sync object, then we did a Finish() earlier
        return true;
    }

    // wait at most 1 second; this should really be never/rarely hit
    const uint64_t ns_per_ms = 1000 * 1000;
    EGLTime timeout = 1000 * ns_per_ms;

    EGLint result = mLibrary->fClientWaitSync(mDisplay,
                                              mSync,
                                              0,
                                              timeout);
    mLibrary->fDestroySync(mDisplay, mSync);
    mSync = nullptr;

    return result == LOCAL_EGL_CONDITION_SATISFIED;
}

} // namespace gl
} // namespace mozilla