Chromium Code Reviews| 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 <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 |
| 14 #include "base/at_exit.h" | |
| 15 #include "base/command_line.h" | |
| 12 #include "base/logging.h" | 16 #include "base/logging.h" |
| 13 #include "base/memory/shared_memory.h" | 17 #include "base/memory/shared_memory.h" |
| 18 #include "ui/gl/gl_bindings.h" | |
| 19 #include "ui/gl/gl_context.h" | |
| 20 #include "ui/gl/gl_enums.h" | |
| 21 #include "ui/gl/gl_surface.h" | |
| 22 #include "ui/gl/gl_surface_egl.h" | |
| 23 #include "ui/gl/init/gl_factory.h" | |
| 24 #include "ui/gl/scoped_make_current.h" | |
| 25 | |
| 26 #if defined(OZONE_PLATFORM_GBM) | |
| 27 #include <drm_fourcc.h> | |
| 28 #include <gbm.h> | |
| 29 #endif | |
| 14 | 30 |
| 15 // Convenient macro that is used to define default deleters for wayland object | 31 // Convenient macro that is used to define default deleters for wayland object |
| 16 // types allowing them to be used with std::unique_ptr. | 32 // types allowing them to be used with std::unique_ptr. |
| 17 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ | 33 #define DEFAULT_DELETER(TypeName, DeleteFunction) \ |
| 18 namespace std { \ | 34 namespace std { \ |
| 19 template <> \ | 35 template <> \ |
| 20 struct default_delete<TypeName> { \ | 36 struct default_delete<TypeName> { \ |
| 21 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \ | 37 void operator()(TypeName* ptr) { DeleteFunction(ptr); } \ |
| 22 }; \ | 38 }; \ |
| 23 } | 39 } |
| 24 | 40 |
| 41 #if defined(OZONE_PLATFORM_GBM) | |
| 42 DEFAULT_DELETER(gbm_device, gbm_device_destroy) | |
| 43 DEFAULT_DELETER(gbm_bo, gbm_bo_destroy) | |
| 44 #endif | |
| 45 | |
| 25 DEFAULT_DELETER(wl_display, wl_display_disconnect) | 46 DEFAULT_DELETER(wl_display, wl_display_disconnect) |
| 26 DEFAULT_DELETER(wl_compositor, wl_compositor_destroy) | 47 DEFAULT_DELETER(wl_compositor, wl_compositor_destroy) |
| 27 DEFAULT_DELETER(wl_shm, wl_shm_destroy) | 48 DEFAULT_DELETER(wl_shm, wl_shm_destroy) |
| 28 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy) | 49 DEFAULT_DELETER(wl_shm_pool, wl_shm_pool_destroy) |
| 29 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy) | 50 DEFAULT_DELETER(wl_buffer, wl_buffer_destroy) |
| 30 DEFAULT_DELETER(wl_surface, wl_surface_destroy) | 51 DEFAULT_DELETER(wl_surface, wl_surface_destroy) |
| 31 DEFAULT_DELETER(wl_region, wl_region_destroy) | 52 DEFAULT_DELETER(wl_region, wl_region_destroy) |
| 32 DEFAULT_DELETER(wl_shell, wl_shell_destroy) | 53 DEFAULT_DELETER(wl_shell, wl_shell_destroy) |
| 33 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy) | 54 DEFAULT_DELETER(wl_shell_surface, wl_shell_surface_destroy) |
| 34 DEFAULT_DELETER(wl_seat, wl_seat_destroy) | 55 DEFAULT_DELETER(wl_seat, wl_seat_destroy) |
| 35 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) | 56 DEFAULT_DELETER(wl_pointer, wl_pointer_destroy) |
| 36 DEFAULT_DELETER(wl_touch, wl_touch_destroy) | 57 DEFAULT_DELETER(wl_touch, wl_touch_destroy) |
| 37 DEFAULT_DELETER(wl_callback, wl_callback_destroy) | 58 DEFAULT_DELETER(wl_callback, wl_callback_destroy) |
| 59 DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy) | |
| 38 | 60 |
| 39 namespace exo { | 61 namespace exo { |
| 40 namespace wayland { | 62 namespace wayland { |
| 41 namespace clients { | 63 namespace clients { |
| 42 namespace { | 64 namespace { |
| 43 | 65 |
| 44 // Window size. | 66 // Window size. |
| 45 const size_t kWidth = 256; | 67 const size_t kWidth = 256; |
| 46 const size_t kHeight = 256; | 68 const size_t kHeight = 256; |
| 47 | 69 |
| 48 // Buffer format. | 70 // Buffer format. |
| 49 const int32_t kFormat = WL_SHM_FORMAT_ABGR8888; | 71 const int32_t kShmFormat = WL_SHM_FORMAT_ABGR8888; |
| 72 #if defined(OZONE_PLATFORM_GBM) | |
| 73 const int32_t kDrmFormat = DRM_FORMAT_ABGR8888; | |
| 74 #endif | |
| 50 const size_t kBytesPerPixel = 4; | 75 const size_t kBytesPerPixel = 4; |
| 51 | 76 |
| 52 // Number of buffers. | 77 // Number of buffers. |
| 53 const size_t kBuffers = 2; | 78 const size_t kBuffers = 2; |
| 54 | 79 |
| 55 // Helper constants. | 80 // Helper constants. |
| 56 const size_t kStride = kWidth * kBytesPerPixel; | 81 const size_t kStride = kWidth * kBytesPerPixel; |
| 57 const size_t kBufferSize = kHeight * kStride; | 82 const size_t kBufferSize = kHeight * kStride; |
| 58 const size_t kMemorySize = kBufferSize * kBuffers; | 83 const size_t kMemorySize = kBufferSize * kBuffers; |
| 59 | 84 |
| 60 struct Globals { | 85 struct Globals { |
| 61 std::unique_ptr<wl_compositor> compositor; | 86 std::unique_ptr<wl_compositor> compositor; |
| 62 std::unique_ptr<wl_shm> shm; | 87 std::unique_ptr<wl_shm> shm; |
| 88 std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf; | |
| 63 std::unique_ptr<wl_shell> shell; | 89 std::unique_ptr<wl_shell> shell; |
| 64 std::unique_ptr<wl_seat> seat; | 90 std::unique_ptr<wl_seat> seat; |
| 65 }; | 91 }; |
| 66 | 92 |
| 67 void RegistryHandler(void* data, | 93 void RegistryHandler(void* data, |
| 68 wl_registry* registry, | 94 wl_registry* registry, |
| 69 uint32_t id, | 95 uint32_t id, |
| 70 const char* interface, | 96 const char* interface, |
| 71 uint32_t version) { | 97 uint32_t version) { |
| 72 Globals* globals = static_cast<Globals*>(data); | 98 Globals* globals = static_cast<Globals*>(data); |
| 73 | 99 |
| 74 if (strcmp(interface, "wl_compositor") == 0) { | 100 if (strcmp(interface, "wl_compositor") == 0) { |
| 75 globals->compositor.reset(static_cast<wl_compositor*>( | 101 globals->compositor.reset(static_cast<wl_compositor*>( |
| 76 wl_registry_bind(registry, id, &wl_compositor_interface, 3))); | 102 wl_registry_bind(registry, id, &wl_compositor_interface, 3))); |
| 77 } else if (strcmp(interface, "wl_shm") == 0) { | 103 } else if (strcmp(interface, "wl_shm") == 0) { |
| 78 globals->shm.reset(static_cast<wl_shm*>( | 104 globals->shm.reset(static_cast<wl_shm*>( |
| 79 wl_registry_bind(registry, id, &wl_shm_interface, 1))); | 105 wl_registry_bind(registry, id, &wl_shm_interface, 1))); |
| 80 } else if (strcmp(interface, "wl_shell") == 0) { | 106 } else if (strcmp(interface, "wl_shell") == 0) { |
| 81 globals->shell.reset(static_cast<wl_shell*>( | 107 globals->shell.reset(static_cast<wl_shell*>( |
| 82 wl_registry_bind(registry, id, &wl_shell_interface, 1))); | 108 wl_registry_bind(registry, id, &wl_shell_interface, 1))); |
| 83 } else if (strcmp(interface, "wl_seat") == 0) { | 109 } else if (strcmp(interface, "wl_seat") == 0) { |
| 84 globals->seat.reset(static_cast<wl_seat*>( | 110 globals->seat.reset(static_cast<wl_seat*>( |
| 85 wl_registry_bind(registry, id, &wl_seat_interface, 5))); | 111 wl_registry_bind(registry, id, &wl_seat_interface, 5))); |
| 112 } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) { | |
| 113 globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>( | |
| 114 wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1))); | |
| 86 } | 115 } |
| 87 } | 116 } |
| 88 | 117 |
| 89 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { | 118 void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { |
| 90 LOG(WARNING) << "Got a registry losing event for " << id; | 119 LOG(WARNING) << "Got a registry losing event for " << id; |
| 91 } | 120 } |
| 92 | 121 |
| 93 struct BufferState { | 122 struct BufferState { |
| 94 std::unique_ptr<wl_buffer> buffer; | 123 std::unique_ptr<wl_buffer> buffer; |
| 95 uint8_t* data = nullptr; | 124 uint8_t* data = nullptr; |
| 96 bool busy = false; | 125 bool busy = false; |
| 126 // dmabuf | |
| 127 #if defined(OZONE_PLATFORM_GBM) | |
| 128 std::unique_ptr<gbm_bo> bo = nullptr; | |
|
reveman
2016/11/04 22:34:14
remove " = nullptr"
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 129 #endif | |
| 130 EGLImageKHR egl_image = 0; | |
|
reveman
2016/11/04 22:34:15
can we have a unique_ptr for this too?
Daniele Castagna
2016/11/05 21:05:11
Added a ScopedEglImage that is slightly nicer than
| |
| 131 unsigned gl_texture = 0; | |
|
reveman
2016/11/04 22:34:14
s/gl_texture/texture/
can we use GLuint instead o
Daniele Castagna
2016/11/05 21:05:11
Done.
| |
| 132 unsigned fb = 0; | |
|
reveman
2016/11/04 22:34:14
s/fb/framebuffer/
and GLuint + ScopedFramebuffer
Daniele Castagna
2016/11/05 21:05:12
This is gone now that we're using skia.
| |
| 97 }; | 133 }; |
| 98 | 134 |
| 99 void BufferRelease(void* data, wl_buffer* buffer) { | 135 void BufferRelease(void* data, wl_buffer* buffer) { |
| 100 BufferState* state = static_cast<BufferState*>(data); | 136 BufferState* state = static_cast<BufferState*>(data); |
| 101 | 137 |
| 102 state->busy = false; | 138 state->busy = false; |
| 103 } | 139 } |
| 104 | 140 |
| 105 struct MainLoopContext { | 141 struct MainLoopContext { |
| 106 uint32_t color = 0xffffffff; | 142 uint32_t color = 0xffffffff; |
| 107 bool needs_redraw = true; | 143 bool needs_redraw = true; |
| 108 bool shutdown = false; | 144 bool shutdown = false; |
| 109 bool throttled = false; | 145 bool throttled = false; |
| 146 base::SharedMemory shared_memory; | |
| 147 std::unique_ptr<wl_shm_pool> shm_pool; | |
| 148 | |
| 149 #if defined(OZONE_PLATFORM_GBM) | |
| 150 std::unique_ptr<gbm_device> device; | |
| 151 #endif | |
| 110 }; | 152 }; |
| 111 | 153 |
| 112 void PointerEnter(void* data, | 154 void PointerEnter(void* data, |
| 113 wl_pointer* pointer, | 155 wl_pointer* pointer, |
| 114 uint32_t serial, | 156 uint32_t serial, |
| 115 wl_surface* surface, | 157 wl_surface* surface, |
| 116 wl_fixed_t x, | 158 wl_fixed_t x, |
| 117 wl_fixed_t y) {} | 159 wl_fixed_t y) {} |
| 118 | 160 |
| 119 void PointerLeave(void* data, | 161 void PointerLeave(void* data, |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 196 void TouchFrame(void* data, wl_touch* touch) {} | 238 void TouchFrame(void* data, wl_touch* touch) {} |
| 197 | 239 |
| 198 void TouchCancel(void* data, wl_touch* touch) {} | 240 void TouchCancel(void* data, wl_touch* touch) {} |
| 199 | 241 |
| 200 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { | 242 void FrameCallback(void* data, wl_callback* callback, uint32_t time) { |
| 201 MainLoopContext* context = static_cast<MainLoopContext*>(data); | 243 MainLoopContext* context = static_cast<MainLoopContext*>(data); |
| 202 | 244 |
| 203 context->throttled = false; | 245 context->throttled = false; |
| 204 } | 246 } |
| 205 | 247 |
| 248 #if defined(OZONE_PLATFORM_GBM) | |
| 249 void LinuxBufferParamsCreated(void* data, | |
| 250 zwp_linux_buffer_params_v1* params, | |
| 251 wl_buffer* buffer) { | |
| 252 std::unique_ptr<wl_buffer>* out_buffer = | |
| 253 static_cast<std::unique_ptr<wl_buffer>*>(data); | |
|
reveman
2016/11/04 22:34:14
nit: maybe cleaner to just pass BufferState* as da
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 254 out_buffer->reset(buffer); | |
| 255 } | |
| 256 | |
| 257 void LinuxBufferParamsFailed(void* data, zwp_linux_buffer_params_v1* params) { | |
| 258 LOG(ERROR) << "Linux buffer params failed callback"; | |
|
reveman
2016/11/04 22:34:14
nit: s/failed callback/failed/
Daniele Castagna
2016/11/05 21:05:11
Done.
| |
| 259 } | |
| 260 #endif | |
| 261 | |
| 262 bool CreateBuffer(MainLoopContext* context, | |
| 263 Globals* globals, | |
| 264 wl_display* display, | |
| 265 size_t index, | |
| 266 BufferState* buffer_state) { | |
| 267 if (base::CommandLine::ForCurrentProcess()->HasSwitch("linux_dmabuf_v1")) { | |
|
reveman
2016/11/04 22:34:14
s/linux_dmabuf_v1/use-drm/ and move the string to
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 268 #if defined(OZONE_PLATFORM_GBM) | |
|
reveman
2016/11/04 22:34:14
move the switch check into this ifdef and just sil
Daniele Castagna
2016/11/05 21:05:11
Done.
| |
| 269 buffer_state->bo.reset( | |
| 270 gbm_bo_create(context->device.get(), kWidth, kHeight, kDrmFormat, | |
| 271 GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING)); | |
| 272 if (!buffer_state->bo) { | |
| 273 LOG(ERROR) << "Can't create gbm buffer."; | |
| 274 return false; | |
| 275 } | |
| 276 base::ScopedFD fd(gbm_bo_get_plane_fd(buffer_state->bo.get(), 0)); | |
| 277 zwp_linux_buffer_params_v1_listener params_listener = { | |
| 278 LinuxBufferParamsCreated, LinuxBufferParamsFailed}; | |
| 279 | |
| 280 zwp_linux_buffer_params_v1* params = | |
|
reveman
2016/11/04 22:34:14
are we leaking this object?
Daniele Castagna
2016/11/05 21:05:11
Fixed.
| |
| 281 zwp_linux_dmabuf_v1_create_params(globals->linux_dmabuf.get()); | |
| 282 zwp_linux_buffer_params_v1_add_listener(params, ¶ms_listener, | |
| 283 &buffer_state->buffer); | |
| 284 zwp_linux_buffer_params_v1_add(params, fd.get(), 0, 0, kStride, 0, 0); | |
| 285 zwp_linux_buffer_params_v1_create(params, kWidth, kHeight, kDrmFormat, 0); | |
| 286 wl_display_dispatch(display); | |
| 287 wl_display_roundtrip(display); | |
|
reveman
2016/11/04 22:34:14
please move this round trip so we only do it once
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 288 | |
| 289 if (!buffer_state->buffer) { | |
| 290 LOG(ERROR) << "Can't create linux dmabuf"; | |
| 291 return false; | |
| 292 } | |
| 293 | |
| 294 const EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT, | |
|
reveman
2016/11/04 22:34:14
nit: not sure about 'const' here
Daniele Castagna
2016/11/05 21:05:12
Removed.
| |
| 295 fd.get(), | |
| 296 EGL_WIDTH, | |
| 297 kWidth, | |
| 298 EGL_HEIGHT, | |
| 299 kHeight, | |
| 300 EGL_LINUX_DRM_FOURCC_EXT, | |
| 301 kDrmFormat, | |
| 302 EGL_DMA_BUF_PLANE0_PITCH_EXT, | |
| 303 kStride, | |
| 304 EGL_DMA_BUF_PLANE0_OFFSET_EXT, | |
| 305 0, | |
| 306 EGL_NONE}; | |
| 307 | |
| 308 buffer_state->egl_image = eglCreateImageKHR( | |
| 309 eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, | |
| 310 NULL /* no client buffer */, khr_image_attrs); | |
|
reveman
2016/11/04 22:34:15
s/NULL/nullptr/
| |
| 311 glGenTextures(1, &buffer_state->gl_texture); | |
| 312 glBindTexture(GL_TEXTURE_2D, buffer_state->gl_texture); | |
| 313 | |
| 314 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, | |
| 315 (GLeglImageOES)buffer_state->egl_image); | |
|
reveman
2016/11/04 22:34:14
static_cast
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 316 glBindTexture(GL_TEXTURE_2D, 0); | |
| 317 glGenFramebuffersEXT(1, &buffer_state->fb); | |
| 318 glBindFramebufferEXT(GL_FRAMEBUFFER, buffer_state->fb); | |
| 319 glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | |
| 320 GL_TEXTURE_2D, buffer_state->gl_texture, 0); | |
| 321 CHECK(GL_FRAMEBUFFER_COMPLETE == | |
| 322 glCheckFramebufferStatusEXT(GL_FRAMEBUFFER)); | |
| 323 #else | |
| 324 LOG(ERROR) << "Ozone GBM is necessary to use --linux_dmabuf_v1 flag"; | |
| 325 return false; | |
| 326 #endif | |
| 327 } else { | |
| 328 buffer_state->buffer.reset(static_cast<wl_buffer*>( | |
| 329 wl_shm_pool_create_buffer(context->shm_pool.get(), index * kBufferSize, | |
| 330 kWidth, kHeight, kStride, kShmFormat))); | |
| 331 if (!buffer_state->buffer) { | |
| 332 LOG(ERROR) << "Can't create buffer"; | |
| 333 return false; | |
| 334 } | |
| 335 buffer_state->data = | |
| 336 static_cast<uint8_t*>(context->shared_memory.memory()) + | |
| 337 kBufferSize * index; | |
| 338 } | |
| 339 return true; | |
| 340 } | |
| 341 | |
| 206 } // namespace | 342 } // namespace |
| 207 | 343 |
| 208 int MotionEventsMain() { | 344 int MotionEventsMain() { |
| 345 bool use_dmabuf = | |
|
reveman
2016/11/04 22:34:14
use_drm and maybe a good idea to add this to the m
Daniele Castagna
2016/11/05 21:05:11
Done.
| |
| 346 base::CommandLine::ForCurrentProcess()->HasSwitch("linux_dmabuf_v1"); | |
| 209 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); | 347 std::unique_ptr<wl_display> display(wl_display_connect(nullptr)); |
| 210 if (!display) { | 348 if (!display) { |
| 211 LOG(ERROR) << "wl_display_connect failed"; | 349 LOG(ERROR) << "wl_display_connect failed"; |
| 212 return 1; | 350 return 1; |
| 213 } | 351 } |
| 214 | 352 |
| 353 bool gl_initialized = gl::init::InitializeGLOneOff(); | |
| 354 DCHECK(gl_initialized); | |
| 355 scoped_refptr<gl::GLSurface> gl_surface = | |
| 356 gl::init::CreateOffscreenGLSurface(gfx::Size()); | |
| 357 scoped_refptr<gl::GLContext> gl_context = | |
| 358 gl::init::CreateGLContext(nullptr, // share_group | |
| 359 gl_surface.get(), gl::PreferIntegratedGpu); | |
| 360 ui::ScopedMakeCurrent smc(gl_context.get(), gl_surface.get()); | |
| 361 | |
| 215 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; | 362 wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover}; |
| 216 | 363 |
| 217 Globals globals; | 364 Globals globals; |
| 218 wl_registry* registry = wl_display_get_registry(display.get()); | 365 wl_registry* registry = wl_display_get_registry(display.get()); |
| 219 wl_registry_add_listener(registry, ®istry_listener, &globals); | 366 wl_registry_add_listener(registry, ®istry_listener, &globals); |
| 220 | 367 |
| 221 wl_display_dispatch(display.get()); | 368 wl_display_dispatch(display.get()); |
| 222 wl_display_roundtrip(display.get()); | 369 wl_display_roundtrip(display.get()); |
| 223 | 370 |
| 224 if (!globals.compositor) { | 371 if (!globals.compositor) { |
| 225 LOG(ERROR) << "Can't find compositor interface"; | 372 LOG(ERROR) << "Can't find compositor interface"; |
| 226 return 1; | 373 return 1; |
| 227 } | 374 } |
| 228 if (!globals.shm) { | 375 if (!globals.shm) { |
| 229 LOG(ERROR) << "Can't find shm interface"; | 376 LOG(ERROR) << "Can't find shm interface"; |
| 230 return 1; | 377 return 1; |
| 231 } | 378 } |
| 379 | |
| 380 if (use_dmabuf && !globals.linux_dmabuf) { | |
| 381 LOG(ERROR) << "Can't find linux_dmabuf interface"; | |
| 382 return 1; | |
| 383 } | |
| 384 | |
| 232 if (!globals.shell) { | 385 if (!globals.shell) { |
| 233 LOG(ERROR) << "Can't find shell interface"; | 386 LOG(ERROR) << "Can't find shell interface"; |
| 234 return 1; | 387 return 1; |
| 235 } | 388 } |
| 236 if (!globals.seat) { | 389 if (!globals.seat) { |
| 237 LOG(ERROR) << "Can't find seat interface"; | 390 LOG(ERROR) << "Can't find seat interface"; |
| 238 return 1; | 391 return 1; |
| 239 } | 392 } |
| 393 MainLoopContext context; | |
| 394 base::ScopedFD fd(open("/dev/dri/renderD128", O_RDWR)); | |
|
reveman
2016/11/04 22:34:14
lets move "/dev/dri/renderD128" to a constant at t
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 395 if (fd.get() < 0) { | |
|
reveman
2016/11/04 22:34:14
we probably want this in the GBM ifdef below or it
Daniele Castagna
2016/11/05 21:05:12
Done.
| |
| 396 LOG(ERROR) << "Can't open drm device '/dev/dri/renderD128'"; | |
| 397 return 1; | |
| 398 } | |
| 399 #if defined(OZONE_PLATFORM_GBM) | |
| 400 context.device.reset(gbm_create_device(fd.get())); | |
| 401 if (!context.device) { | |
| 402 LOG(ERROR) << "Can't create gbm device."; | |
| 403 return 1; | |
| 404 } | |
| 405 #endif | |
| 240 | 406 |
| 241 wl_buffer_listener buffer_listener = {BufferRelease}; | 407 wl_buffer_listener buffer_listener = {BufferRelease}; |
| 242 | 408 |
| 243 BufferState buffers[kBuffers]; | 409 BufferState buffers[kBuffers]; |
| 244 base::SharedMemory shared_memory; | 410 context.shared_memory.CreateAndMapAnonymous(kMemorySize); |
| 245 shared_memory.CreateAndMapAnonymous(kMemorySize); | 411 context.shm_pool.reset( |
| 246 std::unique_ptr<wl_shm_pool> shm_pool( | 412 wl_shm_create_pool(globals.shm.get(), context.shared_memory.handle().fd, |
| 247 wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd, | 413 context.shared_memory.requested_size())); |
| 248 shared_memory.requested_size())); | |
| 249 for (size_t i = 0; i < kBuffers; ++i) { | 414 for (size_t i = 0; i < kBuffers; ++i) { |
| 250 buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer( | 415 if (!CreateBuffer(&context, &globals, display.get(), i, &buffers[i])) { |
| 251 shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat))); | |
| 252 if (!buffers[i].buffer) { | |
| 253 LOG(ERROR) << "Can't create buffer"; | |
| 254 return 1; | 416 return 1; |
| 255 } | 417 } |
| 256 buffers[i].data = | |
| 257 static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i; | |
| 258 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, | 418 wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener, |
| 259 &buffers[i]); | 419 &buffers[i]); |
| 260 } | 420 } |
| 261 | 421 |
| 262 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( | 422 std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>( |
| 263 wl_compositor_create_surface(globals.compositor.get()))); | 423 wl_compositor_create_surface(globals.compositor.get()))); |
| 264 if (!surface) { | 424 if (!surface) { |
| 265 LOG(ERROR) << "Can't create surface"; | 425 LOG(ERROR) << "Can't create surface"; |
| 266 return 1; | 426 return 1; |
| 267 } | 427 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 280 static_cast<wl_shell_surface*>( | 440 static_cast<wl_shell_surface*>( |
| 281 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); | 441 wl_shell_get_shell_surface(globals.shell.get(), surface.get()))); |
| 282 if (!shell_surface) { | 442 if (!shell_surface) { |
| 283 LOG(ERROR) << "Can't get shell surface"; | 443 LOG(ERROR) << "Can't get shell surface"; |
| 284 return 1; | 444 return 1; |
| 285 } | 445 } |
| 286 | 446 |
| 287 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); | 447 wl_shell_surface_set_title(shell_surface.get(), "Test Client"); |
| 288 wl_shell_surface_set_toplevel(shell_surface.get()); | 448 wl_shell_surface_set_toplevel(shell_surface.get()); |
| 289 | 449 |
| 290 MainLoopContext context; | |
| 291 | |
| 292 std::unique_ptr<wl_pointer> pointer( | 450 std::unique_ptr<wl_pointer> pointer( |
| 293 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); | 451 static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get()))); |
| 294 if (!pointer) { | 452 if (!pointer) { |
| 295 LOG(ERROR) << "Can't get pointer"; | 453 LOG(ERROR) << "Can't get pointer"; |
| 296 return 1; | 454 return 1; |
| 297 } | 455 } |
| 298 | 456 |
| 299 wl_pointer_listener pointer_listener = { | 457 wl_pointer_listener pointer_listener = { |
| 300 PointerEnter, PointerLeave, PointerMotion, | 458 PointerEnter, PointerLeave, PointerMotion, |
| 301 PointerButton, PointerAxis, PointerFrame, | 459 PointerButton, PointerAxis, PointerFrame, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 327 continue; | 485 continue; |
| 328 | 486 |
| 329 BufferState* buffer = | 487 BufferState* buffer = |
| 330 std::find_if(std::begin(buffers), std::end(buffers), | 488 std::find_if(std::begin(buffers), std::end(buffers), |
| 331 [](const BufferState& buffer) { return !buffer.busy; }); | 489 [](const BufferState& buffer) { return !buffer.busy; }); |
| 332 if (buffer == std::end(buffers)) | 490 if (buffer == std::end(buffers)) |
| 333 continue; | 491 continue; |
| 334 | 492 |
| 335 context.needs_redraw = false; | 493 context.needs_redraw = false; |
| 336 | 494 |
| 337 static_assert(sizeof(uint32_t) == kBytesPerPixel, | 495 if (use_dmabuf) { |
| 338 "uint32_t must be same size as kBytesPerPixel"); | 496 glBindFramebufferEXT(GL_FRAMEBUFFER, buffer->fb); |
| 339 for (size_t y = 0; y < kHeight; y++) { | 497 glViewport(0, 0, kWidth, kHeight); |
| 340 uint32_t* pixel = reinterpret_cast<uint32_t*>(buffer->data + y * kStride); | 498 const float toUnitRatio = 1.f / 255.f; |
| 341 for (size_t x = 0; x < kWidth; x++) | 499 glClearColor(toUnitRatio * (context.color & 0xFF), |
| 342 *pixel++ = context.color; | 500 toUnitRatio * ((context.color & 0xFF00) >> 8), |
| 501 toUnitRatio * ((context.color & 0xFF0000) >> 16), 1.0f); | |
| 502 glClear(GL_COLOR_BUFFER_BIT); | |
| 503 glFinish(); | |
| 504 } else { | |
| 505 static_assert(sizeof(uint32_t) == kBytesPerPixel, | |
| 506 "uint32_t must be same size as kBytesPerPixel"); | |
| 507 for (size_t y = 0; y < kHeight; y++) { | |
| 508 uint32_t* pixel = | |
| 509 reinterpret_cast<uint32_t*>(buffer->data + y * kStride); | |
| 510 for (size_t x = 0; x < kWidth; x++) | |
| 511 *pixel++ = context.color; | |
| 512 } | |
| 343 } | 513 } |
| 344 | 514 |
| 345 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); | 515 wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); |
| 346 buffer->busy = true; | 516 buffer->busy = true; |
| 347 | 517 |
| 348 frame_callback.reset(wl_surface_frame(surface.get())); | 518 frame_callback.reset(wl_surface_frame(surface.get())); |
| 349 wl_callback_add_listener(frame_callback.get(), &frame_listener, &context); | 519 wl_callback_add_listener(frame_callback.get(), &frame_listener, &context); |
| 350 context.throttled = true; | 520 context.throttled = true; |
| 351 | 521 |
| 352 wl_surface_commit(surface.get()); | 522 wl_surface_commit(surface.get()); |
| 353 wl_display_flush(display.get()); | 523 wl_display_flush(display.get()); |
| 354 } while (wl_display_dispatch(display.get()) != -1); | 524 } while (wl_display_dispatch(display.get()) != -1); |
| 355 | 525 |
| 526 glBindFramebufferEXT(GL_FRAMEBUFFER, 0); | |
| 527 for (uint32_t i = 0; i < kBuffers; ++i) { | |
| 528 BufferState& buffer = buffers[i]; | |
| 529 glDeleteFramebuffersEXT(1, &buffer.fb); | |
| 530 glDeleteTextures(1, &buffer.gl_texture); | |
| 531 eglDestroyImageKHR(eglGetCurrentDisplay(), buffer.egl_image); | |
| 532 } | |
| 533 | |
| 356 return 0; | 534 return 0; |
| 357 } | 535 } |
| 358 | 536 |
| 359 } // namespace clients | 537 } // namespace clients |
| 360 } // namespace wayland | 538 } // namespace wayland |
| 361 } // namespace exo | 539 } // namespace exo |
| 362 | 540 |
| 363 int main() { | 541 int main(int argc, char* argv[]) { |
| 542 base::AtExitManager exit_manager; | |
| 543 base::CommandLine::Init(argc, argv); | |
| 364 return exo::wayland::clients::MotionEventsMain(); | 544 return exo::wayland::clients::MotionEventsMain(); |
| 365 } | 545 } |
| OLD | NEW |