Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Side by Side Diff: components/exo/wayland/clients/motion_events.cc

Issue 2610513006: exo: Implement presentation interface. (Closed)
Patch Set: dcastagna nits Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/exo/wayland/BUILD.gn ('k') | components/exo/wayland/server.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « components/exo/wayland/BUILD.gn ('k') | components/exo/wayland/server.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698