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

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

Issue 2477043002: exo: Add drm support to motion_events. (Closed)
Patch Set: Fix destruction order. 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 | « components/exo/wayland/BUILD.gn ('k') | 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 <fcntl.h>
10 #include <linux-dmabuf-unstable-v1-client-protocol.h>
9 #include <wayland-client-core.h> 11 #include <wayland-client-core.h>
10 #include <wayland-client-protocol.h> 12 #include <wayland-client-protocol.h>
11 13
12 #include <iostream> 14 #include <iostream>
13 #include <vector> 15 #include <vector>
14 16
17 #include "base/at_exit.h"
15 #include "base/command_line.h" 18 #include "base/command_line.h"
16 #include "base/logging.h" 19 #include "base/logging.h"
17 #include "base/macros.h" 20 #include "base/macros.h"
18 #include "base/memory/shared_memory.h" 21 #include "base/memory/shared_memory.h"
19 #include "base/strings/string_number_conversions.h" 22 #include "base/strings/string_number_conversions.h"
20 #include "base/time/time.h" 23 #include "base/time/time.h"
21 #include "third_party/skia/include/core/SkCanvas.h" 24 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkRefCnt.h" 25 #include "third_party/skia/include/core/SkRefCnt.h"
23 #include "third_party/skia/include/core/SkSurface.h" 26 #include "third_party/skia/include/core/SkSurface.h"
27 #include "third_party/skia/include/gpu/GrContext.h"
28 #include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
29 #include "third_party/skia/include/gpu/gl/GrGLInterface.h"
30 #include "ui/gl/gl_bindings.h"
31 #include "ui/gl/gl_context.h"
32 #include "ui/gl/gl_enums.h"
33 #include "ui/gl/gl_surface.h"
34 #include "ui/gl/gl_surface_egl.h"
35 #include "ui/gl/init/gl_factory.h"
36 #include "ui/gl/scoped_make_current.h"
24 37
25 // Convenient macro that is used to define default deleters for wayland object 38 #if defined(OZONE_PLATFORM_GBM)
39 #include <drm_fourcc.h>
40 #include <gbm.h>
41 #endif
42
43 // Convenient macro that is used to define default deleters for object
26 // types allowing them to be used with std::unique_ptr. 44 // types allowing them to be used with std::unique_ptr.
27 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ 45 #define DEFAULT_DELETER(TypeName, DeleteFunction) \
28 namespace std { \ 46 namespace std { \
29 template <> \ 47 template <> \
30 struct default_delete<TypeName> { \ 48 struct default_delete<TypeName> { \
31 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \ 49 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \
32 }; \ 50 }; \
33 } 51 }
34 52
53 #if defined(OZONE_PLATFORM_GBM)
reveman 2016/11/06 22:18:21 nit: move ifdef-ed deleters below other deleters,
Daniele Castagna 2016/11/06 23:58:45 Moved below.
54 DEFAULT_DELETER(gbm_device, gbm_device_destroy)
55 DEFAULT_DELETER(gbm_bo, gbm_bo_destroy)
56 #endif
57
35 DEFAULT_DELETER(wl_display, wl_display_disconnect) 58 DEFAULT_DELETER(wl_display, wl_display_disconnect)
36 DEFAULT_DELETER(wl_compositor, wl_compositor_destroy) 59 DEFAULT_DELETER(wl_compositor, wl_compositor_destroy)
37 DEFAULT_DELETER(wl_shm, wl_shm_destroy) 60 DEFAULT_DELETER(wl_shm, wl_shm_destroy)
38 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy) 61 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy)
39 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy) 62 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy)
40 DEFAULT_DELETER(wl_surface, wl_surface_destroy) 63 DEFAULT_DELETER(wl_surface, wl_surface_destroy)
41 DEFAULT_DELETER(wl_region, wl_region_destroy) 64 DEFAULT_DELETER(wl_region, wl_region_destroy)
42 DEFAULT_DELETER(wl_shell, wl_shell_destroy) 65 DEFAULT_DELETER(wl_shell, wl_shell_destroy)
43 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy) 66 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy)
44 DEFAULT_DELETER(wl_seat, wl_seat_destroy) 67 DEFAULT_DELETER(wl_seat, wl_seat_destroy)
45 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) 68 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy)
46 DEFAULT_DELETER(wl_touch, wl_touch_destroy) 69 DEFAULT_DELETER(wl_touch, wl_touch_destroy)
47 DEFAULT_DELETER(wl_callback, wl_callback_destroy) 70 DEFAULT_DELETER(wl_callback, wl_callback_destroy)
71 DEFAULT_DELETER(zwp_linux_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
72 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
48 73
49 namespace exo { 74 namespace exo {
50 namespace wayland { 75 namespace wayland {
51 namespace clients { 76 namespace clients {
52 namespace { 77 namespace {
53 78
54 // Buffer format. 79 // Buffer format.
55 const int32_t kFormat = WL_SHM_FORMAT_ARGB8888; 80 const int32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
56 const SkColorType kColorType = kBGRA_8888_SkColorType; 81 const SkColorType kColorType = kBGRA_8888_SkColorType;
82 #if defined(OZONE_PLATFORM_GBM)
83 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888;
84 #endif
57 const size_t kBytesPerPixel = 4; 85 const size_t kBytesPerPixel = 4;
58 86
87 #if defined(OZONE_PLATFORM_GBM)
88 // DRI render node path
reveman 2016/11/06 22:18:20 nit: s/path/path./
Daniele Castagna 2016/11/06 23:58:45 Done.
89 const char kDriRenderNode[] = "/dev/dri/renderD128";
90 #endif
91
59 // Number of buffers. 92 // Number of buffers.
60 const size_t kBuffers = 2; 93 const size_t kBuffers = 3;
61 94
62 // Rotation speed (degrees/second). 95 // Rotation speed (degrees/second).
63 const double kRotationSpeed = 360.0; 96 const double kRotationSpeed = 360.0;
64 97
65 // Benchmark interval in seconds. 98 // Benchmark interval in seconds.
66 const int kBenchmarkInterval = 5; 99 const int kBenchmarkInterval = 5;
67 100
68 struct Globals { 101 struct Globals {
69 std::unique_ptr<wl_compositor> compositor; 102 std::unique_ptr<wl_compositor> compositor;
70 std::unique_ptr<wl_shm> shm; 103 std::unique_ptr<wl_shm> shm;
104 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf;
71 std::unique_ptr<wl_shell> shell; 105 std::unique_ptr<wl_shell> shell;
72 std::unique_ptr<wl_seat> seat; 106 std::unique_ptr<wl_seat> seat;
73 }; 107 };
74 108
75 void RegistryHandler(void* data, 109 void RegistryHandler(void* data,
76 wl_registry* registry, 110 wl_registry* registry,
77 uint32_t id, 111 uint32_t id,
78 const char* interface, 112 const char* interface,
79 uint32_t version) { 113 uint32_t version) {
80 Globals* globals = static_cast<Globals*>(data); 114 Globals* globals = static_cast<Globals*>(data);
81 115
82 if (strcmp(interface, "wl_compositor") == 0) { 116 if (strcmp(interface, "wl_compositor") == 0) {
83 globals->compositor.reset(static_cast<wl_compositor*>( 117 globals->compositor.reset(static_cast<wl_compositor*>(
84 wl_registry_bind(registry, id, &wl_compositor_interface, 3))); 118 wl_registry_bind(registry, id, &wl_compositor_interface, 3)));
85 } else if (strcmp(interface, "wl_shm") == 0) { 119 } else if (strcmp(interface, "wl_shm") == 0) {
86 globals->shm.reset(static_cast<wl_shm*>( 120 globals->shm.reset(static_cast<wl_shm*>(
87 wl_registry_bind(registry, id, &wl_shm_interface, 1))); 121 wl_registry_bind(registry, id, &wl_shm_interface, 1)));
88 } else if (strcmp(interface, "wl_shell") == 0) { 122 } else if (strcmp(interface, "wl_shell") == 0) {
89 globals->shell.reset(static_cast<wl_shell*>( 123 globals->shell.reset(static_cast<wl_shell*>(
90 wl_registry_bind(registry, id, &wl_shell_interface, 1))); 124 wl_registry_bind(registry, id, &wl_shell_interface, 1)));
91 } else if (strcmp(interface, "wl_seat") == 0) { 125 } else if (strcmp(interface, "wl_seat") == 0) {
92 globals->seat.reset(static_cast<wl_seat*>( 126 globals->seat.reset(static_cast<wl_seat*>(
93 wl_registry_bind(registry, id, &wl_seat_interface, 5))); 127 wl_registry_bind(registry, id, &wl_seat_interface, 5)));
128 } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
129 globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>(
130 wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1)));
94 } 131 }
95 } 132 }
96 133
97 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { 134 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) {
98 LOG(WARNING) << "Got a registry losing event for " << id; 135 LOG(WARNING) << "Got a registry losing event for " << id;
99 } 136 }
100 137
138 #if defined(OZONE_PLATFORM_GBM)
139 class ScopedTexture {
140 public:
141 ScopedTexture() { glGenTextures(1, &id_); }
142 ~ScopedTexture() { glDeleteTextures(1, &id_); }
143 GLuint id_ = 0;
144 };
145
146 class ScopedEglImage {
147 public:
148 ScopedEglImage(int fd, EGLint khr_image_attrs[]) {
reveman 2016/11/06 22:18:21 fd is unused
Daniele Castagna 2016/11/06 23:58:45 Gone with the ScopedEglImage.
149 image_ = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT,
150 EGL_LINUX_DMA_BUF_EXT,
151 NULL /* no client buffer */, khr_image_attrs);
reveman 2016/11/06 22:18:20 s/NULL/nullptr/
Daniele Castagna 2016/11/06 23:58:45 Done.
152 }
153 ~ScopedEglImage() { eglDestroyImageKHR(eglGetCurrentDisplay(), image_); }
154 EGLImageKHR image_ = 0;
155 };
reveman 2016/11/06 22:18:20 Let's use base::ScopedGeneric for EGLImage and tex
reveman 2016/11/06 22:18:21 Let's use base::ScopedGeneric for EGLImage and tex
Daniele Castagna 2016/11/06 23:58:45 Ok.
156 #endif
157
101 struct Buffer { 158 struct Buffer {
102 std::unique_ptr<wl_buffer> buffer; 159 std::unique_ptr<wl_buffer> buffer;
103 sk_sp<SkSurface> sk_surface; 160 sk_sp<SkSurface> sk_surface;
104 bool busy = false; 161 bool busy = false;
reveman 2016/11/06 22:18:21 nit: move these 3 below
Daniele Castagna 2016/11/06 23:58:45 Moved below.
162 base::SharedMemory shared_memory;
163 std::unique_ptr<wl_shm_pool> shm_pool;
164
reveman 2016/11/06 22:18:20 nit: remove this blankline
Daniele Castagna 2016/11/06 23:58:45 Done.
165 #if defined(OZONE_PLATFORM_GBM)
166 std::unique_ptr<gbm_bo> bo;
167 std::unique_ptr<ScopedEglImage> egl_image;
168 std::unique_ptr<ScopedTexture> texture;
169 #endif
170 std::unique_ptr<zwp_linux_buffer_params_v1> params;
171 sk_sp<SkImage> sk_image;
reveman 2016/11/06 22:18:21 unused
Daniele Castagna 2016/11/06 23:58:45 Removed.
105 }; 172 };
106 173
107 void BufferRelease(void* data, wl_buffer* /* buffer */) { 174 void BufferRelease(void* data, wl_buffer* /* buffer */) {
108 Buffer* buffer = static_cast<Buffer*>(data); 175 Buffer* buffer = static_cast<Buffer*>(data);
109 176
110 buffer->busy = false; 177 buffer->busy = false;
111 } 178 }
112 179
113 using EventTimeStack = std::vector<uint32_t>; 180 using EventTimeStack = std::vector<uint32_t>;
114 181
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 }; 264 };
198 265
199 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { 266 void FrameCallback(void* data, wl_callback* callback, uint32_t time) {
200 Frame* frame = static_cast<Frame*>(data); 267 Frame* frame = static_cast<Frame*>(data);
201 268
202 static uint32_t initial_time = time; 269 static uint32_t initial_time = time;
203 frame->time = time - initial_time; 270 frame->time = time - initial_time;
204 frame->callback_pending = false; 271 frame->callback_pending = false;
205 } 272 }
206 273
274 #if defined(OZONE_PLATFORM_GBM)
275 void LinuxBufferParamsCreated(void* data,
276 zwp_linux_buffer_params_v1* params,
277 wl_buffer* new_buffer) {
278 Buffer* buffer = static_cast<Buffer*>(data);
279 buffer->buffer.reset(new_buffer);
280 }
281
282 void LinuxBufferParamsFailed(void* data, zwp_linux_buffer_params_v1* params) {
283 LOG(ERROR) << "Linux buffer params failed";
284 }
285 #endif
286
207 } // namespace 287 } // namespace
208 288
289 static GrGLFuncPtr egl_get_gl_proc(void* ctx, const char name[]) {
reveman 2016/11/06 22:18:21 nit: remove static, move to unnamed namespace, s/e
Daniele Castagna 2016/11/06 23:58:45 Rmoved this function for a lambda.
290 GrGLFuncPtr ptr = eglGetProcAddress(name);
reveman 2016/11/06 22:18:21 nit: remove temporary variable
reveman 2016/11/06 22:18:21 nit: remove temporary variable
Daniele Castagna 2016/11/06 23:58:45 Done.
291 return ptr;
292 }
293
294 const GrGLInterface* GrGLCreateNativeInterface() {
295 return GrGLAssembleInterface(nullptr, egl_get_gl_proc);
296 }
297
209 class MotionEvents { 298 class MotionEvents {
210 public: 299 public:
211 MotionEvents(size_t width, 300 MotionEvents(size_t width,
212 size_t height, 301 size_t height,
213 int scale, 302 int scale,
214 size_t num_rects, 303 size_t num_rects,
304 bool use_drm,
215 bool fullscreen) 305 bool fullscreen)
216 : width_(width), 306 : width_(width),
217 height_(height), 307 height_(height),
218 scale_(scale), 308 scale_(scale),
219 num_rects_(num_rects), 309 num_rects_(num_rects),
310 use_drm_(use_drm),
220 fullscreen_(fullscreen) {} 311 fullscreen_(fullscreen) {}
221
reveman 2016/11/06 22:18:21 nit: keep this blank line
Daniele Castagna 2016/11/06 23:58:45 Done.
222 // Initialize and run client main loop. 312 // Initialize and run client main loop.
223 int Run(); 313 int Run();
224 314
225 private: 315 private:
316 bool CreateBuffer(Buffer* buffer);
226 size_t stride() const { return width_ * kBytesPerPixel; } 317 size_t stride() const { return width_ * kBytesPerPixel; }
227 size_t buffer_size() const { return stride() * height_; } 318 size_t buffer_size() const { return stride() * height_; }
228 319
229 const size_t width_; 320 const size_t width_;
230 const size_t height_; 321 const size_t height_;
231 const int scale_; 322 const int scale_;
232 const size_t num_rects_; 323 const size_t num_rects_;
324 const bool use_drm_;
233 const bool fullscreen_; 325 const bool fullscreen_;
234 326
327 Globals globals_;
328 std::unique_ptr<wl_display> display_;
329
330 #if defined(OZONE_PLATFORM_GBM)
331 base::ScopedFD drm_fd_;
332 std::unique_ptr<gbm_device> device_;
333 #endif
334
335 scoped_refptr<gl::GLSurface> gl_surface_;
336 scoped_refptr<gl::GLContext> gl_context_;
337 std::unique_ptr<ui::ScopedMakeCurrent> make_current_;
338
339 Buffer buffers_[kBuffers];
340 sk_sp<GrContext> gr_context_;
reveman 2016/11/06 22:18:21 nit: blankline after this
Daniele Castagna 2016/11/06 23:58:45 Done.
235 DISALLOW_COPY_AND_ASSIGN(MotionEvents); 341 DISALLOW_COPY_AND_ASSIGN(MotionEvents);
236 }; 342 };
237 343
238 int MotionEvents::Run() { 344 int MotionEvents::Run() {
239 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); 345 display_.reset(wl_display_connect(nullptr));
240 if (!display) { 346 if (!display_) {
241 LOG(ERROR) << "wl_display_connect failed"; 347 LOG(ERROR) << "wl_display_connect failed";
242 return 1; 348 return 1;
243 } 349 }
244 350
351 bool gl_initialized = gl::init::InitializeGLOneOff();
352 DCHECK(gl_initialized);
353 gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
354 gl_context_ =
355 gl::init::CreateGLContext(nullptr, // share_group
356 gl_surface_.get(), gl::PreferIntegratedGpu);
357
358 make_current_.reset(
359 new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get()));
245 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; 360 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
246 361
247 Globals globals; 362 wl_registry* registry = wl_display_get_registry(display_.get());
248 wl_registry* registry = wl_display_get_registry(display.get()); 363 wl_registry_add_listener(registry, &registry_listener, &globals_);
249 wl_registry_add_listener(registry, &registry_listener, &globals);
250 364
251 wl_display_roundtrip(display.get()); 365 wl_display_roundtrip(display_.get());
252 366
253 if (!globals.compositor) { 367 if (!globals_.compositor) {
254 LOG(ERROR) << "Can't find compositor interface"; 368 LOG(ERROR) << "Can't find compositor interface";
255 return 1; 369 return 1;
256 } 370 }
257 if (!globals.shm) { 371 if (!globals_.shm) {
258 LOG(ERROR) << "Can't find shm interface"; 372 LOG(ERROR) << "Can't find shm interface";
259 return 1; 373 return 1;
260 } 374 }
261 if (!globals.shell) { 375 if (use_drm_ && !globals_.linux_dmabuf) {
376 LOG(ERROR) << "Can't find linux_dmabuf interface";
377 return 1;
378 }
379 if (!globals_.shell) {
262 LOG(ERROR) << "Can't find shell interface"; 380 LOG(ERROR) << "Can't find shell interface";
263 return 1; 381 return 1;
264 } 382 }
265 if (!globals.seat) { 383 if (!globals_.seat) {
266 LOG(ERROR) << "Can't find seat interface"; 384 LOG(ERROR) << "Can't find seat interface";
267 return 1; 385 return 1;
268 } 386 }
269 387
388 #if defined(OZONE_PLATFORM_GBM)
389 drm_fd_.reset(open(kDriRenderNode, O_RDWR));
390 if (drm_fd_.get() < 0) {
391 LOG(ERROR) << "Can't open drm device '" << kDriRenderNode << ";";
reveman 2016/11/06 22:18:20 s/";"/"'"/
Daniele Castagna 2016/11/06 23:58:45 Done.
392 return 1;
393 }
394
395 device_.reset(gbm_create_device(drm_fd_.get()));
396 if (!device_) {
397 LOG(ERROR) << "Can't create gbm device";
398 return 1;
399 }
400 sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface());
401 DCHECK(native_interface);
402 gr_context_ = sk_sp<GrContext>(GrContext::Create(
403 kOpenGL_GrBackend,
404 reinterpret_cast<GrBackendContext>(native_interface.get())));
405 DCHECK(gr_context_);
406 #endif
407
270 wl_buffer_listener buffer_listener = {BufferRelease}; 408 wl_buffer_listener buffer_listener = {BufferRelease};
271 409
272 Buffer buffers[kBuffers];
273 base::SharedMemory shared_memory;
274 shared_memory.CreateAndMapAnonymous(buffer_size() * kBuffers);
275 std::unique_ptr<wl_shm_pool> shm_pool(
276 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd,
277 shared_memory.requested_size()));
278 for (size_t i = 0; i < kBuffers; ++i) { 410 for (size_t i = 0; i < kBuffers; ++i) {
279 buffers[i].buffer.reset(static_cast<wl_buffer*>( 411 if (!CreateBuffer(&buffers_[i]))
280 wl_shm_pool_create_buffer(shm_pool.get(), i * buffer_size(), width_,
281 height_, stride(), kFormat)));
282 if (!buffers[i].buffer) {
283 LOG(ERROR) << "Can't create buffer";
284 return 1; 412 return 1;
285 } 413 }
286 buffers[i].sk_surface = SkSurface::MakeRasterDirect( 414 wl_display_roundtrip(display_.get());
287 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType), 415 for (size_t i = 0; i < kBuffers; ++i) {
288 static_cast<uint8_t*>(shared_memory.memory()) + buffer_size() * i, 416 if (!buffers_[i].buffer)
289 stride());
290 if (!buffers[i].sk_surface) {
291 LOG(ERROR) << "Can't create SkSurface";
292 return 1; 417 return 1;
293 } 418
294 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, 419 wl_buffer_add_listener(buffers_[i].buffer.get(), &buffer_listener,
295 &buffers[i]); 420 &buffers_[i]);
296 } 421 }
297 422
298 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( 423 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>(
299 wl_compositor_create_surface(globals.compositor.get()))); 424 wl_compositor_create_surface(globals_.compositor.get())));
300 if (!surface) { 425 if (!surface) {
301 LOG(ERROR) << "Can't create surface"; 426 LOG(ERROR) << "Can't create surface";
302 return 1; 427 return 1;
303 } 428 }
304 429
305 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>( 430 std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>(
306 wl_compositor_create_region(globals.compositor.get()))); 431 wl_compositor_create_region(globals_.compositor.get())));
307 if (!opaque_region) { 432 if (!opaque_region) {
308 LOG(ERROR) << "Can't create region"; 433 LOG(ERROR) << "Can't create region";
309 return 1; 434 return 1;
310 } 435 }
311 436
312 wl_region_add(opaque_region.get(), 0, 0, width_, height_); 437 wl_region_add(opaque_region.get(), 0, 0, width_, height_);
313 wl_surface_set_opaque_region(surface.get(), opaque_region.get()); 438 wl_surface_set_opaque_region(surface.get(), opaque_region.get());
314 439
315 std::unique_ptr<wl_shell_surface> shell_surface( 440 std::unique_ptr<wl_shell_surface> shell_surface(
316 static_cast<wl_shell_surface*>( 441 static_cast<wl_shell_surface*>(
317 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); 442 wl_shell_get_shell_surface(globals_.shell.get(), surface.get())));
318 if (!shell_surface) { 443 if (!shell_surface) {
319 LOG(ERROR) << "Can't get shell surface"; 444 LOG(ERROR) << "Can't get shell surface";
320 return 1; 445 return 1;
321 } 446 }
322 447
323 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); 448 wl_shell_surface_set_title(shell_surface.get(), "Test Client");
reveman 2016/11/06 22:18:20 nit: while here, can you change this to "Motion Ev
reveman 2016/11/06 22:18:21 nit: while here, can you change this to "Motion Ev
reveman 2016/11/06 22:18:21 while here, "Motion Event Client" and maybe add a
Daniele Castagna 2016/11/06 23:58:45 Done.
449
324 if (fullscreen_) { 450 if (fullscreen_) {
325 wl_shell_surface_set_fullscreen(shell_surface.get(), 451 wl_shell_surface_set_fullscreen(shell_surface.get(),
326 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 452 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
327 0, nullptr); 453 0, nullptr);
328 } else { 454 } else {
329 wl_shell_surface_set_toplevel(shell_surface.get()); 455 wl_shell_surface_set_toplevel(shell_surface.get());
330 } 456 }
331 457
332 EventTimeStack event_times; 458 EventTimeStack event_times;
333 459
334 std::unique_ptr<wl_pointer> pointer( 460 std::unique_ptr<wl_pointer> pointer(
335 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); 461 static_cast<wl_pointer*>(wl_seat_get_pointer(globals_.seat.get())));
336 if (!pointer) { 462 if (!pointer) {
337 LOG(ERROR) << "Can't get pointer"; 463 LOG(ERROR) << "Can't get pointer";
338 return 1; 464 return 1;
339 } 465 }
340 466
341 wl_pointer_listener pointer_listener = { 467 wl_pointer_listener pointer_listener = {
342 PointerEnter, PointerLeave, PointerMotion, 468 PointerEnter, PointerLeave, PointerMotion,
343 PointerButton, PointerAxis, PointerFrame, 469 PointerButton, PointerAxis, PointerFrame,
344 PointerAxisSource, PointerAxisStop, PointerDiscrete}; 470 PointerAxisSource, PointerAxisStop, PointerDiscrete};
345 wl_pointer_add_listener(pointer.get(), &pointer_listener, &event_times); 471 wl_pointer_add_listener(pointer.get(), &pointer_listener, &event_times);
346 472
347 std::unique_ptr<wl_touch> touch( 473 std::unique_ptr<wl_touch> touch(
348 static_cast<wl_touch*>(wl_seat_get_touch(globals.seat.get()))); 474 static_cast<wl_touch*>(wl_seat_get_touch(globals_.seat.get())));
349 if (!touch) { 475 if (!touch) {
350 LOG(ERROR) << "Can't get touch"; 476 LOG(ERROR) << "Can't get touch";
351 return 1; 477 return 1;
352 } 478 }
353 479
354 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion, 480 wl_touch_listener touch_listener = {TouchDown, TouchUp, TouchMotion,
355 TouchFrame, TouchCancel}; 481 TouchFrame, TouchCancel};
356 wl_touch_add_listener(touch.get(), &touch_listener, &event_times); 482 wl_touch_add_listener(touch.get(), &touch_listener, &event_times);
357 483
358 Frame frame; 484 Frame frame;
359 std::unique_ptr<wl_callback> frame_callback; 485 std::unique_ptr<wl_callback> frame_callback;
360 wl_callback_listener frame_listener = {FrameCallback}; 486 wl_callback_listener frame_listener = {FrameCallback};
361 487
362 uint32_t frames = 0; 488 uint32_t frames = 0;
363 base::TimeTicks benchmark_time = base::TimeTicks::Now(); 489 base::TimeTicks benchmark_time = base::TimeTicks::Now();
364 base::TimeDelta benchmark_interval = 490 base::TimeDelta benchmark_interval =
365 base::TimeDelta::FromSeconds(kBenchmarkInterval); 491 base::TimeDelta::FromSeconds(kBenchmarkInterval);
366 492
367 do { 493 do {
368 if (frame.callback_pending) 494 if (frame.callback_pending)
369 continue; 495 continue;
370 496
371 Buffer* buffer = 497 Buffer* buffer =
372 std::find_if(std::begin(buffers), std::end(buffers), 498 std::find_if(std::begin(buffers_), std::end(buffers_),
373 [](const Buffer& buffer) { return !buffer.busy; }); 499 [](const Buffer& buffer) { return !buffer.busy; });
374 if (buffer == std::end(buffers)) 500 if (buffer == std::end(buffers_))
375 continue; 501 continue;
376 502
377 base::TimeTicks current_time = base::TimeTicks::Now(); 503 base::TimeTicks current_time = base::TimeTicks::Now();
378 if ((current_time - benchmark_time) > benchmark_interval) { 504 if ((current_time - benchmark_time) > benchmark_interval) {
379 std::cout << frames << " frames in " << benchmark_interval.InSeconds() 505 std::cout << frames << " frames in " << benchmark_interval.InSeconds()
380 << " seconds: " 506 << " seconds: "
381 << static_cast<double>(frames) / benchmark_interval.InSeconds() 507 << static_cast<double>(frames) / benchmark_interval.InSeconds()
382 << " fps" << std::endl; 508 << " fps" << std::endl;
383 benchmark_time = current_time; 509 benchmark_time = current_time;
384 frames = 0; 510 frames = 0;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 canvas->translate(half_width, half_height); 544 canvas->translate(half_width, half_height);
419 for (size_t i = 0; i < num_rects_; ++i) { 545 for (size_t i = 0; i < num_rects_; ++i) {
420 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN, 546 const SkColor kColors[] = {SK_ColorBLUE, SK_ColorGREEN,
421 SK_ColorRED, SK_ColorYELLOW, 547 SK_ColorRED, SK_ColorYELLOW,
422 SK_ColorCYAN, SK_ColorMAGENTA}; 548 SK_ColorCYAN, SK_ColorMAGENTA};
423 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0)); 549 paint.setColor(SkColorSetA(kColors[i % arraysize(kColors)], 0xA0));
424 canvas->rotate(rotation / num_rects_); 550 canvas->rotate(rotation / num_rects_);
425 canvas->drawIRect(rect, paint); 551 canvas->drawIRect(rect, paint);
426 } 552 }
427 canvas->restore(); 553 canvas->restore();
428 554 if (gr_context_)
555 gr_context_->flush();
556 glFinish();
reveman 2016/11/06 22:18:21 maybe move this into the if-scope as it's a bit we
Daniele Castagna 2016/11/06 23:58:45 Done.
429 wl_surface_set_buffer_scale(surface.get(), scale_); 557 wl_surface_set_buffer_scale(surface.get(), scale_);
430 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); 558 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
431 buffer->busy = true; 559 buffer->busy = true;
432 560
433 frame_callback.reset(wl_surface_frame(surface.get())); 561 frame_callback.reset(wl_surface_frame(surface.get()));
434 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame); 562 wl_callback_add_listener(frame_callback.get(), &frame_listener, &frame);
435 frame.callback_pending = true; 563 frame.callback_pending = true;
436 564
437 ++frames; 565 ++frames;
438 566
439 wl_surface_commit(surface.get()); 567 wl_surface_commit(surface.get());
440 } while (wl_display_dispatch(display.get()) != -1); 568 } while (wl_display_dispatch(display_.get()) != -1);
441 569
442 return 0; 570 return 0;
443 } 571 }
444 572
573 bool MotionEvents::CreateBuffer(Buffer* buffer) {
574 #if defined(OZONE_PLATFORM_GBM)
575 if (use_drm_) {
576 buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat,
577 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING));
578 if (!buffer->bo) {
579 LOG(ERROR) << "Can't create gbm buffer.";
580 return false;
581 }
582 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0));
583 static const zwp_linux_buffer_params_v1_listener params_listener = {
584 LinuxBufferParamsCreated, LinuxBufferParamsFailed};
585
586 buffer->params.reset(
587 zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get()));
588 zwp_linux_buffer_params_v1_add_listener(buffer->params.get(),
589 &params_listener, buffer);
590 zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0,
591 stride(), 0, 0);
592 zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_,
593 kDrmFormat, 0);
594
595 EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT,
596 fd.get(),
597 EGL_WIDTH,
598 width_,
599 EGL_HEIGHT,
600 height_,
601 EGL_LINUX_DRM_FOURCC_EXT,
602 kDrmFormat,
603 EGL_DMA_BUF_PLANE0_PITCH_EXT,
604 stride(),
605 EGL_DMA_BUF_PLANE0_OFFSET_EXT,
606 0,
607 EGL_NONE};
608 buffer->egl_image.reset(new ScopedEglImage(fd.get(), khr_image_attrs));
609 buffer->texture.reset(new ScopedTexture());
610 glBindTexture(GL_TEXTURE_2D, buffer->texture->id_);
611 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width_, height_, 0, GL_RGBA,
Daniele Castagna 2016/11/06 23:58:45 Removed the TexImage2D that was useless.
612 GL_UNSIGNED_BYTE, nullptr);
613 glEGLImageTargetTexture2DOES(
614 GL_TEXTURE_2D, static_cast<GLeglImageOES>(buffer->egl_image->image_));
615 glBindTexture(GL_TEXTURE_2D, 0);
616
617 GrGLTextureInfo texture_info;
618 texture_info.fID = buffer->texture->id_;
619 texture_info.fTarget = GL_TEXTURE_2D;
620 GrBackendTextureDesc desc;
621 desc.fFlags = kRenderTarget_GrBackendTextureFlag;
622 desc.fWidth = width_;
623 desc.fHeight = height_;
624 desc.fConfig = kBGRA_8888_GrPixelConfig;
625 desc.fOrigin = kTopLeft_GrSurfaceOrigin;
626 desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info);
627
628 buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
629 gr_context_.get(), desc, nullptr);
630 DCHECK(buffer->sk_surface);
631 return true;
632 }
633 #endif
634 buffer->shared_memory.CreateAndMapAnonymous(buffer_size());
635 buffer->shm_pool.reset(
636 wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd,
637 buffer->shared_memory.requested_size()));
638
639 buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer(
640 buffer->shm_pool.get(), 0, width_, height_, stride(), kShmFormat)));
641 if (!buffer->buffer) {
642 LOG(ERROR) << "Can't create buffer";
643 return false;
644 }
645
646 buffer->sk_surface = SkSurface::MakeRasterDirect(
647 SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType),
648 static_cast<uint8_t*>(buffer->shared_memory.memory()), stride());
649 return true;
650 }
651
445 } // namespace clients 652 } // namespace clients
446 } // namespace wayland 653 } // namespace wayland
447 } // namespace exo 654 } // namespace exo
448 655
449 namespace switches { 656 namespace switches {
450 657
451 // Specifies the client buffer size. 658 // Specifies the client buffer size.
452 const char kSize[] = "size"; 659 const char kSize[] = "size";
453 660
454 // Specifies the client scale factor (ie. number of physical pixels per DIP). 661 // Specifies the client scale factor (ie. number of physical pixels per DIP).
455 const char kScale[] = "scale"; 662 const char kScale[] = "scale";
456 663
457 // Specifies the number of rotating rects to draw. 664 // Specifies the number of rotating rects to draw.
458 const char kNumRects[] = "num-rects"; 665 const char kNumRects[] = "num-rects";
459 666
667 // Use drm buffer instead of shared memory.
668 const char kUseDrm[] = "use-drm";
669
460 // Specifies if client should be fullscreen. 670 // Specifies if client should be fullscreen.
461 const char kFullscreen[] = "fullscreen"; 671 const char kFullscreen[] = "fullscreen";
462 672
463 } // namespace switches 673 } // namespace switches
464 674
465 int main(int argc, char* argv[]) { 675 int main(int argc, char* argv[]) {
466 base::CommandLine command_line(argc, argv); 676 base::AtExitManager exit_manager;
677 base::CommandLine::Init(argc, argv);
678 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
467 679
468 int width = 256; 680 int width = 256;
469 int height = 256; 681 int height = 256;
470 if (command_line.HasSwitch(switches::kSize)) { 682 if (command_line->HasSwitch(switches::kSize)) {
471 std::string size_str = command_line.GetSwitchValueASCII(switches::kSize); 683 std::string size_str = command_line->GetSwitchValueASCII(switches::kSize);
472 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) { 684 if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) {
473 LOG(ERROR) << "Invalid value for " << switches::kSize; 685 LOG(ERROR) << "Invalid value for " << switches::kSize;
474 return 1; 686 return 1;
475 } 687 }
476 } 688 }
477 689
478 int scale = 1; 690 int scale = 1;
479 if (command_line.HasSwitch(switches::kScale) && 691 if (command_line->HasSwitch(switches::kScale) &&
480 !base::StringToInt(command_line.GetSwitchValueASCII(switches::kScale), 692 !base::StringToInt(command_line->GetSwitchValueASCII(switches::kScale),
481 &scale)) { 693 &scale)) {
482 LOG(ERROR) << "Invalid value for " << switches::kScale; 694 LOG(ERROR) << "Invalid value for " << switches::kScale;
483 return 1; 695 return 1;
484 } 696 }
485 697
486 size_t num_rects = 1; 698 size_t num_rects = 1;
487 if (command_line.HasSwitch(switches::kNumRects) && 699 if (command_line->HasSwitch(switches::kNumRects) &&
488 !base::StringToSizeT( 700 !base::StringToSizeT(
489 command_line.GetSwitchValueASCII(switches::kNumRects), &num_rects)) { 701 command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) {
490 LOG(ERROR) << "Invalid value for " << switches::kNumRects; 702 LOG(ERROR) << "Invalid value for " << switches::kNumRects;
491 return 1; 703 return 1;
492 } 704 }
493 705
494 bool fullscreen = command_line.HasSwitch(switches::kFullscreen); 706 bool use_drm = command_line->HasSwitch("use-drm");
707 bool fullscreen = command_line->HasSwitch(switches::kFullscreen);
495 708
496 exo::wayland::clients::MotionEvents client(width, height, scale, num_rects, 709 exo::wayland::clients::MotionEvents client(width, height, scale, num_rects,
497 fullscreen); 710 use_drm, fullscreen);
498 return client.Run(); 711 return client.Run();
499 } 712 }
OLDNEW
« no previous file with comments | « components/exo/wayland/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698