Repository: google/filament
File: filament/backend/src/opengl/platforms/PlatformEGLAndroid.cpp (C++)

Code before:
                    currentDrawSurface,
                    presentationTimeInNanosecond);
        }
    }
}

Platform::Stream* PlatformEGLAndroid::createStream(void* nativeStream) noexcept {
    return mExternalStreamManager.acquire(static_cast<jobject>(nativeStream));
}

void PlatformEGLAndroid::destroyStream(Stream* stream) noexcept {
    mExternalStreamManager.release(stream);
}

Platform::Sync* PlatformEGLAndroid::createSync() noexcept {
    auto const sync = eglCreateSyncKHR(getEglDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
    if (sync == nullptr) {
        LOG(ERROR) << "Failed to create sync: " << eglGetError();
    }
    return new(std::nothrow) SyncEGLAndroid{ .sync = sync };
}

bool PlatformEGLAndroid::convertSyncToFd(Sync* sync, int* fd) noexcept {
    assert_invariant(sync && fd);

    if (UTILS_UNLIKELY(!ext.egl.ANDROID_native_fence_sync)) {
        return false;
    }

    SyncEGLAndroid const& eglSync = static_cast<SyncEGLAndroid&>(*sync);
    if (eglSync.sync == nullptr) {
        LOG(ERROR) << "Cannot convert sync to fd, because the underlying fence "
                      "does not exist - does this platform support fences?";
        return false;
    }

    *fd = eglDupNativeFenceFDANDROID(getEglDisplay(), eglSync.sync);
    // In the case where there was no native FD, -1 is returned. Return false
    // to indicate there was an error in this case.
    if (*fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
        LOG(ERROR) << "Failed to convert sync to fd: " << eglGetError();
        return false;
    }
    return true;
}

void PlatformEGLAndroid::destroySync(Sync* sync) noexcept {
    assert_invariant(sync);
    SyncEGLAndroid const& eglSync = static_cast<SyncEGLAndroid&>(*sync);
    eglDestroySyncKHR(getEglDisplay(), eglSync.sync);
    delete sync;

Review comment (bug):
should this return SyncEGLAndroid anyway even for the error case? If Sync wouldn't work because of the null `sync`, I think we may as well return a nullptr and handle the exception case at the call site.

Code after:
                    currentDrawSurface,
                    presentationTimeInNanosecond);
        }
    }
}

Platform::Stream* PlatformEGLAndroid::createStream(void* nativeStream) noexcept {
    return mExternalStreamManager.acquire(static_cast<jobject>(nativeStream));
}

void PlatformEGLAndroid::destroyStream(Stream* stream) noexcept {
    mExternalStreamManager.release(stream);
}

Platform::Sync* PlatformEGLAndroid::createSync() noexcept {
    EGLSyncKHR sync = EGL_NO_SYNC_KHR;
    if (UTILS_LIKELY(ext.egl.ANDROID_native_fence_sync)) {
        sync = eglCreateSyncKHR(getEglDisplay(), EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
        if (sync == EGL_NO_SYNC_KHR) {
            LOG(ERROR) << "Failed to create sync: " << eglGetError();
        }
    } else {
        LOG(WARNING) << "Native fences not supported on this device.";
    }
    return new(std::nothrow) SyncEGLAndroid{ .sync = sync };
}

bool PlatformEGLAndroid::convertSyncToFd(Sync* sync, int* fd) noexcept {
    assert_invariant(sync && fd);

    if (UTILS_UNLIKELY(!ext.egl.ANDROID_native_fence_sync)) {
        LOG(WARNING) << "Native fences not supported, cannot convert to fd.";
        return false;
    }

    SyncEGLAndroid const& eglSync = static_cast<SyncEGLAndroid&>(*sync);
    if (eglSync.sync == EGL_NO_SYNC_KHR) {
        LOG(ERROR) << "Invalid fence, cannot convert to fd.";
        return false;
    }

    *fd = eglDupNativeFenceFDANDROID(getEglDisplay(), eglSync.sync);
    // In the case where there was no native FD, -1 is returned. Return false
    // to indicate there was an error in this case.
    if (*fd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
        LOG(ERROR) << "Failed to convert sync to fd: " << eglGetError();
        return false;
    }
    return true;
}