egl/dri2: implement EGL_KHR_cl_event2 (v2)
v2: fix the SYNC_CONDITION query
This commit is contained in:
@@ -531,6 +531,8 @@ dri2_setup_screen(_EGLDisplay *disp)
|
||||
if (dri2_dpy->fence) {
|
||||
disp->Extensions.KHR_fence_sync = EGL_TRUE;
|
||||
disp->Extensions.KHR_wait_sync = EGL_TRUE;
|
||||
if (dri2_dpy->fence->get_fence_from_cl_event)
|
||||
disp->Extensions.KHR_cl_event2 = EGL_TRUE;
|
||||
}
|
||||
|
||||
if (dri2_dpy->image) {
|
||||
@@ -2207,7 +2209,8 @@ dri2_egl_unref_sync(struct dri2_egl_display *dri2_dpy,
|
||||
|
||||
static _EGLSync *
|
||||
dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
EGLenum type, const EGLint *attrib_list)
|
||||
EGLenum type, const EGLint *attrib_list,
|
||||
const EGLAttribKHR *attrib_list64)
|
||||
{
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
struct dri2_egl_display *dri2_dpy = dri2_egl_display(dpy);
|
||||
@@ -2220,7 +2223,8 @@ dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list)) {
|
||||
if (!_eglInitSync(&dri2_sync->base, dpy, type, attrib_list,
|
||||
attrib_list64)) {
|
||||
free(dri2_sync);
|
||||
return NULL;
|
||||
}
|
||||
@@ -2229,6 +2233,23 @@ dri2_create_sync(_EGLDriver *drv, _EGLDisplay *dpy,
|
||||
case EGL_SYNC_FENCE_KHR:
|
||||
dri2_sync->fence = dri2_dpy->fence->create_fence(dri2_ctx->dri_context);
|
||||
break;
|
||||
|
||||
case EGL_SYNC_CL_EVENT_KHR:
|
||||
dri2_sync->fence = dri2_dpy->fence->get_fence_from_cl_event(
|
||||
dri2_dpy->dri_screen,
|
||||
dri2_sync->base.CLEvent);
|
||||
/* this can only happen if the cl_event passed in is invalid. */
|
||||
if (!dri2_sync->fence) {
|
||||
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
|
||||
free(dri2_sync);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* the initial status must be "signaled" if the cl_event is signaled */
|
||||
if (dri2_dpy->fence->client_wait_sync(dri2_ctx->dri_context,
|
||||
dri2_sync->fence, 0, 0))
|
||||
dri2_sync->base.SyncStatus = EGL_SIGNALED_KHR;
|
||||
break;
|
||||
}
|
||||
|
||||
p_atomic_set(&dri2_sync->refcount, 1);
|
||||
|
@@ -407,6 +407,7 @@ _eglCreateExtensionsString(_EGLDisplay *dpy)
|
||||
_EGL_CHECK_EXTENSION(KHR_reusable_sync);
|
||||
_EGL_CHECK_EXTENSION(KHR_fence_sync);
|
||||
_EGL_CHECK_EXTENSION(KHR_wait_sync);
|
||||
_EGL_CHECK_EXTENSION(KHR_cl_event2);
|
||||
|
||||
_EGL_CHECK_EXTENSION(KHR_surfaceless_context);
|
||||
_EGL_CHECK_EXTENSION(KHR_create_context);
|
||||
@@ -1215,6 +1216,7 @@ eglGetProcAddress(const char *procname)
|
||||
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
|
||||
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
|
||||
{ "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
|
||||
{ "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
|
||||
{ "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
|
||||
{ "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
|
||||
{ "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
|
||||
@@ -1655,8 +1657,9 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
|
||||
}
|
||||
|
||||
|
||||
EGLSyncKHR EGLAPIENTRY
|
||||
eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
static EGLSyncKHR
|
||||
_eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
|
||||
const EGLAttribKHR *attrib_list64, EGLBoolean is64)
|
||||
{
|
||||
_EGLDisplay *disp = _eglLockDisplay(dpy);
|
||||
_EGLContext *ctx = _eglGetCurrentContext();
|
||||
@@ -1666,6 +1669,9 @@ eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
|
||||
_EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
|
||||
|
||||
if (!disp->Extensions.KHR_cl_event2 && is64)
|
||||
RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
|
||||
|
||||
/* return an error if the client API doesn't support GL_OES_EGL_sync */
|
||||
if (!ctx || ctx->Resource.Display != dpy ||
|
||||
ctx->ClientAPI != EGL_OPENGL_ES_API)
|
||||
@@ -1680,17 +1686,35 @@ eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
if (!disp->Extensions.KHR_reusable_sync)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
break;
|
||||
case EGL_SYNC_CL_EVENT_KHR:
|
||||
if (!disp->Extensions.KHR_cl_event2)
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
break;
|
||||
default:
|
||||
RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
|
||||
}
|
||||
|
||||
sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
|
||||
sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list, attrib_list64);
|
||||
ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
|
||||
|
||||
RETURN_EGL_EVAL(disp, ret);
|
||||
}
|
||||
|
||||
|
||||
EGLSyncKHR EGLAPIENTRY
|
||||
eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
|
||||
{
|
||||
return _eglCreateSync(dpy, type, attrib_list, NULL, EGL_FALSE);
|
||||
}
|
||||
|
||||
|
||||
EGLSyncKHR EGLAPIENTRY
|
||||
eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list)
|
||||
{
|
||||
return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE);
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean EGLAPIENTRY
|
||||
eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
|
||||
{
|
||||
|
@@ -102,7 +102,7 @@ typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLCo
|
||||
typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image);
|
||||
|
||||
|
||||
typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list);
|
||||
typedef _EGLSync *(*CreateSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum type, const EGLint *attrib_list, const EGLAttribKHR *attrib_list64);
|
||||
typedef EGLBoolean (*DestroySyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
|
||||
typedef EGLint (*ClientWaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint flags, EGLTimeKHR timeout);
|
||||
typedef EGLint (*WaitSyncKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync);
|
||||
|
@@ -107,6 +107,7 @@ struct _egl_extensions
|
||||
EGLBoolean KHR_reusable_sync;
|
||||
EGLBoolean KHR_fence_sync;
|
||||
EGLBoolean KHR_wait_sync;
|
||||
EGLBoolean KHR_cl_event2;
|
||||
|
||||
EGLBoolean KHR_surfaceless_context;
|
||||
EGLBoolean KHR_create_context;
|
||||
|
@@ -65,25 +65,76 @@ _eglParseSyncAttribList(_EGLSync *sync, const EGLint *attrib_list)
|
||||
}
|
||||
|
||||
|
||||
static EGLint
|
||||
_eglParseSyncAttribList64(_EGLSync *sync, const EGLAttribKHR *attrib_list)
|
||||
{
|
||||
EGLint i, err = EGL_SUCCESS;
|
||||
|
||||
if (!attrib_list)
|
||||
return EGL_SUCCESS;
|
||||
|
||||
for (i = 0; attrib_list[i] != EGL_NONE; i++) {
|
||||
EGLint attr = attrib_list[i++];
|
||||
EGLint val = attrib_list[i];
|
||||
|
||||
switch (attr) {
|
||||
case EGL_CL_EVENT_HANDLE_KHR:
|
||||
if (sync->Type == EGL_SYNC_CL_EVENT_KHR) {
|
||||
sync->CLEvent = val;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
(void) val;
|
||||
err = EGL_BAD_ATTRIBUTE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err != EGL_SUCCESS) {
|
||||
_eglLog(_EGL_DEBUG, "bad sync attribute 0x%04x", attr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
|
||||
const EGLint *attrib_list)
|
||||
const EGLint *attrib_list, const EGLAttribKHR *attrib_list64)
|
||||
{
|
||||
EGLint err;
|
||||
|
||||
if (!(type == EGL_SYNC_REUSABLE_KHR && dpy->Extensions.KHR_reusable_sync) &&
|
||||
!(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync))
|
||||
!(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync) &&
|
||||
!(type == EGL_SYNC_CL_EVENT_KHR && dpy->Extensions.KHR_cl_event2 &&
|
||||
attrib_list64))
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
|
||||
|
||||
_eglInitResource(&sync->Resource, sizeof(*sync), dpy);
|
||||
sync->Type = type;
|
||||
sync->SyncStatus = EGL_UNSIGNALED_KHR;
|
||||
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
|
||||
|
||||
err = _eglParseSyncAttribList(sync, attrib_list);
|
||||
switch (type) {
|
||||
case EGL_SYNC_CL_EVENT_KHR:
|
||||
sync->SyncCondition = EGL_SYNC_CL_EVENT_COMPLETE_KHR;
|
||||
break;
|
||||
default:
|
||||
sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
|
||||
}
|
||||
|
||||
if (attrib_list64)
|
||||
err = _eglParseSyncAttribList64(sync, attrib_list64);
|
||||
else
|
||||
err = _eglParseSyncAttribList(sync, attrib_list);
|
||||
|
||||
if (err != EGL_SUCCESS)
|
||||
return _eglError(err, "eglCreateSyncKHR");
|
||||
|
||||
if (type == EGL_SYNC_CL_EVENT_KHR && !sync->CLEvent)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR");
|
||||
|
||||
return EGL_TRUE;
|
||||
}
|
||||
|
||||
@@ -103,7 +154,8 @@ _eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync,
|
||||
*value = sync->SyncStatus;
|
||||
break;
|
||||
case EGL_SYNC_CONDITION_KHR:
|
||||
if (sync->Type != EGL_SYNC_FENCE_KHR)
|
||||
if (sync->Type != EGL_SYNC_FENCE_KHR &&
|
||||
sync->Type != EGL_SYNC_CL_EVENT_KHR)
|
||||
return _eglError(EGL_BAD_ATTRIBUTE, "eglGetSyncAttribKHR");
|
||||
*value = sync->SyncCondition;
|
||||
break;
|
||||
|
@@ -47,12 +47,13 @@ struct _egl_sync
|
||||
EGLenum Type;
|
||||
EGLenum SyncStatus;
|
||||
EGLenum SyncCondition;
|
||||
EGLAttribKHR CLEvent;
|
||||
};
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
_eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type,
|
||||
const EGLint *attrib_list);
|
||||
const EGLint *attrib_list, const EGLAttribKHR *attrib_list64);
|
||||
|
||||
|
||||
extern EGLBoolean
|
||||
|
Reference in New Issue
Block a user