diff --git a/Makefile b/Makefile index d7b1914..fdf0cf9 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,12 @@ +CFLAGS = -Wall -Wextra -I./include/ -g LIBS = $(shell pkg-config --libs wayland-client wayland-egl egl glesv2) -main: main.c - gcc -Wall -Wextra -o main main.c -I./include/ $(LIBS) xdg-shell-protocol.c -g +build/main: src/main.cpp build/shader.o include/state.h build/xdg-shell-protocol.o + g++ -o build/main $(CFLAGS) src/main.cpp build/shader.o build/xdg-shell-protocol.o $(LIBS) + +build/shader.o: src/shader.cpp include/shader.h + g++ -o build/shader.o $(CFLAGS) -c src/shader.cpp + +build/xdg-shell-protocol.o: src/xdg-shell-protocol.c + gcc -o build/xdg-shell-protocol.o -c $(CFLAGS) $(LIBS) src/xdg-shell-protocol.c diff --git a/include/shader.h b/include/shader.h new file mode 100644 index 0000000..14e1f65 --- /dev/null +++ b/include/shader.h @@ -0,0 +1,10 @@ +#ifndef H_SHADER_ +#define H_SHADER_ + +#include + +GLuint compile_shader(GLenum type, const char *src); + +GLuint create_program(const char *vs_src, const char *fs_src); + +#endif // H_SHADER_ diff --git a/include/state.h b/include/state.h new file mode 100644 index 0000000..0e5cdcf --- /dev/null +++ b/include/state.h @@ -0,0 +1,27 @@ +#ifndef H_STATE +#define H_STATE + +#include +#include +#include + +typedef struct { + struct wl_display *display; + EGLDisplay egl_display; + struct wl_egl_window *egl_window; + EGLSurface egl_surface; + bool ready; + + struct wl_compositor *compositor; + struct xdg_wm_base *wm_base; + struct wl_surface *w_surface; + struct xdg_surface *x_surface; + struct xdg_toplevel *toplevel; + + struct wl_shm *shm; + + struct wl_callback *frame_callback; + GLuint program; +} State; + +#endif // H_STATE diff --git a/src/hyprland-surface-v1.c b/src/hyprland-surface-v1.c deleted file mode 100644 index 8ada2f2..0000000 --- a/src/hyprland-surface-v1.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Generated by wayland-scanner 1.24.0 */ - -/* - * Copyright © 2025 outfoxxed - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include "wayland-util.h" - -#ifndef __has_attribute -# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */ -#endif - -#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4) -#define WL_PRIVATE __attribute__ ((visibility("hidden"))) -#else -#define WL_PRIVATE -#endif - -extern const struct wl_interface hyprland_surface_v1_interface; -extern const struct wl_interface wl_region_interface; -extern const struct wl_interface wl_surface_interface; - -static const struct wl_interface *hyprland_surface_v1_types[] = { - NULL, - &hyprland_surface_v1_interface, - &wl_surface_interface, - &wl_region_interface, -}; - -static const struct wl_message hyprland_surface_manager_v1_requests[] = { - { "get_hyprland_surface", "no", hyprland_surface_v1_types + 1 }, - { "destroy", "", hyprland_surface_v1_types + 0 }, -}; - -WL_PRIVATE const struct wl_interface hyprland_surface_manager_v1_interface = { - "hyprland_surface_manager_v1", 2, - 2, hyprland_surface_manager_v1_requests, - 0, NULL, -}; - -static const struct wl_message hyprland_surface_v1_requests[] = { - { "set_opacity", "f", hyprland_surface_v1_types + 0 }, - { "destroy", "", hyprland_surface_v1_types + 0 }, - { "set_visible_region", "2?o", hyprland_surface_v1_types + 3 }, -}; - -WL_PRIVATE const struct wl_interface hyprland_surface_v1_interface = { - "hyprland_surface_v1", 2, - 3, hyprland_surface_v1_requests, - 0, NULL, -}; - diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 8ec4699..0000000 --- a/src/main.c +++ /dev/null @@ -1,362 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include /* For O_* constants */ -#include -#include /* For mode constants */ -#include - -#include "./include/xdg-shell-client-protocol.h" - -#define UNUSED(x) (void)(x) - -#define WIDTH 780 -#define HEIGHT 420 - -typedef struct { - struct wl_display *display; - EGLDisplay egl_display; - struct wl_egl_window *egl_window; - EGLSurface egl_surface; - bool ready; - - struct wl_compositor *compositor; - struct xdg_wm_base *wm_base; - struct wl_surface *w_surface; - struct xdg_surface *x_surface; - struct xdg_toplevel *toplevel; - - struct wl_shm *shm; - // int shm_fd; - // struct wl_shm_pool *pool; - // uint8_t *pool_data; - // struct wl_buffer *buffer; - - struct wl_callback *frame_callback; - GLuint program; -} State; - -static GLuint compile_shader(GLenum type, const char *src) { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &src, NULL); - glCompileShader(shader); - - GLint ok; - glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); - if (!ok) { - char log[512]; - glGetShaderInfoLog(shader, sizeof(log), NULL, log); - fprintf(stderr, "shader compile error: %s\n", log); - exit(1); - } - - return shader; -} - -static GLuint create_program(const char *vs_src, const char *fs_src) { - GLuint vs = compile_shader(GL_VERTEX_SHADER, vs_src); - GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fs_src); - - GLuint prog = glCreateProgram(); - glAttachShader(prog, vs); - glAttachShader(prog, fs); - glLinkProgram(prog); - - GLint ok; - glGetProgramiv(prog, GL_LINK_STATUS, &ok); - if (!ok) { - char log[512]; - glGetProgramInfoLog(prog, sizeof(log), NULL, log); - fprintf(stderr, "program link error: %s\n", log); - exit(1); - } - - glDeleteShader(vs); - glDeleteShader(fs); - - return prog; -} - -const char *vs_src = - "attribute vec2 pos;\n" - "uniform float angle;\n" - "void main() {\n" - " float c = cos(angle);\n" - " float s = sin(angle);\n" - " mat2 rot = mat2(c, -s, s, c);\n" - " gl_Position = vec4(rot * pos, 0.0, 1.0);\n" - "}\n"; - -const char *fs_src = - "precision mediump float;\n" - "void main() {\n" - " gl_FragColor = vec4(1.0, 0.3, 0.2, 1.0);\n" - "}\n"; - -void wm_base_handle_ping(void *data, struct xdg_wm_base *wm_base, - uint32_t serial) { - UNUSED(data); - printf("INFO: ping method fired! sending pong...\n"); - xdg_wm_base_pong(wm_base, serial); -} - -static struct xdg_wm_base_listener wm_base_listener = { - .ping = wm_base_handle_ping, -}; - -void registry_handle_global(void *data, struct wl_registry *registry, - uint32_t name, const char *interface, - uint32_t version) { - State *app_state = data; - printf("HANDLE_GLOBAL: new interface '%s', name = %d, version = %d\n", - interface, name, version); - if (strcmp(interface, "wl_compositor") == 0) { - app_state->compositor = - wl_registry_bind(registry, name, &wl_compositor_interface, version); - printf("%p compositor binding\n", app_state->compositor); - } - if (strcmp(interface, "xdg_wm_base") == 0) { - app_state->wm_base = - wl_registry_bind(registry, name, &xdg_wm_base_interface, version); - if (app_state->wm_base == NULL) { - fprintf(stderr, "ERROR: could not bind to xdg_wm_base\n"); - } - int res = xdg_wm_base_add_listener(app_state->wm_base, &wm_base_listener, - app_state); - printf("bound to wm_base: %d\n", res); - } - if (strcmp(interface, "wl_shm") == 0) { - app_state->shm = - wl_registry_bind(registry, name, &wl_shm_interface, version); - if (app_state->shm == NULL) { - fprintf(stderr, "ERROR: could not bind to wl_shm\n"); - } - } -} - -void registry_handle_global_remove(void *data, struct wl_registry *registry, - uint32_t name) { - UNUSED(data); - UNUSED(registry); - UNUSED(name); -} - -static struct wl_registry_listener listener = { - .global = registry_handle_global, - .global_remove = registry_handle_global_remove, -}; - -static struct wl_callback_listener frame_listener; - -static void frame_done(void *data, - struct wl_callback *cb, - uint32_t time) -{ - UNUSED(time); - printf("INFO: frame callback\n"); - - State *state = data; - printf("state ptr = %p\n", state->w_surface); - - wl_callback_destroy(cb); - state->frame_callback = - wl_surface_frame(state->w_surface); - wl_callback_add_listener(state->frame_callback, - &frame_listener, - state); - - GLint angle_loc = glGetUniformLocation(state->program, "angle"); - - static float angle = 0.0f; - angle += 0.02f; - - glClear(GL_COLOR_BUFFER_BIT); - - glUniform1f(angle_loc, angle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - eglSwapBuffers(state->egl_display, state->egl_surface); -} - -static struct wl_callback_listener frame_listener = { - .done = frame_done, -}; - -static void xsurface_handle_configure(void *data, - struct xdg_surface *surface, - uint32_t serial) { - State *app_state = data; - - xdg_surface_ack_configure(surface, serial); - - app_state->frame_callback = - wl_surface_frame(app_state->w_surface); - printf("frame cb: %p\n", app_state->frame_callback); - - int cb_res = wl_callback_add_listener(app_state->frame_callback, - &frame_listener, - app_state); - - printf("mount callback listener: %d\n", cb_res); - - glClear(GL_COLOR_BUFFER_BIT); - eglSwapBuffers(app_state->egl_display, app_state->egl_surface); -} - -static const struct xdg_surface_listener xsurface_listener = { - .configure = xsurface_handle_configure, -}; - -int main(int argc, char **argv) { - UNUSED(argc); - UNUSED(argv); - State *app_state = (void*)malloc(sizeof(State)); - - app_state->display = wl_display_connect(NULL); - if (app_state->display == NULL) { - fprintf(stderr, "ERROR: could not connect to wl display\n"); - return 1; - } - - struct wl_registry *registry = wl_display_get_registry(app_state->display); - if (registry == NULL) { - fprintf(stderr, "ERROR: could not connect to wl registry\n"); - return 1; - } - - int handle = wl_registry_add_listener(registry, &listener, app_state); - printf("registry listener bound: %d\n", handle); - - wl_display_roundtrip(app_state->display); - - app_state->w_surface = wl_compositor_create_surface(app_state->compositor); - if (app_state->w_surface == NULL) { - fprintf(stderr, "ERROR: could not connect create a surface\n"); - return 1; - } - - PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = - (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress( - "eglGetPlatformDisplayEXT"); - - PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = - (void *)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"); - - app_state->egl_display = - getPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, app_state->display, NULL); - if (app_state->egl_display == NULL) { - fprintf(stderr, "ERROR: could not get platform display\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - if (!eglInitialize(app_state->egl_display, NULL, NULL)) { - fprintf(stderr, "ERROR: could not initialize EGL\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - 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 - }; - - EGLConfig config; - EGLint num_configs; - if (!eglChooseConfig(app_state->egl_display, config_attribs, - &config, 1, &num_configs)) { - fprintf(stderr, "ERROR: could not choose EGL config\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - EGLContext context = - eglCreateContext(app_state->egl_display, - config, - EGL_NO_CONTEXT, - ctx_attribs); - if (context == NULL) { - fprintf(stderr, "ERROR: could not create EGL context\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - app_state->egl_window = wl_egl_window_create(app_state->w_surface, WIDTH, HEIGHT); - if (app_state->egl_window == NULL) { - fprintf(stderr, "ERROR: could not create wl_egl_window\n"); - exit(1); - } - - app_state->egl_surface = createPlatformWindowSurface(app_state->egl_display, config, app_state->egl_window, NULL); - if (app_state->egl_surface == NULL) { - fprintf(stderr, "ERROR: could not create EGL window surface\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - if (!eglMakeCurrent(app_state->egl_display, app_state->egl_surface, app_state->egl_surface, context)) { - fprintf(stderr, "ERROR: could not change current EGL context\n"); - fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); - exit(1); - } - - app_state->program = create_program(vs_src, fs_src); - glUseProgram(app_state->program); - - GLint pos_loc = glGetAttribLocation(app_state->program, "pos"); - // GLint angle_loc = glGetUniformLocation(app_state->program, "angle"); - - float vertices[] = { - 0.0f, 0.6f, - -0.6f, -0.6f, - 0.6f, -0.6f - }; - - glEnableVertexAttribArray(pos_loc); - glVertexAttribPointer(pos_loc, 2, GL_FLOAT, GL_FALSE, 0, vertices); - glViewport(0, 0, WIDTH, HEIGHT); - glClearColor(0.2f, 0.4f, 0.8f, 1.0f); - - app_state->x_surface = - xdg_wm_base_get_xdg_surface(app_state->wm_base, app_state->w_surface); - if (app_state->x_surface == NULL) { - fprintf(stderr, "ERROR: could not get an xdg surface\n"); - return 1; - } - - app_state->toplevel = xdg_surface_get_toplevel(app_state->x_surface); - if (app_state->toplevel == NULL) { - fprintf(stderr, "ERROR: could not get an xdg toplevel\n"); - return 1; - } - - xdg_surface_add_listener(app_state->x_surface, &xsurface_listener, app_state); - app_state->ready = true; - wl_surface_commit(app_state->w_surface); - - while (wl_display_dispatch(app_state->display)) {} - - return 0; -} diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..c0c0e72 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,286 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include /* For O_* constants */ +#include +#include /* For mode constants */ +#include + +#include "shader.h" +#include "state.h" +#include "xdg-shell-client-protocol.h" + +#define UNUSED(x) (void)(x) + +#define WIDTH 780 +#define HEIGHT 420 + +const char *vs_src = "attribute vec2 pos;\n" + "uniform float angle;\n" + "void main() {\n" + " float c = cos(angle);\n" + " float s = sin(angle);\n" + " mat2 rot = mat2(c, -s, s, c);\n" + " gl_Position = vec4(rot * pos, 0.0, 1.0);\n" + "}\n"; + +const char *fs_src = "precision mediump float;\n" + "void main() {\n" + " gl_FragColor = vec4(1.0, 0.3, 0.2, 1.0);\n" + "}\n"; + +void wm_base_handle_ping(void *data, struct xdg_wm_base *wm_base, + uint32_t serial) { + UNUSED(data); + printf("INFO: ping method fired! sending pong...\n"); + xdg_wm_base_pong(wm_base, serial); +} + +static struct xdg_wm_base_listener wm_base_listener = { + .ping = wm_base_handle_ping, +}; + +void registry_handle_global(void *data, struct wl_registry *registry, + uint32_t name, const char *interface, + uint32_t version) { + State *app_state = reinterpret_cast(data); + printf("HANDLE_GLOBAL: new interface '%s', name = %d, version = %d\n", + interface, name, version); + if (strcmp(interface, "wl_compositor") == 0) { + app_state->compositor = reinterpret_cast( + wl_registry_bind(registry, name, &wl_compositor_interface, version)); + printf("%p compositor binding\n", app_state->compositor); + } + if (strcmp(interface, "xdg_wm_base") == 0) { + app_state->wm_base = reinterpret_cast( + wl_registry_bind(registry, name, &xdg_wm_base_interface, version)); + if (app_state->wm_base == NULL) { + fprintf(stderr, "ERROR: could not bind to xdg_wm_base\n"); + } + int res = xdg_wm_base_add_listener(app_state->wm_base, &wm_base_listener, + app_state); + printf("bound to wm_base: %d\n", res); + } + if (strcmp(interface, "wl_shm") == 0) { + app_state->shm = reinterpret_cast( + wl_registry_bind(registry, name, &wl_shm_interface, version)); + if (app_state->shm == NULL) { + fprintf(stderr, "ERROR: could not bind to wl_shm\n"); + } + } +} + +void registry_handle_global_remove(void *data, struct wl_registry *registry, + uint32_t name) { + UNUSED(data); + UNUSED(registry); + UNUSED(name); +} + +static struct wl_registry_listener listener = { + .global = registry_handle_global, + .global_remove = registry_handle_global_remove, +}; + +static struct wl_callback_listener frame_listener; + +static void frame_done(void *data, struct wl_callback *cb, uint32_t time) { + UNUSED(time); + printf("INFO: frame callback\n"); + + State *state = reinterpret_cast(data); + printf("state ptr = %p\n", state->w_surface); + + wl_callback_destroy(cb); + state->frame_callback = wl_surface_frame(state->w_surface); + wl_callback_add_listener(state->frame_callback, &frame_listener, state); + + GLint angle_loc = glGetUniformLocation(state->program, "angle"); + + static float angle = 0.0f; + angle += 0.02f; + + glClear(GL_COLOR_BUFFER_BIT); + + glUniform1f(angle_loc, angle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + eglSwapBuffers(state->egl_display, state->egl_surface); +} + +static void xsurface_handle_configure(void *data, struct xdg_surface *surface, + uint32_t serial) { + State *app_state = reinterpret_cast(data); + + xdg_surface_ack_configure(surface, serial); + + app_state->frame_callback = wl_surface_frame(app_state->w_surface); + printf("frame cb: %p\n", app_state->frame_callback); + + int cb_res = wl_callback_add_listener(app_state->frame_callback, + &frame_listener, app_state); + + printf("mount callback listener: %d\n", cb_res); + + glClear(GL_COLOR_BUFFER_BIT); + eglSwapBuffers(app_state->egl_display, app_state->egl_surface); +} + +static const struct xdg_surface_listener xsurface_listener = { + .configure = xsurface_handle_configure, +}; + +int main(int argc, char **argv) { + UNUSED(argc); + UNUSED(argv); + State *app_state = new State; + + frame_listener.done = frame_done; + + app_state->display = wl_display_connect(NULL); + if (app_state->display == NULL) { + fprintf(stderr, "ERROR: could not connect to wl display\n"); + return 1; + } + + struct wl_registry *registry = wl_display_get_registry(app_state->display); + if (registry == NULL) { + fprintf(stderr, "ERROR: could not connect to wl registry\n"); + return 1; + } + + int handle = wl_registry_add_listener(registry, &listener, app_state); + printf("registry listener bound: %d\n", handle); + + wl_display_roundtrip(app_state->display); + + app_state->w_surface = wl_compositor_create_surface(app_state->compositor); + if (app_state->w_surface == NULL) { + fprintf(stderr, "ERROR: could not connect create a surface\n"); + return 1; + } + + PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = + reinterpret_cast( + eglGetProcAddress("eglGetPlatformDisplayEXT")); + + PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = + reinterpret_cast( + eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT")); + + app_state->egl_display = + getPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, app_state->display, NULL); + if (app_state->egl_display == NULL) { + fprintf(stderr, "ERROR: could not get platform display\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + if (!eglInitialize(app_state->egl_display, NULL, NULL)) { + fprintf(stderr, "ERROR: could not initialize EGL\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + 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}; + + EGLConfig config; + EGLint num_configs; + if (!eglChooseConfig(app_state->egl_display, config_attribs, &config, 1, + &num_configs)) { + fprintf(stderr, "ERROR: could not choose EGL config\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + EGLint ctx_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; + + EGLContext context = eglCreateContext(app_state->egl_display, config, + EGL_NO_CONTEXT, ctx_attribs); + if (context == NULL) { + fprintf(stderr, "ERROR: could not create EGL context\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + app_state->egl_window = + wl_egl_window_create(app_state->w_surface, WIDTH, HEIGHT); + if (app_state->egl_window == NULL) { + fprintf(stderr, "ERROR: could not create wl_egl_window\n"); + exit(1); + } + + app_state->egl_surface = createPlatformWindowSurface( + app_state->egl_display, config, app_state->egl_window, NULL); + if (app_state->egl_surface == NULL) { + fprintf(stderr, "ERROR: could not create EGL window surface\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + if (!eglMakeCurrent(app_state->egl_display, app_state->egl_surface, + app_state->egl_surface, context)) { + fprintf(stderr, "ERROR: could not change current EGL context\n"); + fprintf(stderr, "EGL error: 0x%x\n", eglGetError()); + exit(1); + } + + app_state->program = create_program(vs_src, fs_src); + glUseProgram(app_state->program); + + GLint pos_loc = glGetAttribLocation(app_state->program, "pos"); + // GLint angle_loc = glGetUniformLocation(app_state->program, "angle"); + + float vertices[] = {0.0f, 0.6f, -0.6f, -0.6f, 0.6f, -0.6f}; + + glEnableVertexAttribArray(pos_loc); + glVertexAttribPointer(pos_loc, 2, GL_FLOAT, GL_FALSE, 0, vertices); + glViewport(0, 0, WIDTH, HEIGHT); + glClearColor(0.2f, 0.4f, 0.8f, 1.0f); + + app_state->x_surface = + xdg_wm_base_get_xdg_surface(app_state->wm_base, app_state->w_surface); + if (app_state->x_surface == NULL) { + fprintf(stderr, "ERROR: could not get an xdg surface\n"); + return 1; + } + + app_state->toplevel = xdg_surface_get_toplevel(app_state->x_surface); + if (app_state->toplevel == NULL) { + fprintf(stderr, "ERROR: could not get an xdg toplevel\n"); + return 1; + } + + xdg_surface_add_listener(app_state->x_surface, &xsurface_listener, app_state); + app_state->ready = true; + wl_surface_commit(app_state->w_surface); + + while (wl_display_dispatch(app_state->display)) { + } + + return 0; +} diff --git a/src/shader.cpp b/src/shader.cpp new file mode 100644 index 0000000..f380aab --- /dev/null +++ b/src/shader.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include "shader.h" + +GLuint compile_shader(GLenum type, const char *src) { + GLuint shader = glCreateShader(type); + glShaderSource(shader, 1, &src, NULL); + glCompileShader(shader); + + GLint ok; + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + if (!ok) { + char log[512]; + glGetShaderInfoLog(shader, sizeof(log), NULL, log); + fprintf(stderr, "shader compile error: %s\n", log); + exit(1); + } + + return shader; +} + +GLuint create_program(const char *vs_src, const char *fs_src) { + GLuint vs = compile_shader(GL_VERTEX_SHADER, vs_src); + GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fs_src); + + GLuint prog = glCreateProgram(); + glAttachShader(prog, vs); + glAttachShader(prog, fs); + glLinkProgram(prog); + + GLint ok; + glGetProgramiv(prog, GL_LINK_STATUS, &ok); + if (!ok) { + char log[512]; + glGetProgramInfoLog(prog, sizeof(log), NULL, log); + fprintf(stderr, "program link error: %s\n", log); + exit(1); + } + + glDeleteShader(vs); + glDeleteShader(fs); + + return prog; +}