| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Implementation of a client that produces output in the form of RGBA | 5 // Implementation of a client that produces output in the form of RGBA |
| 6 // buffers when receiving pointer/touch events. RGB contains the lower | 6 // buffers when receiving pointer/touch events. RGB contains the lower |
| 7 // 24 bits of the event timestamp and A is 0xff. | 7 // 24 bits of the event timestamp and A is 0xff. |
| 8 | 8 |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <linux-dmabuf-unstable-v1-client-protocol.h> | 10 #include <linux-dmabuf-unstable-v1-client-protocol.h> |
| 11 #include <presentation-time-client-protocol.h> |
| 11 #include <wayland-client-core.h> | 12 #include <wayland-client-core.h> |
| 12 #include <wayland-client-protocol.h> | 13 #include <wayland-client-protocol.h> |
| 13 | 14 |
| 14 #include <cmath> | 15 #include <cmath> |
| 15 #include <deque> | 16 #include <deque> |
| 16 #include <iostream> | 17 #include <iostream> |
| 17 #include <string> | 18 #include <string> |
| 18 #include <vector> | 19 #include <vector> |
| 19 | 20 |
| 20 #include "base/at_exit.h" | 21 #include "base/at_exit.h" |
| 21 #include "base/command_line.h" | 22 #include "base/command_line.h" |
| 22 #include "base/logging.h" | 23 #include "base/logging.h" |
| 23 #include "base/macros.h" | 24 #include "base/macros.h" |
| 25 #include "base/memory/ptr_util.h" |
| 24 #include "base/memory/shared_memory.h" | 26 #include "base/memory/shared_memory.h" |
| 25 #include "base/scoped_generic.h" | 27 #include "base/scoped_generic.h" |
| 26 #include "base/strings/string_number_conversions.h" | 28 #include "base/strings/string_number_conversions.h" |
| 27 #include "base/strings/stringprintf.h" | 29 #include "base/strings/stringprintf.h" |
| 28 #include "base/time/time.h" | 30 #include "base/time/time.h" |
| 29 #include "third_party/skia/include/core/SkCanvas.h" | 31 #include "third_party/skia/include/core/SkCanvas.h" |
| 30 #include "third_party/skia/include/core/SkRefCnt.h" | 32 #include "third_party/skia/include/core/SkRefCnt.h" |
| 31 #include "third_party/skia/include/core/SkSurface.h" | 33 #include "third_party/skia/include/core/SkSurface.h" |
| 32 #include "third_party/skia/include/gpu/GrContext.h" | 34 #include "third_party/skia/include/gpu/GrContext.h" |
| 33 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h" | 35 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 62 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy) | 64 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy) |
| 63 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy) | 65 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy) |
| 64 DEFAULT_DELETER(wl_surface, wl_surface_destroy) | 66 DEFAULT_DELETER(wl_surface, wl_surface_destroy) |
| 65 DEFAULT_DELETER(wl_region, wl_region_destroy) | 67 DEFAULT_DELETER(wl_region, wl_region_destroy) |
| 66 DEFAULT_DELETER(wl_shell, wl_shell_destroy) | 68 DEFAULT_DELETER(wl_shell, wl_shell_destroy) |
| 67 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy) | 69 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy) |
| 68 DEFAULT_DELETER(wl_seat, wl_seat_destroy) | 70 DEFAULT_DELETER(wl_seat, wl_seat_destroy) |
| 69 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) | 71 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) |
| 70 DEFAULT_DELETER(wl_touch, wl_touch_destroy) | 72 DEFAULT_DELETER(wl_touch, wl_touch_destroy) |
| 71 DEFAULT_DELETER(wl_callback, wl_callback_destroy) | 73 DEFAULT_DELETER(wl_callback, wl_callback_destroy) |
| 74 DEFAULT_DELETER(wp_presentation, wp_presentation_destroy) |
| 75 DEFAULT_DELETER(struct wp_presentation_feedback, |
| 76 wp_presentation_feedback_destroy) |
| 72 DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy) | 77 DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy) |
| 73 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy) | 78 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy) |
| 74 | 79 |
| 75 #if defined(OZONE_PLATFORM_GBM) | 80 #if defined(OZONE_PLATFORM_GBM) |
| 76 DEFAULT_DELETER(gbm_device, gbm_device_destroy) | 81 DEFAULT_DELETER(gbm_device, gbm_device_destroy) |
| 77 DEFAULT_DELETER(gbm_bo, gbm_bo_destroy) | 82 DEFAULT_DELETER(gbm_bo, gbm_bo_destroy) |
| 78 #endif | 83 #endif |
| 79 | 84 |
| 80 namespace exo { | 85 namespace exo { |
| 81 namespace wayland { | 86 namespace wayland { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 104 | 109 |
| 105 // Rotation speed (degrees/second). | 110 // Rotation speed (degrees/second). |
| 106 const double kRotationSpeed = 360.0; | 111 const double kRotationSpeed = 360.0; |
| 107 | 112 |
| 108 // Benchmark warmup frames before starting measurement. | 113 // Benchmark warmup frames before starting measurement. |
| 109 const int kBenchmarkWarmupFrames = 10; | 114 const int kBenchmarkWarmupFrames = 10; |
| 110 | 115 |
| 111 struct Globals { | 116 struct Globals { |
| 112 std::unique_ptr<wl_compositor> compositor; | 117 std::unique_ptr<wl_compositor> compositor; |
| 113 std::unique_ptr<wl_shm> shm; | 118 std::unique_ptr<wl_shm> shm; |
| 119 std::unique_ptr<wp_presentation> presentation; |
| 114 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf; | 120 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf; |
| 115 std::unique_ptr<wl_shell> shell; | 121 std::unique_ptr<wl_shell> shell; |
| 116 std::unique_ptr<wl_seat> seat; | 122 std::unique_ptr<wl_seat> seat; |
| 117 }; | 123 }; |
| 118 | 124 |
| 119 void RegistryHandler(void* data, | 125 void RegistryHandler(void* data, |
| 120 wl_registry* registry, | 126 wl_registry* registry, |
| 121 uint32_t id, | 127 uint32_t id, |
| 122 const char* interface, | 128 const char* interface, |
| 123 uint32_t version) { | 129 uint32_t version) { |
| 124 Globals* globals = static_cast<Globals*>(data); | 130 Globals* globals = static_cast<Globals*>(data); |
| 125 | 131 |
| 126 if (strcmp(interface, "wl_compositor") == 0) { | 132 if (strcmp(interface, "wl_compositor") == 0) { |
| 127 globals->compositor.reset(static_cast<wl_compositor*>( | 133 globals->compositor.reset(static_cast<wl_compositor*>( |
| 128 wl_registry_bind(registry, id, &wl_compositor_interface, 3))); | 134 wl_registry_bind(registry, id, &wl_compositor_interface, 3))); |
| 129 } else if (strcmp(interface, "wl_shm") == 0) { | 135 } else if (strcmp(interface, "wl_shm") == 0) { |
| 130 globals->shm.reset(static_cast<wl_shm*>( | 136 globals->shm.reset(static_cast<wl_shm*>( |
| 131 wl_registry_bind(registry, id, &wl_shm_interface, 1))); | 137 wl_registry_bind(registry, id, &wl_shm_interface, 1))); |
| 132 } else if (strcmp(interface, "wl_shell") == 0) { | 138 } else if (strcmp(interface, "wl_shell") == 0) { |
| 133 globals->shell.reset(static_cast<wl_shell*>( | 139 globals->shell.reset(static_cast<wl_shell*>( |
| 134 wl_registry_bind(registry, id, &wl_shell_interface, 1))); | 140 wl_registry_bind(registry, id, &wl_shell_interface, 1))); |
| 135 } else if (strcmp(interface, "wl_seat") == 0) { | 141 } else if (strcmp(interface, "wl_seat") == 0) { |
| 136 globals->seat.reset(static_cast<wl_seat*>( | 142 globals->seat.reset(static_cast<wl_seat*>( |
| 137 wl_registry_bind(registry, id, &wl_seat_interface, 5))); | 143 wl_registry_bind(registry, id, &wl_seat_interface, 5))); |
| 144 } else if (strcmp(interface, "wp_presentation") == 0) { |
| 145 globals->presentation.reset(static_cast<wp_presentation*>( |
| 146 wl_registry_bind(registry, id, &wp_presentation_interface, 1))); |
| 138 } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) { | 147 } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) { |
| 139 globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>( | 148 globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>( |
| 140 wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1))); | 149 wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1))); |
| 141 } | 150 } |
| 142 } | 151 } |
| 143 | 152 |
| 144 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { | 153 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { |
| 145 LOG(WARNING) << "Got a registry losing event for " << id; | 154 LOG(WARNING) << "Got a registry losing event for " << id; |
| 146 } | 155 } |
| 147 | 156 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 wl_fixed_t y) { | 273 wl_fixed_t y) { |
| 265 EventTimeStack* stack = static_cast<EventTimeStack*>(data); | 274 EventTimeStack* stack = static_cast<EventTimeStack*>(data); |
| 266 | 275 |
| 267 stack->push_back(time); | 276 stack->push_back(time); |
| 268 } | 277 } |
| 269 | 278 |
| 270 void TouchFrame(void* data, wl_touch* touch) {} | 279 void TouchFrame(void* data, wl_touch* touch) {} |
| 271 | 280 |
| 272 void TouchCancel(void* data, wl_touch* touch) {} | 281 void TouchCancel(void* data, wl_touch* touch) {} |
| 273 | 282 |
| 274 struct Frame { | 283 struct Schedule { |
| 275 uint32_t time = 0; | 284 uint32_t time = 0; |
| 276 bool callback_pending = false; | 285 bool callback_pending = false; |
| 277 }; | 286 }; |
| 278 | 287 |
| 279 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { | 288 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { |
| 280 Frame* frame = static_cast<Frame*>(data); | 289 Schedule* schedule = static_cast<Schedule*>(data); |
| 281 | 290 |
| 282 static uint32_t initial_time = time; | 291 static uint32_t initial_time = time; |
| 283 frame->time = time - initial_time; | 292 schedule->time = time - initial_time; |
| 284 frame->callback_pending = false; | 293 schedule->callback_pending = false; |
| 294 } |
| 295 |
| 296 struct Frame { |
| 297 Buffer* buffer = nullptr; |
| 298 base::TimeDelta wall_time; |
| 299 base::TimeDelta cpu_time; |
| 300 std::vector<base::TimeTicks> event_times; |
| 301 std::unique_ptr<struct wp_presentation_feedback> feedback; |
| 302 }; |
| 303 |
| 304 struct Presentation { |
| 305 std::deque<std::unique_ptr<Frame>> scheduled_frames; |
| 306 base::TimeDelta wall_time; |
| 307 base::TimeDelta cpu_time; |
| 308 base::TimeDelta latency_time; |
| 309 uint32_t num_frames_presented = 0; |
| 310 uint32_t num_events_presented = 0; |
| 311 }; |
| 312 |
| 313 void FeedbackSyncOutput(void* data, |
| 314 struct wp_presentation_feedback* presentation_feedback, |
| 315 wl_output* output) {} |
| 316 |
| 317 void FeedbackPresented(void* data, |
| 318 struct wp_presentation_feedback* presentation_feedback, |
| 319 uint32_t tv_sec_hi, |
| 320 uint32_t tv_sec_lo, |
| 321 uint32_t tv_nsec, |
| 322 uint32_t refresh, |
| 323 uint32_t seq_hi, |
| 324 uint32_t seq_lo, |
| 325 uint32_t flags) { |
| 326 Presentation* presentation = static_cast<Presentation*>(data); |
| 327 DCHECK_GT(presentation->scheduled_frames.size(), 0u); |
| 328 std::unique_ptr<Frame> frame = |
| 329 std::move(presentation->scheduled_frames.front()); |
| 330 presentation->scheduled_frames.pop_front(); |
| 331 |
| 332 presentation->wall_time += frame->wall_time; |
| 333 presentation->cpu_time += frame->cpu_time; |
| 334 ++presentation->num_frames_presented; |
| 335 |
| 336 int64_t seconds = (static_cast<int64_t>(tv_sec_hi) << 32) + tv_sec_lo; |
| 337 int64_t microseconds = seconds * base::Time::kMicrosecondsPerSecond + |
| 338 tv_nsec / base::Time::kNanosecondsPerMicrosecond; |
| 339 base::TimeTicks presentation_time = |
| 340 base::TimeTicks::FromInternalValue(microseconds); |
| 341 for (const auto& event_time : frame->event_times) { |
| 342 presentation->latency_time += presentation_time - event_time; |
| 343 ++presentation->num_events_presented; |
| 344 } |
| 345 } |
| 346 |
| 347 void FeedbackDiscarded(void* data, |
| 348 struct wp_presentation_feedback* presentation_feedback) { |
| 349 Presentation* presentation = static_cast<Presentation*>(data); |
| 350 DCHECK_GT(presentation->scheduled_frames.size(), 0u); |
| 351 std::unique_ptr<Frame> frame = |
| 352 std::move(presentation->scheduled_frames.front()); |
| 353 presentation->scheduled_frames.pop_front(); |
| 354 LOG(WARNING) << "Frame discarded"; |
| 285 } | 355 } |
| 286 | 356 |
| 287 #if defined(OZONE_PLATFORM_GBM) | 357 #if defined(OZONE_PLATFORM_GBM) |
| 288 void LinuxBufferParamsCreated(void* data, | 358 void LinuxBufferParamsCreated(void* data, |
| 289 zwp_linux_buffer_params_v1* params, | 359 zwp_linux_buffer_params_v1* params, |
| 290 wl_buffer* new_buffer) { | 360 wl_buffer* new_buffer) { |
| 291 Buffer* buffer = static_cast<Buffer*>(data); | 361 Buffer* buffer = static_cast<Buffer*>(data); |
| 292 buffer->buffer.reset(new_buffer); | 362 buffer->buffer.reset(new_buffer); |
| 293 } | 363 } |
| 294 | 364 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 wl_display_roundtrip(display_.get()); | 448 wl_display_roundtrip(display_.get()); |
| 379 | 449 |
| 380 if (!globals_.compositor) { | 450 if (!globals_.compositor) { |
| 381 LOG(ERROR) << "Can't find compositor interface"; | 451 LOG(ERROR) << "Can't find compositor interface"; |
| 382 return 1; | 452 return 1; |
| 383 } | 453 } |
| 384 if (!globals_.shm) { | 454 if (!globals_.shm) { |
| 385 LOG(ERROR) << "Can't find shm interface"; | 455 LOG(ERROR) << "Can't find shm interface"; |
| 386 return 1; | 456 return 1; |
| 387 } | 457 } |
| 458 if (!globals_.presentation) { |
| 459 LOG(ERROR) << "Can't find presentation interface"; |
| 460 return 1; |
| 461 } |
| 388 if (use_drm_ && !globals_.linux_dmabuf) { | 462 if (use_drm_ && !globals_.linux_dmabuf) { |
| 389 LOG(ERROR) << "Can't find linux_dmabuf interface"; | 463 LOG(ERROR) << "Can't find linux_dmabuf interface"; |
| 390 return 1; | 464 return 1; |
| 391 } | 465 } |
| 392 if (!globals_.shell) { | 466 if (!globals_.shell) { |
| 393 LOG(ERROR) << "Can't find shell interface"; | 467 LOG(ERROR) << "Can't find shell interface"; |
| 394 return 1; | 468 return 1; |
| 395 } | 469 } |
| 396 if (!globals_.seat) { | 470 if (!globals_.seat) { |
| 397 LOG(ERROR) << "Can't find seat interface"; | 471 LOG(ERROR) << "Can't find seat interface"; |
| 398 return 1; | 472 return 1; |
| 399 } | 473 } |
| 400 | 474 |
| 401 #if defined(OZONE_PLATFORM_GBM) | 475 #if defined(OZONE_PLATFORM_GBM) |
| 402 EGLenum egl_sync_type = 0; | 476 EGLenum egl_sync_type = 0; |
| 477 sk_sp<const GrGLInterface> native_interface; |
| 403 if (use_drm_) { | 478 if (use_drm_) { |
| 404 // Number of files to look for when discovering DRM devices. | 479 // Number of files to look for when discovering DRM devices. |
| 405 const uint32_t kDrmMaxMinor = 15; | 480 const uint32_t kDrmMaxMinor = 15; |
| 406 const uint32_t kRenderNodeStart = 128; | 481 const uint32_t kRenderNodeStart = 128; |
| 407 const uint32_t kRenderNodeEnd = kRenderNodeStart + kDrmMaxMinor; | 482 const uint32_t kRenderNodeEnd = kRenderNodeStart + kDrmMaxMinor; |
| 408 | 483 |
| 409 for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) { | 484 for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) { |
| 410 std::string dri_render_node( | 485 std::string dri_render_node( |
| 411 base::StringPrintf(kDriRenderNodeTemplate, i)); | 486 base::StringPrintf(kDriRenderNodeTemplate, i)); |
| 412 base::ScopedFD drm_fd(open(dri_render_node.c_str(), O_RDWR)); | 487 base::ScopedFD drm_fd(open(dri_render_node.c_str(), O_RDWR)); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 make_current_.reset( | 521 make_current_.reset( |
| 447 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get())); | 522 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get())); |
| 448 | 523 |
| 449 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") || | 524 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") || |
| 450 gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) { | 525 gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) { |
| 451 egl_sync_type = EGL_SYNC_FENCE_KHR; | 526 egl_sync_type = EGL_SYNC_FENCE_KHR; |
| 452 } | 527 } |
| 453 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) { | 528 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) { |
| 454 egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID; | 529 egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID; |
| 455 } | 530 } |
| 531 |
| 532 native_interface = sk_sp<const GrGLInterface>(GrGLCreateNativeInterface()); |
| 533 DCHECK(native_interface); |
| 534 gr_context_ = sk_sp<GrContext>(GrContext::Create( |
| 535 kOpenGL_GrBackend, |
| 536 reinterpret_cast<GrBackendContext>(native_interface.get()))); |
| 537 DCHECK(gr_context_); |
| 456 } | 538 } |
| 457 | |
| 458 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface()); | |
| 459 DCHECK(native_interface); | |
| 460 gr_context_ = sk_sp<GrContext>(GrContext::Create( | |
| 461 kOpenGL_GrBackend, | |
| 462 reinterpret_cast<GrBackendContext>(native_interface.get()))); | |
| 463 DCHECK(gr_context_); | |
| 464 #endif | 539 #endif |
| 465 | 540 |
| 466 wl_buffer_listener buffer_listener = {BufferRelease}; | 541 wl_buffer_listener buffer_listener = {BufferRelease}; |
| 467 | 542 |
| 468 for (size_t i = 0; i < kBuffers; ++i) { | 543 for (size_t i = 0; i < kBuffers; ++i) { |
| 469 if (!CreateBuffer(&buffers_[i])) | 544 if (!CreateBuffer(&buffers_[i])) |
| 470 return 1; | 545 return 1; |
| 471 } | 546 } |
| 472 wl_display_roundtrip(display_.get()); | 547 wl_display_roundtrip(display_.get()); |
| 473 for (size_t i = 0; i < kBuffers; ++i) { | 548 for (size_t i = 0; i < kBuffers; ++i) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 532 static_cast<wl_touch*>(wl_seat_get_touch(globals_.seat.get()))); | 607 static_cast<wl_touch*>(wl_seat_get_touch(globals_.seat.get()))); |
| 533 if (!touch) { | 608 if (!touch) { |
| 534 LOG(ERROR) << "Can't get touch"; | 609 LOG(ERROR) << "Can't get touch"; |
| 535 return 1; | 610 return 1; |
| 536 } | 611 } |
| 537 | 612 |
| 538 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, | 613 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, |
| 539 TouchFrame, TouchCancel}; | 614 TouchFrame, TouchCancel}; |
| 540 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); | 615 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); |
| 541 | 616 |
| 542 Frame frame; | 617 Schedule schedule; |
| 543 std::unique_ptr<wl_callback> frame_callback; | 618 std::unique_ptr<wl_callback> frame_callback; |
| 544 wl_callback_listener frame_listener = {FrameCallback}; | 619 wl_callback_listener frame_listener = {FrameCallback}; |
| 545 std::deque<Buffer*> pending_frames; | |
| 546 | 620 |
| 547 uint32_t frames = 0; | 621 Presentation presentation; |
| 622 std::deque<std::unique_ptr<Frame>> pending_frames; |
| 623 |
| 548 size_t num_benchmark_runs_left = num_benchmark_runs_; | 624 size_t num_benchmark_runs_left = num_benchmark_runs_; |
| 549 base::TimeTicks benchmark_time; | 625 base::TimeTicks benchmark_start_time; |
| 550 base::TimeDelta benchmark_wall_time; | |
| 551 base::TimeDelta benchmark_cpu_time; | |
| 552 std::string fps_counter_text("??"); | 626 std::string fps_counter_text("??"); |
| 553 | 627 |
| 628 wp_presentation_feedback_listener feedback_listener = { |
| 629 FeedbackSyncOutput, FeedbackPresented, FeedbackDiscarded}; |
| 630 |
| 554 SkPaint text_paint; | 631 SkPaint text_paint; |
| 555 text_paint.setTextSize(32.0f); | 632 text_paint.setTextSize(32.0f); |
| 556 text_paint.setColor(SK_ColorWHITE); | 633 text_paint.setColor(SK_ColorWHITE); |
| 557 text_paint.setStyle(SkPaint::kFill_Style); | 634 text_paint.setStyle(SkPaint::kFill_Style); |
| 558 | 635 |
| 559 int dispatch_status = 0; | 636 int dispatch_status = 0; |
| 560 do { | 637 do { |
| 561 bool enqueue_frame = frame.callback_pending | 638 bool enqueue_frame = schedule.callback_pending |
| 562 ? pending_frames.size() < max_frames_pending_ | 639 ? pending_frames.size() < max_frames_pending_ |
| 563 : pending_frames.empty(); | 640 : pending_frames.empty(); |
| 564 if (enqueue_frame) { | 641 if (enqueue_frame) { |
| 565 Buffer* buffer = | 642 Buffer* buffer = |
| 566 std::find_if(std::begin(buffers_), std::end(buffers_), | 643 std::find_if(std::begin(buffers_), std::end(buffers_), |
| 567 [](const Buffer& buffer) { return !buffer.busy; }); | 644 [](const Buffer& buffer) { return !buffer.busy; }); |
| 568 if (buffer == std::end(buffers_)) { | 645 if (buffer == std::end(buffers_)) { |
| 569 LOG(ERROR) << "Can't find free buffer"; | 646 LOG(ERROR) << "Can't find free buffer"; |
| 570 return 1; | 647 return 1; |
| 571 } | 648 } |
| 572 | 649 |
| 650 auto frame = base::MakeUnique<Frame>(); |
| 651 frame->buffer = buffer; |
| 652 |
| 573 base::TimeTicks wall_time_start; | 653 base::TimeTicks wall_time_start; |
| 574 base::ThreadTicks cpu_time_start; | 654 base::ThreadTicks cpu_time_start; |
| 575 if (num_benchmark_runs_ || show_fps_counter_) { | 655 if (num_benchmark_runs_ || show_fps_counter_) { |
| 576 wall_time_start = base::TimeTicks::Now(); | 656 wall_time_start = base::TimeTicks::Now(); |
| 577 if (frames <= kBenchmarkWarmupFrames) | 657 if (presentation.num_frames_presented <= kBenchmarkWarmupFrames) |
| 578 benchmark_time = wall_time_start; | 658 benchmark_start_time = wall_time_start; |
| 579 | 659 |
| 580 if ((wall_time_start - benchmark_time) > benchmark_interval_) { | 660 base::TimeDelta benchmark_time = wall_time_start - benchmark_start_time; |
| 581 uint32_t benchmark_frames = frames - kBenchmarkWarmupFrames; | 661 if (benchmark_time > benchmark_interval_) { |
| 662 uint32_t benchmark_frames = |
| 663 presentation.num_frames_presented - kBenchmarkWarmupFrames; |
| 582 if (num_benchmark_runs_left) { | 664 if (num_benchmark_runs_left) { |
| 583 // Print benchmark statistics for the frames produced and exit. | 665 // Print benchmark statistics for the frames presented and exit. |
| 584 // Note: frames produced is not necessarily the same as frames | |
| 585 // displayed. | |
| 586 std::cout << benchmark_frames << '\t' | 666 std::cout << benchmark_frames << '\t' |
| 587 << benchmark_wall_time.InMilliseconds() << '\t' | 667 << benchmark_time.InMilliseconds() << '\t' |
| 588 << benchmark_cpu_time.InMilliseconds() << '\t' | 668 << presentation.wall_time.InMilliseconds() << '\t' |
| 669 << presentation.cpu_time.InMilliseconds() << '\t' |
| 670 << presentation.num_events_presented << '\t' |
| 671 << presentation.latency_time.InMilliseconds() << '\t' |
| 589 << std::endl; | 672 << std::endl; |
| 590 if (!--num_benchmark_runs_left) | 673 if (!--num_benchmark_runs_left) |
| 591 return 0; | 674 return 0; |
| 592 } | 675 } |
| 593 | 676 |
| 594 // Set FPS counter text in case it's being shown. | 677 // Set FPS counter text in case it's being shown. |
| 595 fps_counter_text = base::UintToString( | 678 fps_counter_text = base::UintToString( |
| 596 std::round(benchmark_frames / benchmark_interval_.InSecondsF())); | 679 std::round(benchmark_frames / benchmark_interval_.InSecondsF())); |
| 597 | 680 |
| 598 frames = kBenchmarkWarmupFrames; | 681 benchmark_start_time = wall_time_start; |
| 599 benchmark_time = wall_time_start; | 682 presentation.wall_time = base::TimeDelta(); |
| 600 benchmark_wall_time = base::TimeDelta(); | 683 presentation.cpu_time = base::TimeDelta(); |
| 601 benchmark_cpu_time = base::TimeDelta(); | 684 presentation.latency_time = base::TimeDelta(); |
| 685 presentation.num_frames_presented = kBenchmarkWarmupFrames; |
| 686 presentation.num_events_presented = 0; |
| 602 } | 687 } |
| 603 | 688 |
| 604 cpu_time_start = base::ThreadTicks::Now(); | 689 cpu_time_start = base::ThreadTicks::Now(); |
| 605 } | 690 } |
| 606 | 691 |
| 607 SkCanvas* canvas = buffer->sk_surface->getCanvas(); | 692 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 608 if (event_times.empty()) { | 693 if (event_times.empty()) { |
| 609 canvas->clear(SK_ColorBLACK); | 694 canvas->clear(SK_ColorBLACK); |
| 610 } else { | 695 } else { |
| 611 // Split buffer into one horizontal rectangle for each event received | 696 // Split buffer into one horizontal rectangle for each event received |
| 612 // since last frame. Latest event at the top. | 697 // since last frame. Latest event at the top. |
| 613 int y = 0; | 698 int y = 0; |
| 614 // Note: Rounding up to ensure we cover the whole canvas. | 699 // Note: Rounding up to ensure we cover the whole canvas. |
| 615 int h = (height_ + (event_times.size() / 2)) / event_times.size(); | 700 int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
| 616 while (!event_times.empty()) { | 701 while (!event_times.empty()) { |
| 617 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); | 702 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); |
| 618 SkPaint paint; | 703 SkPaint paint; |
| 619 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, | 704 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, |
| 620 (event_times.back() & 0x00ff00) >> 8, | 705 (event_times.back() & 0x00ff00) >> 8, |
| 621 (event_times.back() & 0xff0000) >> 16)); | 706 (event_times.back() & 0xff0000) >> 16)); |
| 622 canvas->drawIRect(rect, paint); | 707 canvas->drawIRect(rect, paint); |
| 623 std::string text = base::UintToString(event_times.back()); | 708 std::string text = base::UintToString(event_times.back()); |
| 624 canvas->drawText(text.c_str(), text.length(), 8, y + 32, text_paint); | 709 canvas->drawText(text.c_str(), text.length(), 8, y + 32, text_paint); |
| 710 frame->event_times.push_back(base::TimeTicks::FromInternalValue( |
| 711 event_times.back() * base::Time::kMicrosecondsPerMillisecond)); |
| 625 event_times.pop_back(); | 712 event_times.pop_back(); |
| 626 y += h; | 713 y += h; |
| 627 } | 714 } |
| 628 } | 715 } |
| 629 | 716 |
| 630 // Draw rotating rects. | 717 // Draw rotating rects. |
| 631 SkScalar half_width = SkScalarHalf(width_); | 718 SkScalar half_width = SkScalarHalf(width_); |
| 632 SkScalar half_height = SkScalarHalf(height_); | 719 SkScalar half_height = SkScalarHalf(height_); |
| 633 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width), | 720 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width), |
| 634 -SkScalarHalf(half_height), half_width, | 721 -SkScalarHalf(half_height), half_width, |
| 635 half_height); | 722 half_height); |
| 636 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); | 723 SkScalar rotation = SkScalarMulDiv(schedule.time, kRotationSpeed, 1000); |
| 637 canvas->save(); | 724 canvas->save(); |
| 638 canvas->translate(half_width, half_height); | 725 canvas->translate(half_width, half_height); |
| 639 for (size_t i = 0; i < num_rects_; ++i) { | 726 for (size_t i = 0; i < num_rects_; ++i) { |
| 640 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, | 727 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, |
| 641 SK_ColorRED, SK_ColorYELLOW, | 728 SK_ColorRED, SK_ColorYELLOW, |
| 642 SK_ColorCYAN, SK_ColorMAGENTA}; | 729 SK_ColorCYAN, SK_ColorMAGENTA}; |
| 643 SkPaint paint; | 730 SkPaint paint; |
| 644 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); | 731 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); |
| 645 canvas->rotate(rotation / num_rects_); | 732 canvas->rotate(rotation / num_rects_); |
| 646 canvas->drawIRect(rect, paint); | 733 canvas->drawIRect(rect, paint); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 661 buffer->egl_sync.reset(new ScopedEglSync(eglCreateSyncKHR( | 748 buffer->egl_sync.reset(new ScopedEglSync(eglCreateSyncKHR( |
| 662 eglGetCurrentDisplay(), egl_sync_type, nullptr))); | 749 eglGetCurrentDisplay(), egl_sync_type, nullptr))); |
| 663 DCHECK(buffer->egl_sync->is_valid()); | 750 DCHECK(buffer->egl_sync->is_valid()); |
| 664 } | 751 } |
| 665 #endif | 752 #endif |
| 666 | 753 |
| 667 glFlush(); | 754 glFlush(); |
| 668 } | 755 } |
| 669 | 756 |
| 670 buffer->busy = true; | 757 buffer->busy = true; |
| 671 pending_frames.push_back(buffer); | |
| 672 | 758 |
| 673 if (num_benchmark_runs_ || show_fps_counter_) { | 759 if (num_benchmark_runs_) { |
| 674 ++frames; | 760 frame->wall_time = base::TimeTicks::Now() - wall_time_start; |
| 675 benchmark_wall_time += base::TimeTicks::Now() - wall_time_start; | 761 frame->cpu_time = base::ThreadTicks::Now() - cpu_time_start; |
| 676 benchmark_cpu_time += base::ThreadTicks::Now() - cpu_time_start; | |
| 677 } | 762 } |
| 763 pending_frames.push_back(std::move(frame)); |
| 678 continue; | 764 continue; |
| 679 } | 765 } |
| 680 | 766 |
| 681 if (!frame.callback_pending) { | 767 if (!schedule.callback_pending) { |
| 682 DCHECK_GT(pending_frames.size(), 0u); | 768 DCHECK_GT(pending_frames.size(), 0u); |
| 683 Buffer* buffer = pending_frames.front(); | 769 std::unique_ptr<Frame> frame = std::move(pending_frames.front()); |
| 684 pending_frames.pop_front(); | 770 pending_frames.pop_front(); |
| 685 | 771 |
| 686 wl_surface_set_buffer_scale(surface.get(), scale_); | 772 wl_surface_set_buffer_scale(surface.get(), scale_); |
| 687 wl_surface_damage(surface.get(), 0, 0, width_ / scale_, height_ / scale_); | 773 wl_surface_damage(surface.get(), 0, 0, width_ / scale_, height_ / scale_); |
| 688 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); | 774 wl_surface_attach(surface.get(), frame->buffer->buffer.get(), 0, 0); |
| 689 | 775 |
| 690 #if defined(OZONE_PLATFORM_GBM) | 776 #if defined(OZONE_PLATFORM_GBM) |
| 691 if (buffer->egl_sync) { | 777 if (frame->buffer->egl_sync) { |
| 692 eglClientWaitSyncKHR(eglGetCurrentDisplay(), buffer->egl_sync->get(), | 778 eglClientWaitSyncKHR(eglGetCurrentDisplay(), |
| 779 frame->buffer->egl_sync->get(), |
| 693 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); | 780 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
| 694 } | 781 } |
| 695 #endif | 782 #endif |
| 696 | 783 |
| 697 frame_callback.reset(wl_surface_frame(surface.get())); | 784 frame_callback.reset(wl_surface_frame(surface.get())); |
| 698 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); | 785 wl_callback_add_listener(frame_callback.get(), &frame_listener, |
| 699 frame.callback_pending = true; | 786 &schedule); |
| 787 schedule.callback_pending = true; |
| 788 |
| 789 frame->feedback.reset( |
| 790 wp_presentation_feedback(globals_.presentation.get(), surface.get())); |
| 791 wp_presentation_feedback_add_listener(frame->feedback.get(), |
| 792 &feedback_listener, &presentation); |
| 793 presentation.scheduled_frames.push_back(std::move(frame)); |
| 794 |
| 700 wl_surface_commit(surface.get()); | 795 wl_surface_commit(surface.get()); |
| 701 wl_display_flush(display_.get()); | 796 wl_display_flush(display_.get()); |
| 702 continue; | 797 continue; |
| 703 } | 798 } |
| 704 | 799 |
| 705 dispatch_status = wl_display_dispatch(display_.get()); | 800 dispatch_status = wl_display_dispatch(display_.get()); |
| 706 } while (dispatch_status != -1); | 801 } while (dispatch_status != -1); |
| 707 | 802 |
| 708 return 0; | 803 return 0; |
| 709 } | 804 } |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); | 994 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); |
| 900 } | 995 } |
| 901 | 996 |
| 902 exo::wayland::clients::MotionEvents client( | 997 exo::wayland::clients::MotionEvents client( |
| 903 width, height, scale, num_rects, max_frames_pending, | 998 width, height, scale, num_rects, max_frames_pending, |
| 904 command_line->HasSwitch(switches::kFullscreen), | 999 command_line->HasSwitch(switches::kFullscreen), |
| 905 command_line->HasSwitch(switches::kShowFpsCounter), num_benchmark_runs, | 1000 command_line->HasSwitch(switches::kShowFpsCounter), num_benchmark_runs, |
| 906 base::TimeDelta::FromMilliseconds(benchmark_interval_ms), use_drm.get()); | 1001 base::TimeDelta::FromMilliseconds(benchmark_interval_ms), use_drm.get()); |
| 907 return client.Run(); | 1002 return client.Run(); |
| 908 } | 1003 } |
| OLD | NEW |