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

Unified Diff: components/exo/wayland/clients/motion_events.cc

Issue 2477043002: exo: Add drm support to motion_events. (Closed)
Patch Set: Rebase on master. 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 side-by-side diff with in-line comments
Download patch
« components/exo/wayland/BUILD.gn ('K') | « components/exo/wayland/BUILD.gn ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/wayland/clients/motion_events.cc
diff --git a/components/exo/wayland/clients/motion_events.cc b/components/exo/wayland/clients/motion_events.cc
index 99e38eba2b79c3ddac9e12daf2ca9fc85fdb2ec3..239dadab37f791076f4ebc34c0739b2d1e7d9f82 100644
--- a/components/exo/wayland/clients/motion_events.cc
+++ b/components/exo/wayland/clients/motion_events.cc
@@ -6,11 +6,27 @@
// buffers when receiving pointer/touch events. RGB contains the lower
// 24 bits of the event timestamp and A is 0xff.
+#include <fcntl.h>
+#include <linux-dmabuf-unstable-v1-client-protocol.h>
#include <wayland-client-core.h>
#include <wayland-client-protocol.h>
+#include "base/at_exit.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_enums.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/init/gl_factory.h"
+#include "ui/gl/scoped_make_current.h"
+
+#if defined(OZONE_PLATFORM_GBM)
+#include <drm_fourcc.h>
+#include <gbm.h>
+#endif
// Convenient macro that is used to define default deleters for wayland object
// types allowing them to be used with std::unique_ptr.
@@ -22,6 +38,11 @@
}; \
}
+#if defined(OZONE_PLATFORM_GBM)
+DEFAULT_DELETER(gbm_device, gbm_device_destroy)
+DEFAULT_DELETER(gbm_bo, gbm_bo_destroy)
+#endif
+
DEFAULT_DELETER(wl_display, wl_display_disconnect)
DEFAULT_DELETER(wl_compositor, wl_compositor_destroy)
DEFAULT_DELETER(wl_shm, wl_shm_destroy)
@@ -35,6 +56,7 @@ DEFAULT_DELETER(wl_seat, wl_seat_destroy)
DEFAULT_DELETER(wl_pointer, wl_pointer_destroy)
DEFAULT_DELETER(wl_touch, wl_touch_destroy)
DEFAULT_DELETER(wl_callback, wl_callback_destroy)
+DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
namespace exo {
namespace wayland {
@@ -46,7 +68,10 @@ const size_t kWidth = 256;
const size_t kHeight = 256;
// Buffer format.
-const int32_t kFormat = WL_SHM_FORMAT_ABGR8888;
+const int32_t kShmFormat = WL_SHM_FORMAT_ABGR8888;
+#if defined(OZONE_PLATFORM_GBM)
+const int32_t kDrmFormat = DRM_FORMAT_ABGR8888;
+#endif
const size_t kBytesPerPixel = 4;
// Number of buffers.
@@ -60,6 +85,7 @@ const size_t kMemorySize = kBufferSize * kBuffers;
struct Globals {
std::unique_ptr<wl_compositor> compositor;
std::unique_ptr<wl_shm> shm;
+ std::unique_ptr<zwp_linux_dmabuf_v1> linux_dmabuf;
std::unique_ptr<wl_shell> shell;
std::unique_ptr<wl_seat> seat;
};
@@ -83,6 +109,9 @@ void RegistryHandler(void* data,
} else if (strcmp(interface, "wl_seat") == 0) {
globals->seat.reset(static_cast<wl_seat*>(
wl_registry_bind(registry, id, &wl_seat_interface, 5)));
+ } else if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0) {
+ globals->linux_dmabuf.reset(static_cast<zwp_linux_dmabuf_v1*>(
+ wl_registry_bind(registry, id, &zwp_linux_dmabuf_v1_interface, 1)));
}
}
@@ -94,6 +123,13 @@ struct BufferState {
std::unique_ptr<wl_buffer> buffer;
uint8_t* data = nullptr;
bool busy = false;
+// dmabuf
+#if defined(OZONE_PLATFORM_GBM)
+ 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.
+#endif
+ 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
+ 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.
+ 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.
};
void BufferRelease(void* data, wl_buffer* buffer) {
@@ -107,6 +143,12 @@ struct MainLoopContext {
bool needs_redraw = true;
bool shutdown = false;
bool throttled = false;
+ base::SharedMemory shared_memory;
+ std::unique_ptr<wl_shm_pool> shm_pool;
+
+#if defined(OZONE_PLATFORM_GBM)
+ std::unique_ptr<gbm_device> device;
+#endif
};
void PointerEnter(void* data,
@@ -203,15 +245,120 @@ void FrameCallback(void* data, wl_callback* callback, uint32_t time) {
context->throttled = false;
}
+#if defined(OZONE_PLATFORM_GBM)
+void LinuxBufferParamsCreated(void* data,
+ zwp_linux_buffer_params_v1* params,
+ wl_buffer* buffer) {
+ std::unique_ptr<wl_buffer>* out_buffer =
+ 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.
+ out_buffer->reset(buffer);
+}
+
+void LinuxBufferParamsFailed(void* data, zwp_linux_buffer_params_v1* params) {
+ 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.
+}
+#endif
+
+bool CreateBuffer(MainLoopContext* context,
+ Globals* globals,
+ wl_display* display,
+ size_t index,
+ BufferState* buffer_state) {
+ 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.
+#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.
+ buffer_state->bo.reset(
+ gbm_bo_create(context->device.get(), kWidth, kHeight, kDrmFormat,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING));
+ if (!buffer_state->bo) {
+ LOG(ERROR) << "Can't create gbm buffer.";
+ return false;
+ }
+ base::ScopedFD fd(gbm_bo_get_plane_fd(buffer_state->bo.get(), 0));
+ zwp_linux_buffer_params_v1_listener params_listener = {
+ LinuxBufferParamsCreated, LinuxBufferParamsFailed};
+
+ 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.
+ zwp_linux_dmabuf_v1_create_params(globals->linux_dmabuf.get());
+ zwp_linux_buffer_params_v1_add_listener(params, &params_listener,
+ &buffer_state->buffer);
+ zwp_linux_buffer_params_v1_add(params, fd.get(), 0, 0, kStride, 0, 0);
+ zwp_linux_buffer_params_v1_create(params, kWidth, kHeight, kDrmFormat, 0);
+ wl_display_dispatch(display);
+ 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.
+
+ if (!buffer_state->buffer) {
+ LOG(ERROR) << "Can't create linux dmabuf";
+ return false;
+ }
+
+ 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.
+ fd.get(),
+ EGL_WIDTH,
+ kWidth,
+ EGL_HEIGHT,
+ kHeight,
+ EGL_LINUX_DRM_FOURCC_EXT,
+ kDrmFormat,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT,
+ kStride,
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT,
+ 0,
+ EGL_NONE};
+
+ buffer_state->egl_image = eglCreateImageKHR(
+ eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
+ NULL /* no client buffer */, khr_image_attrs);
reveman 2016/11/04 22:34:15 s/NULL/nullptr/
+ glGenTextures(1, &buffer_state->gl_texture);
+ glBindTexture(GL_TEXTURE_2D, buffer_state->gl_texture);
+
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
+ (GLeglImageOES)buffer_state->egl_image);
reveman 2016/11/04 22:34:14 static_cast
Daniele Castagna 2016/11/05 21:05:12 Done.
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glGenFramebuffersEXT(1, &buffer_state->fb);
+ glBindFramebufferEXT(GL_FRAMEBUFFER, buffer_state->fb);
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, buffer_state->gl_texture, 0);
+ CHECK(GL_FRAMEBUFFER_COMPLETE ==
+ glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
+#else
+ LOG(ERROR) << "Ozone GBM is necessary to use --linux_dmabuf_v1 flag";
+ return false;
+#endif
+ } else {
+ buffer_state->buffer.reset(static_cast<wl_buffer*>(
+ wl_shm_pool_create_buffer(context->shm_pool.get(), index * kBufferSize,
+ kWidth, kHeight, kStride, kShmFormat)));
+ if (!buffer_state->buffer) {
+ LOG(ERROR) << "Can't create buffer";
+ return false;
+ }
+ buffer_state->data =
+ static_cast<uint8_t*>(context->shared_memory.memory()) +
+ kBufferSize * index;
+ }
+ return true;
+}
+
} // namespace
int MotionEventsMain() {
+ 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.
+ base::CommandLine::ForCurrentProcess()->HasSwitch("linux_dmabuf_v1");
std::unique_ptr<wl_display> display(wl_display_connect(nullptr));
if (!display) {
LOG(ERROR) << "wl_display_connect failed";
return 1;
}
+ bool gl_initialized = gl::init::InitializeGLOneOff();
+ DCHECK(gl_initialized);
+ scoped_refptr<gl::GLSurface> gl_surface =
+ gl::init::CreateOffscreenGLSurface(gfx::Size());
+ scoped_refptr<gl::GLContext> gl_context =
+ gl::init::CreateGLContext(nullptr, // share_group
+ gl_surface.get(), gl::PreferIntegratedGpu);
+ ui::ScopedMakeCurrent smc(gl_context.get(), gl_surface.get());
+
wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
Globals globals;
@@ -229,6 +376,12 @@ int MotionEventsMain() {
LOG(ERROR) << "Can't find shm interface";
return 1;
}
+
+ if (use_dmabuf && !globals.linux_dmabuf) {
+ LOG(ERROR) << "Can't find linux_dmabuf interface";
+ return 1;
+ }
+
if (!globals.shell) {
LOG(ERROR) << "Can't find shell interface";
return 1;
@@ -237,24 +390,31 @@ int MotionEventsMain() {
LOG(ERROR) << "Can't find seat interface";
return 1;
}
+ MainLoopContext context;
+ 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.
+ 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.
+ LOG(ERROR) << "Can't open drm device '/dev/dri/renderD128'";
+ return 1;
+ }
+#if defined(OZONE_PLATFORM_GBM)
+ context.device.reset(gbm_create_device(fd.get()));
+ if (!context.device) {
+ LOG(ERROR) << "Can't create gbm device.";
+ return 1;
+ }
+#endif
wl_buffer_listener buffer_listener = {BufferRelease};
BufferState buffers[kBuffers];
- base::SharedMemory shared_memory;
- shared_memory.CreateAndMapAnonymous(kMemorySize);
- std::unique_ptr<wl_shm_pool> shm_pool(
- wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd,
- shared_memory.requested_size()));
+ context.shared_memory.CreateAndMapAnonymous(kMemorySize);
+ context.shm_pool.reset(
+ wl_shm_create_pool(globals.shm.get(), context.shared_memory.handle().fd,
+ context.shared_memory.requested_size()));
for (size_t i = 0; i < kBuffers; ++i) {
- buffers[i].buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer(
- shm_pool.get(), i * kBufferSize, kWidth, kHeight, kStride, kFormat)));
- if (!buffers[i].buffer) {
- LOG(ERROR) << "Can't create buffer";
+ if (!CreateBuffer(&context, &globals, display.get(), i, &buffers[i])) {
return 1;
}
- buffers[i].data =
- static_cast<uint8_t*>(shared_memory.memory()) + kBufferSize * i;
wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener,
&buffers[i]);
}
@@ -287,8 +447,6 @@ int MotionEventsMain() {
wl_shell_surface_set_title(shell_surface.get(), "Test Client");
wl_shell_surface_set_toplevel(shell_surface.get());
- MainLoopContext context;
-
std::unique_ptr<wl_pointer> pointer(
static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get())));
if (!pointer) {
@@ -334,12 +492,24 @@ int MotionEventsMain() {
context.needs_redraw = false;
- static_assert(sizeof(uint32_t) == kBytesPerPixel,
- "uint32_t must be same size as kBytesPerPixel");
- for (size_t y = 0; y < kHeight; y++) {
- uint32_t* pixel = reinterpret_cast<uint32_t*>(buffer->data + y * kStride);
- for (size_t x = 0; x < kWidth; x++)
- *pixel++ = context.color;
+ if (use_dmabuf) {
+ glBindFramebufferEXT(GL_FRAMEBUFFER, buffer->fb);
+ glViewport(0, 0, kWidth, kHeight);
+ const float toUnitRatio = 1.f / 255.f;
+ glClearColor(toUnitRatio * (context.color & 0xFF),
+ toUnitRatio * ((context.color & 0xFF00) >> 8),
+ toUnitRatio * ((context.color & 0xFF0000) >> 16), 1.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glFinish();
+ } else {
+ static_assert(sizeof(uint32_t) == kBytesPerPixel,
+ "uint32_t must be same size as kBytesPerPixel");
+ for (size_t y = 0; y < kHeight; y++) {
+ uint32_t* pixel =
+ reinterpret_cast<uint32_t*>(buffer->data + y * kStride);
+ for (size_t x = 0; x < kWidth; x++)
+ *pixel++ = context.color;
+ }
}
wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
@@ -353,6 +523,14 @@ int MotionEventsMain() {
wl_display_flush(display.get());
} while (wl_display_dispatch(display.get()) != -1);
+ glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
+ for (uint32_t i = 0; i < kBuffers; ++i) {
+ BufferState& buffer = buffers[i];
+ glDeleteFramebuffersEXT(1, &buffer.fb);
+ glDeleteTextures(1, &buffer.gl_texture);
+ eglDestroyImageKHR(eglGetCurrentDisplay(), buffer.egl_image);
+ }
+
return 0;
}
@@ -360,6 +538,8 @@ int MotionEventsMain() {
} // namespace wayland
} // namespace exo
-int main() {
+int main(int argc, char* argv[]) {
+ base::AtExitManager exit_manager;
+ base::CommandLine::Init(argc, argv);
return exo::wayland::clients::MotionEventsMain();
}
« components/exo/wayland/BUILD.gn ('K') | « components/exo/wayland/BUILD.gn ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698