Chromium Code Reviews| 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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 } // namespace | 296 } // namespace |
| 297 | 297 |
| 298 class MotionEvents { | 298 class MotionEvents { |
| 299 public: | 299 public: |
| 300 MotionEvents(size_t width, | 300 MotionEvents(size_t width, |
| 301 size_t height, | 301 size_t height, |
| 302 int scale, | 302 int scale, |
| 303 size_t num_rects, | 303 size_t num_rects, |
| 304 size_t max_frames_pending, | 304 size_t max_frames_pending, |
| 305 bool fullscreen, | 305 bool fullscreen, |
| 306 bool show_fps_counter, | |
| 306 const std::string* use_drm) | 307 const std::string* use_drm) |
| 307 : width_(width), | 308 : width_(width), |
| 308 height_(height), | 309 height_(height), |
| 309 scale_(scale), | 310 scale_(scale), |
| 310 num_rects_(num_rects), | 311 num_rects_(num_rects), |
| 311 max_frames_pending_(max_frames_pending), | 312 max_frames_pending_(max_frames_pending), |
| 312 fullscreen_(fullscreen), | 313 fullscreen_(fullscreen), |
| 314 show_fps_counter_(show_fps_counter), | |
| 313 use_drm_(use_drm) {} | 315 use_drm_(use_drm) {} |
| 314 | 316 |
| 315 // Initialize and run client main loop. | 317 // Initialize and run client main loop. |
| 316 int Run(); | 318 int Run(); |
| 317 | 319 |
| 318 private: | 320 private: |
| 319 bool CreateBuffer(Buffer* buffer); | 321 bool CreateBuffer(Buffer* buffer); |
| 320 | 322 |
| 321 const size_t width_; | 323 const size_t width_; |
| 322 const size_t height_; | 324 const size_t height_; |
| 323 const int scale_; | 325 const int scale_; |
| 324 const size_t num_rects_; | 326 const size_t num_rects_; |
| 325 const size_t max_frames_pending_; | 327 const size_t max_frames_pending_; |
| 326 const bool fullscreen_; | 328 const bool fullscreen_; |
| 329 const bool show_fps_counter_; | |
| 327 const std::string* use_drm_; | 330 const std::string* use_drm_; |
| 328 | 331 |
| 329 Globals globals_; | 332 Globals globals_; |
| 330 std::unique_ptr<wl_display> display_; | 333 std::unique_ptr<wl_display> display_; |
| 331 | 334 |
| 332 #if defined(OZONE_PLATFORM_GBM) | 335 #if defined(OZONE_PLATFORM_GBM) |
| 333 base::ScopedFD drm_fd_; | 336 base::ScopedFD drm_fd_; |
| 334 std::unique_ptr<gbm_device> device_; | 337 std::unique_ptr<gbm_device> device_; |
| 335 #endif | 338 #endif |
| 336 | 339 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 std::unique_ptr<wl_callback> frame_callback; | 527 std::unique_ptr<wl_callback> frame_callback; |
| 525 wl_callback_listener frame_listener = {FrameCallback}; | 528 wl_callback_listener frame_listener = {FrameCallback}; |
| 526 std::deque<wl_buffer*> pending_frames; | 529 std::deque<wl_buffer*> pending_frames; |
| 527 | 530 |
| 528 uint32_t frames = 0; | 531 uint32_t frames = 0; |
| 529 base::TimeTicks benchmark_time = base::TimeTicks::Now(); | 532 base::TimeTicks benchmark_time = base::TimeTicks::Now(); |
| 530 base::TimeDelta benchmark_interval = | 533 base::TimeDelta benchmark_interval = |
| 531 base::TimeDelta::FromSeconds(kBenchmarkInterval); | 534 base::TimeDelta::FromSeconds(kBenchmarkInterval); |
| 532 base::TimeDelta benchmark_wall_time; | 535 base::TimeDelta benchmark_wall_time; |
| 533 base::TimeDelta benchmark_cpu_time; | 536 base::TimeDelta benchmark_cpu_time; |
| 537 std::string fps_counter_text; | |
|
Daniele Castagna
2016/11/14 03:04:31
Should it be initialized to something like "fps: N
reveman
2016/11/14 15:00:49
I'd like to have the ability to run this without d
Daniele Castagna
2016/11/14 15:17:03
Sure, but what I was suggesting is to have the N/A
reveman
2016/11/14 16:52:35
Done. But "??" as I want to keep text layout simpl
| |
| 538 | |
| 539 SkPaint text_paint; | |
| 540 text_paint.setTextSize(32.0f); | |
| 541 text_paint.setColor(SK_ColorWHITE); | |
|
Daniele Castagna
2016/11/14 03:04:32
It'd be much more readable if it had a black borde
reveman
2016/11/14 15:00:49
The background is typically black and that makes t
Daniele Castagna
2016/11/14 15:17:03
Acknowledged.
| |
| 542 text_paint.setStyle(SkPaint::kFill_Style); | |
| 534 | 543 |
| 535 int dispatch_status = 0; | 544 int dispatch_status = 0; |
| 536 do { | 545 do { |
| 537 bool enqueue_frame = frame.callback_pending | 546 bool enqueue_frame = frame.callback_pending |
| 538 ? pending_frames.size() < max_frames_pending_ | 547 ? pending_frames.size() < max_frames_pending_ |
| 539 : pending_frames.empty(); | 548 : pending_frames.empty(); |
| 540 if (enqueue_frame) { | 549 if (enqueue_frame) { |
| 541 Buffer* buffer = | 550 Buffer* buffer = |
| 542 std::find_if(std::begin(buffers_), std::end(buffers_), | 551 std::find_if(std::begin(buffers_), std::end(buffers_), |
| 543 [](const Buffer& buffer) { return !buffer.busy; }); | 552 [](const Buffer& buffer) { return !buffer.busy; }); |
| 544 if (buffer == std::end(buffers_)) { | 553 if (buffer == std::end(buffers_)) { |
| 545 LOG(ERROR) << "Can't find free buffer"; | 554 LOG(ERROR) << "Can't find free buffer"; |
| 546 return 1; | 555 return 1; |
| 547 } | 556 } |
| 548 | 557 |
| 549 base::TimeTicks wall_time_start = base::TimeTicks::Now(); | 558 base::TimeTicks wall_time_start = base::TimeTicks::Now(); |
| 550 if ((wall_time_start - benchmark_time) > benchmark_interval) { | 559 if ((wall_time_start - benchmark_time) > benchmark_interval) { |
| 551 // Print benchmark statistics for the frames produced. | 560 // Print benchmark statistics for the frames produced. |
| 552 // Note: frames produced is not necessarily the same as frames | 561 // Note: frames produced is not necessarily the same as frames |
| 553 // displayed. | 562 // displayed. |
| 554 std::cout << frames << " frames in " << benchmark_interval.InSeconds() | 563 std::cout << frames << " frames in " << benchmark_interval.InSeconds() |
| 555 << " seconds: " << frames / benchmark_interval.InSecondsF() | 564 << " seconds: " << frames / benchmark_interval.InSecondsF() |
| 556 << " fps (wall=" | 565 << " fps (wall=" |
| 557 << benchmark_wall_time.InMillisecondsF() / frames | 566 << benchmark_wall_time.InMillisecondsF() / frames |
| 558 << " cpu=" << benchmark_cpu_time.InMillisecondsF() / frames | 567 << " cpu=" << benchmark_cpu_time.InMillisecondsF() / frames |
| 559 << ")" << std::endl; | 568 << ")" << std::endl; |
| 560 | 569 |
| 570 if (show_fps_counter_) { | |
| 571 fps_counter_text = | |
| 572 base::UintToString(frames / benchmark_interval.InSeconds()); | |
|
Daniele Castagna
2016/11/14 03:04:32
Why not a floating point here?
Should it also incl
reveman
2016/11/14 15:00:49
Just printing 2 digits makes it easy from a layout
Daniele Castagna
2016/11/14 15:17:03
Should you round the number instead of getting flo
reveman
2016/11/14 16:52:35
Done.
| |
| 573 } | |
| 574 | |
| 561 frames = 0; | 575 frames = 0; |
| 562 benchmark_time = wall_time_start; | 576 benchmark_time = wall_time_start; |
| 563 benchmark_wall_time = base::TimeDelta(); | 577 benchmark_wall_time = base::TimeDelta(); |
| 564 benchmark_cpu_time = base::TimeDelta(); | 578 benchmark_cpu_time = base::TimeDelta(); |
| 565 } | 579 } |
| 566 | 580 |
| 567 base::ThreadTicks cpu_time_start = base::ThreadTicks::Now(); | 581 base::ThreadTicks cpu_time_start = base::ThreadTicks::Now(); |
| 568 | 582 |
| 569 SkCanvas* canvas = buffer->sk_surface->getCanvas(); | 583 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 570 canvas->save(); | |
| 571 | |
| 572 if (event_times.empty()) { | 584 if (event_times.empty()) { |
| 573 canvas->clear(SK_ColorBLACK); | 585 canvas->clear(SK_ColorBLACK); |
| 574 } else { | 586 } else { |
| 575 // Split buffer into one horizontal rectangle for each event received | 587 // Split buffer into one horizontal rectangle for each event received |
| 576 // since last frame. Latest event at the top. | 588 // since last frame. Latest event at the top. |
| 577 int y = 0; | 589 int y = 0; |
| 578 // Note: Rounding up to ensure we cover the whole canvas. | 590 // Note: Rounding up to ensure we cover the whole canvas. |
| 579 int h = (height_ + (event_times.size() / 2)) / event_times.size(); | 591 int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
| 580 while (!event_times.empty()) { | 592 while (!event_times.empty()) { |
| 581 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); | 593 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); |
| 582 SkPaint paint; | 594 SkPaint paint; |
| 583 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, | 595 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, |
| 584 (event_times.back() & 0x00ff00) >> 8, | 596 (event_times.back() & 0x00ff00) >> 8, |
| 585 (event_times.back() & 0xff0000) >> 16)); | 597 (event_times.back() & 0xff0000) >> 16)); |
| 586 canvas->drawIRect(rect, paint); | 598 canvas->drawIRect(rect, paint); |
| 599 std::string text = base::UintToString(event_times.back()); | |
|
Daniele Castagna
2016/11/14 03:04:32
Should we have something like "event ts: " before
reveman
2016/11/14 15:00:49
Like to keep this consistent with above and just p
| |
| 600 canvas->drawText(text.c_str(), text.length(), 8, y + 32, text_paint); | |
| 587 event_times.pop_back(); | 601 event_times.pop_back(); |
| 588 y += h; | 602 y += h; |
| 589 } | 603 } |
| 590 } | 604 } |
| 591 | 605 |
| 592 // Draw rotating rects. | 606 // Draw rotating rects. |
| 593 SkScalar half_width = SkScalarHalf(width_); | 607 SkScalar half_width = SkScalarHalf(width_); |
| 594 SkScalar half_height = SkScalarHalf(height_); | 608 SkScalar half_height = SkScalarHalf(height_); |
| 595 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width), | 609 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width), |
| 596 -SkScalarHalf(half_height), half_width, | 610 -SkScalarHalf(half_height), half_width, |
| 597 half_height); | 611 half_height); |
| 598 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); | 612 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); |
| 599 SkPaint paint; | 613 canvas->save(); |
| 600 canvas->translate(half_width, half_height); | 614 canvas->translate(half_width, half_height); |
| 601 for (size_t i = 0; i < num_rects_; ++i) { | 615 for (size_t i = 0; i < num_rects_; ++i) { |
| 602 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, | 616 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, |
| 603 SK_ColorRED, SK_ColorYELLOW, | 617 SK_ColorRED, SK_ColorYELLOW, |
| 604 SK_ColorCYAN, SK_ColorMAGENTA}; | 618 SK_ColorCYAN, SK_ColorMAGENTA}; |
| 619 SkPaint paint; | |
| 605 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); | 620 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); |
| 606 canvas->rotate(rotation / num_rects_); | 621 canvas->rotate(rotation / num_rects_); |
| 607 canvas->drawIRect(rect, paint); | 622 canvas->drawIRect(rect, paint); |
| 608 } | 623 } |
| 624 canvas->restore(); | |
| 609 | 625 |
| 610 canvas->restore(); | 626 // Draw FPS counter. |
| 627 if (fps_counter_text.length()) { | |
| 628 canvas->drawText(fps_counter_text.c_str(), fps_counter_text.length(), | |
| 629 width_ - 48, 32, text_paint); | |
| 630 } | |
| 631 | |
| 611 if (gr_context_) { | 632 if (gr_context_) { |
| 612 gr_context_->flush(); | 633 gr_context_->flush(); |
| 613 glFlush(); | 634 glFlush(); |
| 614 | 635 |
| 615 if (egl_sync_type) { | 636 if (egl_sync_type) { |
| 616 EGLSyncKHR sync = | 637 EGLSyncKHR sync = |
| 617 eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type, nullptr); | 638 eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type, nullptr); |
| 618 DCHECK(sync != EGL_NO_SYNC_KHR); | 639 DCHECK(sync != EGL_NO_SYNC_KHR); |
| 619 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync, | 640 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync, |
| 620 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, | 641 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 753 | 774 |
| 754 // Specifies the number of rotating rects to draw. | 775 // Specifies the number of rotating rects to draw. |
| 755 const char kNumRects[] = "num-rects"; | 776 const char kNumRects[] = "num-rects"; |
| 756 | 777 |
| 757 // Specifies the maximum number of pending frames. | 778 // Specifies the maximum number of pending frames. |
| 758 const char kMaxFramesPending[] = "max-frames-pending"; | 779 const char kMaxFramesPending[] = "max-frames-pending"; |
| 759 | 780 |
| 760 // Specifies if client should be fullscreen. | 781 // Specifies if client should be fullscreen. |
| 761 const char kFullscreen[] = "fullscreen"; | 782 const char kFullscreen[] = "fullscreen"; |
| 762 | 783 |
| 784 // Specifies if FPS counter should be shown. | |
| 785 const char kShowFpsCounter[] = "show-fps-counter"; | |
| 786 | |
| 763 // Use drm buffer instead of shared memory. | 787 // Use drm buffer instead of shared memory. |
| 764 const char kUseDrm[] = "use-drm"; | 788 const char kUseDrm[] = "use-drm"; |
| 765 | 789 |
| 766 } // namespace switches | 790 } // namespace switches |
| 767 | 791 |
| 768 int main(int argc, char* argv[]) { | 792 int main(int argc, char* argv[]) { |
| 769 base::AtExitManager exit_manager; | 793 base::AtExitManager exit_manager; |
| 770 base::CommandLine::Init(argc, argv); | 794 base::CommandLine::Init(argc, argv); |
| 771 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 795 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 772 | 796 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 806 } | 830 } |
| 807 | 831 |
| 808 std::unique_ptr<std::string> use_drm; | 832 std::unique_ptr<std::string> use_drm; |
| 809 if (command_line->HasSwitch(switches::kUseDrm)) { | 833 if (command_line->HasSwitch(switches::kUseDrm)) { |
| 810 use_drm.reset( | 834 use_drm.reset( |
| 811 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); | 835 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); |
| 812 } | 836 } |
| 813 | 837 |
| 814 exo::wayland::clients::MotionEvents client( | 838 exo::wayland::clients::MotionEvents client( |
| 815 width, height, scale, num_rects, max_frames_pending, | 839 width, height, scale, num_rects, max_frames_pending, |
| 816 command_line->HasSwitch(switches::kFullscreen), use_drm.get()); | 840 command_line->HasSwitch(switches::kFullscreen), |
| 841 command_line->HasSwitch(switches::kShowFpsCounter), use_drm.get()); | |
|
Daniele Castagna
2016/11/14 03:04:32
Why would you *not* want to see the fps? And if th
reveman
2016/11/14 15:00:49
I'd like to use this client as a benchmark that wo
Daniele Castagna
2016/11/14 15:17:03
Then you might want to be able not to print the ev
reveman
2016/11/14 16:52:35
I think this is OK as these will only be printed a
| |
| 817 return client.Run(); | 842 return client.Run(); |
| 818 } | 843 } |
| OLD | NEW |