| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Implementation of a client that produces output in the form of RGBA | 5 // Implementation of a client that produces output in the form of RGBA |
| 6 // buffers when receiving pointer/touch events. RGB contains the lower | 6 // buffers when receiving pointer/touch events. RGB contains the lower |
| 7 // 24 bits of the event timestamp and A is 0xff. | 7 // 24 bits of the event timestamp and A is 0xff. |
| 8 | 8 |
| 9 #include <fcntl.h> | 9 #include <fcntl.h> |
| 10 #include <linux-dmabuf-unstable-v1-client-protocol.h> | 10 #include <linux-dmabuf-unstable-v1-client-protocol.h> |
| 11 #include <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" |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888; | 92 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888; |
| 92 #endif | 93 #endif |
| 93 const size_t kBytesPerPixel = 4; | 94 const size_t kBytesPerPixel = 4; |
| 94 | 95 |
| 95 #if defined(OZONE_PLATFORM_GBM) | 96 #if defined(OZONE_PLATFORM_GBM) |
| 96 // DRI render node path template. | 97 // DRI render node path template. |
| 97 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u"; | 98 const char kDriRenderNodeTemplate[] = "/dev/dri/renderD%u"; |
| 98 #endif | 99 #endif |
| 99 | 100 |
| 100 // Number of buffers. | 101 // Number of buffers. |
| 101 const size_t kBuffers = 3; | 102 const size_t kBuffers = 8; |
| 102 | 103 |
| 103 // Rotation speed (degrees/second). | 104 // Rotation speed (degrees/second). |
| 104 const double kRotationSpeed = 360.0; | 105 const double kRotationSpeed = 360.0; |
| 105 | 106 |
| 106 // Benchmark interval in seconds. | 107 // Benchmark interval in seconds. |
| 107 const int kBenchmarkInterval = 5; | 108 const int kBenchmarkInterval = 5; |
| 108 | 109 |
| 109 struct Globals { | 110 struct Globals { |
| 110 std::unique_ptr<wl_compositor> compositor; | 111 std::unique_ptr<wl_compositor> compositor; |
| 111 std::unique_ptr<wl_shm> shm; | 112 std::unique_ptr<wl_shm> shm; |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 #endif | 294 #endif |
| 294 | 295 |
| 295 } // namespace | 296 } // namespace |
| 296 | 297 |
| 297 class MotionEvents { | 298 class MotionEvents { |
| 298 public: | 299 public: |
| 299 MotionEvents(size_t width, | 300 MotionEvents(size_t width, |
| 300 size_t height, | 301 size_t height, |
| 301 int scale, | 302 int scale, |
| 302 size_t num_rects, | 303 size_t num_rects, |
| 303 const std::string* use_drm, | 304 size_t max_frames_pending, |
| 304 bool fullscreen) | 305 bool fullscreen, |
| 306 const std::string* use_drm) |
| 305 : width_(width), | 307 : width_(width), |
| 306 height_(height), | 308 height_(height), |
| 307 scale_(scale), | 309 scale_(scale), |
| 308 num_rects_(num_rects), | 310 num_rects_(num_rects), |
| 309 use_drm_(use_drm), | 311 max_frames_pending_(max_frames_pending), |
| 310 fullscreen_(fullscreen) {} | 312 fullscreen_(fullscreen), |
| 313 use_drm_(use_drm) {} |
| 311 | 314 |
| 312 // Initialize and run client main loop. | 315 // Initialize and run client main loop. |
| 313 int Run(); | 316 int Run(); |
| 314 | 317 |
| 315 private: | 318 private: |
| 316 bool CreateBuffer(Buffer* buffer); | 319 bool CreateBuffer(Buffer* buffer); |
| 317 size_t stride() const { return width_ * kBytesPerPixel; } | |
| 318 size_t buffer_size() const { return stride() * height_; } | |
| 319 | 320 |
| 320 const size_t width_; | 321 const size_t width_; |
| 321 const size_t height_; | 322 const size_t height_; |
| 322 const int scale_; | 323 const int scale_; |
| 323 const size_t num_rects_; | 324 const size_t num_rects_; |
| 325 const size_t max_frames_pending_; |
| 326 const bool fullscreen_; |
| 324 const std::string* use_drm_; | 327 const std::string* use_drm_; |
| 325 const bool fullscreen_; | |
| 326 | 328 |
| 327 Globals globals_; | 329 Globals globals_; |
| 328 std::unique_ptr<wl_display> display_; | 330 std::unique_ptr<wl_display> display_; |
| 329 | 331 |
| 330 #if defined(OZONE_PLATFORM_GBM) | 332 #if defined(OZONE_PLATFORM_GBM) |
| 331 base::ScopedFD drm_fd_; | 333 base::ScopedFD drm_fd_; |
| 332 std::unique_ptr<gbm_device> device_; | 334 std::unique_ptr<gbm_device> device_; |
| 333 #endif | 335 #endif |
| 334 | 336 |
| 335 scoped_refptr<gl::GLSurface> gl_surface_; | 337 scoped_refptr<gl::GLSurface> gl_surface_; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 347 if (!display_) { | 349 if (!display_) { |
| 348 LOG(ERROR) << "wl_display_connect failed"; | 350 LOG(ERROR) << "wl_display_connect failed"; |
| 349 return 1; | 351 return 1; |
| 350 } | 352 } |
| 351 | 353 |
| 352 bool gl_initialized = gl::init::InitializeGLOneOff(); | 354 bool gl_initialized = gl::init::InitializeGLOneOff(); |
| 353 DCHECK(gl_initialized); | 355 DCHECK(gl_initialized); |
| 354 gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); | 356 gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); |
| 355 gl_context_ = | 357 gl_context_ = |
| 356 gl::init::CreateGLContext(nullptr, // share_group | 358 gl::init::CreateGLContext(nullptr, // share_group |
| 357 gl_surface_.get(), gl::PreferIntegratedGpu); | 359 gl_surface_.get(), gl::GLContextAttribs()); |
| 358 | 360 |
| 359 make_current_.reset( | 361 make_current_.reset( |
| 360 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get())); | 362 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get())); |
| 363 |
| 361 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; | 364 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; |
| 362 | 365 |
| 363 wl_registry* registry = wl_display_get_registry(display_.get()); | 366 wl_registry* registry = wl_display_get_registry(display_.get()); |
| 364 wl_registry_add_listener(registry, ®istry_listener, &globals_); | 367 wl_registry_add_listener(registry, ®istry_listener, &globals_); |
| 365 | 368 |
| 366 wl_display_roundtrip(display_.get()); | 369 wl_display_roundtrip(display_.get()); |
| 367 | 370 |
| 368 if (!globals_.compositor) { | 371 if (!globals_.compositor) { |
| 369 LOG(ERROR) << "Can't find compositor interface"; | 372 LOG(ERROR) << "Can't find compositor interface"; |
| 370 return 1; | 373 return 1; |
| 371 } | 374 } |
| 372 if (!globals_.shm) { | 375 if (!globals_.shm) { |
| 373 LOG(ERROR) << "Can't find shm interface"; | 376 LOG(ERROR) << "Can't find shm interface"; |
| 374 return 1; | 377 return 1; |
| 375 } | 378 } |
| 376 if (use_drm_ && !globals_.linux_dmabuf) { | 379 if (use_drm_ && !globals_.linux_dmabuf) { |
| 377 LOG(ERROR) << "Can't find linux_dmabuf interface"; | 380 LOG(ERROR) << "Can't find linux_dmabuf interface"; |
| 378 return 1; | 381 return 1; |
| 379 } | 382 } |
| 380 if (!globals_.shell) { | 383 if (!globals_.shell) { |
| 381 LOG(ERROR) << "Can't find shell interface"; | 384 LOG(ERROR) << "Can't find shell interface"; |
| 382 return 1; | 385 return 1; |
| 383 } | 386 } |
| 384 if (!globals_.seat) { | 387 if (!globals_.seat) { |
| 385 LOG(ERROR) << "Can't find seat interface"; | 388 LOG(ERROR) << "Can't find seat interface"; |
| 386 return 1; | 389 return 1; |
| 387 } | 390 } |
| 388 | 391 |
| 392 EGLenum egl_sync_type = 0; |
| 389 #if defined(OZONE_PLATFORM_GBM) | 393 #if defined(OZONE_PLATFORM_GBM) |
| 390 if (use_drm_) { | 394 if (use_drm_) { |
| 391 // Number of files to look for when discovering DRM devices. | 395 // Number of files to look for when discovering DRM devices. |
| 392 const uint32_t kDrmMaxMinor = 15; | 396 const uint32_t kDrmMaxMinor = 15; |
| 393 const uint32_t kRenderNodeStart = 128; | 397 const uint32_t kRenderNodeStart = 128; |
| 394 const uint32_t kRenderNodeEnd = kRenderNodeStart + kDrmMaxMinor; | 398 const uint32_t kRenderNodeEnd = kRenderNodeStart + kDrmMaxMinor; |
| 395 | 399 |
| 396 for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) { | 400 for (uint32_t i = kRenderNodeStart; i < kRenderNodeEnd; i++) { |
| 397 std::string dri_render_node( | 401 std::string dri_render_node( |
| 398 base::StringPrintf(kDriRenderNodeTemplate, i)); | 402 base::StringPrintf(kDriRenderNodeTemplate, i)); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 423 return 1; | 427 return 1; |
| 424 } | 428 } |
| 425 } | 429 } |
| 426 | 430 |
| 427 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface()); | 431 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface()); |
| 428 DCHECK(native_interface); | 432 DCHECK(native_interface); |
| 429 gr_context_ = sk_sp<GrContext>(GrContext::Create( | 433 gr_context_ = sk_sp<GrContext>(GrContext::Create( |
| 430 kOpenGL_GrBackend, | 434 kOpenGL_GrBackend, |
| 431 reinterpret_cast<GrBackendContext>(native_interface.get()))); | 435 reinterpret_cast<GrBackendContext>(native_interface.get()))); |
| 432 DCHECK(gr_context_); | 436 DCHECK(gr_context_); |
| 437 |
| 438 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_EXT_image_flush_external") || |
| 439 gl::GLSurfaceEGL::HasEGLExtension("EGL_ARM_implicit_external_sync")) { |
| 440 egl_sync_type = EGL_SYNC_FENCE_KHR; |
| 441 } |
| 442 if (gl::GLSurfaceEGL::HasEGLExtension("EGL_ANDROID_native_fence_sync")) { |
| 443 egl_sync_type = EGL_SYNC_NATIVE_FENCE_ANDROID; |
| 444 } |
| 433 #endif | 445 #endif |
| 434 | 446 |
| 435 wl_buffer_listener buffer_listener = {BufferRelease}; | 447 wl_buffer_listener buffer_listener = {BufferRelease}; |
| 436 | 448 |
| 437 for (size_t i = 0; i < kBuffers; ++i) { | 449 for (size_t i = 0; i < kBuffers; ++i) { |
| 438 if (!CreateBuffer(&buffers_[i])) | 450 if (!CreateBuffer(&buffers_[i])) |
| 439 return 1; | 451 return 1; |
| 440 } | 452 } |
| 441 wl_display_roundtrip(display_.get()); | 453 wl_display_roundtrip(display_.get()); |
| 442 for (size_t i = 0; i < kBuffers; ++i) { | 454 for (size_t i = 0; i < kBuffers; ++i) { |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 504 return 1; | 516 return 1; |
| 505 } | 517 } |
| 506 | 518 |
| 507 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, | 519 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, |
| 508 TouchFrame, TouchCancel}; | 520 TouchFrame, TouchCancel}; |
| 509 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); | 521 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); |
| 510 | 522 |
| 511 Frame frame; | 523 Frame frame; |
| 512 std::unique_ptr<wl_callback> frame_callback; | 524 std::unique_ptr<wl_callback> frame_callback; |
| 513 wl_callback_listener frame_listener = {FrameCallback}; | 525 wl_callback_listener frame_listener = {FrameCallback}; |
| 526 std::deque<wl_buffer*> pending_frames; |
| 514 | 527 |
| 515 uint32_t frames = 0; | 528 uint32_t frames = 0; |
| 516 base::TimeTicks benchmark_time = base::TimeTicks::Now(); | 529 base::TimeTicks benchmark_time = base::TimeTicks::Now(); |
| 517 base::TimeDelta benchmark_interval = | 530 base::TimeDelta benchmark_interval = |
| 518 base::TimeDelta::FromSeconds(kBenchmarkInterval); | 531 base::TimeDelta::FromSeconds(kBenchmarkInterval); |
| 532 base::TimeDelta benchmark_wall_time; |
| 533 base::TimeDelta benchmark_cpu_time; |
| 519 | 534 |
| 535 int dispatch_status = 0; |
| 520 do { | 536 do { |
| 521 if (frame.callback_pending) | 537 bool enqueue_frame = frame.callback_pending |
| 538 ? pending_frames.size() < max_frames_pending_ |
| 539 : pending_frames.empty(); |
| 540 if (enqueue_frame) { |
| 541 Buffer* buffer = |
| 542 std::find_if(std::begin(buffers_), std::end(buffers_), |
| 543 [](const Buffer& buffer) { return !buffer.busy; }); |
| 544 if (buffer == std::end(buffers_)) { |
| 545 LOG(ERROR) << "Can't find free buffer"; |
| 546 return 1; |
| 547 } |
| 548 |
| 549 base::TimeTicks wall_time_start = base::TimeTicks::Now(); |
| 550 if ((wall_time_start - benchmark_time) > benchmark_interval) { |
| 551 // Print benchmark statistics for the frames produced. |
| 552 // Note: frames produced is not necessarily the same as frames |
| 553 // displayed. |
| 554 std::cout << frames << " frames in " << benchmark_interval.InSeconds() |
| 555 << " seconds: " << frames / benchmark_interval.InSecondsF() |
| 556 << " fps (wall=" |
| 557 << benchmark_wall_time.InMillisecondsF() / frames |
| 558 << " cpu=" << benchmark_cpu_time.InMillisecondsF() / frames |
| 559 << ")" << std::endl; |
| 560 |
| 561 frames = 0; |
| 562 benchmark_time = wall_time_start; |
| 563 benchmark_wall_time = base::TimeDelta(); |
| 564 benchmark_cpu_time = base::TimeDelta(); |
| 565 } |
| 566 |
| 567 base::ThreadTicks cpu_time_start = base::ThreadTicks::Now(); |
| 568 |
| 569 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 570 canvas->save(); |
| 571 |
| 572 if (event_times.empty()) { |
| 573 canvas->clear(SK_ColorBLACK); |
| 574 } else { |
| 575 // Split buffer into one horizontal rectangle for each event received |
| 576 // since last frame. Latest event at the top. |
| 577 int y = 0; |
| 578 // Note: Rounding up to ensure we cover the whole canvas. |
| 579 int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
| 580 while (!event_times.empty()) { |
| 581 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); |
| 582 SkPaint paint; |
| 583 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, |
| 584 (event_times.back() & 0x00ff00) >> 8, |
| 585 (event_times.back() & 0xff0000) >> 16)); |
| 586 canvas->drawIRect(rect, paint); |
| 587 event_times.pop_back(); |
| 588 y += h; |
| 589 } |
| 590 } |
| 591 |
| 592 // Draw rotating rects. |
| 593 SkScalar half_width = SkScalarHalf(width_); |
| 594 SkScalar half_height = SkScalarHalf(height_); |
| 595 SkIRect rect = SkIRect::MakeXYWH(-SkScalarHalf(half_width), |
| 596 -SkScalarHalf(half_height), half_width, |
| 597 half_height); |
| 598 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); |
| 599 SkPaint paint; |
| 600 canvas->translate(half_width, half_height); |
| 601 for (size_t i = 0; i < num_rects_; ++i) { |
| 602 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, |
| 603 SK_ColorRED, SK_ColorYELLOW, |
| 604 SK_ColorCYAN, SK_ColorMAGENTA}; |
| 605 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); |
| 606 canvas->rotate(rotation / num_rects_); |
| 607 canvas->drawIRect(rect, paint); |
| 608 } |
| 609 |
| 610 canvas->restore(); |
| 611 if (gr_context_) { |
| 612 gr_context_->flush(); |
| 613 glFlush(); |
| 614 |
| 615 if (egl_sync_type) { |
| 616 EGLSyncKHR sync = |
| 617 eglCreateSyncKHR(eglGetCurrentDisplay(), egl_sync_type, nullptr); |
| 618 DCHECK(sync != EGL_NO_SYNC_KHR); |
| 619 eglClientWaitSyncKHR(eglGetCurrentDisplay(), sync, |
| 620 EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, |
| 621 EGL_FOREVER_KHR); |
| 622 eglDestroySyncKHR(eglGetCurrentDisplay(), sync); |
| 623 } |
| 624 } |
| 625 |
| 626 buffer->busy = true; |
| 627 pending_frames.push_back(buffer->buffer.get()); |
| 628 |
| 629 ++frames; |
| 630 benchmark_wall_time += base::TimeTicks::Now() - wall_time_start; |
| 631 benchmark_cpu_time += base::ThreadTicks::Now() - cpu_time_start; |
| 522 continue; | 632 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 } | 633 } |
| 539 | 634 |
| 540 SkCanvas* canvas = buffer->sk_surface->getCanvas(); | 635 if (!frame.callback_pending) { |
| 541 canvas->save(); | 636 DCHECK_GT(pending_frames.size(), 0u); |
| 637 wl_surface_set_buffer_scale(surface.get(), scale_); |
| 638 wl_surface_attach(surface.get(), pending_frames.front(), 0, 0); |
| 639 pending_frames.pop_front(); |
| 542 | 640 |
| 543 if (event_times.empty()) { | 641 frame_callback.reset(wl_surface_frame(surface.get())); |
| 544 canvas->clear(SK_ColorBLACK); | 642 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); |
| 545 } else { | 643 frame.callback_pending = true; |
| 546 // Split buffer into one horizontal rectangle for each event received | 644 wl_surface_commit(surface.get()); |
| 547 // since last frame. Latest event at the top. | 645 wl_display_flush(display_.get()); |
| 548 int y = 0; | 646 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 } | 647 } |
| 562 | 648 |
| 563 // Draw rotating rects. | 649 dispatch_status = wl_display_dispatch(display_.get()); |
| 564 SkScalar half_width = SkScalarHalf(width_); | 650 } 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 | 651 |
| 598 return 0; | 652 return 0; |
| 599 } | 653 } |
| 600 | 654 |
| 601 bool MotionEvents::CreateBuffer(Buffer* buffer) { | 655 bool MotionEvents::CreateBuffer(Buffer* buffer) { |
| 602 #if defined(OZONE_PLATFORM_GBM) | 656 #if defined(OZONE_PLATFORM_GBM) |
| 603 if (use_drm_) { | 657 if (use_drm_) { |
| 604 buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat, | 658 buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat, |
| 605 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING)); | 659 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING)); |
| 606 if (!buffer->bo) { | 660 if (!buffer->bo) { |
| 607 LOG(ERROR) << "Can't create gbm buffer"; | 661 LOG(ERROR) << "Can't create gbm buffer"; |
| 608 return false; | 662 return false; |
| 609 } | 663 } |
| 610 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0)); | 664 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0)); |
| 611 static const zwp_linux_buffer_params_v1_listener params_listener = { | 665 static const zwp_linux_buffer_params_v1_listener params_listener = { |
| 612 LinuxBufferParamsCreated, LinuxBufferParamsFailed}; | 666 LinuxBufferParamsCreated, LinuxBufferParamsFailed}; |
| 613 | 667 |
| 614 buffer->params.reset( | 668 buffer->params.reset( |
| 615 zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get())); | 669 zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get())); |
| 616 zwp_linux_buffer_params_v1_add_listener(buffer->params.get(), | 670 zwp_linux_buffer_params_v1_add_listener(buffer->params.get(), |
| 617 ¶ms_listener, buffer); | 671 ¶ms_listener, buffer); |
| 618 zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0, | 672 uint32_t stride = gbm_bo_get_stride(buffer->bo.get()); |
| 619 stride(), 0, 0); | 673 zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0, stride, |
| 674 0, 0); |
| 620 zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_, | 675 zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_, |
| 621 kDrmFormat, 0); | 676 kDrmFormat, 0); |
| 622 | 677 |
| 623 EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT, | 678 EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT, |
| 624 fd.get(), | 679 fd.get(), |
| 625 EGL_WIDTH, | 680 EGL_WIDTH, |
| 626 width_, | 681 width_, |
| 627 EGL_HEIGHT, | 682 EGL_HEIGHT, |
| 628 height_, | 683 height_, |
| 629 EGL_LINUX_DRM_FOURCC_EXT, | 684 EGL_LINUX_DRM_FOURCC_EXT, |
| 630 kDrmFormat, | 685 kDrmFormat, |
| 631 EGL_DMA_BUF_PLANE0_PITCH_EXT, | 686 EGL_DMA_BUF_PLANE0_PITCH_EXT, |
| 632 stride(), | 687 stride, |
| 633 EGL_DMA_BUF_PLANE0_OFFSET_EXT, | 688 EGL_DMA_BUF_PLANE0_OFFSET_EXT, |
| 634 0, | 689 0, |
| 635 EGL_NONE}; | 690 EGL_NONE}; |
| 636 EGLImageKHR image = eglCreateImageKHR( | 691 EGLImageKHR image = eglCreateImageKHR( |
| 637 eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, | 692 eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, |
| 638 nullptr /* no client buffer */, khr_image_attrs); | 693 nullptr /* no client buffer */, khr_image_attrs); |
| 639 | 694 |
| 640 buffer->egl_image.reset(new ScopedEglImage(image)); | 695 buffer->egl_image.reset(new ScopedEglImage(image)); |
| 641 GLuint texture = 0; | 696 GLuint texture = 0; |
| 642 glGenTextures(1, &texture); | 697 glGenTextures(1, &texture); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 656 desc.fConfig = kGrPixelConfig; | 711 desc.fConfig = kGrPixelConfig; |
| 657 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 712 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
| 658 desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info); | 713 desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info); |
| 659 | 714 |
| 660 buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget( | 715 buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget( |
| 661 gr_context_.get(), desc, nullptr); | 716 gr_context_.get(), desc, nullptr); |
| 662 DCHECK(buffer->sk_surface); | 717 DCHECK(buffer->sk_surface); |
| 663 return true; | 718 return true; |
| 664 } | 719 } |
| 665 #endif | 720 #endif |
| 666 buffer->shared_memory.CreateAndMapAnonymous(buffer_size()); | 721 |
| 722 size_t stride = width_ * kBytesPerPixel; |
| 723 buffer->shared_memory.CreateAndMapAnonymous(stride * height_); |
| 667 buffer->shm_pool.reset( | 724 buffer->shm_pool.reset( |
| 668 wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd, | 725 wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd, |
| 669 buffer->shared_memory.requested_size())); | 726 buffer->shared_memory.requested_size())); |
| 670 | 727 |
| 671 buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( | 728 buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( |
| 672 buffer->shm_pool.get(), 0, width_, height_, stride(), kShmFormat))); | 729 buffer->shm_pool.get(), 0, width_, height_, stride, kShmFormat))); |
| 673 if (!buffer->buffer) { | 730 if (!buffer->buffer) { |
| 674 LOG(ERROR) << "Can't create buffer"; | 731 LOG(ERROR) << "Can't create buffer"; |
| 675 return false; | 732 return false; |
| 676 } | 733 } |
| 677 | 734 |
| 678 buffer->sk_surface = SkSurface::MakeRasterDirect( | 735 buffer->sk_surface = SkSurface::MakeRasterDirect( |
| 679 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), | 736 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), |
| 680 static_cast<uint8_t*>(buffer->shared_memory.memory()), stride()); | 737 static_cast<uint8_t*>(buffer->shared_memory.memory()), stride); |
| 681 DCHECK(buffer->sk_surface); | 738 DCHECK(buffer->sk_surface); |
| 682 return true; | 739 return true; |
| 683 } | 740 } |
| 684 | 741 |
| 685 } // namespace clients | 742 } // namespace clients |
| 686 } // namespace wayland | 743 } // namespace wayland |
| 687 } // namespace exo | 744 } // namespace exo |
| 688 | 745 |
| 689 namespace switches { | 746 namespace switches { |
| 690 | 747 |
| 691 // Specifies the client buffer size. | 748 // Specifies the client buffer size. |
| 692 const char kSize[] = "size"; | 749 const char kSize[] = "size"; |
| 693 | 750 |
| 694 // Specifies the client scale factor (ie. number of physical pixels per DIP). | 751 // Specifies the client scale factor (ie. number of physical pixels per DIP). |
| 695 const char kScale[] = "scale"; | 752 const char kScale[] = "scale"; |
| 696 | 753 |
| 697 // Specifies the number of rotating rects to draw. | 754 // Specifies the number of rotating rects to draw. |
| 698 const char kNumRects[] = "num-rects"; | 755 const char kNumRects[] = "num-rects"; |
| 699 | 756 |
| 757 // Specifies the maximum number of pending frames. |
| 758 const char kMaxFramesPending[] = "max-frames-pending"; |
| 759 |
| 760 // Specifies if client should be fullscreen. |
| 761 const char kFullscreen[] = "fullscreen"; |
| 762 |
| 700 // Use drm buffer instead of shared memory. | 763 // Use drm buffer instead of shared memory. |
| 701 const char kUseDrm[] = "use-drm"; | 764 const char kUseDrm[] = "use-drm"; |
| 702 | 765 |
| 703 // Specifies if client should be fullscreen. | |
| 704 const char kFullscreen[] = "fullscreen"; | |
| 705 | |
| 706 } // namespace switches | 766 } // namespace switches |
| 707 | 767 |
| 708 int main(int argc, char* argv[]) { | 768 int main(int argc, char* argv[]) { |
| 709 base::AtExitManager exit_manager; | 769 base::AtExitManager exit_manager; |
| 710 base::CommandLine::Init(argc, argv); | 770 base::CommandLine::Init(argc, argv); |
| 711 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); | 771 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); |
| 712 | 772 |
| 713 int width = 256; | 773 int width = 256; |
| 714 int height = 256; | 774 int height = 256; |
| 715 if (command_line->HasSwitch(switches::kSize)) { | 775 if (command_line->HasSwitch(switches::kSize)) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 729 } | 789 } |
| 730 | 790 |
| 731 size_t num_rects = 1; | 791 size_t num_rects = 1; |
| 732 if (command_line->HasSwitch(switches::kNumRects) && | 792 if (command_line->HasSwitch(switches::kNumRects) && |
| 733 !base::StringToSizeT( | 793 !base::StringToSizeT( |
| 734 command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) { | 794 command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) { |
| 735 LOG(ERROR) << "Invalid value for " << switches::kNumRects; | 795 LOG(ERROR) << "Invalid value for " << switches::kNumRects; |
| 736 return 1; | 796 return 1; |
| 737 } | 797 } |
| 738 | 798 |
| 799 size_t max_frames_pending = 0; |
| 800 if (command_line->HasSwitch(switches::kMaxFramesPending) && |
| 801 (!base::StringToSizeT( |
| 802 command_line->GetSwitchValueASCII(switches::kMaxFramesPending), |
| 803 &max_frames_pending))) { |
| 804 LOG(ERROR) << "Invalid value for " << switches::kMaxFramesPending; |
| 805 return 1; |
| 806 } |
| 807 |
| 739 std::unique_ptr<std::string> use_drm; | 808 std::unique_ptr<std::string> use_drm; |
| 740 if (command_line->HasSwitch(switches::kUseDrm)) { | 809 if (command_line->HasSwitch(switches::kUseDrm)) { |
| 741 use_drm.reset( | 810 use_drm.reset( |
| 742 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); | 811 new std::string(command_line->GetSwitchValueASCII(switches::kUseDrm))); |
| 743 } | 812 } |
| 744 | 813 |
| 745 bool fullscreen = command_line->HasSwitch(switches::kFullscreen); | 814 exo::wayland::clients::MotionEvents client( |
| 746 | 815 width, height, scale, num_rects, max_frames_pending, |
| 747 exo::wayland::clients::MotionEvents client(width, height, scale, num_rects, | 816 command_line->HasSwitch(switches::kFullscreen), use_drm.get()); |
| 748 use_drm.get(), fullscreen); | |
| 749 return client.Run(); | 817 return client.Run(); |
| 750 } | 818 } |
| OLD | NEW |