Commit 00a49766 by Jeff Vigil Committed by Commit Bot

EGL: Implement EGL_KHR_reusable_sync

Add extension string and flags Add EGLReusableSync files to libANGLE and gni Test: angle_deqp_egl_tests --deqp-case=dEQP-EGL.functional.reusable_sync.* --deqp-case=dEQP-EGL.functional.fence_sync.* Bug: angleproject:5168 Change-Id: I967a10cf387047c9ee1963acfc854a8288325a8e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2477293 Commit-Queue: Jeff Vigil <j.vigil@samsung.com> Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 5f7eeb93
...@@ -1418,6 +1418,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1418,6 +1418,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_EXT_image_dma_buf_import_modifiers", imageDmaBufImportModifiersEXT, &extensionStrings); InsertExtensionString("EGL_EXT_image_dma_buf_import_modifiers", imageDmaBufImportModifiersEXT, &extensionStrings);
InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings); InsertExtensionString("EGL_NOK_texture_from_pixmap", textureFromPixmapNOK, &extensionStrings);
InsertExtensionString("EGL_NV_robustness_video_memory_purge", robustnessVideoMemoryPurgeNV, &extensionStrings); InsertExtensionString("EGL_NV_robustness_video_memory_purge", robustnessVideoMemoryPurgeNV, &extensionStrings);
InsertExtensionString("EGL_KHR_reusable_sync", reusableSyncKHR, &extensionStrings);
// clang-format on // clang-format on
return extensionStrings; return extensionStrings;
......
...@@ -1122,6 +1122,9 @@ struct DisplayExtensions ...@@ -1122,6 +1122,9 @@ struct DisplayExtensions
// EGL_NV_robustness_video_memory_purge // EGL_NV_robustness_video_memory_purge
bool robustnessVideoMemoryPurgeNV = false; bool robustnessVideoMemoryPurgeNV = false;
// EGL_KHR_reusable_sync
bool reusableSyncKHR = false;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -1664,6 +1664,7 @@ void Display::initDisplayExtensions() ...@@ -1664,6 +1664,7 @@ void Display::initDisplayExtensions()
mDisplayExtensions.createContextBindGeneratesResource = true; mDisplayExtensions.createContextBindGeneratesResource = true;
mDisplayExtensions.createContextClientArrays = true; mDisplayExtensions.createContextClientArrays = true;
mDisplayExtensions.pixelFormatFloat = true; mDisplayExtensions.pixelFormatFloat = true;
mDisplayExtensions.reusableSyncKHR = true;
// Force EGL_KHR_get_all_proc_addresses on. // Force EGL_KHR_get_all_proc_addresses on.
mDisplayExtensions.getAllProcAddresses = true; mDisplayExtensions.getAllProcAddresses = true;
......
...@@ -12,19 +12,34 @@ ...@@ -12,19 +12,34 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/renderer/EGLImplFactory.h" #include "libANGLE/renderer/EGLImplFactory.h"
#include "libANGLE/renderer/EGLReusableSync.h"
#include "libANGLE/renderer/EGLSyncImpl.h" #include "libANGLE/renderer/EGLSyncImpl.h"
namespace egl namespace egl
{ {
Sync::Sync(rx::EGLImplFactory *factory, EGLenum type, const AttributeMap &attribs) Sync::Sync(rx::EGLImplFactory *factory, EGLenum type, const AttributeMap &attribs)
: mFence(factory->createSync(attribs)), : mLabel(nullptr),
mLabel(nullptr),
mType(type), mType(type),
mCondition(EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR), mCondition(EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR),
mNativeFenceFD( mNativeFenceFD(
attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID)) attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID))
{ {
switch (type)
{
case EGL_SYNC_FENCE:
case EGL_SYNC_NATIVE_FENCE_ANDROID:
mFence = std::unique_ptr<rx::EGLSyncImpl>(factory->createSync(attribs));
break;
case EGL_SYNC_REUSABLE_KHR:
mFence = std::unique_ptr<rx::EGLSyncImpl>(new rx::ReusableSync(attribs));
break;
default:
UNREACHABLE();
}
// Per extension spec: Signaling Condition. // Per extension spec: Signaling Condition.
// "If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not // "If the EGL_SYNC_NATIVE_FENCE_FD_ANDROID attribute is not
// EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute // EGL_NO_NATIVE_FENCE_FD_ANDROID then the EGL_SYNC_CONDITION_KHR attribute
...@@ -75,6 +90,11 @@ Error Sync::serverWait(const Display *display, const gl::Context *context, EGLin ...@@ -75,6 +90,11 @@ Error Sync::serverWait(const Display *display, const gl::Context *context, EGLin
return mFence->serverWait(display, context, flags); return mFence->serverWait(display, context, flags);
} }
Error Sync::signal(const Display *display, const gl::Context *context, EGLint mode)
{
return mFence->signal(display, context, mode);
}
Error Sync::getStatus(const Display *display, EGLint *outStatus) const Error Sync::getStatus(const Display *display, EGLint *outStatus) const
{ {
return mFence->getStatus(display, outStatus); return mFence->getStatus(display, outStatus);
......
...@@ -47,6 +47,7 @@ class Sync final : public angle::RefCountObject<Display, angle::Result>, public ...@@ -47,6 +47,7 @@ class Sync final : public angle::RefCountObject<Display, angle::Result>, public
EGLTime timeout, EGLTime timeout,
EGLint *outResult); EGLint *outResult);
Error serverWait(const Display *display, const gl::Context *context, EGLint flags); Error serverWait(const Display *display, const gl::Context *context, EGLint flags);
Error signal(const Display *display, const gl::Context *context, EGLint mode);
Error getStatus(const Display *display, EGLint *outStatus) const; Error getStatus(const Display *display, EGLint *outStatus) const;
Error dupNativeFenceFD(const Display *display, EGLint *result) const; Error dupNativeFenceFD(const Display *display, EGLint *result) const;
......
//
// Copyright 2020 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.
//
// EGLReusableSync.cpp: Implements the egl::ReusableSync class.
#include "libANGLE/renderer/EGLReusableSync.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/ContextImpl.h"
namespace rx
{
ReusableSync::ReusableSync(const egl::AttributeMap &attribs)
: EGLSyncImpl(), mStatus(EGL_UNSIGNALED)
{}
void ReusableSync::onDestroy(const egl::Display *display) {}
ReusableSync::~ReusableSync()
{
// Release any waiting thread.
mCondVar.notify_all();
}
egl::Error ReusableSync::initialize(const egl::Display *display,
const gl::Context *context,
EGLenum type)
{
return egl::NoError();
}
egl::Error ReusableSync::clientWait(const egl::Display *display,
const gl::Context *context,
EGLint flags,
EGLTime timeout,
EGLint *outResult)
{
if (mStatus == EGL_SIGNALED)
{
*outResult = EGL_CONDITION_SATISFIED_KHR;
return egl::NoError();
}
if (((flags & EGL_SYNC_FLUSH_COMMANDS_BIT) != 0) && (context != nullptr))
{
angle::Result result = context->getImplementation()->flush(context);
if (result != angle::Result::Continue)
{
return ResultToEGL(result);
}
}
if (timeout == 0)
{
*outResult = EGL_TIMEOUT_EXPIRED_KHR;
return egl::NoError();
}
using NanoSeconds = std::chrono::duration<int64_t, std::nano>;
NanoSeconds duration = (timeout == EGL_FOREVER) ? NanoSeconds::max() : NanoSeconds(timeout);
std::cv_status waitStatus = std::cv_status::no_timeout;
mMutex.lock();
waitStatus = mCondVar.wait_for(mMutex, duration);
mMutex.unlock();
switch (waitStatus)
{
case std::cv_status::no_timeout: // Signaled.
*outResult = EGL_CONDITION_SATISFIED_KHR;
break;
case std::cv_status::timeout: // Timed-out.
*outResult = EGL_TIMEOUT_EXPIRED_KHR;
break;
default:
break;
}
return egl::NoError();
}
egl::Error ReusableSync::serverWait(const egl::Display *display,
const gl::Context *context,
EGLint flags)
{
// Does not support server wait.
return egl::EglBadMatch();
}
egl::Error ReusableSync::signal(const egl::Display *display,
const gl::Context *context,
EGLint mode)
{
if (mode == EGL_SIGNALED)
{
if (mStatus == EGL_UNSIGNALED)
{
// Release all threads.
mCondVar.notify_all();
}
mStatus = EGL_SIGNALED;
}
else
{
mStatus = EGL_UNSIGNALED;
}
return egl::NoError();
}
egl::Error ReusableSync::getStatus(const egl::Display *display, EGLint *outStatus)
{
*outStatus = mStatus;
return egl::NoError();
}
} // namespace rx
//
// Copyright 2020 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.
//
// EGL_KHR_reusable_sync
#ifndef LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
#define LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
#include "libANGLE/AttributeMap.h"
#include "libANGLE/renderer/EGLSyncImpl.h"
#include "common/angleutils.h"
namespace rx
{
class ReusableSync final : public EGLSyncImpl
{
public:
ReusableSync(const egl::AttributeMap &attribs);
~ReusableSync() override;
void onDestroy(const egl::Display *display) override;
egl::Error initialize(const egl::Display *display,
const gl::Context *context,
EGLenum type) override;
egl::Error clientWait(const egl::Display *display,
const gl::Context *context,
EGLint flags,
EGLTime timeout,
EGLint *outResult) override;
egl::Error serverWait(const egl::Display *display,
const gl::Context *context,
EGLint flags) override;
egl::Error signal(const egl::Display *display,
const gl::Context *context,
EGLint mode) override;
egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
private:
EGLint mStatus;
std::condition_variable mCondVar;
std::unique_lock<std::mutex> mMutex;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_EGLREUSABLESYNC_H_
//
// Copyright 2020 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.
//
// EGLSyncImpl.cpp: Implements the rx::EGLSyncImpl class.
#include "libANGLE/renderer/EGLReusableSync.h"
#include "angle_gl.h"
#include "common/utilities.h"
namespace rx
{
egl::Error EGLSyncImpl::signal(const egl::Display *display, const gl::Context *context, EGLint mode)
{
UNREACHABLE();
return egl::EglBadMatch();
}
egl::Error EGLSyncImpl::dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const
{
UNREACHABLE();
return egl::EglBadMatch();
}
} // namespace rx
...@@ -37,18 +37,18 @@ class EGLSyncImpl : angle::NonCopyable ...@@ -37,18 +37,18 @@ class EGLSyncImpl : angle::NonCopyable
virtual egl::Error initialize(const egl::Display *display, virtual egl::Error initialize(const egl::Display *display,
const gl::Context *context, const gl::Context *context,
EGLenum type) = 0; EGLenum type) = 0;
virtual egl::Error clientWait(const egl::Display *display, virtual egl::Error clientWait(const egl::Display *display,
const gl::Context *context, const gl::Context *context,
EGLint flags, EGLint flags,
EGLTime timeout, EGLTime timeout,
EGLint *outResult) = 0; EGLint *outResult) = 0;
virtual egl::Error serverWait(const egl::Display *display, virtual egl::Error serverWait(const egl::Display *display,
const gl::Context *context, const gl::Context *context,
EGLint flags) = 0; EGLint flags) = 0;
virtual egl::Error signal(const egl::Display *display, const gl::Context *context, EGLint mode);
virtual egl::Error getStatus(const egl::Display *display, EGLint *outStatus) = 0; virtual egl::Error getStatus(const egl::Display *display, EGLint *outStatus) = 0;
virtual egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const;
virtual egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *fdOut) const = 0;
}; };
} // namespace rx } // namespace rx
......
...@@ -152,8 +152,6 @@ class EGLSyncMtl final : public EGLSyncImpl ...@@ -152,8 +152,6 @@ class EGLSyncMtl final : public EGLSyncImpl
EGLint flags) override; EGLint flags) override;
egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override; egl::Error getStatus(const egl::Display *display, EGLint *outStatus) override;
egl::Error dupNativeFenceFD(const egl::Display *display, EGLint *result) const override;
private: private:
mtl::Sync mSync; mtl::Sync mSync;
}; };
......
...@@ -307,10 +307,4 @@ egl::Error EGLSyncMtl::getStatus(const egl::Display *display, EGLint *outStatus) ...@@ -307,10 +307,4 @@ egl::Error EGLSyncMtl::getStatus(const egl::Display *display, EGLint *outStatus)
return egl::NoError(); return egl::NoError();
} }
egl::Error EGLSyncMtl::dupNativeFenceFD(const egl::Display *display, EGLint *result) const
{
UNREACHABLE();
return egl::EglBadDisplay();
}
} }
...@@ -2819,15 +2819,51 @@ Error ValidateCreateSyncBase(const Display *display, ...@@ -2819,15 +2819,51 @@ Error ValidateCreateSyncBase(const Display *display,
{ {
return EglBadAttribute() << "Invalid attribute"; return EglBadAttribute() << "Invalid attribute";
} }
if (!display->getExtensions().fenceSync)
{
return EglBadMatch() << "EGL_KHR_fence_sync extension is not available";
}
if (display != currentDisplay)
{
return EglBadMatch() << "CreateSync can only be called on the current display";
}
ANGLE_TRY(ValidateContext(currentDisplay, currentContext));
if (!currentContext->getExtensions().eglSyncOES)
{
return EglBadMatch() << "EGL_SYNC_FENCE_KHR cannot be used without "
"GL_OES_EGL_sync support.";
}
break; break;
case EGL_SYNC_NATIVE_FENCE_ANDROID: case EGL_SYNC_NATIVE_FENCE_ANDROID:
if (!display->getExtensions().fenceSync)
{
return EglBadMatch() << "EGL_KHR_fence_sync extension is not available";
}
if (!display->getExtensions().nativeFenceSyncANDROID) if (!display->getExtensions().nativeFenceSyncANDROID)
{ {
return EglBadDisplay() return EglBadDisplay()
<< "EGL_ANDROID_native_fence_sync extension is not available."; << "EGL_ANDROID_native_fence_sync extension is not available.";
} }
if (display != currentDisplay)
{
return EglBadMatch() << "CreateSync can only be called on the current display";
}
ANGLE_TRY(ValidateContext(currentDisplay, currentContext));
if (!currentContext->getExtensions().eglSyncOES)
{
return EglBadMatch() << "EGL_SYNC_FENCE_KHR cannot be used without "
"GL_OES_EGL_sync support.";
}
for (const auto &attributeIter : attribs) for (const auto &attributeIter : attribs)
{ {
EGLAttrib attribute = attributeIter.first; EGLAttrib attribute = attributeIter.first;
...@@ -2843,6 +2879,18 @@ Error ValidateCreateSyncBase(const Display *display, ...@@ -2843,6 +2879,18 @@ Error ValidateCreateSyncBase(const Display *display,
} }
break; break;
case EGL_SYNC_REUSABLE_KHR:
if (!attribs.isEmpty())
{
return EglBadAttribute() << "Invalid attribute";
}
if (!display->getExtensions().reusableSyncKHR)
{
return EglBadMatch() << "EGL_KHR_reusable_sync extension is not available.";
}
break;
default: default:
if (isExt) if (isExt)
{ {
...@@ -2854,19 +2902,6 @@ Error ValidateCreateSyncBase(const Display *display, ...@@ -2854,19 +2902,6 @@ Error ValidateCreateSyncBase(const Display *display,
} }
} }
if (display != currentDisplay)
{
return EglBadMatch() << "CreateSync can only be called on the current display";
}
ANGLE_TRY(ValidateContext(currentDisplay, currentContext));
if (!currentContext->getExtensions().eglSyncOES)
{
return EglBadMatch() << "EGL_SYNC_FENCE_KHR cannot be used without "
"GL_OES_EGL_sync support.";
}
return NoError(); return NoError();
} }
...@@ -2907,14 +2942,6 @@ Error ValidateCreateSyncKHR(const Display *display, ...@@ -2907,14 +2942,6 @@ Error ValidateCreateSyncKHR(const Display *display,
const Display *currentDisplay, const Display *currentDisplay,
const gl::Context *currentContext) const gl::Context *currentContext)
{ {
ANGLE_TRY(ValidateDisplay(display));
const DisplayExtensions &extensions = display->getExtensions();
if (!extensions.fenceSync)
{
return EglBadAccess() << "EGL_KHR_fence_sync extension is not available";
}
return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, true); return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, true);
} }
...@@ -4622,4 +4649,29 @@ Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display, ...@@ -4622,4 +4649,29 @@ Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display,
return NoError(); return NoError();
} }
Error ValidateSignalSyncKHR(const Display *display, const Sync *sync, EGLint mode)
{
ANGLE_TRY(ValidateDisplay(display));
ANGLE_TRY(ValidateSync(display, sync));
if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
{
if (!display->getExtensions().reusableSyncKHR)
{
return EglBadMatch() << "EGL_KHR_reusable_sync extension is not available.";
}
if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
{
return EglBadParameter() << "eglSignalSyncKHR invalid mode.";
}
return NoError();
}
return EglBadMatch();
}
} // namespace egl } // namespace egl
...@@ -347,6 +347,9 @@ Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display, ...@@ -347,6 +347,9 @@ Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display,
const Surface *surface, const Surface *surface,
EGLFrameTokenANGLE frametoken); EGLFrameTokenANGLE frametoken);
// EGL_KHR_reusable_sync
Error ValidateSignalSyncKHR(const Display *display, const Sync *sync, EGLint mode);
} // namespace egl } // namespace egl
#define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \ #define ANGLE_EGL_TRY(THREAD, EXPR, FUNCNAME, LABELOBJECT) \
......
...@@ -287,6 +287,7 @@ libangle_headers = [ ...@@ -287,6 +287,7 @@ libangle_headers = [
"src/libANGLE/renderer/DeviceImpl.h", "src/libANGLE/renderer/DeviceImpl.h",
"src/libANGLE/renderer/DisplayImpl.h", "src/libANGLE/renderer/DisplayImpl.h",
"src/libANGLE/renderer/EGLImplFactory.h", "src/libANGLE/renderer/EGLImplFactory.h",
"src/libANGLE/renderer/EGLReusableSync.h",
"src/libANGLE/renderer/EGLSyncImpl.h", "src/libANGLE/renderer/EGLSyncImpl.h",
"src/libANGLE/renderer/FenceNVImpl.h", "src/libANGLE/renderer/FenceNVImpl.h",
"src/libANGLE/renderer/FormatID_autogen.h", "src/libANGLE/renderer/FormatID_autogen.h",
...@@ -417,6 +418,8 @@ libangle_sources = [ ...@@ -417,6 +418,8 @@ libangle_sources = [
"src/libANGLE/renderer/ContextImpl.cpp", "src/libANGLE/renderer/ContextImpl.cpp",
"src/libANGLE/renderer/DeviceImpl.cpp", "src/libANGLE/renderer/DeviceImpl.cpp",
"src/libANGLE/renderer/DisplayImpl.cpp", "src/libANGLE/renderer/DisplayImpl.cpp",
"src/libANGLE/renderer/EGLReusableSync.cpp",
"src/libANGLE/renderer/EGLSyncImpl.cpp",
"src/libANGLE/renderer/Format_table_autogen.cpp", "src/libANGLE/renderer/Format_table_autogen.cpp",
"src/libANGLE/renderer/ProgramPipelineImpl.cpp", "src/libANGLE/renderer/ProgramPipelineImpl.cpp",
"src/libANGLE/renderer/QueryImpl.cpp", "src/libANGLE/renderer/QueryImpl.cpp",
......
...@@ -1646,8 +1646,17 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_SignalSyncKHR(EGLDisplay dpy, EGLSync sy ...@@ -1646,8 +1646,17 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY EGL_SignalSyncKHR(EGLDisplay dpy, EGLSync sy
", EGLint mode = 0x%X", ", EGLint mode = 0x%X",
(uintptr_t)dpy, (uintptr_t)sync, mode); (uintptr_t)dpy, (uintptr_t)sync, mode);
Thread *thread = egl::GetCurrentThread(); Thread *thread = egl::GetCurrentThread();
// Unimplemented. egl::Display *display = static_cast<egl::Display *>(dpy);
egl::Sync *syncObject = static_cast<Sync *>(sync);
ANGLE_EGL_TRY_RETURN(thread, ValidateSignalSyncKHR(display, syncObject, mode),
"eglSignalSyncKHR", GetSyncIfValid(display, syncObject), EGL_FALSE);
gl::Context *currentContext = thread->getContext();
ANGLE_EGL_TRY_RETURN(thread, syncObject->signal(display, currentContext, mode),
"eglSignalSyncKHR", GetSyncIfValid(display, syncObject), EGL_FALSE);
thread->setSuccess(); thread->setSuccess();
return EGL_TRUE; return EGL_TRUE;
} }
......
...@@ -194,7 +194,6 @@ ...@@ -194,7 +194,6 @@
// Tests were being hidden by flakiness (anglebug.com/3271) // Tests were being hidden by flakiness (anglebug.com/3271)
3325 : dEQP-EGL.functional.fence_sync.* = SKIP 3325 : dEQP-EGL.functional.fence_sync.* = SKIP
3325 : dEQP-EGL.functional.reusable_sync.* = SKIP
// Nexus 5x // Nexus 5x
2546 NEXUS5X : dEQP-EGL.functional.query_context.get_current_context.* = SKIP 2546 NEXUS5X : dEQP-EGL.functional.query_context.get_current_context.* = SKIP
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment