gfx/gl/EGLUtils.cpp
author Ciure Andrei <aciure@mozilla.com>
Mon, 14 Jan 2019 05:55:46 +0200
changeset 453695 d23f6e4d9ba23840b511babbf651e37b297e863d
parent 448947 6f3709b3878117466168c40affa7bca0b60cf75b
child 461783 5b5e6a9942777d6faee07db57fd6b14d465b3ab3
permissions -rw-r--r--
Merge mozilla-central to mozilla-inbound. a=merge CLOSED TREE

/* 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