4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[Bb]uild*
|
||||||
|
result
|
||||||
|
.cache
|
||||||
|
.direnv
|
||||||
163
CMakeLists.txt
Normal file
163
CMakeLists.txt
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
project(skia_wayland_nodeco LANGUAGES C CXX)
|
||||||
|
|
||||||
|
# --- toolchain & opts ---------------------------------------------------------
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
||||||
|
# --- deps (pkg-config) --------------------------------------------------------
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
|
||||||
|
pkg_check_modules(WAYLAND_EGL REQUIRED wayland-egl)
|
||||||
|
pkg_check_modules(EGL REQUIRED egl)
|
||||||
|
pkg_check_modules(GLES2 REQUIRED glesv2)
|
||||||
|
# Skia package name varies; this works on many distros. Adjust if needed.
|
||||||
|
pkg_check_modules(SKIA REQUIRED skia)
|
||||||
|
# The protocol XMLs live here:
|
||||||
|
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols)
|
||||||
|
|
||||||
|
# --- scanners -----------------------------------------------------------------
|
||||||
|
find_program(WAYLAND_SCANNER wayland-scanner REQUIRED)
|
||||||
|
# waylandpp's generator; provided by the waylandpp package
|
||||||
|
# (typically installed as 'wayland-scanner++')
|
||||||
|
find_program(WAYLAND_SCANNER_PP wayland-scanner++ REQUIRED)
|
||||||
|
|
||||||
|
# --- protocol XML paths -------------------------------------------------------
|
||||||
|
pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir)
|
||||||
|
|
||||||
|
# fallback via datarootdir if needed
|
||||||
|
if(NOT WAYLAND_PROTOCOLS_DIR OR NOT EXISTS "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml")
|
||||||
|
pkg_get_variable(_WP_DATAROOT wayland-protocols datarootdir)
|
||||||
|
if(_WP_DATAROOT AND EXISTS "${_WP_DATAROOT}/wayland-protocols")
|
||||||
|
set(WAYLAND_PROTOCOLS_DIR "${_WP_DATAROOT}/wayland-protocols")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# last-resort search (covers odd layouts)
|
||||||
|
if(NOT WAYLAND_PROTOCOLS_DIR OR NOT EXISTS "${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml")
|
||||||
|
find_path(WAYLAND_PROTOCOLS_DIR
|
||||||
|
NAMES stable/xdg-shell/xdg-shell.xml
|
||||||
|
HINTS ${CMAKE_SYSTEM_PREFIX_PATH}
|
||||||
|
PATH_SUFFIXES wayland-protocols share/wayland-protocols
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT WAYLAND_PROTOCOLS_DIR)
|
||||||
|
message(FATAL_ERROR "Could not locate wayland-protocols datadir (install wayland-protocols?)")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(XDG_SHELL_XML
|
||||||
|
"${WAYLAND_PROTOCOLS_DIR}/stable/xdg-shell/xdg-shell.xml"
|
||||||
|
)
|
||||||
|
set(XDG_DECOR_XML
|
||||||
|
"${WAYLAND_PROTOCOLS_DIR}/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- generated outputs (into build dir) ---------------------------------------
|
||||||
|
set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
|
||||||
|
file(MAKE_DIRECTORY "${GEN_DIR}")
|
||||||
|
|
||||||
|
# waylandpp C++ headers + code (used by the app)
|
||||||
|
set(GEN_CXX_HEADERS
|
||||||
|
"${GEN_DIR}/xdg-shell-client-protocol.hpp"
|
||||||
|
"${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.hpp"
|
||||||
|
)
|
||||||
|
set(GEN_CXX_SOURCES
|
||||||
|
"${GEN_DIR}/xdg-shell-client-protocol.cpp"
|
||||||
|
"${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.cpp"
|
||||||
|
)
|
||||||
|
|
||||||
|
# (optional) C headers + private impls (not linked, but generated)
|
||||||
|
set(GEN_C_HEADERS
|
||||||
|
"${GEN_DIR}/xdg-shell-client-protocol.h"
|
||||||
|
"${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.h"
|
||||||
|
)
|
||||||
|
set(GEN_C_PRIVATES
|
||||||
|
"${GEN_DIR}/xdg-shell-protocol.c"
|
||||||
|
"${GEN_DIR}/xdg-decoration-unstable-v1-protocol.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- custom commands: generate C++ (required) ---------------------------------
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${GEN_CXX_HEADERS} ${GEN_CXX_SOURCES}
|
||||||
|
COMMAND "${WAYLAND_SCANNER_PP}" "${XDG_SHELL_XML}" "${GEN_DIR}/xdg-shell-client-protocol.hpp" "${GEN_DIR}/xdg-shell-client-protocol.cpp"
|
||||||
|
COMMAND "${WAYLAND_SCANNER_PP}" "${XDG_DECOR_XML}" "${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.hpp" "${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.cpp"
|
||||||
|
DEPENDS "${XDG_SHELL_XML}" "${XDG_DECOR_XML}"
|
||||||
|
COMMENT "Generating waylandpp C++ protocol headers/sources with wayland-scanner++"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- custom commands: generate C (optional) -----------------------------------
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${GEN_C_HEADERS} ${GEN_C_PRIVATES}
|
||||||
|
COMMAND "${WAYLAND_SCANNER}" client-header "${XDG_SHELL_XML}" "${GEN_DIR}/xdg-shell-client-protocol.h"
|
||||||
|
COMMAND "${WAYLAND_SCANNER}" private-code "${XDG_SHELL_XML}" "${GEN_DIR}/xdg-shell-protocol.c"
|
||||||
|
COMMAND "${WAYLAND_SCANNER}" client-header "${XDG_DECOR_XML}" "${GEN_DIR}/xdg-decoration-unstable-v1-client-protocol.h"
|
||||||
|
COMMAND "${WAYLAND_SCANNER}" private-code "${XDG_DECOR_XML}" "${GEN_DIR}/xdg-decoration-unstable-v1-protocol.c"
|
||||||
|
DEPENDS "${XDG_SHELL_XML}" "${XDG_DECOR_XML}"
|
||||||
|
COMMENT "Generating C client headers + private code with wayland-scanner (optional)"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_target(generate_protocols ALL
|
||||||
|
DEPENDS ${GEN_CXX_HEADERS} ${GEN_CXX_SOURCES} ${GEN_C_HEADERS} ${GEN_C_PRIVATES}
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- executable ---------------------------------------------------------------
|
||||||
|
add_executable(skia_wayland
|
||||||
|
${GEN_CXX_HEADERS}
|
||||||
|
${GEN_CXX_SOURCES}
|
||||||
|
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
||||||
|
)
|
||||||
|
add_dependencies(skia_wayland generate_protocols)
|
||||||
|
|
||||||
|
# include dirs (system + generated)
|
||||||
|
target_include_directories(skia_wayland PRIVATE
|
||||||
|
${WAYLAND_CLIENT_INCLUDE_DIRS}
|
||||||
|
${WAYLAND_EGL_INCLUDE_DIRS}
|
||||||
|
${EGL_INCLUDE_DIRS}
|
||||||
|
${GLES2_INCLUDE_DIRS}
|
||||||
|
${SKIA_INCLUDE_DIRS}
|
||||||
|
# waylandpp headers (wayland-client.hpp). If they aren't system-wide, add your path here:
|
||||||
|
# ${CMAKE_CURRENT_SOURCE_DIR}/external/waylandpp/include
|
||||||
|
${GEN_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# libs
|
||||||
|
target_link_libraries(skia_wayland PRIVATE
|
||||||
|
${WAYLAND_CLIENT_LIBRARIES}
|
||||||
|
${WAYLAND_EGL_LIBRARIES}
|
||||||
|
${EGL_LIBRARIES}
|
||||||
|
${GLES2_LIBRARIES}
|
||||||
|
${SKIA_LIBRARIES}
|
||||||
|
# some distros need these as well:
|
||||||
|
m
|
||||||
|
dl
|
||||||
|
pthread
|
||||||
|
)
|
||||||
|
|
||||||
|
# cflags/ldflags from pkg-config
|
||||||
|
target_compile_options(skia_wayland PRIVATE
|
||||||
|
${WAYLAND_CLIENT_CFLAGS_OTHER}
|
||||||
|
${WAYLAND_EGL_CFLAGS_OTHER}
|
||||||
|
${EGL_CFLAGS_OTHER}
|
||||||
|
${GLES2_CFLAGS_OTHER}
|
||||||
|
${SKIA_CFLAGS_OTHER}
|
||||||
|
)
|
||||||
|
target_link_options(skia_wayland PRIVATE
|
||||||
|
${WAYLAND_CLIENT_LDFLAGS_OTHER}
|
||||||
|
${WAYLAND_EGL_LDFLAGS_OTHER}
|
||||||
|
${EGL_LDFLAGS_OTHER}
|
||||||
|
${GLES2_LDFLAGS_OTHER}
|
||||||
|
${SKIA_LDFLAGS_OTHER}
|
||||||
|
)
|
||||||
|
|
||||||
|
# --- warnings -----------------------------------------------------------------
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
|
||||||
|
target_compile_options(skia_wayland PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# --- install (optional) -------------------------------------------------------
|
||||||
|
install(TARGETS skia_wayland RUNTIME DESTINATION bin)
|
||||||
59
flake.lock
generated
Normal file
59
flake.lock
generated
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1759381078,
|
||||||
|
"narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
|
||||||
|
"rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
|
||||||
|
"revCount": 870157,
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.870157%2Brev-7df7ff7d8e00218376575f0acdcc5d66741351ee/0199a6ee-287f-71cc-b285-5fb880bb8f7f/source.tar.gz?rev=7df7ff7d8e00218376575f0acdcc5d66741351ee&revCount=870157"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://flakehub.com/f/NixOS/nixpkgs/0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
60
flake.nix
Normal file
60
flake.nix
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
description = "My flake";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs { inherit system; };
|
||||||
|
nativeBuildInputs = [ ];
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
cmake
|
||||||
|
ninja
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
devShells.default = pkgs.mkShell.override { stdenv = pkgs.llvmPackages_21.libcxxStdenv; } {
|
||||||
|
packages =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
llvmPackages_21.clang-tools
|
||||||
|
lldb
|
||||||
|
codespell
|
||||||
|
doxygen
|
||||||
|
gtest
|
||||||
|
cppcheck
|
||||||
|
|
||||||
|
pkg-config
|
||||||
|
wayland
|
||||||
|
wayland-protocols
|
||||||
|
wayland-scanner
|
||||||
|
waylandpp
|
||||||
|
libGL
|
||||||
|
skia
|
||||||
|
]
|
||||||
|
++ buildInputs
|
||||||
|
++ nativeBuildInputs
|
||||||
|
++ pkgs.lib.optionals pkgs.stdenv.isLinux (
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
|
valgrind-light
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
env = { };
|
||||||
|
|
||||||
|
shellHook = '''';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
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