| 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 <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 "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/shared_memory.h" | 13 #include "base/memory/shared_memory.h" |
| 14 #include "third_party/skia/include/core/SkCanvas.h" |
| 15 #include "third_party/skia/include/core/SkRefCnt.h" |
| 16 #include "third_party/skia/include/core/SkSurface.h" |
| 14 | 17 |
| 15 // Convenient macro that is used to define default deleters for wayland object | 18 // Convenient macro that is used to define default deleters for wayland object |
| 16 // types allowing them to be used with std::unique_ptr. | 19 // types allowing them to be used with std::unique_ptr. |
| 17 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ | 20 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ |
| 18 namespace std { \ | 21 namespace std { \ |
| 19 template <> \ | 22 template <> \ |
| 20 struct default_delete<TypeName> { \ | 23 struct default_delete<TypeName> { \ |
| 21 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \ | 24 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \ |
| 22 }; \ | 25 }; \ |
| 23 } | 26 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 39 namespace exo { | 42 namespace exo { |
| 40 namespace wayland { | 43 namespace wayland { |
| 41 namespace clients { | 44 namespace clients { |
| 42 namespace { | 45 namespace { |
| 43 | 46 |
| 44 // Window size. | 47 // Window size. |
| 45 const size_t kWidth = 256; | 48 const size_t kWidth = 256; |
| 46 const size_t kHeight = 256; | 49 const size_t kHeight = 256; |
| 47 | 50 |
| 48 // Buffer format. | 51 // Buffer format. |
| 49 const int32_t kFormat = WL_SHM_FORMAT_ABGR8888; | 52 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; |
| 53 const SkColorType kColorType = kBGRA_8888_SkColorType; |
| 50 const size_t kBytesPerPixel = 4; | 54 const size_t kBytesPerPixel = 4; |
| 51 | 55 |
| 52 // Number of buffers. | 56 // Number of buffers. |
| 53 const size_t kBuffers = 2; | 57 const size_t kBuffers = 2; |
| 54 | 58 |
| 59 // Rotation speed (degrees/second). |
| 60 const double kRotationSpeed = 360.0; |
| 61 |
| 55 // Helper constants. | 62 // Helper constants. |
| 56 const size_t kStride = kWidth * kBytesPerPixel; | 63 const size_t kStride = kWidth * kBytesPerPixel; |
| 57 const size_t kBufferSize = kHeight * kStride; | 64 const size_t kBufferSize = kHeight * kStride; |
| 58 const size_t kMemorySize = kBufferSize * kBuffers; | 65 const size_t kMemorySize = kBufferSize * kBuffers; |
| 59 | 66 |
| 60 struct Globals { | 67 struct Globals { |
| 61 std::unique_ptr<wl_compositor> compositor; | 68 std::unique_ptr<wl_compositor> compositor; |
| 62 std::unique_ptr<wl_shm> shm; | 69 std::unique_ptr<wl_shm> shm; |
| 63 std::unique_ptr<wl_shell> shell; | 70 std::unique_ptr<wl_shell> shell; |
| 64 std::unique_ptr<wl_seat> seat; | 71 std::unique_ptr<wl_seat> seat; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 85 wl_registry_bind(registry, id, &wl_seat_interface, 5))); | 92 wl_registry_bind(registry, id, &wl_seat_interface, 5))); |
| 86 } | 93 } |
| 87 } | 94 } |
| 88 | 95 |
| 89 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { | 96 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { |
| 90 LOG(WARNING) << "Got a registry losing event for " << id; | 97 LOG(WARNING) << "Got a registry losing event for " << id; |
| 91 } | 98 } |
| 92 | 99 |
| 93 struct BufferState { | 100 struct BufferState { |
| 94 std::unique_ptr<wl_buffer> buffer; | 101 std::unique_ptr<wl_buffer> buffer; |
| 95 uint8_t* data = nullptr; | 102 sk_sp<SkSurface> sk_surface; |
| 96 bool busy = false; | 103 bool busy = false; |
| 97 }; | 104 }; |
| 98 | 105 |
| 99 void BufferRelease(void* data, wl_buffer* buffer) { | 106 void BufferRelease(void* data, wl_buffer* buffer) { |
| 100 BufferState* state = static_cast<BufferState*>(data); | 107 BufferState* state = static_cast<BufferState*>(data); |
| 101 | 108 |
| 102 state->busy = false; | 109 state->busy = false; |
| 103 } | 110 } |
| 104 | 111 |
| 105 struct MainLoopContext { | 112 struct MainLoopContext { |
| 106 uint32_t color = 0xffffffff; | |
| 107 bool needs_redraw = true; | |
| 108 bool shutdown = false; | 113 bool shutdown = false; |
| 109 bool throttled = false; | 114 uint32_t last_event_time = 0; |
| 115 bool frame_callback_pending = false; |
| 116 double rotation = 0.0; |
| 110 }; | 117 }; |
| 111 | 118 |
| 112 void PointerEnter(void* data, | 119 void PointerEnter(void* data, |
| 113 wl_pointer* pointer, | 120 wl_pointer* pointer, |
| 114 uint32_t serial, | 121 uint32_t serial, |
| 115 wl_surface* surface, | 122 wl_surface* surface, |
| 116 wl_fixed_t x, | 123 wl_fixed_t x, |
| 117 wl_fixed_t y) {} | 124 wl_fixed_t y) {} |
| 118 | 125 |
| 119 void PointerLeave(void* data, | 126 void PointerLeave(void* data, |
| 120 wl_pointer* pointer, | 127 wl_pointer* pointer, |
| 121 uint32_t serial, | 128 uint32_t serial, |
| 122 wl_surface* surface) {} | 129 wl_surface* surface) {} |
| 123 | 130 |
| 124 void PointerMotion(void* data, | 131 void PointerMotion(void* data, |
| 125 wl_pointer* pointer, | 132 wl_pointer* pointer, |
| 126 uint32_t time, | 133 uint32_t time, |
| 127 wl_fixed_t x, | 134 wl_fixed_t x, |
| 128 wl_fixed_t y) { | 135 wl_fixed_t y) { |
| 129 MainLoopContext* context = static_cast<MainLoopContext*>(data); | 136 MainLoopContext* context = static_cast<MainLoopContext*>(data); |
| 130 | 137 |
| 131 context->color = 0xff000000 | time; | 138 context->last_event_time = time; |
| 132 } | 139 } |
| 133 | 140 |
| 134 void PointerButton(void* data, | 141 void PointerButton(void* data, |
| 135 wl_pointer* pointer, | 142 wl_pointer* pointer, |
| 136 uint32_t serial, | 143 uint32_t serial, |
| 137 uint32_t time, | 144 uint32_t time, |
| 138 uint32_t button, | 145 uint32_t button, |
| 139 uint32_t state) { | 146 uint32_t state) { |
| 140 MainLoopContext* context = static_cast<MainLoopContext*>(data); | 147 MainLoopContext* context = static_cast<MainLoopContext*>(data); |
| 141 | 148 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 153 void PointerAxisStop(void* data, | 160 void PointerAxisStop(void* data, |
| 154 wl_pointer* pointer, | 161 wl_pointer* pointer, |
| 155 uint32_t time, | 162 uint32_t time, |
| 156 uint32_t axis) {} | 163 uint32_t axis) {} |
| 157 | 164 |
| 158 void PointerDiscrete(void* data, | 165 void PointerDiscrete(void* data, |
| 159 wl_pointer* pointer, | 166 wl_pointer* pointer, |
| 160 uint32_t axis, | 167 uint32_t axis, |
| 161 int32_t discrete) {} | 168 int32_t discrete) {} |
| 162 | 169 |
| 163 void PointerFrame(void* data, wl_pointer* pointer) { | 170 void PointerFrame(void* data, wl_pointer* pointer) {} |
| 164 MainLoopContext* context = static_cast<MainLoopContext*>(data); | |
| 165 | |
| 166 context->needs_redraw = true; | |
| 167 } | |
| 168 | 171 |
| 169 void TouchDown(void* data, | 172 void TouchDown(void* data, |
| 170 wl_touch* touch, | 173 wl_touch* touch, |
| 171 uint32_t serial, | 174 uint32_t serial, |
| 172 uint32_t time, | 175 uint32_t time, |
| 173 wl_surface* surface, | 176 wl_surface* surface, |
| 174 int32_t id, | 177 int32_t id, |
| 175 wl_fixed_t x, | 178 wl_fixed_t x, |
| 176 wl_fixed_t y) {} | 179 wl_fixed_t y) {} |
| 177 | 180 |
| 178 void TouchUp(void* data, | 181 void TouchUp(void* data, |
| 179 wl_touch* touch, | 182 wl_touch* touch, |
| 180 uint32_t serial, | 183 uint32_t serial, |
| 181 uint32_t time, | 184 uint32_t time, |
| 182 int32_t id) {} | 185 int32_t id) {} |
| 183 | 186 |
| 184 void TouchMotion(void* data, | 187 void TouchMotion(void* data, |
| 185 wl_touch* touch, | 188 wl_touch* touch, |
| 186 uint32_t time, | 189 uint32_t time, |
| 187 int32_t id, | 190 int32_t id, |
| 188 wl_fixed_t x, | 191 wl_fixed_t x, |
| 189 wl_fixed_t y) { | 192 wl_fixed_t y) { |
| 190 MainLoopContext* context = static_cast<MainLoopContext*>(data); | 193 MainLoopContext* context = static_cast<MainLoopContext*>(data); |
| 191 | 194 |
| 192 context->color = 0xff000000 | time; | 195 context->last_event_time = time; |
| 193 context->needs_redraw = true; | |
| 194 } | 196 } |
| 195 | 197 |
| 196 void TouchFrame(void* data, wl_touch* touch) {} | 198 void TouchFrame(void* data, wl_touch* touch) {} |
| 197 | 199 |
| 198 void TouchCancel(void* data, wl_touch* touch) {} | 200 void TouchCancel(void* data, wl_touch* touch) {} |
| 199 | 201 |
| 200 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { | 202 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { |
| 201 MainLoopContext* context = static_cast<MainLoopContext*>(data); | 203 MainLoopContext* context = static_cast<MainLoopContext*>(data); |
| 202 | 204 |
| 203 context->throttled = false; | 205 static uint32_t initial_time = time; |
| 206 context->rotation = ((time - initial_time) / 1000.0) * kRotationSpeed; |
| 207 context->frame_callback_pending = false; |
| 204 } | 208 } |
| 205 | 209 |
| 206 } // namespace | 210 } // namespace |
| 207 | 211 |
| 208 int MotionEventsMain() { | 212 int MotionEventsMain() { |
| 209 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); | 213 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); |
| 210 if (!display) { | 214 if (!display) { |
| 211 LOG(ERROR) << "wl_display_connect failed"; | 215 LOG(ERROR) << "wl_display_connect failed"; |
| 212 return 1; | 216 return 1; |
| 213 } | 217 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 std::unique_ptr<wl_shm_pool> shm_pool( | 250 std::unique_ptr<wl_shm_pool> shm_pool( |
| 247 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, | 251 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, |
| 248 shared_memory.requested_size())); | 252 shared_memory.requested_size())); |
| 249 for (size_t i = 0; i < kBuffers; ++i) { | 253 for (size_t i = 0; i < kBuffers; ++i) { |
| 250 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( | 254 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( |
| 251 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); | 255 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); |
| 252 if (!buffers[i].buffer) { | 256 if (!buffers[i].buffer) { |
| 253 LOG(ERROR) << "Can't create buffer"; | 257 LOG(ERROR) << "Can't create buffer"; |
| 254 return 1; | 258 return 1; |
| 255 } | 259 } |
| 256 buffers[i].data = | 260 buffers[i].sk_surface = SkSurface::MakeRasterDirect( |
| 257 static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i; | 261 SkImageInfo::Make(kWidth, kHeight, kColorType, kUnpremul_SkAlphaType), |
| 262 static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i, |
| 263 kStride); |
| 264 if (!buffers[i].sk_surface) { |
| 265 LOG(ERROR) << "Can't create SkSurface"; |
| 266 return 1; |
| 267 } |
| 258 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, | 268 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, |
| 259 &buffers[i]); | 269 &buffers[i]); |
| 260 } | 270 } |
| 261 | 271 |
| 262 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( | 272 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( |
| 263 wl_compositor_create_surface(globals.compositor.get()))); | 273 wl_compositor_create_surface(globals.compositor.get()))); |
| 264 if (!surface) { | 274 if (!surface) { |
| 265 LOG(ERROR) << "Can't create surface"; | 275 LOG(ERROR) << "Can't create surface"; |
| 266 return 1; | 276 return 1; |
| 267 } | 277 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 TouchFrame, TouchCancel}; | 323 TouchFrame, TouchCancel}; |
| 314 wl_touch_add_listener(touch.get(), &touch_listener, &context); | 324 wl_touch_add_listener(touch.get(), &touch_listener, &context); |
| 315 | 325 |
| 316 std::unique_ptr<wl_callback> frame_callback; | 326 std::unique_ptr<wl_callback> frame_callback; |
| 317 wl_callback_listener frame_listener = {FrameCallback}; | 327 wl_callback_listener frame_listener = {FrameCallback}; |
| 318 | 328 |
| 319 do { | 329 do { |
| 320 if (context.shutdown) | 330 if (context.shutdown) |
| 321 break; | 331 break; |
| 322 | 332 |
| 323 if (!context.needs_redraw) | 333 if (context.frame_callback_pending) |
| 324 continue; | |
| 325 | |
| 326 if (context.throttled) | |
| 327 continue; | 334 continue; |
| 328 | 335 |
| 329 BufferState* buffer = | 336 BufferState* buffer = |
| 330 std::find_if(std::begin(buffers), std::end(buffers), | 337 std::find_if(std::begin(buffers), std::end(buffers), |
| 331 [](const BufferState& buffer) { return !buffer.busy; }); | 338 [](const BufferState& buffer) { return !buffer.busy; }); |
| 332 if (buffer == std::end(buffers)) | 339 if (buffer == std::end(buffers)) |
| 333 continue; | 340 continue; |
| 334 | 341 |
| 335 context.needs_redraw = false; | 342 SkCanvas* canvas = buffer->sk_surface->getCanvas(); |
| 336 | 343 canvas->save(); |
| 337 static_assert(sizeof(uint32_t) == kBytesPerPixel, | 344 canvas->clear(SkColorSetRGB((context.last_event_time & 0x0000ff) >> 0, |
| 338 "uint32_t must be same size as kBytesPerPixel"); | 345 (context.last_event_time & 0x00ff00) >> 8, |
| 339 for (size_t y = 0; y < kHeight; y++) { | 346 (context.last_event_time & 0xff0000) >> 16)); |
| 340 uint32_t* pixel = reinterpret_cast<uint32_t*>(buffer->data + y * kStride); | 347 canvas->translate(SkIntToScalar(kWidth / 2), SkIntToScalar(kHeight / 2)); |
| 341 for (size_t x = 0; x < kWidth; x++) | 348 canvas->rotate(SkDoubleToScalar(context.rotation)); |
| 342 *pixel++ = context.color; | 349 SkRect rect = SkRect::MakeXYWH(-(kWidth / 4.0f), -(kHeight / 4.0f), |
| 343 } | 350 kWidth / 2.0f, kHeight / 2.0f); |
| 351 SkPaint paint; |
| 352 paint.setColor(SK_ColorBLUE); |
| 353 canvas->drawRect(rect, paint); |
| 354 canvas->restore(); |
| 344 | 355 |
| 345 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); | 356 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); |
| 346 buffer->busy = true; | 357 buffer->busy = true; |
| 347 | 358 |
| 348 frame_callback.reset(wl_surface_frame(surface.get())); | 359 frame_callback.reset(wl_surface_frame(surface.get())); |
| 349 wl_callback_add_listener(frame_callback.get(), &frame_listener, &context); | 360 wl_callback_add_listener(frame_callback.get(), &frame_listener, &context); |
| 350 context.throttled = true; | 361 context.frame_callback_pending = true; |
| 351 | 362 |
| 352 wl_surface_commit(surface.get()); | 363 wl_surface_commit(surface.get()); |
| 353 wl_display_flush(display.get()); | 364 wl_display_flush(display.get()); |
| 354 } while (wl_display_dispatch(display.get()) != -1); | 365 } while (wl_display_dispatch(display.get()) != -1); |
| 355 | 366 |
| 356 return 0; | 367 return 0; |
| 357 } | 368 } |
| 358 | 369 |
| 359 } // namespace clients | 370 } // namespace clients |
| 360 } // namespace wayland | 371 } // namespace wayland |
| 361 } // namespace exo | 372 } // namespace exo |
| 362 | 373 |
| 363 int main() { | 374 int main() { |
| 364 return exo::wayland::clients::MotionEventsMain(); | 375 return exo::wayland::clients::MotionEventsMain(); |
| 365 } | 376 } |
| OLD | NEW |