we wrote a single frame. yipeeeee
This commit is contained in:
382
src/main.cpp
382
src/main.cpp
@@ -1,33 +1,158 @@
|
|||||||
#include "spdlog/spdlog.h"
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <glad/gles2.h>
|
||||||
|
|
||||||
#include <wayland-client-core.h>
|
#include <wayland-client-core.h>
|
||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
#include <wayland-egl-core.h>
|
#include <wayland-egl-core.h>
|
||||||
|
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
|
|
||||||
static void output_handle_geometry(void* data, wl_output* output,
|
// ============================================================================
|
||||||
int32_t x, int32_t y, int32_t physical_width, int32_t physical_height,
|
// EGL setup
|
||||||
int32_t subpixel, const char* make, const char* model, int32_t transform)
|
// ============================================================================
|
||||||
{
|
|
||||||
auto& out = *static_cast<state::Output*>(data);
|
void init_egl(state::LockScreenState& ctx) {
|
||||||
spdlog::debug("Output: {} {}", make, model);
|
ctx.egl_display = eglGetDisplay((EGLNativeDisplayType)ctx.display);
|
||||||
|
if (ctx.egl_display == EGL_NO_DISPLAY) {
|
||||||
|
throw std::runtime_error("Failed to get EGL display");
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLint major = 0, minor = 0;
|
||||||
|
if (!eglInitialize(ctx.egl_display, &major, &minor)) {
|
||||||
|
throw std::runtime_error("Failed to initialize EGL");
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("EGL version {}.{}", major, minor);
|
||||||
|
|
||||||
|
if (!eglBindAPI(EGL_OPENGL_ES_API)) {
|
||||||
|
throw std::runtime_error("Failed to bind OpenGL ES API");
|
||||||
|
}
|
||||||
|
|
||||||
|
const EGLint config_attribs[] = {
|
||||||
|
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 num_configs = 0;
|
||||||
|
if (!eglChooseConfig(ctx.egl_display,
|
||||||
|
config_attribs,
|
||||||
|
&ctx.egl_config,
|
||||||
|
1,
|
||||||
|
&num_configs) ||
|
||||||
|
num_configs == 0) {
|
||||||
|
throw std::runtime_error("Failed to choose EGL config");
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("EGL initialized successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_handle_mode(void* data, wl_output* output,
|
void create_egl_surface_for_output(state::LockScreenState& ctx,
|
||||||
uint32_t flags, int32_t width, int32_t height, int32_t refresh)
|
state::Output& out,
|
||||||
{
|
bool load_glad) {
|
||||||
|
if (!out.configured) {
|
||||||
|
throw std::runtime_error("Output not configured");
|
||||||
|
}
|
||||||
|
|
||||||
|
out.window = wl_egl_window_create(out.wl_out_surface,
|
||||||
|
out.surface_width,
|
||||||
|
out.surface_height);
|
||||||
|
if (!out.window) {
|
||||||
|
throw std::runtime_error("Failed to create wl_egl_window");
|
||||||
|
}
|
||||||
|
|
||||||
|
out.egl_surface = eglCreateWindowSurface(
|
||||||
|
ctx.egl_display,
|
||||||
|
ctx.egl_config,
|
||||||
|
(EGLNativeWindowType)out.window,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
if (out.egl_surface == EGL_NO_SURFACE) {
|
||||||
|
throw std::runtime_error("Failed to create EGL surface");
|
||||||
|
}
|
||||||
|
|
||||||
|
const EGLint context_attribs[] = {
|
||||||
|
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||||
|
EGL_NONE
|
||||||
|
};
|
||||||
|
|
||||||
|
out.egl_context = eglCreateContext(ctx.egl_display,
|
||||||
|
ctx.egl_config,
|
||||||
|
EGL_NO_CONTEXT,
|
||||||
|
context_attribs);
|
||||||
|
|
||||||
|
if (out.egl_context == EGL_NO_CONTEXT) {
|
||||||
|
throw std::runtime_error("Failed to create EGL context");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglMakeCurrent(ctx.egl_display,
|
||||||
|
out.egl_surface,
|
||||||
|
out.egl_surface,
|
||||||
|
out.egl_context)) {
|
||||||
|
throw std::runtime_error("eglMakeCurrent failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (load_glad) {
|
||||||
|
if (!gladLoadGLES2((GLADloadfunc)eglGetProcAddress)) {
|
||||||
|
throw std::runtime_error("Failed to load GLAD");
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("GL_VENDOR = {}",
|
||||||
|
reinterpret_cast<const char*>(glGetString(GL_VENDOR)));
|
||||||
|
spdlog::info("GL_RENDERER = {}",
|
||||||
|
reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
|
||||||
|
spdlog::info("GL_VERSION = {}",
|
||||||
|
reinterpret_cast<const char*>(glGetString(GL_VERSION)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("EGL surface created for output {} ({}x{})",
|
||||||
|
out.registry_id,
|
||||||
|
out.surface_width,
|
||||||
|
out.surface_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Wayland listeners
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
static void output_handle_geometry(void*, wl_output*, int32_t, int32_t,
|
||||||
|
int32_t, int32_t, int32_t,
|
||||||
|
const char*, const char*, int32_t) {}
|
||||||
|
|
||||||
|
static void output_handle_mode(void* data,
|
||||||
|
wl_output*,
|
||||||
|
uint32_t flags,
|
||||||
|
int32_t width,
|
||||||
|
int32_t height,
|
||||||
|
int32_t refresh) {
|
||||||
|
if (!(flags & WL_OUTPUT_MODE_CURRENT)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto& out = *static_cast<state::Output*>(data);
|
auto& out = *static_cast<state::Output*>(data);
|
||||||
if (flags & WL_OUTPUT_MODE_CURRENT) {
|
|
||||||
out.width = static_cast<uint32_t>(width);
|
out.width = static_cast<uint32_t>(width);
|
||||||
out.height = static_cast<uint32_t>(height);
|
out.height = static_cast<uint32_t>(height);
|
||||||
spdlog::info("Output mode: {}x{} @ {}Hz", width, height, refresh / 1000);
|
|
||||||
}
|
spdlog::info("Output mode {}x{} @ {}Hz",
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
refresh / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void output_handle_done(void* data, wl_output* output) {}
|
static void output_handle_done(void*, wl_output*) {}
|
||||||
static void output_handle_scale(void* data, wl_output* output, int32_t factor) {}
|
static void output_handle_scale(void*, wl_output*, int32_t) {}
|
||||||
|
|
||||||
static const wl_output_listener output_listener = {
|
static const wl_output_listener output_listener = {
|
||||||
.geometry = output_handle_geometry,
|
.geometry = output_handle_geometry,
|
||||||
@@ -36,73 +161,61 @@ static const wl_output_listener output_listener = {
|
|||||||
.scale = output_handle_scale,
|
.scale = output_handle_scale,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Registry callbacks - discover globals
|
static void registry_handle_global(void* data,
|
||||||
static void registry_handle_global(
|
|
||||||
void* data,
|
|
||||||
wl_registry* registry,
|
wl_registry* registry,
|
||||||
uint32_t name,
|
uint32_t name,
|
||||||
const char* interface,
|
const char* interface,
|
||||||
uint32_t version)
|
uint32_t) {
|
||||||
{
|
|
||||||
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
||||||
|
|
||||||
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||||
ctx.compostier = static_cast<wl_compositor*>(
|
ctx.compostier = static_cast<wl_compositor*>(
|
||||||
wl_registry_bind(registry, name, &wl_compositor_interface, 6)
|
wl_registry_bind(registry,
|
||||||
);
|
name,
|
||||||
spdlog::info("Bound to wl_compositor");
|
&wl_compositor_interface,
|
||||||
}
|
6));
|
||||||
else if (strcmp(interface, wl_output_interface.name) == 0) {
|
} else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
auto output = std::make_shared<state::Output>();
|
auto out = std::make_shared<state::Output>();
|
||||||
output->output = static_cast<wl_output*>(
|
out->output = static_cast<wl_output*>(
|
||||||
wl_registry_bind(registry, name, &wl_output_interface, 4)
|
wl_registry_bind(registry,
|
||||||
);
|
name,
|
||||||
output->registry_id = name;
|
&wl_output_interface,
|
||||||
|
4));
|
||||||
|
out->registry_id = name;
|
||||||
|
|
||||||
ctx.outputs.push_back(output);
|
wl_output_add_listener(out->output,
|
||||||
|
&output_listener,
|
||||||
|
out.get());
|
||||||
|
|
||||||
// Pass raw pointer to the Output object
|
ctx.outputs.push_back(out);
|
||||||
wl_output_add_listener(output->output, &output_listener, output.get());
|
} else if (strcmp(interface,
|
||||||
|
ext_session_lock_manager_v1_interface.name) == 0) {
|
||||||
spdlog::info("Discovered output (registry_id={})", name);
|
ctx.lock_manager =
|
||||||
}
|
static_cast<ext_session_lock_manager_v1*>(
|
||||||
else if (strcmp(interface, ext_session_lock_manager_v1_interface.name) == 0) {
|
wl_registry_bind(registry,
|
||||||
ctx.lock_manager = static_cast<ext_session_lock_manager_v1*>(
|
name,
|
||||||
wl_registry_bind(registry, name, &ext_session_lock_manager_v1_interface, 1)
|
&ext_session_lock_manager_v1_interface,
|
||||||
);
|
1));
|
||||||
spdlog::info("Bound to ext_session_lock_manager_v1");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_handle_global_remove(void* data, wl_registry* registry, uint32_t name) {
|
static void registry_handle_global_remove(void*, wl_registry*, uint32_t) {}
|
||||||
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
|
||||||
|
|
||||||
spdlog::debug("Global removed: {}", name);
|
|
||||||
|
|
||||||
// Remove output if it matches
|
|
||||||
ctx.outputs.erase(
|
|
||||||
std::remove_if(ctx.outputs.begin(), ctx.outputs.end(),
|
|
||||||
[name](const auto& out) { return out->registry_id == name; }),
|
|
||||||
ctx.outputs.end()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const wl_registry_listener registry_listener = {
|
static const wl_registry_listener registry_listener = {
|
||||||
.global = registry_handle_global,
|
.global = registry_handle_global,
|
||||||
.global_remove = registry_handle_global_remove,
|
.global_remove = registry_handle_global_remove,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void lock_handle_locked(void* data, ext_session_lock_v1*) {
|
||||||
static void lock_handle_locked(void* data, ext_session_lock_v1* lock) {
|
|
||||||
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
||||||
ctx.locked = true;
|
ctx.locked = true;
|
||||||
spdlog::info("🔒 Session LOCKED! We now control all input");
|
spdlog::info("🔒 Session locked");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lock_handle_finished(void* data, ext_session_lock_v1* lock) {
|
static void lock_handle_finished(void* data, ext_session_lock_v1*) {
|
||||||
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
auto& ctx = *static_cast<state::LockScreenState*>(data);
|
||||||
spdlog::error("Lock finished/denied by compositor - exiting");
|
|
||||||
ctx.running = false;
|
ctx.running = false;
|
||||||
|
spdlog::error("Session lock denied/finished");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ext_session_lock_v1_listener lock_listener = {
|
static const ext_session_lock_v1_listener lock_listener = {
|
||||||
@@ -110,105 +223,126 @@ static const ext_session_lock_v1_listener lock_listener = {
|
|||||||
.finished = lock_handle_finished,
|
.finished = lock_handle_finished,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void lock_surface_handle_configure(
|
static void lock_surface_handle_configure(void* data,
|
||||||
void* data,
|
ext_session_lock_surface_v1* surface,
|
||||||
ext_session_lock_surface_v1* lock_surface,
|
|
||||||
uint32_t serial,
|
uint32_t serial,
|
||||||
uint32_t width,
|
uint32_t width,
|
||||||
uint32_t height)
|
uint32_t height) {
|
||||||
{
|
|
||||||
auto& out = *static_cast<state::Output*>(data);
|
auto& out = *static_cast<state::Output*>(data);
|
||||||
|
|
||||||
// MUST acknowledge the configure
|
ext_session_lock_surface_v1_ack_configure(surface, serial);
|
||||||
ext_session_lock_surface_v1_ack_configure(lock_surface, serial);
|
|
||||||
|
|
||||||
out.surface_width = width;
|
out.surface_width = width;
|
||||||
out.surface_height = height;
|
out.surface_height = height;
|
||||||
out.configured = true;
|
out.configured = true;
|
||||||
|
|
||||||
spdlog::info("Lock surface configured: {}x{}", width, height);
|
spdlog::info("Lock surface configured {}x{}", width, height);
|
||||||
|
|
||||||
// TODO: Create EGL surface here with these dimensions
|
|
||||||
// TODO: Render first frame
|
|
||||||
|
|
||||||
// For now, just commit an empty surface
|
|
||||||
wl_surface_commit(out.wl_out_surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ext_session_lock_surface_v1_listener lock_surface_listener = {
|
static const ext_session_lock_surface_v1_listener lock_surface_listener = {
|
||||||
.configure = lock_surface_handle_configure,
|
.configure = lock_surface_handle_configure,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Main
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
int main (int argc, char *argv[]) {
|
int main() {
|
||||||
std::shared_ptr<state::LockScreenState> application_state = std::make_shared<state::LockScreenState>();
|
auto ctx = std::make_shared<state::LockScreenState>();
|
||||||
application_state->display = wl_display_connect(nullptr);
|
|
||||||
|
|
||||||
if(!application_state->display) throw std::runtime_error("failed to initialize display");
|
ctx->display = wl_display_connect(nullptr);
|
||||||
spdlog::debug("Successfully initialized a display");
|
if (!ctx->display) {
|
||||||
|
throw std::runtime_error("Failed to connect to Wayland");
|
||||||
application_state->compositer_registry = wl_display_get_registry(application_state->display);
|
|
||||||
|
|
||||||
application_state->compositer_registry = wl_display_get_registry(application_state->display);
|
|
||||||
wl_registry_add_listener(application_state->compositer_registry, ®istry_listener, application_state.get());
|
|
||||||
|
|
||||||
// Process all registry events
|
|
||||||
wl_display_roundtrip(application_state->display);
|
|
||||||
|
|
||||||
// Validate we got what we need
|
|
||||||
if (!application_state->compostier) {
|
|
||||||
throw std::runtime_error("Compositor doesn't support wl_compositor");
|
|
||||||
}
|
|
||||||
if (!application_state->lock_manager) {
|
|
||||||
throw std::runtime_error("Compositor doesn't support ext_session_lock_manager_v1");
|
|
||||||
}
|
|
||||||
if (application_state->outputs.empty()) {
|
|
||||||
throw std::runtime_error("No outputs found");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::info("Found {} output(s)", application_state->outputs.size());
|
wl_registry* registry = wl_display_get_registry(ctx->display);
|
||||||
|
wl_registry_add_listener(registry,
|
||||||
|
®istry_listener,
|
||||||
|
ctx.get());
|
||||||
|
wl_display_roundtrip(ctx->display);
|
||||||
|
|
||||||
spdlog::info("Found {} output(s)", application_state->outputs.size());
|
if (!ctx->compostier || !ctx->lock_manager || ctx->outputs.empty()) {
|
||||||
|
throw std::runtime_error("Required Wayland globals missing");
|
||||||
|
}
|
||||||
|
|
||||||
// Request lock session
|
ctx->session_lock =
|
||||||
spdlog::info("Requesting session lock...");
|
ext_session_lock_manager_v1_lock(ctx->lock_manager);
|
||||||
application_state->session_lock = ext_session_lock_manager_v1_lock(application_state->lock_manager);
|
ext_session_lock_v1_add_listener(ctx->session_lock,
|
||||||
ext_session_lock_v1_add_listener(application_state->session_lock, &lock_listener, application_state.get());
|
&lock_listener,
|
||||||
|
ctx.get());
|
||||||
|
|
||||||
// Create lock surface for each output
|
for (auto& out : ctx->outputs) {
|
||||||
for (auto& output : application_state->outputs) {
|
out->wl_out_surface =
|
||||||
// Create Wayland surface
|
wl_compositor_create_surface(ctx->compostier);
|
||||||
output->wl_out_surface= wl_compositor_create_surface(application_state->compostier);
|
|
||||||
|
|
||||||
// Get lock surface for this output
|
out->lock_surface =
|
||||||
output->lock_surface = ext_session_lock_v1_get_lock_surface(
|
ext_session_lock_v1_get_lock_surface(
|
||||||
application_state->session_lock,
|
ctx->session_lock,
|
||||||
output->wl_out_surface,
|
out->wl_out_surface,
|
||||||
output->output
|
out->output);
|
||||||
);
|
|
||||||
|
|
||||||
// Add listener for configure events
|
|
||||||
ext_session_lock_surface_v1_add_listener(
|
ext_session_lock_surface_v1_add_listener(
|
||||||
output->lock_surface,
|
out->lock_surface,
|
||||||
&lock_surface_listener,
|
&lock_surface_listener,
|
||||||
output.get()
|
out.get());
|
||||||
);
|
|
||||||
|
|
||||||
// Commit to trigger configure
|
wl_surface_commit(out->wl_out_surface);
|
||||||
wl_surface_commit(output->wl_out_surface);
|
|
||||||
|
|
||||||
spdlog::debug("Created lock surface for output {}", output->registry_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush and wait for configure/locked events
|
wl_display_roundtrip(ctx->display);
|
||||||
wl_display_flush(application_state->display);
|
|
||||||
wl_display_roundtrip(application_state->display);
|
|
||||||
|
|
||||||
if (!application_state->locked) {
|
init_egl(*ctx);
|
||||||
throw std::runtime_error("Failed to acquire lock");
|
|
||||||
|
bool glad_loaded = false;
|
||||||
|
|
||||||
|
for (auto& out : ctx->outputs) {
|
||||||
|
create_egl_surface_for_output(*ctx,
|
||||||
|
*out,
|
||||||
|
!glad_loaded);
|
||||||
|
glad_loaded = true;
|
||||||
|
|
||||||
|
glViewport(0, 0,
|
||||||
|
out->surface_width,
|
||||||
|
out->surface_height);
|
||||||
|
glClearColor(0.1f, 0.1f, 0.2f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
eglSwapBuffers(ctx->egl_display, out->egl_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
spdlog::info("✅ Lock acquired successfully!");
|
wl_display_roundtrip(ctx->display);
|
||||||
|
|
||||||
|
// ======================
|
||||||
|
// CLEAN SHUTDOWN
|
||||||
|
// ======================
|
||||||
|
|
||||||
|
for (auto& out : ctx->outputs) {
|
||||||
|
if (out->egl_context != EGL_NO_CONTEXT) {
|
||||||
|
eglDestroyContext(ctx->egl_display, out->egl_context);
|
||||||
|
}
|
||||||
|
if (out->egl_surface != EGL_NO_SURFACE) {
|
||||||
|
eglDestroySurface(ctx->egl_display, out->egl_surface);
|
||||||
|
}
|
||||||
|
if (out->window) {
|
||||||
|
wl_egl_window_destroy(out->window);
|
||||||
|
}
|
||||||
|
if (out->lock_surface) {
|
||||||
|
ext_session_lock_surface_v1_destroy(out->lock_surface);
|
||||||
|
}
|
||||||
|
if (out->wl_out_surface) {
|
||||||
|
wl_surface_destroy(out->wl_out_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->session_lock) {
|
||||||
|
ext_session_lock_v1_destroy(ctx->session_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
eglTerminate(ctx->egl_display);
|
||||||
|
wl_display_disconnect(ctx->display);
|
||||||
|
|
||||||
|
spdlog::info("Exited cleanly after one frame");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ namespace state{
|
|||||||
// IMPORTANT: Clear outputs BEFORE destroying display
|
// IMPORTANT: Clear outputs BEFORE destroying display
|
||||||
// This ensures Output destructors run while display is still valid
|
// This ensures Output destructors run while display is still valid
|
||||||
outputs.clear();
|
outputs.clear();
|
||||||
|
if (egl_display != EGL_NO_DISPLAY) {
|
||||||
|
eglTerminate(egl_display);
|
||||||
|
egl_display = EGL_NO_DISPLAY;
|
||||||
|
}
|
||||||
if (lock_manager) {
|
if (lock_manager) {
|
||||||
ext_session_lock_manager_v1_destroy(lock_manager);
|
ext_session_lock_manager_v1_destroy(lock_manager);
|
||||||
lock_manager = nullptr;
|
lock_manager = nullptr;
|
||||||
@@ -35,6 +39,14 @@ namespace state{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Output::~Output() {
|
Output::~Output() {
|
||||||
|
if (egl_context != EGL_NO_CONTEXT) {
|
||||||
|
eglDestroyContext(eglGetCurrentDisplay(), egl_context);
|
||||||
|
egl_context = EGL_NO_CONTEXT;
|
||||||
|
}
|
||||||
|
if (egl_surface != EGL_NO_SURFACE) {
|
||||||
|
eglDestroySurface(eglGetCurrentDisplay(), egl_surface);
|
||||||
|
egl_surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
if (output) {
|
if (output) {
|
||||||
wl_output_destroy(output);
|
wl_output_destroy(output);
|
||||||
output = nullptr;
|
output = nullptr;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
#include <wayland-client-protocol.h>
|
#include <wayland-client-protocol.h>
|
||||||
#include <wayland-egl-core.h>
|
#include <wayland-egl-core.h>
|
||||||
#include "ext-session-lock-v1-client-protocol.h"
|
#include "ext-session-lock-v1-client-protocol.h"
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <GLES2/gl2.h>
|
||||||
|
|
||||||
namespace state{
|
namespace state{
|
||||||
struct Output{
|
struct Output{
|
||||||
wl_output* output = nullptr;
|
wl_output* output = nullptr;
|
||||||
@@ -21,6 +24,12 @@ namespace state{
|
|||||||
bool configured = false;
|
bool configured = false;
|
||||||
uint32_t surface_width = uint32_t {0};
|
uint32_t surface_width = uint32_t {0};
|
||||||
uint32_t surface_height = uint32_t {0};
|
uint32_t surface_height = uint32_t {0};
|
||||||
|
|
||||||
|
wl_egl_window* window = nullptr;
|
||||||
|
EGLSurface egl_surface = EGL_NO_SURFACE;
|
||||||
|
EGLContext egl_context = EGL_NO_CONTEXT;
|
||||||
|
|
||||||
|
|
||||||
~Output();
|
~Output();
|
||||||
};
|
};
|
||||||
struct LockScreenState{
|
struct LockScreenState{
|
||||||
@@ -38,6 +47,9 @@ namespace state{
|
|||||||
ext_session_lock_v1* session_lock = nullptr;
|
ext_session_lock_v1* session_lock = nullptr;
|
||||||
bool locked=false;
|
bool locked=false;
|
||||||
|
|
||||||
|
EGLDisplay egl_display = EGL_NO_DISPLAY;
|
||||||
|
EGLConfig egl_config = nullptr;
|
||||||
|
|
||||||
~LockScreenState();
|
~LockScreenState();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user