atomic: Use CPU-side KMS fence synchronisation
Atomic does not let us have multiple requests in flight at once; if we
don't synchronise with the request completion on the CPU side, we can
get -EBUSY from the atomic commit.
We already have everything required to do this, namely the out-fence
from the last commit. Block on that with a CPU-side wait before we call
atomic commit, to make sure we'll never attempt to queue an atomic
commit before the previous one has completed.
Signed-off-by: Daniel Stone <daniels@collabora.com>
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
Daniel Stone
7 years ago
154 | 154 |
get_proc_dpy(EGL_KHR_fence_sync, eglCreateSyncKHR);
|
155 | 155 |
get_proc_dpy(EGL_KHR_fence_sync, eglDestroySyncKHR);
|
156 | 156 |
get_proc_dpy(EGL_KHR_fence_sync, eglWaitSyncKHR);
|
|
157 |
get_proc_dpy(EGL_KHR_fence_sync, eglClientWaitSyncKHR);
|
157 | 158 |
get_proc_dpy(EGL_ANDROID_native_fence_sync, eglDupNativeFenceFDANDROID);
|
158 | 159 |
|
159 | 160 |
printf("Using display %p with EGL version %d.%d\n",
|
78 | 78 |
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
|
79 | 79 |
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
|
80 | 80 |
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR;
|
|
81 |
PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR;
|
81 | 82 |
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
|
82 | 83 |
|
83 | 84 |
void (*draw)(unsigned i);
|
209 | 209 |
|
210 | 210 |
if (drm.kms_out_fence_fd != -1) {
|
211 | 211 |
kms_fence = create_fence(egl, drm.kms_out_fence_fd);
|
|
212 |
assert(kms_fence);
|
212 | 213 |
|
213 | 214 |
/* driver now has ownership of the fence fd: */
|
214 | 215 |
drm.kms_out_fence_fd = -1;
|
|
219 | 220 |
* the buffer that is still on screen.
|
220 | 221 |
*/
|
221 | 222 |
egl->eglWaitSyncKHR(egl->display, kms_fence, 0);
|
222 | |
egl->eglDestroySyncKHR(egl->display, kms_fence);
|
223 | 223 |
}
|
224 | 224 |
|
225 | 225 |
egl->draw(i++);
|
|
228 | 228 |
* signaled when gpu rendering done
|
229 | 229 |
*/
|
230 | 230 |
gpu_fence = create_fence(egl, EGL_NO_NATIVE_FENCE_FD_ANDROID);
|
|
231 |
assert(gpu_fence);
|
231 | 232 |
|
232 | 233 |
eglSwapBuffers(egl->display, egl->surface);
|
233 | 234 |
|
|
243 | 244 |
if (!fb) {
|
244 | 245 |
printf("Failed to get a new framebuffer BO\n");
|
245 | 246 |
return -1;
|
|
247 |
}
|
|
248 |
|
|
249 |
if (kms_fence) {
|
|
250 |
EGLint status;
|
|
251 |
|
|
252 |
/* Wait on the CPU side for the _previous_ commit to
|
|
253 |
* complete before we post the flip through KMS, as
|
|
254 |
* atomic will reject the commit if we post a new one
|
|
255 |
* whilst the previous one is still pending.
|
|
256 |
*/
|
|
257 |
do {
|
|
258 |
status = egl->eglClientWaitSyncKHR(egl->display,
|
|
259 |
kms_fence,
|
|
260 |
0,
|
|
261 |
EGL_FOREVER_KHR);
|
|
262 |
} while (status != EGL_CONDITION_SATISFIED_KHR);
|
|
263 |
|
|
264 |
egl->eglDestroySyncKHR(egl->display, kms_fence);
|
246 | 265 |
}
|
247 | 266 |
|
248 | 267 |
/*
|