Hash :
d0bdec30
Author :
Date :
2024-05-13T18:11:17
EGL: Handle null resultOut for sync tail call destruction Syncs can be destroyed during eglDestroySync or as part of display destruction. During display distruction there is no result so swallow any errors. Bug: angleproject:8434 Change-Id: I172d268c91fd0d6ba534eceff8914f9c719bdf39 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5533777 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
//
// Copyright 2019 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.
//
// SyncEGL.cpp: Implements the rx::SyncEGL class.
#include "libANGLE/renderer/gl/egl/SyncEGL.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/Display.h"
#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
namespace rx
{
SyncEGL::SyncEGL(const FunctionsEGL *egl) : mEGL(egl), mSync(EGL_NO_SYNC_KHR) {}
SyncEGL::~SyncEGL()
{
ASSERT(mSync == EGL_NO_SYNC_KHR);
}
void SyncEGL::onDestroy(const egl::Display *display)
{
if (mSync != EGL_NO_SYNC_KHR)
{
egl::Display::GetCurrentThreadUnlockedTailCall()->add(
[egl = mEGL, sync = mSync](void *resultOut) {
EGLBoolean result = egl->destroySyncKHR(sync);
if (resultOut)
{
// It's possible for resultOut to be null if this sync is being destructed as
// part of display destruction.
*static_cast<EGLBoolean *>(resultOut) = result;
}
});
mSync = EGL_NO_SYNC_KHR;
}
}
egl::Error SyncEGL::initialize(const egl::Display *display,
const gl::Context *context,
EGLenum type,
const egl::AttributeMap &attribs)
{
ASSERT(type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID);
constexpr size_t kAttribVectorSize = 3;
angle::FixedVector<EGLint, kAttribVectorSize> nativeAttribs;
if (type == EGL_SYNC_NATIVE_FENCE_ANDROID)
{
EGLint fenceFd =
attribs.getAsInt(EGL_SYNC_NATIVE_FENCE_FD_ANDROID, EGL_NO_NATIVE_FENCE_FD_ANDROID);
nativeAttribs.push_back(EGL_SYNC_NATIVE_FENCE_FD_ANDROID);
nativeAttribs.push_back(fenceFd);
}
nativeAttribs.push_back(EGL_NONE);
egl::Display::GetCurrentThreadUnlockedTailCall()->add(
[egl = mEGL, &sync = mSync, type, attribs = nativeAttribs](void *resultOut) {
sync = egl->createSyncKHR(type, attribs.data());
// If sync creation failed, force the return value of eglCreateSync to EGL_NO_SYNC. This
// won't delete this sync object but a driver error is unexpected at this point.
if (sync == EGL_NO_SYNC_KHR)
{
ERR() << "eglCreateSync failed with " << gl::FmtHex(egl->getError());
*static_cast<EGLSync *>(resultOut) = EGL_NO_SYNC_KHR;
}
});
return egl::NoError();
}
egl::Error SyncEGL::clientWait(const egl::Display *display,
const gl::Context *context,
EGLint flags,
EGLTime timeout,
EGLint *outResult)
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
// If we need to perform a CPU wait don't set the resultOut parameter passed into the
// method, instead set the parameter passed into the unlocked tail call.
egl::Display::GetCurrentThreadUnlockedTailCall()->add(
[egl = mEGL, sync = mSync, flags, timeout](void *resultOut) {
*static_cast<EGLint *>(resultOut) = egl->clientWaitSyncKHR(sync, flags, timeout);
});
return egl::NoError();
}
egl::Error SyncEGL::serverWait(const egl::Display *display,
const gl::Context *context,
EGLint flags)
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
egl::Display::GetCurrentThreadUnlockedTailCall()->add(
[egl = mEGL, sync = mSync, flags](void *resultOut) {
*static_cast<EGLBoolean *>(resultOut) = egl->waitSyncKHR(sync, flags);
});
return egl::NoError();
}
egl::Error SyncEGL::getStatus(const egl::Display *display, EGLint *outStatus)
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
EGLBoolean result = mEGL->getSyncAttribKHR(mSync, EGL_SYNC_STATUS_KHR, outStatus);
if (result == EGL_FALSE)
{
return egl::Error(mEGL->getError(), "eglGetSyncAttribKHR with EGL_SYNC_STATUS_KHR failed");
}
return egl::NoError();
}
egl::Error SyncEGL::dupNativeFenceFD(const egl::Display *display, EGLint *result) const
{
ASSERT(mSync != EGL_NO_SYNC_KHR);
*result = mEGL->dupNativeFenceFDANDROID(mSync);
if (*result == EGL_NO_NATIVE_FENCE_FD_ANDROID)
{
return egl::Error(mEGL->getError(), "eglDupNativeFenceFDANDROID failed");
}
return egl::NoError();
}
} // namespace rx