Chromium Code Reviews| 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..2b0681a426f365eb40811007e279a10e1ae43ef5 100644 |
| --- a/components/exo/wayland/clients/motion_events.cc |
| +++ b/components/exo/wayland/clients/motion_events.cc |
| @@ -6,12 +6,15 @@ |
| // 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" |
| @@ -21,8 +24,23 @@ |
| #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 { \ |
| @@ -32,6 +50,11 @@ |
| }; \ |
| } |
| +#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.
|
| +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) |
| @@ -45,6 +68,8 @@ 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) |
| namespace exo { |
| namespace wayland { |
| @@ -52,12 +77,20 @@ namespace clients { |
| namespace { |
| // 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 |
|
reveman
2016/11/06 22:18:20
nit: s/path/path./
Daniele Castagna
2016/11/06 23:58:45
Done.
|
| +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 +101,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 +125,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 +135,40 @@ void RegistryRemover(void* data, wl_registry* registry, uint32_t id) { |
| LOG(WARNING) << "Got a registry losing event for " << id; |
| } |
| +#if defined(OZONE_PLATFORM_GBM) |
| +class ScopedTexture { |
| + public: |
| + ScopedTexture() { glGenTextures(1, &id_); } |
| + ~ScopedTexture() { glDeleteTextures(1, &id_); } |
| + GLuint id_ = 0; |
| +}; |
| + |
| +class ScopedEglImage { |
| + public: |
| + 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.
|
| + image_ = eglCreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, |
| + EGL_LINUX_DMA_BUF_EXT, |
| + 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.
|
| + } |
| + ~ScopedEglImage() { eglDestroyImageKHR(eglGetCurrentDisplay(), image_); } |
| + EGLImageKHR image_ = 0; |
| +}; |
|
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.
|
| +#endif |
| + |
| struct Buffer { |
| std::unique_ptr<wl_buffer> buffer; |
| sk_sp<SkSurface> sk_surface; |
| 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.
|
| + base::SharedMemory shared_memory; |
| + std::unique_ptr<wl_shm_pool> shm_pool; |
| + |
|
reveman
2016/11/06 22:18:20
nit: remove this blankline
Daniele Castagna
2016/11/06 23:58:45
Done.
|
| +#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; |
| + sk_sp<SkImage> sk_image; |
|
reveman
2016/11/06 22:18:21
unused
Daniele Castagna
2016/11/06 23:58:45
Removed.
|
| }; |
| void BufferRelease(void* data, wl_buffer* /* buffer */) { |
| @@ -204,25 +271,49 @@ 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"; |
| +} |
| +#endif |
| + |
| } // namespace |
| +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.
|
| + 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.
|
| + return ptr; |
| +} |
| + |
| +const GrGLInterface* GrGLCreateNativeInterface() { |
| + return GrGLAssembleInterface(nullptr, egl_get_gl_proc); |
| +} |
| + |
| class MotionEvents { |
| public: |
| MotionEvents(size_t width, |
| 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) {} |
| - |
|
reveman
2016/11/06 22:18:21
nit: keep this blank line
Daniele Castagna
2016/11/06 23:58:45
Done.
|
| // 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 +321,114 @@ 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_; |
|
reveman
2016/11/06 22:18:21
nit: blankline after this
Daniele Castagna
2016/11/06 23:58:45
Done.
|
| 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, ®istry_listener, &globals); |
| + wl_registry* registry = wl_display_get_registry(display_.get()); |
| + wl_registry_add_listener(registry, ®istry_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 << ";"; |
|
reveman
2016/11/06 22:18:20
s/";"/"'"/
Daniele Castagna
2016/11/06 23:58:45
Done.
|
| + 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 +439,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"); |
|
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.
|
| + |
| if (fullscreen_) { |
| wl_shell_surface_set_fullscreen(shell_surface.get(), |
| WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, |
| @@ -332,7 +458,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 +471,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 +495,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 +551,9 @@ int MotionEvents::Run() { |
| canvas->drawIRect(rect, paint); |
| } |
| canvas->restore(); |
| - |
| + if (gr_context_) |
| + gr_context_->flush(); |
| + 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.
|
| wl_surface_set_buffer_scale(surface.get(), scale_); |
| wl_surface_attach(surface.get(), buffer->buffer.get(), 0, 0); |
| buffer->busy = true; |
| @@ -437,11 +565,90 @@ 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."; |
| + 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(), |
| + ¶ms_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}; |
| + buffer->egl_image.reset(new ScopedEglImage(fd.get(), khr_image_attrs)); |
| + buffer->texture.reset(new ScopedTexture()); |
| + glBindTexture(GL_TEXTURE_2D, buffer->texture->id_); |
| + 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.
|
| + GL_UNSIGNED_BYTE, nullptr); |
| + glEGLImageTargetTexture2DOES( |
| + GL_TEXTURE_2D, static_cast<GLeglImageOES>(buffer->egl_image->image_)); |
| + glBindTexture(GL_TEXTURE_2D, 0); |
| + |
| + GrGLTextureInfo texture_info; |
| + texture_info.fID = buffer->texture->id_; |
| + texture_info.fTarget = GL_TEXTURE_2D; |
| + GrBackendTextureDesc desc; |
| + desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
| + desc.fWidth = width_; |
| + desc.fHeight = height_; |
| + desc.fConfig = kBGRA_8888_GrPixelConfig; |
| + 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()); |
| + return true; |
| +} |
| + |
| } // namespace clients |
| } // namespace wayland |
| } // namespace exo |
| @@ -457,18 +664,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 +688,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("use-drm"); |
| + bool fullscreen = command_line->HasSwitch(switches::kFullscreen); |
| exo::wayland::clients::MotionEvents client(width, height, scale, num_rects, |
| - fullscreen); |
| + use_drm, fullscreen); |
| return client.Run(); |
| } |