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

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

Issue 2484503002: exo: Add useful flags and benchmarking to motion event client. (Closed)
Patch Set: minor cleanup 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 <wayland-client-core.h> 9 #include <wayland-client-core.h>
10 #include <wayland-client-protocol.h> 10 #include <wayland-client-protocol.h>
11 11
12 #include <iostream>
12 #include <vector> 13 #include <vector>
13 14
15 #include "base/command_line.h"
14 #include "base/logging.h" 16 #include "base/logging.h"
15 #include "base/macros.h" 17 #include "base/macros.h"
16 #include "base/memory/shared_memory.h" 18 #include "base/memory/shared_memory.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/time/time.h"
17 #include "third_party/skia/include/core/SkCanvas.h" 21 #include "third_party/skia/include/core/SkCanvas.h"
18 #include "third_party/skia/include/core/SkRefCnt.h" 22 #include "third_party/skia/include/core/SkRefCnt.h"
19 #include "third_party/skia/include/core/SkSurface.h" 23 #include "third_party/skia/include/core/SkSurface.h"
20 24
21 // Convenient macro that is used to define default deleters for wayland object 25 // Convenient macro that is used to define default deleters for wayland object
22 // types allowing them to be used with std::unique_ptr. 26 // types allowing them to be used with std::unique_ptr.
23 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ 27 #define DEFAULT_DELETER(TypeName, DeleteFunction) \
24 namespace std { \ 28 namespace std { \
25 template <> \ 29 template <> \
26 struct default_delete<TypeName> { \ 30 struct default_delete<TypeName> { \
(...skipping 13 matching lines...) Expand all
40 DEFAULT_DELETER(wl_seat, wl_seat_destroy) 44 DEFAULT_DELETER(wl_seat, wl_seat_destroy)
41 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) 45 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy)
42 DEFAULT_DELETER(wl_touch, wl_touch_destroy) 46 DEFAULT_DELETER(wl_touch, wl_touch_destroy)
43 DEFAULT_DELETER(wl_callback, wl_callback_destroy) 47 DEFAULT_DELETER(wl_callback, wl_callback_destroy)
44 48
45 namespace exo { 49 namespace exo {
46 namespace wayland { 50 namespace wayland {
47 namespace clients { 51 namespace clients {
48 namespace { 52 namespace {
49 53
50 // Window size.
51 const size_t kWidth = 256;
52 const size_t kHeight = 256;
53
54 // Buffer format. 54 // Buffer format.
55 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; 55 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888;
56 const SkColorType kColorType = kBGRA_8888_SkColorType; 56 const SkColorType kColorType = kBGRA_8888_SkColorType;
57 const size_t kBytesPerPixel = 4; 57 const size_t kBytesPerPixel = 4;
58 58
59 // Number of buffers. 59 // Number of buffers.
60 const size_t kBuffers = 2; 60 const size_t kBuffers = 2;
61 61
62 // Rotation speed (degrees/second). 62 // Rotation speed (degrees/second).
63 const double kRotationSpeed = 360.0; 63 const double kRotationSpeed = 360.0;
64 64
65 // Helper constants. 65 // Benchmark interval in seconds.
66 const size_t kStride = kWidth * kBytesPerPixel; 66 const int kBenchmarkInterval = 5;
67 const size_t kBufferSize = kHeight * kStride;
68 const size_t kMemorySize = kBufferSize * kBuffers;
69 67
70 struct Globals { 68 struct Globals {
71 std::unique_ptr<wl_compositor> compositor; 69 std::unique_ptr<wl_compositor> compositor;
72 std::unique_ptr<wl_shm> shm; 70 std::unique_ptr<wl_shm> shm;
73 std::unique_ptr<wl_shell> shell; 71 std::unique_ptr<wl_shell> shell;
74 std::unique_ptr<wl_seat> seat; 72 std::unique_ptr<wl_seat> seat;
75 }; 73 };
76 74
77 void RegistryHandler(void* data, 75 void RegistryHandler(void* data,
78 wl_registry* registry, 76 wl_registry* registry,
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 201
204 static uint32_t initial_time = time; 202 static uint32_t initial_time = time;
205 frame->time = time - initial_time; 203 frame->time = time - initial_time;
206 frame->callback_pending = false; 204 frame->callback_pending = false;
207 } 205 }
208 206
209 } // namespace 207 } // namespace
210 208
211 class MotionEvents { 209 class MotionEvents {
212 public: 210 public:
213 MotionEvents() {} 211 MotionEvents(size_t width,
212 size_t height,
213 int scale,
214 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
215 bool fullscreen)
216 : width_(width),
217 height_(height),
218 scale_(scale),
219 rects_(rects),
220 fullscreen_(fullscreen) {}
214 221
215 // Initialize and run client main loop. 222 // Initialize and run client main loop.
216 int Run(); 223 int Run();
217 224
218 private: 225 private:
226 size_t stride() const { return width_ * kBytesPerPixel; }
227 size_t buffer_size() const { return stride() * height_; }
228
229 const size_t width_;
230 const size_t height_;
231 const int scale_;
232 const size_t rects_;
Daniele Castagna 2016/11/05 21:49:19 rect_num_?
reveman 2016/11/05 22:38:19 Done.
233 const bool fullscreen_;
234
219 DISALLOW_COPY_AND_ASSIGN(MotionEvents); 235 DISALLOW_COPY_AND_ASSIGN(MotionEvents);
220 }; 236 };
221 237
222 int MotionEvents::Run() { 238 int MotionEvents::Run() {
223 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); 239 std::unique_ptr<wl_display> display(wl_display_connect(nullptr));
224 if (!display) { 240 if (!display) {
225 LOG(ERROR) << "wl_display_connect failed"; 241 LOG(ERROR) << "wl_display_connect failed";
226 return 1; 242 return 1;
227 } 243 }
228 244
229 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; 245 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
230 246
231 Globals globals; 247 Globals globals;
232 wl_registry* registry = wl_display_get_registry(display.get()); 248 wl_registry* registry = wl_display_get_registry(display.get());
233 wl_registry_add_listener(registry, &registry_listener, &globals); 249 wl_registry_add_listener(registry, &registry_listener, &globals);
234 250
235 wl_display_dispatch(display.get());
236 wl_display_roundtrip(display.get()); 251 wl_display_roundtrip(display.get());
237 252
238 if (!globals.compositor) { 253 if (!globals.compositor) {
239 LOG(ERROR) << "Can't find compositor interface"; 254 LOG(ERROR) << "Can't find compositor interface";
240 return 1; 255 return 1;
241 } 256 }
242 if (!globals.shm) { 257 if (!globals.shm) {
243 LOG(ERROR) << "Can't find shm interface"; 258 LOG(ERROR) << "Can't find shm interface";
244 return 1; 259 return 1;
245 } 260 }
246 if (!globals.shell) { 261 if (!globals.shell) {
247 LOG(ERROR) << "Can't find shell interface"; 262 LOG(ERROR) << "Can't find shell interface";
248 return 1; 263 return 1;
249 } 264 }
250 if (!globals.seat) { 265 if (!globals.seat) {
251 LOG(ERROR) << "Can't find seat interface"; 266 LOG(ERROR) << "Can't find seat interface";
252 return 1; 267 return 1;
253 } 268 }
254 269
255 wl_buffer_listener buffer_listener = {BufferRelease}; 270 wl_buffer_listener buffer_listener = {BufferRelease};
256 271
257 Buffer buffers[kBuffers]; 272 Buffer buffers[kBuffers];
258 base::SharedMemory shared_memory; 273 base::SharedMemory shared_memory;
259 shared_memory.CreateAndMapAnonymous(kMemorySize); 274 shared_memory.CreateAndMapAnonymous(buffer_size() * kBuffers);
260 std::unique_ptr<wl_shm_pool> shm_pool( 275 std::unique_ptr<wl_shm_pool> shm_pool(
261 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, 276 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd,
262 shared_memory.requested_size())); 277 shared_memory.requested_size()));
263 for (size_t i = 0; i < kBuffers; ++i) { 278 for (size_t i = 0; i < kBuffers; ++i) {
264 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( 279 buffers[i].buffer.reset(static_cast<wl_buffer*>(
265 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); 280 wl_shm_pool_create_buffer(shm_pool.get(), i * buffer_size(), width_,
281 height_, stride(), kFormat)));
266 if (!buffers[i].buffer) { 282 if (!buffers[i].buffer) {
267 LOG(ERROR) << "Can't create buffer"; 283 LOG(ERROR) << "Can't create buffer";
268 return 1; 284 return 1;
269 } 285 }
270 buffers[i].sk_surface = SkSurface::MakeRasterDirect( 286 buffers[i].sk_surface = SkSurface::MakeRasterDirect(
271 SkImageInfo::Make(kWidth, kHeight, kColorType, kUnpremul_SkAlphaType), 287 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType),
272 static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i, 288 static_cast<uint8_t*>(shared_memory.memory()) + buffer_size() * i,
273 kStride); 289 stride());
274 if (!buffers[i].sk_surface) { 290 if (!buffers[i].sk_surface) {
275 LOG(ERROR) << "Can't create SkSurface"; 291 LOG(ERROR) << "Can't create SkSurface";
276 return 1; 292 return 1;
277 } 293 }
278 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, 294 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener,
279 &buffers[i]); 295 &buffers[i]);
280 } 296 }
281 297
282 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( 298 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>(
283 wl_compositor_create_surface(globals.compositor.get()))); 299 wl_compositor_create_surface(globals.compositor.get())));
284 if (!surface) { 300 if (!surface) {
285 LOG(ERROR) << "Can't create surface"; 301 LOG(ERROR) << "Can't create surface";
286 return 1; 302 return 1;
287 } 303 }
288 304
289 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>( 305 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>(
290 wl_compositor_create_region(globals.compositor.get()))); 306 wl_compositor_create_region(globals.compositor.get())));
291 if (!opaque_region) { 307 if (!opaque_region) {
292 LOG(ERROR) << "Can't create region"; 308 LOG(ERROR) << "Can't create region";
293 return 1; 309 return 1;
294 } 310 }
295 311
296 wl_region_add(opaque_region.get(), 0, 0, kWidth, kHeight); 312 wl_region_add(opaque_region.get(), 0, 0, width_, height_);
297 wl_surface_set_opaque_region(surface.get(), opaque_region.get()); 313 wl_surface_set_opaque_region(surface.get(), opaque_region.get());
298 314
299 std::unique_ptr<wl_shell_surface> shell_surface( 315 std::unique_ptr<wl_shell_surface> shell_surface(
300 static_cast<wl_shell_surface*>( 316 static_cast<wl_shell_surface*>(
301 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); 317 wl_shell_get_shell_surface(globals.shell.get(), surface.get())));
302 if (!shell_surface) { 318 if (!shell_surface) {
303 LOG(ERROR) << "Can't get shell surface"; 319 LOG(ERROR) << "Can't get shell surface";
304 return 1; 320 return 1;
305 } 321 }
306 322
307 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); 323 wl_shell_surface_set_title(shell_surface.get(), "Test Client");
308 wl_shell_surface_set_toplevel(shell_surface.get()); 324 if (fullscreen_) {
325 wl_shell_surface_set_fullscreen(shell_surface.get(),
326 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
327 0, nullptr);
328 } else {
329 wl_shell_surface_set_toplevel(shell_surface.get());
330 }
309 331
310 EventTimeStack event_times; 332 EventTimeStack event_times;
311 333
312 std::unique_ptr<wl_pointer> pointer( 334 std::unique_ptr<wl_pointer> pointer(
313 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); 335 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get())));
314 if (!pointer) { 336 if (!pointer) {
315 LOG(ERROR) << "Can't get pointer"; 337 LOG(ERROR) << "Can't get pointer";
316 return 1; 338 return 1;
317 } 339 }
318 340
(...skipping 11 matching lines...) Expand all
330 } 352 }
331 353
332 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, 354 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion,
333 TouchFrame, TouchCancel}; 355 TouchFrame, TouchCancel};
334 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); 356 wl_touch_add_listener(touch.get(), &touch_listener, &event_times);
335 357
336 Frame frame; 358 Frame frame;
337 std::unique_ptr<wl_callback> frame_callback; 359 std::unique_ptr<wl_callback> frame_callback;
338 wl_callback_listener frame_listener = {FrameCallback}; 360 wl_callback_listener frame_listener = {FrameCallback};
339 361
362 uint32_t frames = 0;
363 base::TimeTicks benchmark_time = base::TimeTicks::Now();
364 base::TimeDelta benchmark_interval =
365 base::TimeDelta::FromSeconds(kBenchmarkInterval);
366
340 do { 367 do {
341 if (frame.callback_pending) 368 if (frame.callback_pending)
342 continue; 369 continue;
343 370
344 Buffer* buffer = 371 Buffer* buffer =
345 std::find_if(std::begin(buffers), std::end(buffers), 372 std::find_if(std::begin(buffers), std::end(buffers),
346 [](const Buffer& buffer) { return !buffer.busy; }); 373 [](const Buffer& buffer) { return !buffer.busy; });
347 if (buffer == std::end(buffers)) 374 if (buffer == std::end(buffers))
348 continue; 375 continue;
349 376
377 base::TimeTicks current_time = base::TimeTicks::Now();
378 if ((current_time - benchmark_time) > benchmark_interval) {
379 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
380 << " seconds: "
381 << static_cast<double>(frames) / benchmark_interval.InSeconds()
382 << " fps" << std::endl;
383 benchmark_time = current_time;
384 frames = 0;
385 }
386
350 SkCanvas* canvas = buffer->sk_surface->getCanvas(); 387 SkCanvas* canvas = buffer->sk_surface->getCanvas();
351 canvas->save(); 388 canvas->save();
352 389
353 // Clear background to black. 390 if (event_times.empty()) {
354 canvas->clear(SK_ColorBLACK); 391 canvas->clear(SK_ColorBLACK);
355 392 } else {
356 // Split buffer into one horizontal rectangle for each event received since 393 // Split buffer into one horizontal rectangle for each event received
357 // last frame. Latest event at the top. 394 // since last frame. Latest event at the top.
358 if (!event_times.empty()) { 395 int y = 0;
359 double y = 0; 396 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
360 double height = static_cast<double>(kHeight) / event_times.size();
361 while (!event_times.empty()) { 397 while (!event_times.empty()) {
362 SkRect rect = SkRect::MakeXYWH(0, y, kWidth, height); 398 SkIRect rect = SkIRect::MakeXYWH(0, y, width_, h);
363 SkPaint paint; 399 SkPaint paint;
364 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0, 400 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0,
365 (event_times.back() & 0x00ff00) >> 8, 401 (event_times.back() & 0x00ff00) >> 8,
366 (event_times.back() & 0xff0000) >> 16)); 402 (event_times.back() & 0xff0000) >> 16));
367 canvas->drawRect(rect, paint); 403 canvas->drawIRect(rect, paint);
368 event_times.pop_back(); 404 event_times.pop_back();
369 y += height; 405 y += h;
370 } 406 }
371 } 407 }
372 408
373 // Draw a blue rotating rectangle on top. 409 // Draw rotating rects.
374 canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)); 410 SkScalar half_width = SkScalarHalf(width_);
375 canvas->rotate(SkDoubleToScalar((frame.time / 1000.0f) * kRotationSpeed)); 411 SkScalar half_height = SkScalarHalf(height_);
376 SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f), 412 SkIRect rect =
377 kWidth / 2.0f, kHeight / 2.0f); 413 SkIRect::MakeXYWH(-SkScalarHalf(half_width), -SkScalarHalf(half_height),
414 half_width, half_height);
415 SkScalar rotation = SkScalarMulDiv(frame.time, kRotationSpeed, 1000);
378 SkPaint paint; 416 SkPaint paint;
379 paint.setColor(SK_ColorBLUE); 417 canvas->translate(half_width, half_height);
380 canvas->drawRect(rect, paint); 418 for (size_t i = 0; i < rects_; ++i) {
381 419 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN,
420 SK_ColorRED, SK_ColorYELLOW,
421 SK_ColorCYAN, SK_ColorMAGENTA};
422 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0));
423 canvas->rotate(rotation / rects_);
424 canvas->drawIRect(rect, paint);
425 }
382 canvas->restore(); 426 canvas->restore();
383 427
428 wl_surface_set_buffer_scale(surface.get(), scale_);
384 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); 429 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
385 buffer->busy = true; 430 buffer->busy = true;
386 431
387 frame_callback.reset(wl_surface_frame(surface.get())); 432 frame_callback.reset(wl_surface_frame(surface.get()));
388 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); 433 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
389 frame.callback_pending = true; 434 frame.callback_pending = true;
390 435
436 ++frames;
437
391 wl_surface_commit(surface.get()); 438 wl_surface_commit(surface.get());
392 wl_display_flush(display.get());
393 } while (wl_display_dispatch(display.get()) != -1); 439 } while (wl_display_dispatch(display.get()) != -1);
394 440
395 return 0; 441 return 0;
396 } 442 }
397 443
398 } // namespace clients 444 } // namespace clients
399 } // namespace wayland 445 } // namespace wayland
400 } // namespace exo 446 } // namespace exo
401 447
402 int main() { 448 namespace switches {
403 return exo::wayland::clients::MotionEvents().Run(); 449
450 // Specifies the client buffer size.
451 const char kSize[] = "size";
452
453 // 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.
454 const char kScale[] = "scale";
455
456 // Specifies the number of rotating rects to draw.
457 const char kRects[] = "rects";
458
459 // Specifies if client should be fullscreen.
460 const char kFullscreen[] = "fullscreen";
461
462 } // namespace switches
463
464 int main(int argc, char* argv[]) {
465 base::CommandLine command_line(argc, argv);
466
467 int width = 256;
468 int height = 256;
469 if (command_line.HasSwitch(switches::kSize)) {
470 std::string size_str = command_line.GetSwitchValueASCII(switches::kSize);
471 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) {
472 LOG(ERROR) << "Invalid value for " << switches::kSize;
473 return 1;
474 }
475 }
476
477 int scale = 1;
478 if (command_line.HasSwitch(switches::kScale) &&
479 !base::StringToInt(command_line.GetSwitchValueASCII(switches::kScale),
480 &scale)) {
481 LOG(ERROR) << "Invalid value for " << switches::kScale;
482 return 1;
483 }
484
485 size_t rects = 1;
486 if (command_line.HasSwitch(switches::kRects) &&
487 !base::StringToSizeT(command_line.GetSwitchValueASCII(switches::kRects),
488 &rects)) {
489 LOG(ERROR) << "Invalid value for " << switches::kRects;
490 return 1;
491 }
492
493 bool fullscreen = command_line.HasSwitch(switches::kFullscreen);
494
495 exo::wayland::clients::MotionEvents client(width, height, scale, rects,
496 fullscreen);
497 return client.Run();
404 } 498 }
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