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

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

Issue 2475423002: exo: Cleanup and improve event time rendering in motion event client. (Closed)
Patch Set: exo: Cleanup and improve event time rendering in motion event client. 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 <vector>
13
12 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/macros.h"
13 #include "base/memory/shared_memory.h" 16 #include "base/memory/shared_memory.h"
14 #include "third_party/skia/include/core/SkCanvas.h" 17 #include "third_party/skia/include/core/SkCanvas.h"
15 #include "third_party/skia/include/core/SkRefCnt.h" 18 #include "third_party/skia/include/core/SkRefCnt.h"
16 #include "third_party/skia/include/core/SkSurface.h" 19 #include "third_party/skia/include/core/SkSurface.h"
17 20
18 // Convenient macro that is used to define default deleters for wayland object 21 // Convenient macro that is used to define default deleters for wayland object
19 // types allowing them to be used with std::unique_ptr. 22 // types allowing them to be used with std::unique_ptr.
20 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ 23 #define DEFAULT_DELETER(TypeName, DeleteFunction) \
21 namespace std { \ 24 namespace std { \
22 template <> \ 25 template <> \
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 } else if (strcmp(interface, "wl_seat") == 0) { 93 } else if (strcmp(interface, "wl_seat") == 0) {
91 globals->seat.reset(static_cast<wl_seat*>( 94 globals->seat.reset(static_cast<wl_seat*>(
92 wl_registry_bind(registry, id, &wl_seat_interface, 5))); 95 wl_registry_bind(registry, id, &wl_seat_interface, 5)));
93 } 96 }
94 } 97 }
95 98
96 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { 99 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) {
97 LOG(WARNING) << "Got a registry losing event for " << id; 100 LOG(WARNING) << "Got a registry losing event for " << id;
98 } 101 }
99 102
100 struct BufferState { 103 struct Buffer {
101 std::unique_ptr<wl_buffer> buffer; 104 std::unique_ptr<wl_buffer> buffer;
102 sk_sp<SkSurface> sk_surface; 105 sk_sp<SkSurface> sk_surface;
103 bool busy = false; 106 bool busy = false;
104 }; 107 };
105 108
106 void BufferRelease(void* data, wl_buffer* buffer) { 109 void BufferRelease(void* data, wl_buffer* /* buffer */) {
107 BufferState* state = static_cast<BufferState*>(data); 110 Buffer* buffer = static_cast<Buffer*>(data);
108 111
109 state->busy = false; 112 buffer->busy = false;
110 } 113 }
111 114
112 struct MainLoopContext { 115 using EventTimeStack = std::vector<uint32_t>;
113 bool shutdown = false;
114 uint32_t last_event_time = 0;
115 bool frame_callback_pending = false;
116 double rotation = 0.0;
117 };
118 116
119 void PointerEnter(void* data, 117 void PointerEnter(void* data,
120 wl_pointer* pointer, 118 wl_pointer* pointer,
121 uint32_t serial, 119 uint32_t serial,
122 wl_surface* surface, 120 wl_surface* surface,
123 wl_fixed_t x, 121 wl_fixed_t x,
124 wl_fixed_t y) {} 122 wl_fixed_t y) {}
125 123
126 void PointerLeave(void* data, 124 void PointerLeave(void* data,
127 wl_pointer* pointer, 125 wl_pointer* pointer,
128 uint32_t serial, 126 uint32_t serial,
129 wl_surface* surface) {} 127 wl_surface* surface) {}
130 128
131 void PointerMotion(void* data, 129 void PointerMotion(void* data,
132 wl_pointer* pointer, 130 wl_pointer* pointer,
133 uint32_t time, 131 uint32_t time,
134 wl_fixed_t x, 132 wl_fixed_t x,
135 wl_fixed_t y) { 133 wl_fixed_t y) {
136 MainLoopContext* context = static_cast<MainLoopContext*>(data); 134 EventTimeStack* stack = static_cast<EventTimeStack*>(data);
137 135
138 context->last_event_time = time; 136 stack->push_back(time);
139 } 137 }
140 138
141 void PointerButton(void* data, 139 void PointerButton(void* data,
142 wl_pointer* pointer, 140 wl_pointer* pointer,
143 uint32_t serial, 141 uint32_t serial,
144 uint32_t time, 142 uint32_t time,
145 uint32_t button, 143 uint32_t button,
146 uint32_t state) { 144 uint32_t state) {}
147 MainLoopContext* context = static_cast<MainLoopContext*>(data);
148
149 context->shutdown = true;
150 }
151 145
152 void PointerAxis(void* data, 146 void PointerAxis(void* data,
153 wl_pointer* pointer, 147 wl_pointer* pointer,
154 uint32_t time, 148 uint32_t time,
155 uint32_t axis, 149 uint32_t axis,
156 wl_fixed_t value) {} 150 wl_fixed_t value) {}
157 151
158 void PointerAxisSource(void* data, wl_pointer* pointer, uint32_t axis_source) {} 152 void PointerAxisSource(void* data, wl_pointer* pointer, uint32_t axis_source) {}
159 153
160 void PointerAxisStop(void* data, 154 void PointerAxisStop(void* data,
(...skipping 22 matching lines...) Expand all
183 uint32_t serial, 177 uint32_t serial,
184 uint32_t time, 178 uint32_t time,
185 int32_t id) {} 179 int32_t id) {}
186 180
187 void TouchMotion(void* data, 181 void TouchMotion(void* data,
188 wl_touch* touch, 182 wl_touch* touch,
189 uint32_t time, 183 uint32_t time,
190 int32_t id, 184 int32_t id,
191 wl_fixed_t x, 185 wl_fixed_t x,
192 wl_fixed_t y) { 186 wl_fixed_t y) {
193 MainLoopContext* context = static_cast<MainLoopContext*>(data); 187 EventTimeStack* stack = static_cast<EventTimeStack*>(data);
194 188
195 context->last_event_time = time; 189 stack->push_back(time);
196 } 190 }
197 191
198 void TouchFrame(void* data, wl_touch* touch) {} 192 void TouchFrame(void* data, wl_touch* touch) {}
199 193
200 void TouchCancel(void* data, wl_touch* touch) {} 194 void TouchCancel(void* data, wl_touch* touch) {}
201 195
196 struct Frame {
197 uint32_t time = 0;
198 bool callback_pending = false;
199 };
200
202 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { 201 void FrameCallback(void* data, wl_callback* callback, uint32_t time) {
203 MainLoopContext* context = static_cast<MainLoopContext*>(data); 202 Frame* frame = static_cast<Frame*>(data);
204 203
205 static uint32_t initial_time = time; 204 static uint32_t initial_time = time;
206 context->rotation = ((time - initial_time) / 1000.0) * kRotationSpeed; 205 frame->time = time - initial_time;
207 context->frame_callback_pending = false; 206 frame->callback_pending = false;
208 } 207 }
209 208
210 } // namespace 209 } // namespace
211 210
212 int MotionEventsMain() { 211 class MotionEvents {
212 public:
213 MotionEvents() {}
214
215 // Initialize and run client main loop.
216 int Run();
217
218 private:
219 DISALLOW_COPY_AND_ASSIGN(MotionEvents);
220 };
221
222 int MotionEvents::Run() {
213 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); 223 std::unique_ptr<wl_display> display(wl_display_connect(nullptr));
214 if (!display) { 224 if (!display) {
215 LOG(ERROR) << "wl_display_connect failed"; 225 LOG(ERROR) << "wl_display_connect failed";
216 return 1; 226 return 1;
217 } 227 }
218 228
219 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; 229 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
220 230
221 Globals globals; 231 Globals globals;
222 wl_registry* registry = wl_display_get_registry(display.get()); 232 wl_registry* registry = wl_display_get_registry(display.get());
(...skipping 14 matching lines...) Expand all
237 LOG(ERROR) << "Can't find shell interface"; 247 LOG(ERROR) << "Can't find shell interface";
238 return 1; 248 return 1;
239 } 249 }
240 if (!globals.seat) { 250 if (!globals.seat) {
241 LOG(ERROR) << "Can't find seat interface"; 251 LOG(ERROR) << "Can't find seat interface";
242 return 1; 252 return 1;
243 } 253 }
244 254
245 wl_buffer_listener buffer_listener = {BufferRelease}; 255 wl_buffer_listener buffer_listener = {BufferRelease};
246 256
247 BufferState buffers[kBuffers]; 257 Buffer buffers[kBuffers];
248 base::SharedMemory shared_memory; 258 base::SharedMemory shared_memory;
249 shared_memory.CreateAndMapAnonymous(kMemorySize); 259 shared_memory.CreateAndMapAnonymous(kMemorySize);
250 std::unique_ptr<wl_shm_pool> shm_pool( 260 std::unique_ptr<wl_shm_pool> shm_pool(
251 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, 261 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd,
252 shared_memory.requested_size())); 262 shared_memory.requested_size()));
253 for (size_t i = 0; i < kBuffers; ++i) { 263 for (size_t i = 0; i < kBuffers; ++i) {
254 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( 264 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer(
255 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); 265 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat)));
256 if (!buffers[i].buffer) { 266 if (!buffers[i].buffer) {
257 LOG(ERROR) << "Can't create buffer"; 267 LOG(ERROR) << "Can't create buffer";
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 static_cast<wl_shell_surface*>( 300 static_cast<wl_shell_surface*>(
291 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); 301 wl_shell_get_shell_surface(globals.shell.get(), surface.get())));
292 if (!shell_surface) { 302 if (!shell_surface) {
293 LOG(ERROR) << "Can't get shell surface"; 303 LOG(ERROR) << "Can't get shell surface";
294 return 1; 304 return 1;
295 } 305 }
296 306
297 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); 307 wl_shell_surface_set_title(shell_surface.get(), "Test Client");
298 wl_shell_surface_set_toplevel(shell_surface.get()); 308 wl_shell_surface_set_toplevel(shell_surface.get());
299 309
300 MainLoopContext context; 310 EventTimeStack event_times;
301 311
302 std::unique_ptr<wl_pointer> pointer( 312 std::unique_ptr<wl_pointer> pointer(
303 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); 313 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get())));
304 if (!pointer) { 314 if (!pointer) {
305 LOG(ERROR) << "Can't get pointer"; 315 LOG(ERROR) << "Can't get pointer";
306 return 1; 316 return 1;
307 } 317 }
308 318
309 wl_pointer_listener pointer_listener = { 319 wl_pointer_listener pointer_listener = {
310 PointerEnter, PointerLeave, PointerMotion, 320 PointerEnter, PointerLeave, PointerMotion,
311 PointerButton, PointerAxis, PointerFrame, 321 PointerButton, PointerAxis, PointerFrame,
312 PointerAxisSource, PointerAxisStop, PointerDiscrete}; 322 PointerAxisSource, PointerAxisStop, PointerDiscrete};
313 wl_pointer_add_listener(pointer.get(), &pointer_listener, &context); 323 wl_pointer_add_listener(pointer.get(), &pointer_listener, &event_times);
314 324
315 std::unique_ptr<wl_touch> touch( 325 std::unique_ptr<wl_touch> touch(
316 static_cast<wl_touch*>(wl_seat_get_touch(globals.seat.get()))); 326 static_cast<wl_touch*>(wl_seat_get_touch(globals.seat.get())));
317 if (!touch) { 327 if (!touch) {
318 LOG(ERROR) << "Can't get touch"; 328 LOG(ERROR) << "Can't get touch";
319 return 1; 329 return 1;
320 } 330 }
321 331
322 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, 332 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion,
323 TouchFrame, TouchCancel}; 333 TouchFrame, TouchCancel};
324 wl_touch_add_listener(touch.get(), &touch_listener, &context); 334 wl_touch_add_listener(touch.get(), &touch_listener, &event_times);
325 335
336 Frame frame;
326 std::unique_ptr<wl_callback> frame_callback; 337 std::unique_ptr<wl_callback> frame_callback;
327 wl_callback_listener frame_listener = {FrameCallback}; 338 wl_callback_listener frame_listener = {FrameCallback};
328 339
329 do { 340 do {
330 if (context.shutdown) 341 if (frame.callback_pending)
331 break;
332
333 if (context.frame_callback_pending)
334 continue; 342 continue;
335 343
336 BufferState* buffer = 344 Buffer* buffer =
337 std::find_if(std::begin(buffers), std::end(buffers), 345 std::find_if(std::begin(buffers), std::end(buffers),
338 [](const BufferState& buffer) { return !buffer.busy; }); 346 [](const Buffer& buffer) { return !buffer.busy; });
339 if (buffer == std::end(buffers)) 347 if (buffer == std::end(buffers))
340 continue; 348 continue;
341 349
342 SkCanvas* canvas = buffer->sk_surface->getCanvas(); 350 SkCanvas* canvas = buffer->sk_surface->getCanvas();
343 canvas->save(); 351 canvas->save();
344 canvas->clear(SkColorSetRGB((context.last_event_time & 0x0000ff) >> 0, 352
345 (context.last_event_time & 0x00ff00) >> 8, 353 // Clear background to black.
346 (context.last_event_time & 0xff0000) >> 16)); 354 canvas->clear(SK_ColorBLACK);
355
356 // Split buffer into one horizontal rectangle for each event received since
357 // last frame. Latest event at the top.
358 if (!event_times.empty()) {
359 double y = 0;
360 double height = static_cast<double>(kHeight) / event_times.size();
361 while (!event_times.empty()) {
362 SkRect rect = SkRect::MakeXYWH(0, y, kWidth, height);
363 SkPaint paint;
364 paint.setColor(SkColorSetRGB((event_times.back() & 0x0000ff) >> 0,
365 (event_times.back() & 0x00ff00) >> 8,
366 (event_times.back() & 0xff0000) >> 16));
367 canvas->drawRect(rect, paint);
368 event_times.pop_back();
369 y += height;
370 }
371 }
372
373 // Draw a blue rotating rectangle on top.
347 canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)); 374 canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2));
348 canvas->rotate(SkDoubleToScalar(context.rotation)); 375 canvas->rotate(SkDoubleToScalar((frame.time / 1000.0f) * kRotationSpeed));
349 SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f), 376 SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f),
350 kWidth / 2.0f, kHeight / 2.0f); 377 kWidth / 2.0f, kHeight / 2.0f);
351 SkPaint paint; 378 SkPaint paint;
352 paint.setColor(SK_ColorBLUE); 379 paint.setColor(SK_ColorBLUE);
353 canvas->drawRect(rect, paint); 380 canvas->drawRect(rect, paint);
381
354 canvas->restore(); 382 canvas->restore();
355 383
356 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); 384 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
357 buffer->busy = true; 385 buffer->busy = true;
358 386
359 frame_callback.reset(wl_surface_frame(surface.get())); 387 frame_callback.reset(wl_surface_frame(surface.get()));
360 wl_callback_add_listener(frame_callback.get(), &frame_listener, &context); 388 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
361 context.frame_callback_pending = true; 389 frame.callback_pending = true;
362 390
363 wl_surface_commit(surface.get()); 391 wl_surface_commit(surface.get());
364 wl_display_flush(display.get()); 392 wl_display_flush(display.get());
365 } while (wl_display_dispatch(display.get()) != -1); 393 } while (wl_display_dispatch(display.get()) != -1);
366 394
367 return 0; 395 return 0;
368 } 396 }
369 397
370 } // namespace clients 398 } // namespace clients
371 } // namespace wayland 399 } // namespace wayland
372 } // namespace exo 400 } // namespace exo
373 401
374 int main() { 402 int main() {
375 return exo::wayland::clients::MotionEventsMain(); 403 return exo::wayland::clients::MotionEvents().Run();
376 } 404 }
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