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

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

Issue 2477383002: exo: Add max frames pending flag to motion event client. (Closed)
Patch Set: rebase Created 4 years, 1 month 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 | « no previous file | no next file » | 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 <wayland-client-core.h> 11 #include <wayland-client-core.h>
12 #include <wayland-client-protocol.h> 12 #include <wayland-client-protocol.h>
13 13
14 #include <deque>
14 #include <iostream> 15 #include <iostream>
15 #include <string> 16 #include <string>
16 #include <vector> 17 #include <vector>
17 18
18 #include "base/at_exit.h" 19 #include "base/at_exit.h"
19 #include "base/command_line.h" 20 #include "base/command_line.h"
20 #include "base/logging.h" 21 #include "base/logging.h"
21 #include "base/macros.h" 22 #include "base/macros.h"
22 #include "base/memory/shared_memory.h" 23 #include "base/memory/shared_memory.h"
23 #include "base/scoped_generic.h" 24 #include "base/scoped_generic.h"
24 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/stringprintf.h" 26 #include "base/strings/stringprintf.h"
26 #include "base/time/time.h" 27 #include "base/time/time.h"
27 #include "third_party/skia/include/core/SkCanvas.h" 28 #include "third_party/skia/include/core/SkCanvas.h"
28 #include "third_party/skia/include/core/SkRefCnt.h" 29 #include "third_party/skia/include/core/SkRefCnt.h"
29 #include "third_party/skia/include/core/SkSurface.h" 30 #include "third_party/skia/include/core/SkSurface.h"
30 #include "third_party/skia/include/gpu/GrContext.h" 31 #include "third_party/skia/include/gpu/GrContext.h"
31 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h" 32 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
32 #include "third_party/skia/include/gpu/gl/GrGLInterface.h" 33 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
33 #include "ui/gl/gl_bindings.h" 34 #include "ui/gl/gl_bindings.h"
34 #include "ui/gl/gl_context.h" 35 #include "ui/gl/gl_context.h"
35 #include "ui/gl/gl_enums.h" 36 #include "ui/gl/gl_enums.h"
36 #include "ui/gl/gl_surface.h" 37 #include "ui/gl/gl_surface.h"
37 #include "ui/gl/gl_surface_egl.h" 38 #include "ui/gl/gl_surface_egl.h"
39 #include "ui/gl/gpu_timing.h"
38 #include "ui/gl/init/gl_factory.h" 40 #include "ui/gl/init/gl_factory.h"
39 #include "ui/gl/scoped_make_current.h" 41 #include "ui/gl/scoped_make_current.h"
40 42
41 #if defined(OZONE_PLATFORM_GBM) 43 #if defined(OZONE_PLATFORM_GBM)
42 #include <drm_fourcc.h> 44 #include <drm_fourcc.h>
43 #include <gbm.h> 45 #include <gbm.h>
44 #include <xf86drm.h> 46 #include <xf86drm.h>
45 #endif 47 #endif
46 48
47 // Convenient macro that is used to define default deleters for object 49 // Convenient macro that is used to define default deleters for object
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888; 93 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888;
92 #endif 94 #endif
93 const size_t kBytesPerPixel = 4; 95 const size_t kBytesPerPixel = 4;
94 96
95 #if defined(OZONE_PLATFORM_GBM) 97 #if defined(OZONE_PLATFORM_GBM)
96 // DRI render node path template. 98 // DRI render node path template.
97 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u"; 99 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u";
98 #endif 100 #endif
99 101
100 // Number of buffers. 102 // Number of buffers.
101 const size_t kBuffers = 3; 103 const size_t kBuffers = 8;
102 104
103 // Rotation speed (degrees/second). 105 // Rotation speed (degrees/second).
104 const double kRotationSpeed = 360.0; 106 const double kRotationSpeed = 360.0;
105 107
106 // Benchmark interval in seconds. 108 // Benchmark interval in seconds.
107 const int kBenchmarkInterval = 5; 109 const int kBenchmarkInterval = 5;
108 110
109 struct Globals { 111 struct Globals {
110 std::unique_ptr<wl_compositor> compositor; 112 std::unique_ptr<wl_compositor> compositor;
111 std::unique_ptr<wl_shm> shm; 113 std::unique_ptr<wl_shm> shm;
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 #endif 295 #endif
294 296
295 } // namespace 297 } // namespace
296 298
297 class MotionEvents { 299 class MotionEvents {
298 public: 300 public:
299 MotionEvents(size_t width, 301 MotionEvents(size_t width,
300 size_t height, 302 size_t height,
301 int scale, 303 int scale,
302 size_t num_rects, 304 size_t num_rects,
303 const std::string* use_drm, 305 size_t max_frames_pending,
304 bool fullscreen) 306 bool fullscreen,
307 const std::string* use_drm)
305 : width_(width), 308 : width_(width),
306 height_(height), 309 height_(height),
307 scale_(scale), 310 scale_(scale),
308 num_rects_(num_rects), 311 num_rects_(num_rects),
309 use_drm_(use_drm), 312 max_frames_pending_(max_frames_pending),
310 fullscreen_(fullscreen) {} 313 fullscreen_(fullscreen),
314 use_drm_(use_drm) {}
311 315
312 // Initialize and run client main loop. 316 // Initialize and run client main loop.
313 int Run(); 317 int Run();
314 318
315 private: 319 private:
316 bool CreateBuffer(Buffer* buffer); 320 bool CreateBuffer(Buffer* buffer);
317 size_t stride() const { return width_ * kBytesPerPixel; }
318 size_t buffer_size() const { return stride() * height_; }
319 321
320 const size_t width_; 322 const size_t width_;
321 const size_t height_; 323 const size_t height_;
322 const int scale_; 324 const int scale_;
323 const size_t num_rects_; 325 const size_t num_rects_;
326 const size_t max_frames_pending_;
327 const bool fullscreen_;
324 const std::string* use_drm_; 328 const std::string* use_drm_;
325 const bool fullscreen_;
326 329
327 Globals globals_; 330 Globals globals_;
328 std::unique_ptr<wl_display> display_; 331 std::unique_ptr<wl_display> display_;
329 332
330 #if defined(OZONE_PLATFORM_GBM) 333 #if defined(OZONE_PLATFORM_GBM)
331 base::ScopedFD drm_fd_; 334 base::ScopedFD drm_fd_;
332 std::unique_ptr<gbm_device> device_; 335 std::unique_ptr<gbm_device> device_;
333 #endif 336 #endif
334 337
335 scoped_refptr<gl::GLSurface> gl_surface_; 338 scoped_refptr<gl::GLSurface> gl_surface_;
(...skipping 11 matching lines...) Expand all
347 if (!display_) { 350 if (!display_) {
348 LOG(ERROR) << "wl_display_connect failed"; 351 LOG(ERROR) << "wl_display_connect failed";
349 return 1; 352 return 1;
350 } 353 }
351 354
352 bool gl_initialized = gl::init::InitializeGLOneOff(); 355 bool gl_initialized = gl::init::InitializeGLOneOff();
353 DCHECK(gl_initialized); 356 DCHECK(gl_initialized);
354 gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); 357 gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
355 gl_context_ = 358 gl_context_ =
356 gl::init::CreateGLContext(nullptr, // share_group 359 gl::init::CreateGLContext(nullptr, // share_group
357 gl_surface_.get(), gl::PreferIntegratedGpu); 360 gl_surface_.get(), gl::GLContextAttribs());
Daniele Castagna 2016/11/12 00:04:05 What does this do?
reveman 2016/11/12 01:18:13 needed for ToT to compile
Daniele Castagna 2016/11/12 01:20:59 We should at least build this target on the trybot
358 361
359 make_current_.reset( 362 make_current_.reset(
360 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get())); 363 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get()));
364 scoped_refptr<gl::GPUTimingClient> gpu_timing_client =
365 gl_context_->CreateGPUTimingClient();
366 if (!gpu_timing_client->IsAvailable())
367 LOG(WARNING) << "GPU timing is not available";
368
361 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; 369 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
362 370
363 wl_registry* registry = wl_display_get_registry(display_.get()); 371 wl_registry* registry = wl_display_get_registry(display_.get());
364 wl_registry_add_listener(registry, &registry_listener, &globals_); 372 wl_registry_add_listener(registry, &registry_listener, &globals_);
365 373
366 wl_display_roundtrip(display_.get()); 374 wl_display_roundtrip(display_.get());
367 375
368 if (!globals_.compositor) { 376 if (!globals_.compositor) {
369 LOG(ERROR) << "Can't find compositor interface"; 377 LOG(ERROR) << "Can't find compositor interface";
370 return 1; 378 return 1;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 return 1; 431 return 1;
424 } 432 }
425 } 433 }
426 434
427 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface()); 435 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface());
428 DCHECK(native_interface); 436 DCHECK(native_interface);
429 gr_context_ = sk_sp<GrContext>(GrContext::Create( 437 gr_context_ = sk_sp<GrContext>(GrContext::Create(
430 kOpenGL_GrBackend, 438 kOpenGL_GrBackend,
431 reinterpret_cast<GrBackendContext>(native_interface.get()))); 439 reinterpret_cast<GrBackendContext>(native_interface.get())));
432 DCHECK(gr_context_); 440 DCHECK(gr_context_);
441
442 EGLenum egl_sync_type = 0;
443 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") ||
444 gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) {
445 egl_sync_type = EGL_SYNC_FENCE_KHR;
Daniele Castagna 2016/11/12 00:04:05 Nit: Can you use g_driver_egl.ext.b_EGL_EXT_image_
reveman 2016/11/12 01:18:13 There's no g_driver_egl.ext.b_ANDROID_native_fence
446 }
447 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) {
448 egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID;
449 }
433 #endif 450 #endif
434 451
435 wl_buffer_listener buffer_listener = {BufferRelease}; 452 wl_buffer_listener buffer_listener = {BufferRelease};
436 453
437 for (size_t i = 0; i < kBuffers; ++i) { 454 for (size_t i = 0; i < kBuffers; ++i) {
438 if (!CreateBuffer(&buffers_[i])) 455 if (!CreateBuffer(&buffers_[i]))
439 return 1; 456 return 1;
440 } 457 }
441 wl_display_roundtrip(display_.get()); 458 wl_display_roundtrip(display_.get());
442 for (size_t i = 0; i < kBuffers; ++i) { 459 for (size_t i = 0; i < kBuffers; ++i) {
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 return 1; 521 return 1;
505 } 522 }
506 523
507 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, 524 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion,
508 TouchFrame, TouchCancel}; 525 TouchFrame, TouchCancel};
509 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); 526 wl_touch_add_listener(touch.get(), &touch_listener, &event_times);
510 527
511 Frame frame; 528 Frame frame;
512 std::unique_ptr<wl_callback> frame_callback; 529 std::unique_ptr<wl_callback> frame_callback;
513 wl_callback_listener frame_listener = {FrameCallback}; 530 wl_callback_listener frame_listener = {FrameCallback};
531 std::deque<wl_buffer*> pending_frames;
514 532
515 uint32_t frames = 0; 533 uint32_t frames = 0;
516 base::TimeTicks benchmark_time = base::TimeTicks::Now(); 534 base::TimeTicks benchmark_time = base::TimeTicks::Now();
517 base::TimeDelta benchmark_interval = 535 base::TimeDelta benchmark_interval =
518 base::TimeDelta::FromSeconds(kBenchmarkInterval); 536 base::TimeDelta::FromSeconds(kBenchmarkInterval);
537 base::TimeDelta benchmark_wall_time;
Daniele Castagna 2016/11/12 00:04:05 Isn't this going be ~benchmark_interval?
reveman 2016/11/12 01:18:13 This is different as discussed.
538 base::TimeDelta benchmark_cpu_time;
539 std::vector<std::unique_ptr<gl::GPUTimer>> gpu_timers;
519 540
541 int dispatch_status = 0;
520 do { 542 do {
Daniele Castagna 2016/11/12 00:04:05 I think it'd be much more readable if we could man
reveman 2016/11/12 01:18:13 Let's clean this up in a follow up instead.
521 if (frame.callback_pending) 543 bool enqueue_frame = frame.callback_pending
544 ? pending_frames.size() < max_frames_pending_
545 : pending_frames.empty();
546 if (enqueue_frame) {
547 Buffer* buffer =
548 std::find_if(std::begin(buffers_), std::end(buffers_),
549 [](const Buffer& buffer) { return !buffer.busy; });
550 if (buffer == std::end(buffers_)) {
551 LOG(WARNING) << "Can't find free buffer";
Daniele Castagna 2016/11/12 00:04:05 nit: LOG(ERROR)?
reveman 2016/11/12 01:18:13 Done.
552 return 1;
553 }
554
555 base::TimeTicks wall_time_start = base::TimeTicks::Now();
556 if ((wall_time_start - benchmark_time) > benchmark_interval) {
557 base::TimeDelta benchmark_gpu_time;
558 bool gpu_timer_errors = true;
559 if (gpu_timing_client->IsAvailable())
560 gpu_timer_errors = gpu_timing_client->CheckAndResetTimerErrors();
561 if (!gpu_timer_errors) {
562 for (auto& gpu_timer : gpu_timers) {
563 if (gpu_timer->IsAvailable()) {
Daniele Castagna 2016/11/12 00:04:04 If we produce frames as fast as we can just flushi
reveman 2016/11/12 01:18:13 Remove the GPU timers from latest patch.
564 benchmark_gpu_time += base::TimeDelta::FromMicroseconds(
565 gpu_timer->GetDeltaElapsed());
566 }
567 }
568 }
569 std::cout << frames << " frames in " << benchmark_interval.InSeconds()
Daniele Castagna 2016/11/12 00:04:05 Should this mention that this is the number of fra
reveman 2016/11/12 01:18:13 Added a comment here about it.
570 << " seconds: " << frames / benchmark_interval.InSecondsF()
571 << " fps (wall="
572 << benchmark_wall_time.InMillisecondsF() / frames
573 << " cpu=" << benchmark_cpu_time.InMillisecondsF() / frames
574 << " gpu="
575 << (!gpu_timer_errors
576 ? base::DoubleToString(
577 benchmark_gpu_time.InMillisecondsF() / frames)
578 : std::string("?"))
579 << ")" << std::endl;
580
581 frames = 0;
582 benchmark_time = wall_time_start;
583 benchmark_wall_time = base::TimeDelta();
584 benchmark_cpu_time = base::TimeDelta();
585 gpu_timers.clear();
586 }
587
588 DCHECK(base::ThreadTicks::IsSupported());
589 base::ThreadTicks::WaitUntilInitialized();
Daniele Castagna 2016/11/12 00:04:05 Are you sure this is necessary? And if it is, can
reveman 2016/11/12 01:18:13 Not needed.
590 base::ThreadTicks cpu_time_start = base::ThreadTicks::Now();
591 std::unique_ptr<gl::GPUTimer> gpu_timer;
592 if (gpu_timing_client->IsAvailable()) {
593 gpu_timer = gpu_timing_client->CreateGPUTimer(true);
594 gpu_timer->Start();
595 }
596
597 SkCanvas* canvas = buffer->sk_surface->getCanvas();
598 canvas->save();
599
600 if (event_times.empty()) {
601 canvas->clear(SK_ColorBLACK);
602 } else {
603 // Split buffer into one horizontal rectangle for each event received
604 // since last frame. Latest event at the top.
605 int y = 0;
606 // Note: Rounding up to ensure we cover the whole canvas.
607 int h = (height_ + (event_times.size() / 2)) / event_times.size();
608 while (!event_times.empty()) {
609 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h);
610 SkPaint paint;
611 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0,
612 (event_times.back() & 0x00ff00) >> 8,
613 (event_times.back() & 0xff0000) >> 16));
614 canvas->drawIRect(rect, paint);
615 event_times.pop_back();
616 y += h;
617 }
618 }
619
620 // Draw rotating rects.
621 SkScalar half_width = SkScalarHalf(width_);
622 SkScalar half_height = SkScalarHalf(height_);
623 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width),
624 -SkScalarHalf(half_height), half_width,
625 half_height);
626 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000);
627 SkPaint paint;
628 canvas->translate(half_width, half_height);
629 for (size_t i = 0; i < num_rects_; ++i) {
630 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN,
631 SK_ColorRED, SK_ColorYELLOW,
632 SK_ColorCYAN, SK_ColorMAGENTA};
633 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0));
634 canvas->rotate(rotation / num_rects_);
635 canvas->drawIRect(rect, paint);
636 }
637
638 canvas->restore();
639 if (gr_context_) {
640 gr_context_->flush();
641 glFlush();
642
643 if (egl_sync_type) {
644 EGLSyncKHR sync =
645 eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type, nullptr);
646 DCHECK(sync != EGL_NO_SYNC_KHR);
Daniele Castagna 2016/11/12 00:04:05 nit: DCHECK_NE? Nevermind, you'd need the cast to
647 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync,
648 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
649 EGL_FOREVER_KHR);
650 eglDestroySyncKHR(eglGetCurrentDisplay(), sync);
651 }
652 }
653
654 buffer->busy = true;
655 pending_frames.push_back(buffer->buffer.get());
656
657 ++frames;
658 benchmark_wall_time += base::TimeTicks::Now() - wall_time_start;
659 benchmark_cpu_time += base::ThreadTicks::Now() - cpu_time_start;
660 if (gpu_timer) {
661 gpu_timer->End();
662 gpu_timers.push_back(std::move(gpu_timer));
663 }
522 continue; 664 continue;
523
524 Buffer* buffer =
525 std::find_if(std::begin(buffers_), std::end(buffers_),
526 [](const Buffer& buffer) { return !buffer.busy; });
527 if (buffer == std::end(buffers_))
528 continue;
529
530 base::TimeTicks current_time = base::TimeTicks::Now();
531 if ((current_time - benchmark_time) > benchmark_interval) {
532 std::cout << frames << " frames in " << benchmark_interval.InSeconds()
533 << " seconds: "
534 << static_cast<double>(frames) / benchmark_interval.InSeconds()
535 << " fps" << std::endl;
536 benchmark_time = current_time;
537 frames = 0;
538 } 665 }
539 666
540 SkCanvas* canvas = buffer->sk_surface->getCanvas(); 667 if (!frame.callback_pending) {
541 canvas->save(); 668 DCHECK_GT(pending_frames.size(), 0u);
669 wl_surface_set_buffer_scale(surface.get(), scale_);
670 wl_surface_attach(surface.get(), pending_frames.front(), 0, 0);
671 pending_frames.pop_front();
542 672
543 if (event_times.empty()) { 673 frame_callback.reset(wl_surface_frame(surface.get()));
544 canvas->clear(SK_ColorBLACK); 674 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
545 } else { 675 frame.callback_pending = true;
546 // Split buffer into one horizontal rectangle for each event received 676 wl_surface_commit(surface.get());
547 // since last frame. Latest event at the top. 677 wl_display_flush(display_.get());
548 int y = 0; 678 continue;
549 // Note: Rounding up to ensure we cover the whole canvas.
550 int h = (height_ + (event_times.size() / 2)) / event_times.size();
551 while (!event_times.empty()) {
552 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h);
553 SkPaint paint;
554 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0,
555 (event_times.back() & 0x00ff00) >> 8,
556 (event_times.back() & 0xff0000) >> 16));
557 canvas->drawIRect(rect, paint);
558 event_times.pop_back();
559 y += h;
560 }
561 } 679 }
562 680
563 // Draw rotating rects. 681 dispatch_status = wl_display_dispatch(display_.get());
564 SkScalar half_width = SkScalarHalf(width_); 682 } while (dispatch_status != -1);
565 SkScalar half_height = SkScalarHalf(height_);
566 SkIRect rect =
567 SkIRect::MakeXYWH(-SkScalarHalf(half_width), -SkScalarHalf(half_height),
568 half_width, half_height);
569 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000);
570 SkPaint paint;
571 canvas->translate(half_width, half_height);
572 for (size_t i = 0; i < num_rects_; ++i) {
573 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN,
574 SK_ColorRED, SK_ColorYELLOW,
575 SK_ColorCYAN, SK_ColorMAGENTA};
576 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0));
577 canvas->rotate(rotation / num_rects_);
578 canvas->drawIRect(rect, paint);
579 }
580 canvas->restore();
581 if (gr_context_) {
582 gr_context_->flush();
583 glFinish();
584 }
585 wl_surface_set_buffer_scale(surface.get(), scale_);
586 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
587 buffer->busy = true;
588
589 frame_callback.reset(wl_surface_frame(surface.get()));
590 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
591 frame.callback_pending = true;
592
593 ++frames;
594
595 wl_surface_commit(surface.get());
596 } while (wl_display_dispatch(display_.get()) != -1);
597 683
598 return 0; 684 return 0;
599 } 685 }
600 686
601 bool MotionEvents::CreateBuffer(Buffer* buffer) { 687 bool MotionEvents::CreateBuffer(Buffer* buffer) {
602 #if defined(OZONE_PLATFORM_GBM) 688 #if defined(OZONE_PLATFORM_GBM)
603 if (use_drm_) { 689 if (use_drm_) {
604 buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat, 690 buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat,
605 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING)); 691 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING));
606 if (!buffer->bo) { 692 if (!buffer->bo) {
607 LOG(ERROR) << "Can't create gbm buffer"; 693 LOG(ERROR) << "Can't create gbm buffer";
608 return false; 694 return false;
609 } 695 }
610 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0)); 696 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0));
611 static const zwp_linux_buffer_params_v1_listener params_listener = { 697 static const zwp_linux_buffer_params_v1_listener params_listener = {
612 LinuxBufferParamsCreated, LinuxBufferParamsFailed}; 698 LinuxBufferParamsCreated, LinuxBufferParamsFailed};
613 699
614 buffer->params.reset( 700 buffer->params.reset(
615 zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get())); 701 zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get()));
616 zwp_linux_buffer_params_v1_add_listener(buffer->params.get(), 702 zwp_linux_buffer_params_v1_add_listener(buffer->params.get(),
617 &params_listener, buffer); 703 &params_listener, buffer);
618 zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0, 704 uint32_t stride = gbm_bo_get_stride(buffer->bo.get());
619 stride(), 0, 0); 705 zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0, stride,
706 0, 0);
620 zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_, 707 zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_,
621 kDrmFormat, 0); 708 kDrmFormat, 0);
622 709
623 EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT, 710 EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT,
624 fd.get(), 711 fd.get(),
625 EGL_WIDTH, 712 EGL_WIDTH,
626 width_, 713 width_,
627 EGL_HEIGHT, 714 EGL_HEIGHT,
628 height_, 715 height_,
629 EGL_LINUX_DRM_FOURCC_EXT, 716 EGL_LINUX_DRM_FOURCC_EXT,
630 kDrmFormat, 717 kDrmFormat,
631 EGL_DMA_BUF_PLANE0_PITCH_EXT, 718 EGL_DMA_BUF_PLANE0_PITCH_EXT,
632 stride(), 719 stride,
633 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 720 EGL_DMA_BUF_PLANE0_OFFSET_EXT,
634 0, 721 0,
635 EGL_NONE}; 722 EGL_NONE};
636 EGLImageKHR image = eglCreateImageKHR( 723 EGLImageKHR image = eglCreateImageKHR(
637 eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, 724 eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
638 nullptr /* no client buffer */, khr_image_attrs); 725 nullptr /* no client buffer */, khr_image_attrs);
639 726
640 buffer->egl_image.reset(new ScopedEglImage(image)); 727 buffer->egl_image.reset(new ScopedEglImage(image));
641 GLuint texture = 0; 728 GLuint texture = 0;
642 glGenTextures(1, &texture); 729 glGenTextures(1, &texture);
(...skipping 13 matching lines...) Expand all
656 desc.fConfig = kGrPixelConfig; 743 desc.fConfig = kGrPixelConfig;
657 desc.fOrigin = kTopLeft_GrSurfaceOrigin; 744 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
658 desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info); 745 desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info);
659 746
660 buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget( 747 buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
661 gr_context_.get(), desc, nullptr); 748 gr_context_.get(), desc, nullptr);
662 DCHECK(buffer->sk_surface); 749 DCHECK(buffer->sk_surface);
663 return true; 750 return true;
664 } 751 }
665 #endif 752 #endif
666 buffer->shared_memory.CreateAndMapAnonymous(buffer_size()); 753
754 size_t stride = width_ * kBytesPerPixel;
755 buffer->shared_memory.CreateAndMapAnonymous(stride * height_);
667 buffer->shm_pool.reset( 756 buffer->shm_pool.reset(
668 wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd, 757 wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd,
669 buffer->shared_memory.requested_size())); 758 buffer->shared_memory.requested_size()));
670 759
671 buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( 760 buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer(
672 buffer->shm_pool.get(), 0, width_, height_, stride(), kShmFormat))); 761 buffer->shm_pool.get(), 0, width_, height_, stride, kShmFormat)));
673 if (!buffer->buffer) { 762 if (!buffer->buffer) {
674 LOG(ERROR) << "Can't create buffer"; 763 LOG(ERROR) << "Can't create buffer";
675 return false; 764 return false;
676 } 765 }
677 766
678 buffer->sk_surface = SkSurface::MakeRasterDirect( 767 buffer->sk_surface = SkSurface::MakeRasterDirect(
679 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), 768 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType),
680 static_cast<uint8_t*>(buffer->shared_memory.memory()), stride()); 769 static_cast<uint8_t*>(buffer->shared_memory.memory()), stride);
681 DCHECK(buffer->sk_surface); 770 DCHECK(buffer->sk_surface);
682 return true; 771 return true;
683 } 772 }
684 773
685 } // namespace clients 774 } // namespace clients
686 } // namespace wayland 775 } // namespace wayland
687 } // namespace exo 776 } // namespace exo
688 777
689 namespace switches { 778 namespace switches {
690 779
691 // Specifies the client buffer size. 780 // Specifies the client buffer size.
692 const char kSize[] = "size"; 781 const char kSize[] = "size";
693 782
694 // Specifies the client scale factor (ie. number of physical pixels per DIP). 783 // Specifies the client scale factor (ie. number of physical pixels per DIP).
695 const char kScale[] = "scale"; 784 const char kScale[] = "scale";
696 785
697 // Specifies the number of rotating rects to draw. 786 // Specifies the number of rotating rects to draw.
698 const char kNumRects[] = "num-rects"; 787 const char kNumRects[] = "num-rects";
699 788
789 // Specifies the maximum number of pending frames.
790 const char kMaxFramesPending[] = "max-frames-pending";
791
792 // Specifies if client should be fullscreen.
793 const char kFullscreen[] = "fullscreen";
794
700 // Use drm buffer instead of shared memory. 795 // Use drm buffer instead of shared memory.
701 const char kUseDrm[] = "use-drm"; 796 const char kUseDrm[] = "use-drm";
702 797
703 // Specifies if client should be fullscreen.
704 const char kFullscreen[] = "fullscreen";
705
706 } // namespace switches 798 } // namespace switches
707 799
708 int main(int argc, char* argv[]) { 800 int main(int argc, char* argv[]) {
709 base::AtExitManager exit_manager; 801 base::AtExitManager exit_manager;
710 base::CommandLine::Init(argc, argv); 802 base::CommandLine::Init(argc, argv);
711 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 803 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
712 804
713 int width = 256; 805 int width = 256;
714 int height = 256; 806 int height = 256;
715 if (command_line->HasSwitch(switches::kSize)) { 807 if (command_line->HasSwitch(switches::kSize)) {
(...skipping 13 matching lines...) Expand all
729 } 821 }
730 822
731 size_t num_rects = 1; 823 size_t num_rects = 1;
732 if (command_line->HasSwitch(switches::kNumRects) && 824 if (command_line->HasSwitch(switches::kNumRects) &&
733 !base::StringToSizeT( 825 !base::StringToSizeT(
734 command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) { 826 command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) {
735 LOG(ERROR) << "Invalid value for " << switches::kNumRects; 827 LOG(ERROR) << "Invalid value for " << switches::kNumRects;
736 return 1; 828 return 1;
737 } 829 }
738 830
831 size_t max_frames_pending = 0;
832 if (command_line->HasSwitch(switches::kMaxFramesPending) &&
833 (!base::StringToSizeT(
834 command_line->GetSwitchValueASCII(switches::kMaxFramesPending),
835 &max_frames_pending))) {
836 LOG(ERROR) << "Invalid value for " << switches::kMaxFramesPending;
837 return 1;
838 }
839
739 std::unique_ptr<std::string> use_drm; 840 std::unique_ptr<std::string> use_drm;
740 if (command_line->HasSwitch(switches::kUseDrm)) { 841 if (command_line->HasSwitch(switches::kUseDrm)) {
741 use_drm.reset( 842 use_drm.reset(
742 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); 843 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm)));
743 } 844 }
744 845
745 bool fullscreen = command_line->HasSwitch(switches::kFullscreen); 846 exo::wayland::clients::MotionEvents client(
746 847 width, height, scale, num_rects, max_frames_pending,
747 exo::wayland::clients::MotionEvents client(width, height, scale, num_rects, 848 command_line->HasSwitch(switches::kFullscreen), use_drm.get());
748 use_drm.get(), fullscreen);
749 return client.Run(); 849 return client.Run();
750 } 850 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698