Blob Blame History Raw
/* 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"

namespace mozilla {
namespace gl {

bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl) {
  return sEGLLibrary.HasKHRImageBase() && sEGLLibrary.HasKHRImageTexture2D() &&
         gl->IsExtensionSupported(GLContext::OES_EGL_image);
}

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

  EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
  EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
  EGLImage image =
      sEGLLibrary.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));

  GLLibraryEGL& library = sEGLLibrary;
  EGLDisplay display = EGL_DISPLAY();
  EGLContext eglContext = GLContextEGL::Cast(gl)->mContext;
  EGLClientBuffer clientBuffer = (EGLClientBuffer)((uint64_t)tex);
  EGLImage image = library.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",
                  sEGLLibrary.fGetError());
#endif
    return nullptr;
  }

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

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