Chromium Code Reviews| Index: components/exo/wayland/clients/motion_events.cc |
| diff --git a/components/exo/wayland/clients/motion_events.cc b/components/exo/wayland/clients/motion_events.cc |
| index 29f352c1c4f02f5eb99b14b211842375cf56ed2e..0902f769bdbd21564798cb16c487ff424968cf44 100644 |
| --- a/components/exo/wayland/clients/motion_events.cc |
| +++ b/components/exo/wayland/clients/motion_events.cc |
| @@ -9,11 +9,15 @@ |
| #include <wayland-client-core.h> |
| #include <wayland-client-protocol.h> |
| +#include <iostream> |
| #include <vector> |
| +#include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/macros.h" |
| #include "base/memory/shared_memory.h" |
| +#include "base/strings/string_number_conversions.h" |
| +#include "base/time/time.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkRefCnt.h" |
| #include "third_party/skia/include/core/SkSurface.h" |
| @@ -47,10 +51,6 @@ namespace wayland { |
| namespace clients { |
| namespace { |
| -// Window size. |
| -const size_t kWidth = 256; |
| -const size_t kHeight = 256; |
| - |
| // Buffer format. |
| const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; |
| const SkColorType kColorType = kBGRA_8888_SkColorType; |
| @@ -62,10 +62,8 @@ const size_t kBuffers = 2; |
| // Rotation speed (degrees/second). |
| const double kRotationSpeed = 360.0; |
| -// Helper constants. |
| -const size_t kStride = kWidth * kBytesPerPixel; |
| -const size_t kBufferSize = kHeight * kStride; |
| -const size_t kMemorySize = kBufferSize * kBuffers; |
| +// Benchmark interval in seconds. |
| +const int kBenchmarkInterval = 5; |
| struct Globals { |
| std::unique_ptr<wl_compositor> compositor; |
| @@ -210,12 +208,30 @@ void FrameCallback(void* data, wl_callback* callback, uint32_t time) { |
| class MotionEvents { |
| public: |
| - MotionEvents() {} |
| + MotionEvents(size_t width, |
| + size_t height, |
| + int scale, |
| + size_t rects, |
|
Daniele Castagna
2016/11/05 21:49:20
nit: maybe rect_num?
reveman
2016/11/05 22:38:20
Done. "num_rects" now
|
| + bool fullscreen) |
| + : width_(width), |
| + height_(height), |
| + scale_(scale), |
| + rects_(rects), |
| + fullscreen_(fullscreen) {} |
| // Initialize and run client main loop. |
| int Run(); |
| private: |
| + size_t stride() const { return width_ * kBytesPerPixel; } |
| + size_t buffer_size() const { return stride() * height_; } |
| + |
| + const size_t width_; |
| + const size_t height_; |
| + const int scale_; |
| + const size_t rects_; |
|
Daniele Castagna
2016/11/05 21:49:19
rect_num_?
reveman
2016/11/05 22:38:19
Done.
|
| + const bool fullscreen_; |
| + |
| DISALLOW_COPY_AND_ASSIGN(MotionEvents); |
| }; |
| @@ -232,7 +248,6 @@ int MotionEvents::Run() { |
| wl_registry* registry = wl_display_get_registry(display.get()); |
| wl_registry_add_listener(registry, ®istry_listener, &globals); |
| - wl_display_dispatch(display.get()); |
| wl_display_roundtrip(display.get()); |
| if (!globals.compositor) { |
| @@ -256,21 +271,22 @@ int MotionEvents::Run() { |
| Buffer buffers[kBuffers]; |
| base::SharedMemory shared_memory; |
| - shared_memory.CreateAndMapAnonymous(kMemorySize); |
| + shared_memory.CreateAndMapAnonymous(buffer_size() * kBuffers); |
| std::unique_ptr<wl_shm_pool> shm_pool( |
| wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, |
| shared_memory.requested_size())); |
| for (size_t i = 0; i < kBuffers; ++i) { |
| - buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( |
| - shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); |
| + buffers[i].buffer.reset(static_cast<wl_buffer*>( |
| + wl_shm_pool_create_buffer(shm_pool.get(), i * buffer_size(), width_, |
| + height_, stride(), kFormat))); |
| if (!buffers[i].buffer) { |
| LOG(ERROR) << "Can't create buffer"; |
| return 1; |
| } |
| buffers[i].sk_surface = SkSurface::MakeRasterDirect( |
| - SkImageInfo::Make(kWidth, kHeight, kColorType, kUnpremul_SkAlphaType), |
| - static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i, |
| - kStride); |
| + SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), |
| + static_cast<uint8_t*>(shared_memory.memory()) + buffer_size() * i, |
| + stride()); |
| if (!buffers[i].sk_surface) { |
| LOG(ERROR) << "Can't create SkSurface"; |
| return 1; |
| @@ -293,7 +309,7 @@ int MotionEvents::Run() { |
| return 1; |
| } |
| - wl_region_add(opaque_region.get(), 0, 0, kWidth, kHeight); |
| + wl_region_add(opaque_region.get(), 0, 0, width_, height_); |
| wl_surface_set_opaque_region(surface.get(), opaque_region.get()); |
| std::unique_ptr<wl_shell_surface> shell_surface( |
| @@ -305,7 +321,13 @@ int MotionEvents::Run() { |
| } |
| wl_shell_surface_set_title(shell_surface.get(), "Test Client"); |
| - wl_shell_surface_set_toplevel(shell_surface.get()); |
| + if (fullscreen_) { |
| + wl_shell_surface_set_fullscreen(shell_surface.get(), |
| + WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, |
| + 0, nullptr); |
| + } else { |
| + wl_shell_surface_set_toplevel(shell_surface.get()); |
| + } |
| EventTimeStack event_times; |
| @@ -337,6 +359,11 @@ int MotionEvents::Run() { |
| std::unique_ptr<wl_callback> frame_callback; |
| wl_callback_listener frame_listener = {FrameCallback}; |
| + uint32_t frames = 0; |
| + base::TimeTicks benchmark_time = base::TimeTicks::Now(); |
| + base::TimeDelta benchmark_interval = |
| + base::TimeDelta::FromSeconds(kBenchmarkInterval); |
| + |
| do { |
| if (frame.callback_pending) |
| continue; |
| @@ -347,40 +374,58 @@ int MotionEvents::Run() { |
| if (buffer == std::end(buffers)) |
| continue; |
| + base::TimeTicks current_time = base::TimeTicks::Now(); |
| + if ((current_time - benchmark_time) > benchmark_interval) { |
| + std::cout << frames << " frames in " << benchmark_interval.InSeconds() |
|
Daniele Castagna
2016/11/05 21:49:19
Couldn't we just print this info to the canvas its
reveman
2016/11/05 22:38:20
Yes, lets add a --fps-counter flag for that in a f
|
| + << " seconds: " |
| + << static_cast<double>(frames) / benchmark_interval.InSeconds() |
| + << " fps" << std::endl; |
| + benchmark_time = current_time; |
| + frames = 0; |
| + } |
| + |
| SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| canvas->save(); |
| - // Clear background to black. |
| - canvas->clear(SK_ColorBLACK); |
| - |
| - // Split buffer into one horizontal rectangle for each event received since |
| - // last frame. Latest event at the top. |
| - if (!event_times.empty()) { |
| - double y = 0; |
| - double height = static_cast<double>(kHeight) / event_times.size(); |
| + if (event_times.empty()) { |
| + canvas->clear(SK_ColorBLACK); |
| + } else { |
| + // Split buffer into one horizontal rectangle for each event received |
| + // since last frame. Latest event at the top. |
| + int y = 0; |
| + int h = (height_ + (event_times.size() / 2)) / event_times.size(); |
|
Daniele Castagna
2016/11/05 21:49:19
Is the + event_time.size/2 to make sure it'll cove
reveman
2016/11/05 22:38:20
Yes, added a comment to make that clear in latest
|
| while (!event_times.empty()) { |
| - SkRect rect = SkRect::MakeXYWH(0, y, kWidth, height); |
| + SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h); |
| SkPaint paint; |
| paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, |
| (event_times.back() & 0x00ff00) >> 8, |
| (event_times.back() & 0xff0000) >> 16)); |
| - canvas->drawRect(rect, paint); |
| + canvas->drawIRect(rect, paint); |
| event_times.pop_back(); |
| - y += height; |
| + y += h; |
| } |
| } |
| - // Draw a blue rotating rectangle on top. |
| - canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)); |
| - canvas->rotate(SkDoubleToScalar((frame.time / 1000.0f) * kRotationSpeed)); |
| - SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f), |
| - kWidth / 2.0f, kHeight / 2.0f); |
| + // Draw rotating rects. |
| + SkScalar half_width = SkScalarHalf(width_); |
| + SkScalar half_height = SkScalarHalf(height_); |
| + SkIRect rect = |
| + SkIRect::MakeXYWH(-SkScalarHalf(half_width), -SkScalarHalf(half_height), |
| + half_width, half_height); |
| + SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000); |
| SkPaint paint; |
| - paint.setColor(SK_ColorBLUE); |
| - canvas->drawRect(rect, paint); |
| - |
| + canvas->translate(half_width, half_height); |
| + for (size_t i = 0; i < rects_; ++i) { |
| + const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, |
| + SK_ColorRED, SK_ColorYELLOW, |
| + SK_ColorCYAN, SK_ColorMAGENTA}; |
| + paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); |
| + canvas->rotate(rotation / rects_); |
| + canvas->drawIRect(rect, paint); |
| + } |
| canvas->restore(); |
| + wl_surface_set_buffer_scale(surface.get(), scale_); |
| wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); |
| buffer->busy = true; |
| @@ -388,8 +433,9 @@ int MotionEvents::Run() { |
| wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); |
| frame.callback_pending = true; |
| + ++frames; |
| + |
| wl_surface_commit(surface.get()); |
| - wl_display_flush(display.get()); |
| } while (wl_display_dispatch(display.get()) != -1); |
| return 0; |
| @@ -399,6 +445,54 @@ int MotionEvents::Run() { |
| } // namespace wayland |
| } // namespace exo |
| -int main() { |
| - return exo::wayland::clients::MotionEvents().Run(); |
| +namespace switches { |
| + |
| +// Specifies the client buffer size. |
| +const char kSize[] = "size"; |
| + |
| +// Specifies the client scale factor. |
|
Daniele Castagna
2016/11/05 21:49:20
You might want to expand a little on that. If I we
reveman
2016/11/05 22:38:20
Done.
|
| +const char kScale[] = "scale"; |
| + |
| +// Specifies the number of rotating rects to draw. |
| +const char kRects[] = "rects"; |
| + |
| +// Specifies if client should be fullscreen. |
| +const char kFullscreen[] = "fullscreen"; |
| + |
| +} // namespace switches |
| + |
| +int main(int argc, char* argv[]) { |
| + base::CommandLine command_line(argc, argv); |
| + |
| + int width = 256; |
| + int height = 256; |
| + if (command_line.HasSwitch(switches::kSize)) { |
| + std::string size_str = command_line.GetSwitchValueASCII(switches::kSize); |
| + if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) { |
| + LOG(ERROR) << "Invalid value for " << switches::kSize; |
| + return 1; |
| + } |
| + } |
| + |
| + int scale = 1; |
| + if (command_line.HasSwitch(switches::kScale) && |
| + !base::StringToInt(command_line.GetSwitchValueASCII(switches::kScale), |
| + &scale)) { |
| + LOG(ERROR) << "Invalid value for " << switches::kScale; |
| + return 1; |
| + } |
| + |
| + size_t rects = 1; |
| + if (command_line.HasSwitch(switches::kRects) && |
| + !base::StringToSizeT(command_line.GetSwitchValueASCII(switches::kRects), |
| + &rects)) { |
| + LOG(ERROR) << "Invalid value for " << switches::kRects; |
| + return 1; |
| + } |
| + |
| + bool fullscreen = command_line.HasSwitch(switches::kFullscreen); |
| + |
| + exo::wayland::clients::MotionEvents client(width, height, scale, rects, |
| + fullscreen); |
| + return client.Run(); |
| } |