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

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

Issue 2477043002: exo: Add drm support to motion_events. (Closed)
Patch Set: Make linux compile. 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
« no previous file with comments | « 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 6db6313caf23def692e5d15d0d97e6514c006dea..55aa120159aeadbbae358a22756c431a5698e0e7 100644
--- a/components/exo/wayland/clients/motion_events.cc
+++ b/components/exo/wayland/clients/motion_events.cc
@@ -6,23 +6,42 @@
// 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 <iostream>
#include <vector>
+#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
+#include "base/scoped_generic.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkSurface.h"
-
-// Convenient macro that is used to define default deleters for wayland object
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.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 object
// types allowing them to be used with std::unique_ptr.
#define DEFAULT_DELETER(TypeName, DeleteFunction) \
namespace std { \
@@ -45,19 +64,37 @@ 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_buffer_params_v1, zwp_linux_buffer_params_v1_destroy)
+DEFAULT_DELETER(zwp_linux_dmabuf_v1, zwp_linux_dmabuf_v1_destroy)
+
+#if defined(OZONE_PLATFORM_GBM)
+DEFAULT_DELETER(gbm_device, gbm_device_destroy)
+DEFAULT_DELETER(gbm_bo, gbm_bo_destroy)
+#endif
namespace exo {
namespace wayland {
namespace clients {
namespace {
+// Title for the wayland client.
+const char kClientTitle[] = "Motion Event Client";
+
// Buffer format.
-const int32_t kFormat = WL_SHM_FORMAT_ARGB8888;
+const int32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
const SkColorType kColorType = kBGRA_8888_SkColorType;
+#if defined(OZONE_PLATFORM_GBM)
+const int32_t kDrmFormat = DRM_FORMAT_ABGR8888;
+#endif
const size_t kBytesPerPixel = 4;
+#if defined(OZONE_PLATFORM_GBM)
+// DRI render node path.
+const char kDriRenderNode[] = "/dev/dri/renderD128";
+#endif
+
// Number of buffers.
-const size_t kBuffers = 2;
+const size_t kBuffers = 3;
// Rotation speed (degrees/second).
const double kRotationSpeed = 360.0;
@@ -68,6 +105,7 @@ const int kBenchmarkInterval = 5;
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;
};
@@ -91,6 +129,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)));
}
}
@@ -98,10 +139,34 @@ void RegistryRemover(void* data, wl_registry* registry, uint32_t id) {
LOG(WARNING) << "Got a registry losing event for " << id;
}
+#if defined(OZONE_PLATFORM_GBM)
+struct DeleteTextureTraits {
+ static GLuint InvalidValue() { return 0; }
+ static void Free(GLuint texture) { glDeleteTextures(1, &texture); }
+};
+typedef base::ScopedGeneric<GLuint, DeleteTextureTraits> ScopedTexture;
reveman 2016/11/07 02:44:34 nit: using ScopedTexture = ...
Daniele Castagna 2016/11/07 05:46:53 Done.
+
+struct DeleteEglImageTraits {
+ static EGLImageKHR InvalidValue() { return 0; }
+ static void Free(EGLImageKHR image) {
+ eglDestroyImageKHR(eglGetCurrentDisplay(), image);
+ }
+};
+typedef base::ScopedGeneric<EGLImageKHR, DeleteEglImageTraits> ScopedEglImage;
reveman 2016/11/07 02:44:34 nit: using ScopedEglImage = ...
Daniele Castagna 2016/11/07 05:46:53 Done.
+#endif
+
struct Buffer {
std::unique_ptr<wl_buffer> buffer;
- sk_sp<SkSurface> sk_surface;
bool busy = false;
+#if defined(OZONE_PLATFORM_GBM)
+ std::unique_ptr<gbm_bo> bo;
+ std::unique_ptr<ScopedEglImage> egl_image;
+ std::unique_ptr<ScopedTexture> texture;
+#endif
+ std::unique_ptr<zwp_linux_buffer_params_v1> params;
+ base::SharedMemory shared_memory;
+ std::unique_ptr<wl_shm_pool> shm_pool;
+ sk_sp<SkSurface> sk_surface;
};
void BufferRelease(void* data, wl_buffer* /* buffer */) {
@@ -204,6 +269,26 @@ void FrameCallback(void* data, wl_callback* callback, uint32_t time) {
frame->callback_pending = false;
}
+#if defined(OZONE_PLATFORM_GBM)
+void LinuxBufferParamsCreated(void* data,
+ zwp_linux_buffer_params_v1* params,
+ wl_buffer* new_buffer) {
+ Buffer* buffer = static_cast<Buffer*>(data);
+ buffer->buffer.reset(new_buffer);
+}
+
+void LinuxBufferParamsFailed(void* data, zwp_linux_buffer_params_v1* params) {
+ LOG(ERROR) << "Linux buffer params failed";
+}
+
+const GrGLInterface* GrGLCreateNativeInterface() {
+ return GrGLAssembleInterface(nullptr, [](void* ctx, const char name[]) {
+ return eglGetProcAddress(name);
+ });
+}
+
Daniele Castagna 2016/11/07 05:46:53 This line is gone.
+#endif
+
} // namespace
class MotionEvents {
@@ -212,17 +297,20 @@ class MotionEvents {
size_t height,
int scale,
size_t num_rects,
+ bool use_drm,
bool fullscreen)
: width_(width),
height_(height),
scale_(scale),
num_rects_(num_rects),
+ use_drm_(use_drm),
fullscreen_(fullscreen) {}
// Initialize and run client main loop.
int Run();
private:
+ bool CreateBuffer(Buffer* buffer);
size_t stride() const { return width_ * kBytesPerPixel; }
size_t buffer_size() const { return stride() * height_; }
@@ -230,80 +318,115 @@ class MotionEvents {
const size_t height_;
const int scale_;
const size_t num_rects_;
+ const bool use_drm_;
const bool fullscreen_;
+ Globals globals_;
+ std::unique_ptr<wl_display> display_;
+
+#if defined(OZONE_PLATFORM_GBM)
+ base::ScopedFD drm_fd_;
+ std::unique_ptr<gbm_device> device_;
+#endif
+
+ scoped_refptr<gl::GLSurface> gl_surface_;
+ scoped_refptr<gl::GLContext> gl_context_;
+ std::unique_ptr<ui::ScopedMakeCurrent> make_current_;
+
+ Buffer buffers_[kBuffers];
+ sk_sp<GrContext> gr_context_;
+
DISALLOW_COPY_AND_ASSIGN(MotionEvents);
};
int MotionEvents::Run() {
- std::unique_ptr<wl_display> display(wl_display_connect(nullptr));
- if (!display) {
+ display_.reset(wl_display_connect(nullptr));
+ if (!display_) {
LOG(ERROR) << "wl_display_connect failed";
return 1;
}
+ bool gl_initialized = gl::init::InitializeGLOneOff();
+ DCHECK(gl_initialized);
+ gl_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
+ gl_context_ =
+ gl::init::CreateGLContext(nullptr, // share_group
+ gl_surface_.get(), gl::PreferIntegratedGpu);
+
+ make_current_.reset(
+ new ui::ScopedMakeCurrent(gl_context_.get(), gl_surface_.get()));
wl_registry_listener registry_listener = {RegistryHandler, RegistryRemover};
- Globals globals;
- wl_registry* registry = wl_display_get_registry(display.get());
- wl_registry_add_listener(registry, &registry_listener, &globals);
+ wl_registry* registry = wl_display_get_registry(display_.get());
+ wl_registry_add_listener(registry, &registry_listener, &globals_);
- wl_display_roundtrip(display.get());
+ wl_display_roundtrip(display_.get());
- if (!globals.compositor) {
+ if (!globals_.compositor) {
LOG(ERROR) << "Can't find compositor interface";
return 1;
}
- if (!globals.shm) {
+ if (!globals_.shm) {
LOG(ERROR) << "Can't find shm interface";
return 1;
}
- if (!globals.shell) {
+ if (use_drm_ && !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;
}
- if (!globals.seat) {
+ if (!globals_.seat) {
LOG(ERROR) << "Can't find seat interface";
return 1;
}
+#if defined(OZONE_PLATFORM_GBM)
+ drm_fd_.reset(open(kDriRenderNode, O_RDWR));
+ if (drm_fd_.get() < 0) {
+ LOG(ERROR) << "Can't open drm device '" << kDriRenderNode << "'";
+ return 1;
+ }
+
+ device_.reset(gbm_create_device(drm_fd_.get()));
+ if (!device_) {
+ LOG(ERROR) << "Can't create gbm device";
+ return 1;
+ }
+ sk_sp<const GrGLInterface> native_interface(GrGLCreateNativeInterface());
+ DCHECK(native_interface);
+ gr_context_ = sk_sp<GrContext>(GrContext::Create(
+ kOpenGL_GrBackend,
+ reinterpret_cast<GrBackendContext>(native_interface.get())));
+ DCHECK(gr_context_);
+#endif
+
wl_buffer_listener buffer_listener = {BufferRelease};
- Buffer buffers[kBuffers];
- base::SharedMemory shared_memory;
- shared_memory.CreateAndMapAnonymous(buffer_size() * kBuffers);
- std::unique_ptr<wl_shm_pool> shm_pool(
- wl_shm_create_pool(globals.shm.get(), shared_memory.handle().fd,
- 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 * buffer_size(), width_,
- height_, stride(), kFormat)));
- if (!buffers[i].buffer) {
- LOG(ERROR) << "Can't create buffer";
+ if (!CreateBuffer(&buffers_[i]))
return 1;
- }
- buffers[i].sk_surface = SkSurface::MakeRasterDirect(
- SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType),
- static_cast<uint8_t*>(shared_memory.memory()) + buffer_size() * i,
- stride());
- if (!buffers[i].sk_surface) {
- LOG(ERROR) << "Can't create SkSurface";
+ }
+ wl_display_roundtrip(display_.get());
+ for (size_t i = 0; i < kBuffers; ++i) {
+ if (!buffers_[i].buffer)
return 1;
- }
- wl_buffer_add_listener(buffers[i].buffer.get(), &buffer_listener,
- &buffers[i]);
+
+ wl_buffer_add_listener(buffers_[i].buffer.get(), &buffer_listener,
+ &buffers_[i]);
}
std::unique_ptr<wl_surface> surface(static_cast<wl_surface*>(
- wl_compositor_create_surface(globals.compositor.get())));
+ wl_compositor_create_surface(globals_.compositor.get())));
if (!surface) {
LOG(ERROR) << "Can't create surface";
return 1;
}
std::unique_ptr<wl_region> opaque_region(static_cast<wl_region*>(
- wl_compositor_create_region(globals.compositor.get())));
+ wl_compositor_create_region(globals_.compositor.get())));
if (!opaque_region) {
LOG(ERROR) << "Can't create region";
return 1;
@@ -314,13 +437,14 @@ int MotionEvents::Run() {
std::unique_ptr<wl_shell_surface> shell_surface(
static_cast<wl_shell_surface*>(
- wl_shell_get_shell_surface(globals.shell.get(), surface.get())));
+ wl_shell_get_shell_surface(globals_.shell.get(), surface.get())));
if (!shell_surface) {
LOG(ERROR) << "Can't get shell surface";
return 1;
}
- wl_shell_surface_set_title(shell_surface.get(), "Test Client");
+ wl_shell_surface_set_title(shell_surface.get(), kClientTitle);
+
if (fullscreen_) {
wl_shell_surface_set_fullscreen(shell_surface.get(),
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
@@ -332,7 +456,7 @@ int MotionEvents::Run() {
EventTimeStack event_times;
std::unique_ptr<wl_pointer> pointer(
- static_cast<wl_pointer*>(wl_seat_get_pointer(globals.seat.get())));
+ static_cast<wl_pointer*>(wl_seat_get_pointer(globals_.seat.get())));
if (!pointer) {
LOG(ERROR) << "Can't get pointer";
return 1;
@@ -345,7 +469,7 @@ int MotionEvents::Run() {
wl_pointer_add_listener(pointer.get(), &pointer_listener, &event_times);
std::unique_ptr<wl_touch> touch(
- static_cast<wl_touch*>(wl_seat_get_touch(globals.seat.get())));
+ static_cast<wl_touch*>(wl_seat_get_touch(globals_.seat.get())));
if (!touch) {
LOG(ERROR) << "Can't get touch";
return 1;
@@ -369,9 +493,9 @@ int MotionEvents::Run() {
continue;
Buffer* buffer =
- std::find_if(std::begin(buffers), std::end(buffers),
+ std::find_if(std::begin(buffers_), std::end(buffers_),
[](const Buffer& buffer) { return !buffer.busy; });
- if (buffer == std::end(buffers))
+ if (buffer == std::end(buffers_))
continue;
base::TimeTicks current_time = base::TimeTicks::Now();
@@ -425,7 +549,10 @@ int MotionEvents::Run() {
canvas->drawIRect(rect, paint);
}
canvas->restore();
-
+ if (gr_context_) {
+ gr_context_->flush();
+ glFinish();
+ }
wl_surface_set_buffer_scale(surface.get(), scale_);
wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0);
buffer->busy = true;
@@ -437,11 +564,94 @@ int MotionEvents::Run() {
++frames;
wl_surface_commit(surface.get());
- } while (wl_display_dispatch(display.get()) != -1);
+ } while (wl_display_dispatch(display_.get()) != -1);
return 0;
}
+bool MotionEvents::CreateBuffer(Buffer* buffer) {
+#if defined(OZONE_PLATFORM_GBM)
+ if (use_drm_) {
+ buffer->bo.reset(gbm_bo_create(device_.get(), width_, height_, kDrmFormat,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING));
+ if (!buffer->bo) {
+ LOG(ERROR) << "Can't create gbm buffer.";
reveman 2016/11/07 02:44:34 s/buffer./buffer/ for consistency
Daniele Castagna 2016/11/07 05:46:53 Done.
+ return false;
+ }
+ base::ScopedFD fd(gbm_bo_get_plane_fd(buffer->bo.get(), 0));
+ static const zwp_linux_buffer_params_v1_listener params_listener = {
+ LinuxBufferParamsCreated, LinuxBufferParamsFailed};
+
+ buffer->params.reset(
+ zwp_linux_dmabuf_v1_create_params(globals_.linux_dmabuf.get()));
+ zwp_linux_buffer_params_v1_add_listener(buffer->params.get(),
+ &params_listener, buffer);
+ zwp_linux_buffer_params_v1_add(buffer->params.get(), fd.get(), 0, 0,
+ stride(), 0, 0);
+ zwp_linux_buffer_params_v1_create(buffer->params.get(), width_, height_,
+ kDrmFormat, 0);
+
+ EGLint khr_image_attrs[] = {EGL_DMA_BUF_PLANE0_FD_EXT,
+ fd.get(),
+ EGL_WIDTH,
+ width_,
+ EGL_HEIGHT,
+ height_,
+ EGL_LINUX_DRM_FOURCC_EXT,
+ kDrmFormat,
+ EGL_DMA_BUF_PLANE0_PITCH_EXT,
+ stride(),
+ EGL_DMA_BUF_PLANE0_OFFSET_EXT,
+ 0,
+ EGL_NONE};
+ EGLImageKHR image = eglCreateImageKHR(
+ eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
+ nullptr /* no client buffer */, khr_image_attrs);
+
+ buffer->egl_image.reset(new ScopedEglImage(image));
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ buffer->texture.reset(new ScopedTexture(texture));
+ glBindTexture(GL_TEXTURE_2D, buffer->texture->get());
+ glEGLImageTargetTexture2DOES(
+ GL_TEXTURE_2D, static_cast<GLeglImageOES>(buffer->egl_image->get()));
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ GrGLTextureInfo texture_info;
+ texture_info.fID = buffer->texture->get();
+ texture_info.fTarget = GL_TEXTURE_2D;
+ GrBackendTextureDesc desc;
+ desc.fFlags = kRenderTarget_GrBackendTextureFlag;
+ desc.fWidth = width_;
+ desc.fHeight = height_;
+ desc.fConfig = kBGRA_8888_GrPixelConfig;
reveman 2016/11/07 02:44:34 nit: move to constant at the top with other BGRA c
Daniele Castagna 2016/11/07 05:46:53 Done.
+ desc.fOrigin = kTopLeft_GrSurfaceOrigin;
+ desc.fTextureHandle = reinterpret_cast<GrBackendObject>(&texture_info);
+
+ buffer->sk_surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
+ gr_context_.get(), desc, nullptr);
+ DCHECK(buffer->sk_surface);
+ return true;
+ }
+#endif
+ buffer->shared_memory.CreateAndMapAnonymous(buffer_size());
+ buffer->shm_pool.reset(
+ wl_shm_create_pool(globals_.shm.get(), buffer->shared_memory.handle().fd,
+ buffer->shared_memory.requested_size()));
+
+ buffer->buffer.reset(static_cast<wl_buffer*>(wl_shm_pool_create_buffer(
+ buffer->shm_pool.get(), 0, width_, height_, stride(), kShmFormat)));
+ if (!buffer->buffer) {
+ LOG(ERROR) << "Can't create buffer";
+ return false;
+ }
+
+ buffer->sk_surface = SkSurface::MakeRasterDirect(
+ SkImageInfo::Make(width_, height_, kColorType, kOpaque_SkAlphaType),
+ static_cast<uint8_t*>(buffer->shared_memory.memory()), stride());
reveman 2016/11/07 02:44:34 nit: add a DCHECK(buffer->sk_surface) here too
Daniele Castagna 2016/11/07 05:46:53 Done.
+ return true;
+}
+
} // namespace clients
} // namespace wayland
} // namespace exo
@@ -457,18 +667,23 @@ const char kScale[] = "scale";
// Specifies the number of rotating rects to draw.
const char kNumRects[] = "num-rects";
+// Use drm buffer instead of shared memory.
+const char kUseDrm[] = "use-drm";
+
// Specifies if client should be fullscreen.
const char kFullscreen[] = "fullscreen";
} // namespace switches
int main(int argc, char* argv[]) {
- base::CommandLine command_line(argc, argv);
+ base::AtExitManager exit_manager;
+ base::CommandLine::Init(argc, argv);
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
int width = 256;
int height = 256;
- if (command_line.HasSwitch(switches::kSize)) {
- std::string size_str = command_line.GetSwitchValueASCII(switches::kSize);
+ if (command_line->HasSwitch(switches::kSize)) {
+ std::string size_str = command_line->GetSwitchValueASCII(switches::kSize);
if (sscanf(size_str.c_str(), "%dx%d", &width, &height) != 2) {
LOG(ERROR) << "Invalid value for " << switches::kSize;
return 1;
@@ -476,24 +691,25 @@ int main(int argc, char* argv[]) {
}
int scale = 1;
- if (command_line.HasSwitch(switches::kScale) &&
- !base::StringToInt(command_line.GetSwitchValueASCII(switches::kScale),
+ if (command_line->HasSwitch(switches::kScale) &&
+ !base::StringToInt(command_line->GetSwitchValueASCII(switches::kScale),
&scale)) {
LOG(ERROR) << "Invalid value for " << switches::kScale;
return 1;
}
size_t num_rects = 1;
- if (command_line.HasSwitch(switches::kNumRects) &&
+ if (command_line->HasSwitch(switches::kNumRects) &&
!base::StringToSizeT(
- command_line.GetSwitchValueASCII(switches::kNumRects), &num_rects)) {
+ command_line->GetSwitchValueASCII(switches::kNumRects), &num_rects)) {
LOG(ERROR) << "Invalid value for " << switches::kNumRects;
return 1;
}
- bool fullscreen = command_line.HasSwitch(switches::kFullscreen);
+ bool use_drm = command_line->HasSwitch(switches::kUseDrm);
+ bool fullscreen = command_line->HasSwitch(switches::kFullscreen);
exo::wayland::clients::MotionEvents client(width, height, scale, num_rects,
- fullscreen);
+ use_drm, fullscreen);
return client.Run();
}
« 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