Index: ui/ozone/platform/dri/gbm_surfaceless.cc |
diff --git a/ui/ozone/platform/dri/gbm_surfaceless.cc b/ui/ozone/platform/dri/gbm_surfaceless.cc |
index b3748445a369b53d97866b759da0455c26cc4c0d..4a995002cd27ba75dc82a64bf6a60960abeab09a 100644 |
--- a/ui/ozone/platform/dri/gbm_surfaceless.cc |
+++ b/ui/ozone/platform/dri/gbm_surfaceless.cc |
@@ -32,8 +32,20 @@ bool GbmSurfaceless::OnSwapBuffers() { |
if (!controller) |
return true; |
- bool success = controller->SchedulePageFlip(); |
+ // Ensure any previous PageFlip events are handled. Doing this here also makes |
+ // sure we don't throttle GPU in case it's still handling previous PageFlip |
+ // request. This also makes sure we have at most two frames "in flight". Let's |
+ // say we submitted all the commands for render buffer A to GPU and then |
+ // requested the driver to display it. GPU might still be rendering buffer A, |
+ // so the flip is still pending. However, we might already be busy at work |
+ // submitting commands for render buffer B. Once done submitting commands for |
+ // buffer B, we queue B for page flip, and continue render for frame C. If we |
+ // try page flipping B without handling the events, the driver might return |
+ // EBusy(in case it's still handling previous flip) here, and also we don't |
+ // want to use any more than triple buffering. Thus, we sleep waiting for A |
+ // to show up on the screen, before issuing a flip request for B. |
controller->WaitForPageFlipEvent(); |
+ bool success = controller->SchedulePageFlip(); |
return success; |
} |