200
main.cpp
Normal file
200
main.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "xdg-shell-client-protocol.hpp"
|
||||
|
||||
#include "xdg-decoration-unstable-v1-client-protocol.hpp"
|
||||
|
||||
#include <wayland-client-protocol.hpp>
|
||||
#include <wayland-client.hpp>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <GLES2/gl2.h>
|
||||
#include <wayland-egl.h>
|
||||
|
||||
#include <skia/core/SkCanvas.h>
|
||||
#include <skia/core/SkColor.h>
|
||||
#include <skia/core/SkFont.h>
|
||||
#include <skia/core/SkPaint.h>
|
||||
#include <skia/core/SkSurface.h>
|
||||
#include <skia/core/SkTextBlob.h>
|
||||
#include <skia/gpu/GrDirectContext.h>
|
||||
#include <skia/gpu/ganesh/SkSurfaceGanesh.h>
|
||||
#include <skia/gpu/gl/GrGLInterface.h>
|
||||
#include <skia/gpu/gl/GrGLTypes.h>
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <thread>
|
||||
|
||||
struct App {
|
||||
wayland::display_t display;
|
||||
wayland::registry_t registry;
|
||||
wayland::compositor_t compositor;
|
||||
wayland::xdg_wm_base_t xdg_wm;
|
||||
wayland::zxdg_decoration_manager_v1_t dec_mgr;
|
||||
wayland::surface_t wl_surface;
|
||||
wayland::xdg_surface_t xdg_surface;
|
||||
wayland::xdg_toplevel_t xdg_toplevel;
|
||||
|
||||
EGLDisplay edpy = EGL_NO_DISPLAY;
|
||||
EGLConfig ecfg = nullptr;
|
||||
EGLContext ectx = EGL_NO_CONTEXT;
|
||||
EGLSurface esurf = EGL_NO_SURFACE;
|
||||
wl_egl_window *wegl = nullptr;
|
||||
|
||||
sk_sp<const GrGLInterface> gl_iface;
|
||||
sk_sp<GrDirectContext> gr_ctx;
|
||||
sk_sp<SkSurface> sk_surface;
|
||||
|
||||
int win_w = 800, win_h = 600;
|
||||
bool running = true;
|
||||
|
||||
void init_wayland() {
|
||||
registry = display.get_registry();
|
||||
registry.on_global() = [&](uint32_t name, const std::string &iface,
|
||||
uint32_t ver) {
|
||||
if (iface == wayland::compositor_t::interface_name)
|
||||
compositor = registry.bind<wayland::compositor_t>(
|
||||
name, std::min<uint32_t>(ver, 4));
|
||||
else if (iface == wayland::xdg_wm_base_t::interface_name)
|
||||
xdg_wm = registry.bind<xdg_wm_base_t>(name, 1);
|
||||
else if (iface == wayland::zxdg_decoration_manager_v1_t::interface_name)
|
||||
dec_mgr = registry.bind<wayland::zxdg_decoration_manager_v1_t>(name, 1);
|
||||
};
|
||||
xdg_wm.on_ping() = [&](uint32_t serial) { xdg_wm.pong(serial); };
|
||||
display.roundtrip();
|
||||
if (!compositor || !xdg_wm) {
|
||||
fprintf(stderr, "missing compositor\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wl_surface = compositor.create_surface();
|
||||
xdg_surface = xdg_wm.get_xdg_surface(wl_surface);
|
||||
xdg_toplevel = xdg_surface.get_toplevel();
|
||||
|
||||
if (dec_mgr) {
|
||||
auto deco = dec_mgr.get_toplevel_decoration(xdg_toplevel);
|
||||
deco.set_mode(wayland::zxdg_toplevel_decoration_v1_mode::client_side);
|
||||
}
|
||||
xdg_toplevel.set_title("Skia Hello World");
|
||||
xdg_toplevel.on_close() = [&] { running = false; };
|
||||
|
||||
xdg_surface.on_configure() = [&](uint32_t serial) {
|
||||
xdg_surface.ack_configure(serial);
|
||||
wl_surface.commit();
|
||||
};
|
||||
xdg_toplevel.on_configure() = [&](int32_t w, int32_t h,
|
||||
std::vector<uint32_t>) {
|
||||
if (w > 0 && h > 0 && (w != win_w || h != win_h)) {
|
||||
win_w = w;
|
||||
win_h = h;
|
||||
if (wegl) {
|
||||
wl_egl_window_resize(wegl, win_w, win_h, 0, 0);
|
||||
recreate_skia_surface();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
wl_surface.commit();
|
||||
display.roundtrip();
|
||||
}
|
||||
|
||||
void init_egl() {
|
||||
edpy = eglGetDisplay((EGLNativeDisplayType)display.c_ptr());
|
||||
eglInitialize(edpy, nullptr, nullptr);
|
||||
|
||||
const EGLint cfgAttribs[] = {EGL_SURFACE_TYPE,
|
||||
EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE,
|
||||
EGL_OPENGL_ES2_BIT,
|
||||
EGL_RED_SIZE,
|
||||
8,
|
||||
EGL_GREEN_SIZE,
|
||||
8,
|
||||
EGL_BLUE_SIZE,
|
||||
8,
|
||||
EGL_ALPHA_SIZE,
|
||||
8,
|
||||
EGL_NONE};
|
||||
EGLint n = 0;
|
||||
eglChooseConfig(edpy, cfgAttribs, &ecfg, 1, &n);
|
||||
const EGLint ctxAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
ectx = eglCreateContext(edpy, ecfg, EGL_NO_CONTEXT, ctxAttribs);
|
||||
wegl = wl_egl_window_create(wl_surface, win_w, win_h);
|
||||
esurf =
|
||||
eglCreateWindowSurface(edpy, ecfg, (EGLNativeWindowType)wegl, nullptr);
|
||||
eglMakeCurrent(edpy, esurf, esurf, ectx);
|
||||
eglSwapInterval(edpy, 1);
|
||||
}
|
||||
|
||||
void init_skia() {
|
||||
gl_iface = GrGLMakeNativeInterface();
|
||||
gr_ctx = GrDirectContext::MakeGL(gl_iface);
|
||||
recreate_skia_surface();
|
||||
}
|
||||
|
||||
void recreate_skia_surface() {
|
||||
GrGLFramebufferInfo fbInfo{0, GL_RGBA8};
|
||||
GrBackendRenderTarget backendRT(win_w, win_h, 0, 8, fbInfo);
|
||||
SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
|
||||
sk_surface = SkSurfaces::WrapBackendRenderTarget(
|
||||
gr_ctx.get(), backendRT, kBottomLeft_GrSurfaceOrigin,
|
||||
kRGBA_8888_SkColorType, nullptr, &props);
|
||||
}
|
||||
|
||||
void draw_frame() {
|
||||
SkCanvas *c = sk_surface->getCanvas();
|
||||
c->clear(SkColorSetARGB(255, 20, 22, 26));
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setColor(SkColorSetARGB(255, 240, 240, 255));
|
||||
|
||||
SkFont font;
|
||||
font.setSize(48);
|
||||
|
||||
const char *text = "Hello, world!";
|
||||
SkRect bounds;
|
||||
font.measureText(text, strlen(text), SkTextEncoding::kUTF8, &bounds);
|
||||
|
||||
float x = (win_w - bounds.width()) / 2 - bounds.left();
|
||||
float y = (win_h + bounds.height()) / 2 - bounds.bottom();
|
||||
|
||||
c->drawSimpleText(text, strlen(text), SkTextEncoding::kUTF8, x, y, font,
|
||||
paint);
|
||||
|
||||
sk_surface->flushAndSubmit();
|
||||
eglSwapBuffers(edpy, esurf);
|
||||
}
|
||||
|
||||
void run() {
|
||||
while (running) {
|
||||
display.dispatch_pending();
|
||||
display.flush();
|
||||
draw_frame();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
||||
}
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
gr_ctx->flushAndSubmit();
|
||||
gr_ctx->releaseResourcesAndAbandonContext();
|
||||
sk_surface.reset();
|
||||
gl_iface.reset();
|
||||
eglMakeCurrent(edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroySurface(edpy, esurf);
|
||||
wl_egl_window_destroy(wegl);
|
||||
eglDestroyContext(edpy, ectx);
|
||||
eglTerminate(edpy);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
App a;
|
||||
a.init_wayland();
|
||||
a.init_egl();
|
||||
a.init_skia();
|
||||
a.run();
|
||||
a.cleanup();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user