| Index: ui/gl/gl_surface_ozone.cc
 | 
| diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
 | 
| index eecd06413876bdbceb9b0d7a50c26c5f40eb6559..cba706bda4e030b6daa599525846ebebbc847640 100644
 | 
| --- a/ui/gl/gl_surface_ozone.cc
 | 
| +++ b/ui/gl/gl_surface_ozone.cc
 | 
| @@ -105,7 +105,9 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
 | 
|                              AcceleratedWidget widget)
 | 
|        : SurfacelessEGL(gfx::Size()),
 | 
|          ozone_surface_(ozone_surface.Pass()),
 | 
| -        widget_(widget) {}
 | 
| +        widget_(widget),
 | 
| +        has_implicit_external_sync_(
 | 
| +            HasEGLExtension("EGL_ARM_implicit_external_sync")) {}
 | 
|  
 | 
|    bool Initialize() override {
 | 
|      if (!SurfacelessEGL::Initialize())
 | 
| @@ -122,8 +124,8 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
 | 
|      return SurfacelessEGL::Resize(size);
 | 
|    }
 | 
|    bool SwapBuffers() override {
 | 
| -    // TODO: this should be replaced by a fence when supported by the driver.
 | 
| -    glFlush();
 | 
| +    if (!Flush())
 | 
| +      return false;
 | 
|      return ozone_surface_->OnSwapBuffers();
 | 
|    }
 | 
|    bool ScheduleOverlayPlane(int z_order,
 | 
| @@ -143,8 +145,8 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
 | 
|      return true;
 | 
|    }
 | 
|    bool SwapBuffersAsync(const SwapCompletionCallback& callback) override {
 | 
| -    // TODO: this should be replaced by a fence when supported by the driver.
 | 
| -    glFlush();
 | 
| +    if (!Flush())
 | 
| +      return false;
 | 
|      return ozone_surface_->OnSwapBuffersAsync(callback);
 | 
|    }
 | 
|    bool PostSubBufferAsync(int x,
 | 
| @@ -160,11 +162,35 @@ class GL_EXPORT GLSurfaceOzoneSurfaceless : public SurfacelessEGL {
 | 
|      Destroy();  // EGL surface must be destroyed before SurfaceOzone
 | 
|    }
 | 
|  
 | 
| +  bool Flush() {
 | 
| +    glFlush();
 | 
| +    // TODO: the following should be replaced by a per surface flush as it gets
 | 
| +    // implemented in GL drivers.
 | 
| +    if (has_implicit_external_sync_) {
 | 
| +      const EGLint attrib_list[] = {
 | 
| +          EGL_SYNC_CONDITION_KHR,
 | 
| +          EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
 | 
| +          EGL_NONE};
 | 
| +      EGLSyncKHR fence =
 | 
| +          eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
 | 
| +      if (fence) {
 | 
| +        // TODO(dbehr): piman@ suggests we could improve here by moving
 | 
| +        // following wait to right before drmModePageFlip crbug.com/456417.
 | 
| +        eglClientWaitSyncKHR(GetDisplay(), fence,
 | 
| +                             EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR);
 | 
| +        eglDestroySyncKHR(GetDisplay(), fence);
 | 
| +      } else {
 | 
| +        return false;
 | 
| +      }
 | 
| +    }
 | 
| +    return true;
 | 
| +  }
 | 
| +
 | 
|    // The native surface. Deleting this is allowed to free the EGLNativeWindow.
 | 
|    scoped_ptr<ui::SurfaceOzoneEGL> ozone_surface_;
 | 
|    AcceleratedWidget widget_;
 | 
|    scoped_ptr<VSyncProvider> vsync_provider_;
 | 
| -
 | 
| +  bool has_implicit_external_sync_;
 | 
|    DISALLOW_COPY_AND_ASSIGN(GLSurfaceOzoneSurfaceless);
 | 
|  };
 | 
|  
 | 
| 
 |