| Index: components/exo/wayland/clients/motion_events.cc
|
| diff --git a/components/exo/wayland/clients/motion_events.cc b/components/exo/wayland/clients/motion_events.cc
|
| index 6d913b4ae4e73f0e37166c904fccd34c7bd4f438..09535c26065aabeee55da3aed3b2d28f3083c9a8 100644
|
| --- a/components/exo/wayland/clients/motion_events.cc
|
| +++ b/components/exo/wayland/clients/motion_events.cc
|
| @@ -8,6 +8,7 @@
|
|
|
| #include <fcntl.h>
|
| #include <linux-dmabuf-unstable-v1-client-protocol.h>
|
| +#include <linux-explicit-synchronization-unstable-v1-client-protocol.h>
|
| #include <wayland-client-core.h>
|
| #include <wayland-client-protocol.h>
|
|
|
| @@ -68,6 +69,9 @@ DEFAULT_DELETER(wl_seat, wl_seat_destroy)
|
| DEFAULT_DELETER(wl_pointer, wl_pointer_destroy)
|
| DEFAULT_DELETER(wl_touch, wl_touch_destroy)
|
| DEFAULT_DELETER(wl_callback, wl_callback_destroy)
|
| +DEFAULT_DELETER(zcr_linux_explicit_synchronization_v1,
|
| + zcr_linux_explicit_synchronization_v1_destroy)
|
| +DEFAULT_DELETER(zcr_synchronization_v1, zcr_synchronization_v1_destroy)
|
| DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
|
| DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
|
|
|
| @@ -110,6 +114,8 @@ const int kBenchmarkInterval = 5;
|
| struct Globals {
|
| std::unique_ptr<wl_compositor> compositor;
|
| std::unique_ptr<wl_shm> shm;
|
| + std::unique_ptr<zcr_linux_explicit_synchronization_v1>
|
| + linux_explicit_synchronization;
|
| std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf;
|
| std::unique_ptr<wl_shell> shell;
|
| std::unique_ptr<wl_seat> seat;
|
| @@ -134,6 +140,11 @@ void RegistryHandler(void* data,
|
| } else if (strcmp(interface, "wl_seat") == 0) {
|
| globals->seat.reset(static_cast<wl_seat*>(
|
| wl_registry_bind(registry, id, &wl_seat_interface, 5)));
|
| + } else if (strcmp(interface, "zcr_linux_explicit_synchronization_v1") == 0) {
|
| + globals->linux_explicit_synchronization.reset(
|
| + static_cast<zcr_linux_explicit_synchronization_v1*>(wl_registry_bind(
|
| + registry, id, &zcr_linux_explicit_synchronization_v1_interface,
|
| + 1)));
|
| } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
|
| globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>(
|
| wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1)));
|
| @@ -158,6 +169,14 @@ struct DeleteEglImageTraits {
|
| }
|
| };
|
| using ScopedEglImage = base::ScopedGeneric<EGLImageKHR, DeleteEglImageTraits>;
|
| +
|
| +struct DeleteEglSyncTraits {
|
| + static EGLSyncKHR InvalidValue() { return 0; }
|
| + static void Free(EGLSyncKHR sync) {
|
| + eglDestroySyncKHR(eglGetCurrentDisplay(), sync);
|
| + }
|
| +};
|
| +using ScopedEglSync = base::ScopedGeneric<EGLSyncKHR, DeleteEglSyncTraits>;
|
| #endif
|
|
|
| struct Buffer {
|
| @@ -166,6 +185,7 @@ struct Buffer {
|
| #if defined(OZONE_PLATFORM_GBM)
|
| std::unique_ptr<gbm_bo> bo;
|
| std::unique_ptr<ScopedEglImage> egl_image;
|
| + std::unique_ptr<ScopedEglSync> egl_sync;
|
| std::unique_ptr<ScopedTexture> texture;
|
| #endif
|
| std::unique_ptr<zwp_linux_buffer_params_v1> params;
|
| @@ -303,6 +323,7 @@ class MotionEvents {
|
| size_t num_rects,
|
| size_t max_frames_pending,
|
| bool fullscreen,
|
| + bool use_explicit_synchronization,
|
| const std::string* use_drm)
|
| : width_(width),
|
| height_(height),
|
| @@ -310,6 +331,7 @@ class MotionEvents {
|
| num_rects_(num_rects),
|
| max_frames_pending_(max_frames_pending),
|
| fullscreen_(fullscreen),
|
| + use_explicit_synchronization_(use_explicit_synchronization),
|
| use_drm_(use_drm) {}
|
|
|
| // Initialize and run client main loop.
|
| @@ -324,6 +346,7 @@ class MotionEvents {
|
| const size_t num_rects_;
|
| const size_t max_frames_pending_;
|
| const bool fullscreen_;
|
| + const bool use_explicit_synchronization_;
|
| const std::string* use_drm_;
|
|
|
| Globals globals_;
|
| @@ -376,6 +399,11 @@ int MotionEvents::Run() {
|
| LOG(ERROR) << "Can't find shm interface";
|
| return 1;
|
| }
|
| + if (use_explicit_synchronization_ &&
|
| + !globals_.linux_explicit_synchronization) {
|
| + LOG(ERROR) << "Can't find linux_explicit_synchronization interface";
|
| + return 1;
|
| + }
|
| if (use_drm_ && !globals_.linux_dmabuf) {
|
| LOG(ERROR) << "Can't find linux_dmabuf interface";
|
| return 1;
|
| @@ -389,8 +417,8 @@ int MotionEvents::Run() {
|
| return 1;
|
| }
|
|
|
| - EGLenum egl_sync_type = 0;
|
| #if defined(OZONE_PLATFORM_GBM)
|
| + EGLenum egl_sync_type = 0;
|
| if (use_drm_) {
|
| // Number of files to look for when discovering DRM devices.
|
| const uint32_t kDrmMaxMinor = 15;
|
| @@ -426,6 +454,14 @@ int MotionEvents::Run() {
|
| LOG(ERROR) << "Can't create gbm device";
|
| return 1;
|
| }
|
| +
|
| + if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") ||
|
| + gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) {
|
| + egl_sync_type = EGL_SYNC_FENCE_KHR;
|
| + }
|
| + if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) {
|
| + egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID;
|
| + }
|
| }
|
|
|
| sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface());
|
| @@ -434,14 +470,6 @@ int MotionEvents::Run() {
|
| kOpenGL_GrBackend,
|
| reinterpret_cast<GrBackendContext>(native_interface.get())));
|
| DCHECK(gr_context_);
|
| -
|
| - if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") ||
|
| - gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) {
|
| - egl_sync_type = EGL_SYNC_FENCE_KHR;
|
| - }
|
| - if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) {
|
| - egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID;
|
| - }
|
| #endif
|
|
|
| wl_buffer_listener buffer_listener = {BufferRelease};
|
| @@ -476,6 +504,17 @@ int MotionEvents::Run() {
|
| wl_region_add(opaque_region.get(), 0, 0, width_, height_);
|
| wl_surface_set_opaque_region(surface.get(), opaque_region.get());
|
|
|
| + std::unique_ptr<zcr_synchronization_v1> synchronization;
|
| + if (use_explicit_synchronization_) {
|
| + synchronization.reset(static_cast<zcr_synchronization_v1*>(
|
| + zcr_linux_explicit_synchronization_v1_get_synchronization(
|
| + globals_.linux_explicit_synchronization.get(), surface.get())));
|
| + if (!synchronization) {
|
| + LOG(ERROR) << "Can't get synchronization";
|
| + return 1;
|
| + }
|
| + }
|
| +
|
| std::unique_ptr<wl_shell_surface> shell_surface(
|
| static_cast<wl_shell_surface*>(
|
| wl_shell_get_shell_surface(globals_.shell.get(), surface.get())));
|
| @@ -523,7 +562,7 @@ int MotionEvents::Run() {
|
| Frame frame;
|
| std::unique_ptr<wl_callback> frame_callback;
|
| wl_callback_listener frame_listener = {FrameCallback};
|
| - std::deque<wl_buffer*> pending_frames;
|
| + std::deque<Buffer*> pending_frames;
|
|
|
| uint32_t frames = 0;
|
| base::TimeTicks benchmark_time = base::TimeTicks::Now();
|
| @@ -610,21 +649,20 @@ int MotionEvents::Run() {
|
| canvas->restore();
|
| if (gr_context_) {
|
| gr_context_->flush();
|
| - glFlush();
|
|
|
| +#if defined(OZONE_PLATFORM_GBM)
|
| if (egl_sync_type) {
|
| - EGLSyncKHR sync =
|
| - eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type, nullptr);
|
| - DCHECK(sync != EGL_NO_SYNC_KHR);
|
| - eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync,
|
| - EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
|
| - EGL_FOREVER_KHR);
|
| - eglDestroySyncKHR(eglGetCurrentDisplay(), sync);
|
| + buffer->egl_sync.reset(new ScopedEglSync(eglCreateSyncKHR(
|
| + eglGetCurrentDisplay(), egl_sync_type, nullptr)));
|
| + DCHECK(buffer->egl_sync->is_valid());
|
| }
|
| +#endif
|
| +
|
| + glFlush();
|
| }
|
|
|
| buffer->busy = true;
|
| - pending_frames.push_back(buffer->buffer.get());
|
| + pending_frames.push_back(buffer);
|
|
|
| ++frames;
|
| benchmark_wall_time += base::TimeTicks::Now() - wall_time_start;
|
| @@ -634,10 +672,31 @@ int MotionEvents::Run() {
|
|
|
| if (!frame.callback_pending) {
|
| DCHECK_GT(pending_frames.size(), 0u);
|
| - wl_surface_set_buffer_scale(surface.get(), scale_);
|
| - wl_surface_attach(surface.get(), pending_frames.front(), 0, 0);
|
| + Buffer* buffer = pending_frames.front();
|
| pending_frames.pop_front();
|
|
|
| + wl_surface_set_buffer_scale(surface.get(), scale_);
|
| + wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
|
| +
|
| +#if defined(OZONE_PLATFORM_GBM)
|
| + if (buffer->egl_sync->is_valid()) {
|
| + if (use_explicit_synchronization_) {
|
| + DCHECK_EQ(egl_sync_type,
|
| + static_cast<EGLenum>(EGL_SYNC_NATIVE_FENCE_ANDROID));
|
| + base::ScopedFD fence_fd(eglDupNativeFenceFDANDROID(
|
| + eglGetCurrentDisplay(), buffer->egl_sync->get()));
|
| + DCHECK(fence_fd.is_valid());
|
| + DCHECK(synchronization);
|
| + zcr_synchronization_v1_set_acquire_fence(synchronization.get(),
|
| + fence_fd.get());
|
| + } else {
|
| + eglClientWaitSyncKHR(eglGetCurrentDisplay(), buffer->egl_sync->get(),
|
| + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
|
| + EGL_FOREVER_KHR);
|
| + }
|
| + }
|
| +#endif
|
| +
|
| frame_callback.reset(wl_surface_frame(surface.get()));
|
| wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
|
| frame.callback_pending = true;
|
| @@ -760,6 +819,9 @@ const char kMaxFramesPending[] = "max-frames-pending";
|
| // Specifies if client should be fullscreen.
|
| const char kFullscreen[] = "fullscreen";
|
|
|
| +// Specifies if client should be using explicit synchronization.
|
| +const char kUseExplicitSynchronization[] = "use-explicit-synchronization";
|
| +
|
| // Use drm buffer instead of shared memory.
|
| const char kUseDrm[] = "use-drm";
|
|
|
| @@ -813,6 +875,8 @@ int main(int argc, char* argv[]) {
|
|
|
| exo::wayland::clients::MotionEvents client(
|
| width, height, scale, num_rects, max_frames_pending,
|
| - command_line->HasSwitch(switches::kFullscreen), use_drm.get());
|
| + command_line->HasSwitch(switches::kFullscreen),
|
| + command_line->HasSwitch(switches::kUseExplicitSynchronization),
|
| + use_drm.get());
|
| return client.Run();
|
| }
|
|
|