| 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> |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 // DRI render node path template. | 98 // DRI render node path template. |
| 99 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u"; | 99 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u"; |
| 100 #endif | 100 #endif |
| 101 | 101 |
| 102 // Number of buffers. | 102 // Number of buffers. |
| 103 const size_t kBuffers = 8; | 103 const size_t kBuffers = 8; |
| 104 | 104 |
| 105 // Rotation speed (degrees/second). | 105 // Rotation speed (degrees/second). |
| 106 const double kRotationSpeed = 360.0; | 106 const double kRotationSpeed = 360.0; |
| 107 | 107 |
| 108 // Benchmark interval in seconds. | 108 // Benchmark warmup frames before starting measurement. |
| 109 const int kBenchmarkInterval = 5; | 109 const int kBenchmarkWarmupFrames = 10; |
| 110 | 110 |
| 111 struct Globals { | 111 struct Globals { |
| 112 std::unique_ptr<wl_compositor> compositor; | 112 std::unique_ptr<wl_compositor> compositor; |
| 113 std::unique_ptr<wl_shm> shm; | 113 std::unique_ptr<wl_shm> shm; |
| 114 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf; | 114 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf; |
| 115 std::unique_ptr<wl_shell> shell; | 115 std::unique_ptr<wl_shell> shell; |
| 116 std::unique_ptr<wl_seat> seat; | 116 std::unique_ptr<wl_seat> seat; |
| 117 }; | 117 }; |
| 118 | 118 |
| 119 void RegistryHandler(void* data, | 119 void RegistryHandler(void* data, |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 | 298 |
| 299 class MotionEvents { | 299 class MotionEvents { |
| 300 public: | 300 public: |
| 301 MotionEvents(size_t width, | 301 MotionEvents(size_t width, |
| 302 size_t height, | 302 size_t height, |
| 303 int scale, | 303 int scale, |
| 304 size_t num_rects, | 304 size_t num_rects, |
| 305 size_t max_frames_pending, | 305 size_t max_frames_pending, |
| 306 bool fullscreen, | 306 bool fullscreen, |
| 307 bool show_fps_counter, | 307 bool show_fps_counter, |
| 308 size_t num_benchmark_runs, |
| 309 base::TimeDelta benchmark_interval, |
| 308 const std::string* use_drm) | 310 const std::string* use_drm) |
| 309 : width_(width), | 311 : width_(width), |
| 310 height_(height), | 312 height_(height), |
| 311 scale_(scale), | 313 scale_(scale), |
| 312 num_rects_(num_rects), | 314 num_rects_(num_rects), |
| 313 max_frames_pending_(max_frames_pending), | 315 max_frames_pending_(max_frames_pending), |
| 314 fullscreen_(fullscreen), | 316 fullscreen_(fullscreen), |
| 315 show_fps_counter_(show_fps_counter), | 317 show_fps_counter_(show_fps_counter), |
| 318 num_benchmark_runs_(num_benchmark_runs), |
| 319 benchmark_interval_(benchmark_interval), |
| 316 use_drm_(use_drm) {} | 320 use_drm_(use_drm) {} |
| 317 | 321 |
| 318 // Initialize and run client main loop. | 322 // Initialize and run client main loop. |
| 319 int Run(); | 323 int Run(); |
| 320 | 324 |
| 321 private: | 325 private: |
| 322 bool CreateBuffer(Buffer* buffer); | 326 bool CreateBuffer(Buffer* buffer); |
| 323 | 327 |
| 324 const size_t width_; | 328 const size_t width_; |
| 325 const size_t height_; | 329 const size_t height_; |
| 326 const int scale_; | 330 const int scale_; |
| 327 const size_t num_rects_; | 331 const size_t num_rects_; |
| 328 const size_t max_frames_pending_; | 332 const size_t max_frames_pending_; |
| 329 const bool fullscreen_; | 333 const bool fullscreen_; |
| 330 const bool show_fps_counter_; | 334 const bool show_fps_counter_; |
| 335 const size_t num_benchmark_runs_; |
| 336 const base::TimeDelta benchmark_interval_; |
| 331 const std::string* use_drm_; | 337 const std::string* use_drm_; |
| 332 | 338 |
| 333 Globals globals_; | 339 Globals globals_; |
| 334 std::unique_ptr<wl_display> display_; | 340 std::unique_ptr<wl_display> display_; |
| 335 | 341 |
| 336 #if defined(OZONE_PLATFORM_GBM) | 342 #if defined(OZONE_PLATFORM_GBM) |
| 337 base::ScopedFD drm_fd_; | 343 base::ScopedFD drm_fd_; |
| 338 std::unique_ptr<gbm_device> device_; | 344 std::unique_ptr<gbm_device> device_; |
| 339 #endif | 345 #endif |
| 340 | 346 |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, | 529 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, |
| 524 TouchFrame, TouchCancel}; | 530 TouchFrame, TouchCancel}; |
| 525 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); | 531 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); |
| 526 | 532 |
| 527 Frame frame; | 533 Frame frame; |
| 528 std::unique_ptr<wl_callback> frame_callback; | 534 std::unique_ptr<wl_callback> frame_callback; |
| 529 wl_callback_listener frame_listener = {FrameCallback}; | 535 wl_callback_listener frame_listener = {FrameCallback}; |
| 530 std::deque<wl_buffer*> pending_frames; | 536 std::deque<wl_buffer*> pending_frames; |
| 531 | 537 |
| 532 uint32_t frames = 0; | 538 uint32_t frames = 0; |
| 533 base::TimeTicks benchmark_time = base::TimeTicks::Now(); | 539 size_t num_benchmark_runs_left = num_benchmark_runs_; |
| 534 base::TimeDelta benchmark_interval = | 540 base::TimeTicks benchmark_time; |
| 535 base::TimeDelta::FromSeconds(kBenchmarkInterval); | |
| 536 base::TimeDelta benchmark_wall_time; | 541 base::TimeDelta benchmark_wall_time; |
| 537 base::TimeDelta benchmark_cpu_time; | 542 base::TimeDelta benchmark_cpu_time; |
| 538 std::string fps_counter_text("??"); | 543 std::string fps_counter_text("??"); |
| 539 | 544 |
| 540 SkPaint text_paint; | 545 SkPaint text_paint; |
| 541 text_paint.setTextSize(32.0f); | 546 text_paint.setTextSize(32.0f); |
| 542 text_paint.setColor(SK_ColorWHITE); | 547 text_paint.setColor(SK_ColorWHITE); |
| 543 text_paint.setStyle(SkPaint::kFill_Style); | 548 text_paint.setStyle(SkPaint::kFill_Style); |
| 544 | 549 |
| 545 int dispatch_status = 0; | 550 int dispatch_status = 0; |
| 546 do { | 551 do { |
| 547 bool enqueue_frame = frame.callback_pending | 552 bool enqueue_frame = frame.callback_pending |
| 548 ? pending_frames.size() < max_frames_pending_ | 553 ? pending_frames.size() < max_frames_pending_ |
| 549 : pending_frames.empty(); | 554 : pending_frames.empty(); |
| 550 if (enqueue_frame) { | 555 if (enqueue_frame) { |
| 551 Buffer* buffer = | 556 Buffer* buffer = |
| 552 std::find_if(std::begin(buffers_), std::end(buffers_), | 557 std::find_if(std::begin(buffers_), std::end(buffers_), |
| 553 [](const Buffer& buffer) { return !buffer.busy; }); | 558 [](const Buffer& buffer) { return !buffer.busy; }); |
| 554 if (buffer == std::end(buffers_)) { | 559 if (buffer == std::end(buffers_)) { |
| 555 LOG(ERROR) << "Can't find free buffer"; | 560 LOG(ERROR) << "Can't find free buffer"; |
| 556 return 1; | 561 return 1; |
| 557 } | 562 } |
| 558 | 563 |
| 559 base::TimeTicks wall_time_start = base::TimeTicks::Now(); | 564 base::TimeTicks wall_time_start; |
| 560 if ((wall_time_start - benchmark_time) > benchmark_interval) { | 565 base::ThreadTicks cpu_time_start; |
| 561 // Print benchmark statistics for the frames produced. | 566 if (num_benchmark_runs_ || show_fps_counter_) { |
| 562 // Note: frames produced is not necessarily the same as frames | 567 wall_time_start = base::TimeTicks::Now(); |
| 563 // displayed. | 568 if (frames <= kBenchmarkWarmupFrames) |
| 564 std::cout << frames << " frames in " << benchmark_interval.InSeconds() | 569 benchmark_time = wall_time_start; |
| 565 << " seconds: " << frames / benchmark_interval.InSecondsF() | |
| 566 << " fps (wall=" | |
| 567 << benchmark_wall_time.InMillisecondsF() / frames | |
| 568 << " cpu=" << benchmark_cpu_time.InMillisecondsF() / frames | |
| 569 << ")" << std::endl; | |
| 570 | 570 |
| 571 // Set FPS counter text in case it's being shown. | 571 if ((wall_time_start - benchmark_time) > benchmark_interval_) { |
| 572 fps_counter_text = base::UintToString( | 572 uint32_t benchmark_frames = frames - kBenchmarkWarmupFrames; |
| 573 std::round(frames / benchmark_interval.InSecondsF())); | 573 if (num_benchmark_runs_left) { |
| 574 // Print benchmark statistics for the frames produced and exit. |
| 575 // Note: frames produced is not necessarily the same as frames |
| 576 // displayed. |
| 577 std::cout << benchmark_frames << '\t' |
| 578 << benchmark_wall_time.InMilliseconds() << '\t' |
| 579 << benchmark_cpu_time.InMilliseconds() << '\t' |
| 580 << std::endl; |
| 581 if (!--num_benchmark_runs_left) |
| 582 return 0; |
| 583 } |
| 574 | 584 |
| 575 frames = 0; | 585 // Set FPS counter text in case it's being shown. |
| 576 benchmark_time = wall_time_start; | 586 fps_counter_text = base::UintToString( |
| 577 benchmark_wall_time = base::TimeDelta(); | 587 std::round(benchmark_frames / benchmark_interval_.InSecondsF())); |
| 578 benchmark_cpu_time = base::TimeDelta(); | 588 |
| 589 frames = kBenchmarkWarmupFrames; |
| 590 benchmark_time = wall_time_start; |
| 591 benchmark_wall_time = base::TimeDelta(); |
| 592 benchmark_cpu_time = base::TimeDelta(); |
| 593 } |
| 594 |
| 595 cpu_time_start = base::ThreadTicks::Now(); |
| 579 } | 596 } |
| 580 | 597 |
| 581 base::ThreadTicks cpu_time_start = base::ThreadTicks::Now(); | |
| 582 | |
| 583 SkCanvas* canvas = buffer->sk_surface->getCanvas(); | 598 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 584 if (event_times.empty()) { | 599 if (event_times.empty()) { |
| 585 canvas->clear(SK_ColorBLACK); | 600 canvas->clear(SK_ColorBLACK); |
| 586 } else { | 601 } else { |
| 587 // Split buffer into one horizontal rectangle for each event received | 602 // Split buffer into one horizontal rectangle for each event received |
| 588 // since last frame. Latest event at the top. | 603 // since last frame. Latest event at the top. |
| 589 int y = 0; | 604 int y = 0; |
| 590 // Note: Rounding up to ensure we cover the whole canvas. | 605 // Note: Rounding up to ensure we cover the whole canvas. |
| 591 int h = (height_ + (event_times.size() / 2)) / event_times.size(); | 606 int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
| 592 while (!event_times.empty()) { | 607 while (!event_times.empty()) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync, | 655 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync, |
| 641 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, | 656 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, |
| 642 EGL_FOREVER_KHR); | 657 EGL_FOREVER_KHR); |
| 643 eglDestroySyncKHR(eglGetCurrentDisplay(), sync); | 658 eglDestroySyncKHR(eglGetCurrentDisplay(), sync); |
| 644 } | 659 } |
| 645 } | 660 } |
| 646 | 661 |
| 647 buffer->busy = true; | 662 buffer->busy = true; |
| 648 pending_frames.push_back(buffer->buffer.get()); | 663 pending_frames.push_back(buffer->buffer.get()); |
| 649 | 664 |
| 650 ++frames; | 665 if (num_benchmark_runs_ || show_fps_counter_) { |
| 651 benchmark_wall_time += base::TimeTicks::Now() - wall_time_start; | 666 ++frames; |
| 652 benchmark_cpu_time += base::ThreadTicks::Now() - cpu_time_start; | 667 benchmark_wall_time += base::TimeTicks::Now() - wall_time_start; |
| 668 benchmark_cpu_time += base::ThreadTicks::Now() - cpu_time_start; |
| 669 } |
| 653 continue; | 670 continue; |
| 654 } | 671 } |
| 655 | 672 |
| 656 if (!frame.callback_pending) { | 673 if (!frame.callback_pending) { |
| 657 DCHECK_GT(pending_frames.size(), 0u); | 674 DCHECK_GT(pending_frames.size(), 0u); |
| 658 wl_surface_set_buffer_scale(surface.get(), scale_); | 675 wl_surface_set_buffer_scale(surface.get(), scale_); |
| 659 wl_surface_attach(surface.get(), pending_frames.front(), 0, 0); | 676 wl_surface_attach(surface.get(), pending_frames.front(), 0, 0); |
| 660 pending_frames.pop_front(); | 677 pending_frames.pop_front(); |
| 661 | 678 |
| 662 frame_callback.reset(wl_surface_frame(surface.get())); | 679 frame_callback.reset(wl_surface_frame(surface.get())); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 | 794 |
| 778 // Specifies the maximum number of pending frames. | 795 // Specifies the maximum number of pending frames. |
| 779 const char kMaxFramesPending[] = "max-frames-pending"; | 796 const char kMaxFramesPending[] = "max-frames-pending"; |
| 780 | 797 |
| 781 // Specifies if client should be fullscreen. | 798 // Specifies if client should be fullscreen. |
| 782 const char kFullscreen[] = "fullscreen"; | 799 const char kFullscreen[] = "fullscreen"; |
| 783 | 800 |
| 784 // Specifies if FPS counter should be shown. | 801 // Specifies if FPS counter should be shown. |
| 785 const char kShowFpsCounter[] = "show-fps-counter"; | 802 const char kShowFpsCounter[] = "show-fps-counter"; |
| 786 | 803 |
| 804 // Enables benchmark mode and specifies the number of benchmark runs to |
| 805 // perform before client will exit. Client will print the results to |
| 806 // standard output as a tab seperated list. |
| 807 // |
| 808 // The output format is: |
| 809 // "frames wall-time-ms cpu-time-ms" |
| 810 const char kBenchmark[] = "benchmark"; |
| 811 |
| 812 // Specifies the number of milliseconds to use as benchmark interval. |
| 813 const char kBenchmarkInterval[] = "benchmark-interval"; |
| 814 |
| 787 // Use drm buffer instead of shared memory. | 815 // Use drm buffer instead of shared memory. |
| 788 const char kUseDrm[] = "use-drm"; | 816 const char kUseDrm[] = "use-drm"; |
| 789 | 817 |
| 790 } // namespace switches | 818 } // namespace switches |
| 791 | 819 |
| 792 int main(int argc, char* argv[]) { | 820 int main(int argc, char* argv[]) { |
| 793 base::AtExitManager exit_manager; | 821 base::AtExitManager exit_manager; |
| 794 base::CommandLine::Init(argc, argv); | 822 base::CommandLine::Init(argc, argv); |
| 795 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 823 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 796 | 824 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 822 | 850 |
| 823 size_t max_frames_pending = 0; | 851 size_t max_frames_pending = 0; |
| 824 if (command_line->HasSwitch(switches::kMaxFramesPending) && | 852 if (command_line->HasSwitch(switches::kMaxFramesPending) && |
| 825 (!base::StringToSizeT( | 853 (!base::StringToSizeT( |
| 826 command_line->GetSwitchValueASCII(switches::kMaxFramesPending), | 854 command_line->GetSwitchValueASCII(switches::kMaxFramesPending), |
| 827 &max_frames_pending))) { | 855 &max_frames_pending))) { |
| 828 LOG(ERROR) << "Invalid value for " << switches::kMaxFramesPending; | 856 LOG(ERROR) << "Invalid value for " << switches::kMaxFramesPending; |
| 829 return 1; | 857 return 1; |
| 830 } | 858 } |
| 831 | 859 |
| 860 size_t num_benchmark_runs = 0; |
| 861 if (command_line->HasSwitch(switches::kBenchmark) && |
| 862 (!base::StringToSizeT( |
| 863 command_line->GetSwitchValueASCII(switches::kBenchmark), |
| 864 &num_benchmark_runs))) { |
| 865 LOG(ERROR) << "Invalid value for " << switches::kBenchmark; |
| 866 return 1; |
| 867 } |
| 868 |
| 869 size_t benchmark_interval_ms = 5000; // 5 seconds. |
| 870 if (command_line->HasSwitch(switches::kBenchmarkInterval) && |
| 871 (!base::StringToSizeT( |
| 872 command_line->GetSwitchValueASCII(switches::kBenchmark), |
| 873 &benchmark_interval_ms))) { |
| 874 LOG(ERROR) << "Invalid value for " << switches::kBenchmark; |
| 875 return 1; |
| 876 } |
| 877 |
| 832 std::unique_ptr<std::string> use_drm; | 878 std::unique_ptr<std::string> use_drm; |
| 833 if (command_line->HasSwitch(switches::kUseDrm)) { | 879 if (command_line->HasSwitch(switches::kUseDrm)) { |
| 834 use_drm.reset( | 880 use_drm.reset( |
| 835 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); | 881 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); |
| 836 } | 882 } |
| 837 | 883 |
| 838 exo::wayland::clients::MotionEvents client( | 884 exo::wayland::clients::MotionEvents client( |
| 839 width, height, scale, num_rects, max_frames_pending, | 885 width, height, scale, num_rects, max_frames_pending, |
| 840 command_line->HasSwitch(switches::kFullscreen), | 886 command_line->HasSwitch(switches::kFullscreen), |
| 841 command_line->HasSwitch(switches::kShowFpsCounter), use_drm.get()); | 887 command_line->HasSwitch(switches::kShowFpsCounter), num_benchmark_runs, |
| 888 base::TimeDelta::FromMilliseconds(benchmark_interval_ms), use_drm.get()); |
| 842 return client.Run(); | 889 return client.Run(); |
| 843 } | 890 } |
| OLD | NEW |