-// #include <sys/epoll.h>
#include <iostream>
#include <cstdlib>
+#include <string>
+#include <sys/mman.h>
#include <wayland-client.h>
namespace wayland {
/*static*/
-int Display::evtMaskUpdate(uint32_t mask, void *data)
+int Display::evtMaskUpdate(uint32_t mask, void* data)
{
Display* display = static_cast<Display*>(data);
display->mask_ = mask;
-
return 0;
}
/*static*/
+void Display::handleShmFormat(void* data, wl_shm* shm, uint32_t format)
+{
+ Display* display = static_cast<Display*>(data);
+ display->formats_ |= (1 << format);
+}
+
+/*static*/
+wl_shm_listener Display::shmListener_ = {
+ Display::handleShmFormat
+};
+
+/*static*/
void Display::handleGlobal(wl_display* wldisplay, uint32_t id, const char* interface, uint32_t version, void* data)
{
Display* display = static_cast<Display*>(data);
- if ("wl_compositor" == interface)
- {
+ const std::string intfc(interface);
+
+ if ("wl_compositor" == intfc) {
display->compositor_ = static_cast<wl_compositor*>(
wl_display_bind(
wldisplay, id, &wl_compositor_interface
)
);
}
- else if ("wl_shell" == interface)
- {
+ else if ("wl_shell" == intfc) {
display->shell_ = static_cast<wl_shell*>(
wl_display_bind(
wldisplay, id, &wl_shell_interface
)
);
}
+ else if ("wl_shm" == intfc) {
+ display->shm_ = static_cast<wl_shm*>(
+ wl_display_bind(
+ wldisplay, id, &wl_shm_interface
+ )
+ );
+ wl_shm_add_listener(display->shm_, &shmListener_, display);
+ }
}
Display::Display()
: display_(wl_display_connect(0))
+ , formats_(0)
+ , compositor_(0)
+ , shell_(0)
+ , shm_(0)
+ , mask_(0)
{
- if (not display_)
- {
+ if (not display_) {
std::cerr << "Failed to create display!" << std::endl;
exit(1);
}
wl_display_add_global_listener(display_, handleGlobal, this);
wl_display_iterate(display_, WL_DISPLAY_READABLE);
- if (initEGL() < 0)
- {
- std::cerr << "Failed to initialize egl!" << std::endl;
+ wl_display_roundtrip(display_);
+
+ if (not (formats_ & (1 << WL_SHM_FORMAT_XRGB8888))) {
+ std::cerr << "WL_SHM_FORMAT_XRGB32 not available!" << std::endl;
exit(1);
}
+
+ wl_display_get_fd(display_, evtMaskUpdate, this);
}
-bool Display::initEGL()
+Display::~Display()
{
- EGLint major, minor, n;
-
- static const EGLint argb_cfg_attribs[] = {
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, 1,
- EGL_DEPTH_SIZE, 1,
- EGL_RENDERABLE_TYPE, GL_BIT,
- EGL_NONE
- };
-
-#ifdef USE_CAIRO_GLESV2
- static const EGLint context_attribs[] = {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- EGLint api = EGL_OPENGL_ES_API;
-#else
- EGLint *context_attribs = NULL;
- EGLint api = EGL_OPENGL_API;
-#endif
-
- eglDisplay_ = eglGetDisplay( (EGLNativeDisplayType)display_);
- if (not eglInitialize(eglDisplay_, &major, &minor))
- {
-// fprintf(stderr, "failed to initialize display\n");
- return false;
+ if (shm_) {
+ wl_shm_destroy(shm_);
}
- if (not eglBindAPI(api))
- {
-// fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
- return false;
+ if (shell_) {
+ wl_shell_destroy(shell_);
}
- if (not eglChooseConfig(eglDisplay_, argb_cfg_attribs,
- &argbConfig_, 1, &n) || n != 1)
- {
-// fprintf(stderr, "failed to choose argb config\n");
- return false;
+ if (compositor_) {
+ wl_compositor_destroy(compositor_);
}
- argbContext_ = eglCreateContext(eglDisplay_, argbConfig_,
- EGL_NO_CONTEXT, context_attribs);
- if (not argbContext_)
- {
-// fprintf(stderr, "failed to create context\n");
- return false;
+ wl_display_flush(display_);
+ wl_display_disconnect(display_);
+}
+
+wl_buffer* Display::createShmBuffer(int w, int h, uint32_t format, void** dout)
+{
+ char filename[] = "/tmp/wayland-shm-XXXXXX";
+ int fd(mkstemp(filename));
+
+ if (fd < 0) {
+ std::cerr << "open " << filename << " failed: %m" << std::endl;
+ return NULL;
}
- if (not eglMakeCurrent(eglDisplay_, NULL, NULL, argbContext_))
- {
-// fprintf(stderr, "failed to make context current\n");
- return false;
+ int stride(w * 4);
+ int size(stride * h);
+
+ if (ftruncate(fd, size) < 0) {
+ std::cerr << "ftruncate failed: %m" << std::endl;
+ close(fd);
+ return NULL;
}
-#ifdef HAVE_CAIRO_EGL
- argbDevice_ = cairo_egl_device_create(eglDisplay_, argbContext_);
- if (cairo_device_status(argbDevice_) != CAIRO_STATUS_SUCCESS)
- {
-// fprintf(stderr, "failed to get cairo egl argb device\n");
- return false;
+ void* data(
+ mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)
+ );
+ unlink(filename);
+
+ if (data == MAP_FAILED) {
+ std::cerr << "mmap failed: %m" << std::endl;
+ close(fd);
+ return NULL;
}
-#endif
- return true;
-}
+ wl_shm_pool* pool(
+ wl_shm_create_pool(shm_, fd, size)
+ );
+
+ wl_buffer* buffer(
+ wl_shm_pool_create_buffer(pool, 0, w, h, stride, format)
+ );
+
+ wl_shm_pool_destroy(pool);
+ close(fd);
+
+ *dout = data;
+
+ return buffer;
+}
} // namespace wayland
#ifndef __WAYLAND_DISPLAY_H__
#define __WAYLAND_DISPLAY_H__
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-#ifdef USE_CAIRO_GLESV2
- #include <GLES2/gl2.h>
- #include <GLES2/gl2ext.h>
-
- #define GL_BIT EGL_OPENGL_ES2_BIT
-#else
- #include <GL/gl.h>
- #define GL_BIT EGL_OPENGL_BIT
-#endif
-
-#ifdef HAVE_CAIRO_EGL
- #include <cairo-gl.h>
-#endif
-
-
#include <cstdint>
struct wl_display;
struct wl_compositor;
struct wl_shell;
+struct wl_shm;
+struct wl_buffer;
+struct wl_shm_listener;
namespace wayland {
public:
Display();
+ virtual ~Display();
+
wl_compositor* compositor() { return compositor_; }
wl_display* display() { return display_; }
wl_shell* shell() { return shell_; }
- EGLConfig& config() { return argbConfig_; }
- EGLContext& context() { return argbContext_; }
+
+ wl_buffer* createShmBuffer(int, int, uint32_t, void**);
private:
wl_display* display_;
- uint32_t mask_;
+ uint32_t formats_;
wl_compositor* compositor_;
wl_shell* shell_;
-
- bool running_;
-
- EGLDisplay eglDisplay_;
- EGLConfig argbConfig_;
- EGLContext argbContext_;
+ wl_shm* shm_;
+ uint32_t mask_;
static int evtMaskUpdate(uint32_t, void*);
+ static void handleShmFormat(void*, wl_shm*, uint32_t);
static void handleGlobal(wl_display*, uint32_t, const char*, uint32_t, void*);
- bool initEGL();
+ static wl_shm_listener shmListener_;
};
} // namespace wayland
#include <cassert>
#include <wayland-client.h>
-#include <wayland-egl.h>
#include "window.h"
namespace wayland {
-Window::Window(Display& display)
+Window::Window(Display& display, int width, int height)
: display_(display)
+ , width_(width)
+ , height_(height)
+ , surface_(wl_compositor_create_surface(display_.compositor()))
+ , shellSurface_(wl_shell_get_shell_surface(display_.shell(), surface_))
+ , shmData_(0)
+ , buffer_(
+ display_.createShmBuffer(
+ width_
+ , height_
+ , WL_SHM_FORMAT_XRGB8888
+ , &shmData_
+ )
+ )
+ , callback_(0)
{
- EGLBoolean result;
-
- surface_ = wl_compositor_create_surface(display_.compositor());
- shellSurface_ = wl_shell_get_shell_surface(display_.shell(), surface_);
- native_ = wl_egl_window_create(surface_, width_, height_);
- eglSurface_ = eglCreateWindowSurface(display_.display(), display_.config(), native_, NULL);
-
wl_shell_surface_set_toplevel(shellSurface_);
+}
+
+Window::~Window()
+{
+ if (callback_) {
+ wl_callback_destroy(callback_);
+ }
- assert(
- eglMakeCurrent(display_.display(), eglSurface_, eglSurface_, &display_.context())
- == EGL_TRUE
- );
+ wl_buffer_destroy(buffer_);
+ wl_shell_surface_destroy(shellSurface_);
+ wl_surface_destroy(surface_);
}
} // namespace wayland