summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--meson.build21
-rw-r--r--shaders/frag.frag23
-rw-r--r--shaders/vert.vert24
-rw-r--r--src/egl.c166
-rw-r--r--src/egl.h25
-rw-r--r--src/entry.c15
-rw-r--r--src/gl.c325
-rw-r--r--src/gl.h27
-rw-r--r--src/image.h1
-rw-r--r--src/ipc.c121
-rw-r--r--src/ipc.h13
-rw-r--r--src/log.c13
-rw-r--r--src/main.c38
-rw-r--r--src/shm.c49
-rw-r--r--src/shm.h8
-rw-r--r--src/string_vec.c2
-rw-r--r--src/surface.c90
-rw-r--r--src/surface.h17
-rw-r--r--src/tofi.h3
-rw-r--r--src/xmalloc.c7
20 files changed, 171 insertions, 817 deletions
diff --git a/meson.build b/meson.build
index e00635b..06ce596 100644
--- a/meson.build
+++ b/meson.build
@@ -25,12 +25,6 @@ data_location = join_paths(
'tofi'
)
-shader_location = join_paths(
- debug ? '' : data_location,
- 'shaders',
- ''
-)
-
completion_location = join_paths(
get_option('prefix'),
get_option('datadir'),
@@ -38,11 +32,6 @@ completion_location = join_paths(
'completions'
)
-install_subdir(
- 'shaders',
- install_dir: data_location
-)
-
install_data(
'completions/tofi',
install_dir: completion_location
@@ -55,7 +44,6 @@ add_project_arguments(
'-Wshadow',
'-Wno-unused-parameter',
'-D_POSIX_C_SOURCE=200809L',
- '-DSHADER_PATH="@0@"'.format(shader_location),
],
language: 'c'
)
@@ -64,12 +52,10 @@ sources = files(
'src/main.c',
'src/color.c',
'src/compgen.c',
- 'src/egl.c',
'src/entry.c',
- 'src/gl.c',
'src/history.c',
- 'src/ipc.c',
'src/log.c',
+ 'src/shm.c',
'src/string_vec.c',
'src/surface.c',
'src/wlr-layer-shell-unstable-v1.c',
@@ -77,12 +63,9 @@ sources = files(
)
cc = meson.get_compiler('c')
-epoxy = dependency('epoxy')
glib = dependency('glib-2.0')
-json = dependency('json-c')
pangocairo = dependency('pangocairo')
wayland_client = dependency('wayland-client')
-wayland_egl = dependency('wayland-egl')
wayland_protocols = dependency('wayland-protocols', native: true)
wayland_scanner_dep = dependency('wayland-scanner', native: true)
xkbcommon = dependency('xkbcommon')
@@ -119,7 +102,7 @@ endforeach
executable(
'tofi',
sources, wl_proto_src, wl_proto_headers,
- dependencies: [epoxy, json, glib, pangocairo, wayland_egl, xkbcommon],
+ dependencies: [glib, pangocairo, wayland_client, xkbcommon],
install: true
)
diff --git a/shaders/frag.frag b/shaders/frag.frag
deleted file mode 100644
index 88d2337..0000000
--- a/shaders/frag.frag
+++ /dev/null
@@ -1,23 +0,0 @@
-#version 100
-
-/*
- * Copyright (C) 2021 Philip Jones
- *
- * Licensed under the MIT License.
- * See either the LICENSE file, or:
- *
- * https://opensource.org/licenses/MIT
- *
- * I don't think you can really copyright this shader though :)
- */
-
-precision lowp float;
-
-varying vec2 Texcoord;
-
-uniform sampler2D tex;
-
-void main()
-{
- gl_FragColor = texture2D(tex, Texcoord);
-}
diff --git a/shaders/vert.vert b/shaders/vert.vert
deleted file mode 100644
index 3364718..0000000
--- a/shaders/vert.vert
+++ /dev/null
@@ -1,24 +0,0 @@
-#version 100
-
-/*
- * Copyright (C) 2017-2020 Philip Jones
- *
- * Licensed under the MIT License.
- * See either the LICENSE file, or:
- *
- * https://opensource.org/licenses/MIT
- *
- */
-
-precision lowp float;
-
-attribute vec2 position;
-attribute vec2 texcoord;
-
-varying vec2 Texcoord;
-
-void main()
-{
- Texcoord = texcoord;
- gl_Position = vec4(position, 0.0, 1.0);
-}
diff --git a/src/egl.c b/src/egl.c
deleted file mode 100644
index 8ae70f2..0000000
--- a/src/egl.c
+++ /dev/null
@@ -1,166 +0,0 @@
-#include <assert.h>
-#include <string.h>
-#include <wayland-egl.h>
-#include "egl.h"
-#include "log.h"
-
-static const char *egl_error_string();
-
-void egl_create_window(
- struct egl *egl,
- struct wl_surface *wl_surface,
- uint32_t width,
- uint32_t height)
-{
- egl->window = wl_egl_window_create(wl_surface, width, height);
-
- if (egl->window == EGL_NO_SURFACE) {
- egl_log_error("Couldn't create EGL window");
- }
-}
-
-void egl_create_context(struct egl *egl, struct wl_display *wl_display)
-{
- egl->display = eglGetDisplay(wl_display);
- if (egl->display == EGL_NO_DISPLAY) {
- egl_log_error("Couldn't get EGL display");
- return;
- }
-
- if (!eglInitialize(egl->display, NULL, NULL)) {
- egl_log_error("Couldn't initialise EGL");
- return;
- }
-
- EGLBoolean result;
- EGLConfig config;
- EGLint num_configs;
- static 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
- };
-
- result = eglGetConfigs(egl->display, NULL, 0, &num_configs);
- if ((result != EGL_TRUE) || (num_configs == 0)) {
- egl_log_error("No EGL configs available");
- return;
- }
-
- result = eglChooseConfig(
- egl->display,
- config_attribs,
- &config,
- 1,
- &num_configs);
- if ((result != EGL_TRUE) || (num_configs != 1)) {
- egl_log_error("Failed to choose EGL config");
- return;
- }
-
- egl->surface = eglCreateWindowSurface(
- egl->display,
- config,
- egl->window,
- NULL);
- if (egl->surface == EGL_NO_SURFACE) {
- egl_log_error("Couldn't create EGL window surface");
- return;
- }
-
- static const EGLint context_attribs[] = {
- EGL_CONTEXT_MAJOR_VERSION, 2,
- EGL_NONE
- };
-
- egl->context = eglCreateContext(
- egl->display,
- config,
- EGL_NO_CONTEXT,
- context_attribs);
- if (egl->context == EGL_NO_CONTEXT) {
- egl_log_error("Couldn't create EGL context");
- return;
- }
-
- result = eglMakeCurrent(
- egl->display,
- egl->surface,
- egl->surface,
- egl->context);
- if (!result) {
- egl_log_error("Couldn't make EGL context current");
- return;
- }
-}
-
-void egl_destroy(struct egl *egl)
-{
- eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglDestroySurface(egl->display, egl->surface);
- wl_egl_window_destroy(egl->window);
-}
-
-void egl_log_error(const char *msg)
-{
- log_error("%s: %s\n", msg, egl_error_string());
-}
-
-void egl_make_current(struct egl *egl)
-{
- bool result = eglMakeCurrent(
- egl->display,
- egl->surface,
- egl->surface,
- egl->context);
- if (!result) {
- egl_log_error("Couldn't make EGL context current");
- return;
- }
-}
-
-void egl_swap_buffers(struct egl *egl)
-{
- eglSwapBuffers(egl->display, egl->surface);
-}
-
-const char *egl_error_string()
-{
- switch(eglGetError()) {
- case EGL_SUCCESS:
- return "EGL_SUCCESS";
- case EGL_NOT_INITIALIZED:
- return "EGL_NOT_INITIALIZED";
- case EGL_BAD_ACCESS:
- return "EGL_BAD_ACCESS";
- case EGL_BAD_ALLOC:
- return "EGL_BAD_ALLOC";
- case EGL_BAD_ATTRIBUTE:
- return "EGL_BAD_ATTRIBUTE";
- case EGL_BAD_CONTEXT:
- return "EGL_BAD_CONTEXT";
- case EGL_BAD_CONFIG:
- return "EGL_BAD_CONFIG";
- case EGL_BAD_CURRENT_SURFACE:
- return "EGL_BAD_CURRENT_SURFACE";
- case EGL_BAD_DISPLAY:
- return "EGL_BAD_DISPLAY";
- case EGL_BAD_SURFACE:
- return "EGL_BAD_SURFACE";
- case EGL_BAD_MATCH:
- return "EGL_BAD_MATCH";
- case EGL_BAD_PARAMETER:
- return "EGL_BAD_PARAMETER";
- case EGL_BAD_NATIVE_PIXMAP:
- return "EGL_BAD_NATIVE_PIXMAP";
- case EGL_BAD_NATIVE_WINDOW:
- return "EGL_BAD_NATIVE_WINDOW";
- case EGL_CONTEXT_LOST:
- return "EGL_CONTEXT_LOST";
- }
- return "Unknown EGL error";
-}
diff --git a/src/egl.h b/src/egl.h
deleted file mode 100644
index a3f17a2..0000000
--- a/src/egl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef EGL_H
-#define EGL_H
-
-#include <wayland-egl.h>
-#include <epoxy/egl.h>
-
-struct egl {
- EGLNativeWindowType window;
- EGLDisplay display;
- EGLContext context;
- EGLSurface surface;
-};
-
-void egl_create_window(
- struct egl *egl,
- struct wl_surface *wl_surface,
- uint32_t width,
- uint32_t height);
-void egl_create_context(struct egl *egl, struct wl_display *wl_display);
-void egl_destroy(struct egl *egl);
-void egl_log_error(const char *msg);
-void egl_make_current(struct egl *egl);
-void egl_swap_buffers(struct egl *egl);
-
-#endif /* EGL_H */
diff --git a/src/entry.c b/src/entry.c
index 644fe39..845df0a 100644
--- a/src/entry.c
+++ b/src/entry.c
@@ -1,4 +1,3 @@
-#include <arpa/inet.h>
#include <cairo/cairo.h>
#include <glib.h>
#include <pango/pangocairo.h>
@@ -17,14 +16,6 @@ void entry_init(struct entry *entry, uint32_t width, uint32_t height, uint32_t s
height /= scale;
/*
- * Cairo uses native 32 bit integers for pixels, so if this processor
- * is little endian we have to tell OpenGL to swizzle the texture.
- */
- if (htonl(0xFFu) != 0xFFu) {
- entry->image.swizzle = true;
- }
-
- /*
* Create the cairo surface and context we'll be using.
*/
cairo_surface_t *surface = cairo_image_surface_create(
@@ -90,8 +81,10 @@ void entry_init(struct entry *entry, uint32_t width, uint32_t height, uint32_t s
cairo_clip(cr);
/* Setup Pango. */
+ log_debug("Creating Pango context.\n");
PangoContext *context = pango_cairo_create_context(cr);
+ log_debug("Creating Pango font description.\n");
PangoFontDescription *font_description =
pango_font_description_from_string(entry->font_name);
pango_font_description_set_size(
@@ -101,10 +94,13 @@ void entry_init(struct entry *entry, uint32_t width, uint32_t height, uint32_t s
pango_font_description_free(font_description);
entry->pango.prompt_layout = pango_layout_new(context);
+ log_debug("Setting Pango text.\n");
pango_layout_set_text(entry->pango.prompt_layout, "run: ", -1);
int prompt_width;
int prompt_height;
+ log_debug("Get Pango pixel size.\n");
pango_layout_get_pixel_size(entry->pango.prompt_layout, &prompt_width, &prompt_height);
+ log_debug("First Pango draw.\n");
pango_cairo_update_layout(cr, entry->pango.prompt_layout);
/* Draw the prompt now, as this only needs to be done once */
@@ -118,6 +114,7 @@ void entry_init(struct entry *entry, uint32_t width, uint32_t height, uint32_t s
cairo_rectangle(cr, 0, 0, width, height);
cairo_clip(cr);
+ log_debug("Creating Pango layout.\n");
entry->pango.entry_layout = pango_layout_new(context);
pango_layout_set_text(entry->pango.entry_layout, "", -1);
diff --git a/src/gl.c b/src/gl.c
deleted file mode 100644
index 09c7e1d..0000000
--- a/src/gl.c
+++ /dev/null
@@ -1,325 +0,0 @@
-#include <epoxy/gl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "gl.h"
-#include "log.h"
-#include "xmalloc.h"
-
-#define max(a, b) ((a) > (b) ? (a) : (b))
-
-static void load_shader(GLuint shader, const char *filename);
-static GLuint create_shader_program(const char *vert, const char *frag);
-static void GLAPIENTRY MessageCallback(
- GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const GLchar* message,
- const void* userParam);
-static const char *gl_debug_source_string(GLenum type);
-static const char *gl_debug_type_string(GLenum type);
-static const char *gl_debug_severity_string(GLenum type);
-
-
-void gl_initialise(struct gl *gl, struct image *texture)
-{
-#ifdef DEBUG
- //glEnable(GL_DEBUG_OUTPUT);
- //glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
- //glDebugMessageCallback(MessageCallback, 0);
-#endif
- if (texture == NULL || texture->buffer == NULL) {
- return;
- }
-
- /* Compile and link the shader programs */
- gl->shader = create_shader_program(
- SHADER_PATH "vert.vert",
- SHADER_PATH "frag.frag"
- );
- glUseProgram(gl->shader);
- glUniform1i(glGetUniformLocation(gl->shader, "tex"), 0);
-
- /* Create a vertex buffer for a quad filling the screen */
- float vertices[] = {
- // Position Texcoords
- -1.0f, 1.0f, 0.0f, 0.0f, // Top-left
- 1.0f, 1.0f, 1.0f, 0.0f, // Top-right
- 1.0f, -1.0f, 1.0f, 1.0f, // Bottom-right
- -1.0f, -1.0f, 0.0f, 1.0f // Bottom-left
- };
-
- glGenBuffers(1, &gl->vbo);
- glBindBuffer(GL_ARRAY_BUFFER, gl->vbo);
- glBufferData(
- GL_ARRAY_BUFFER,
- sizeof(vertices),
- vertices,
- GL_STATIC_DRAW);
-
- /*
- * Create a vertex array and enable vertex attributes for the shaders.
- */
- glGenVertexArrays(1, &gl->vao);
- glBindVertexArray(gl->vao);
-
- GLint posAttrib = glGetAttribLocation(gl->shader, "position");
- glVertexAttribPointer(
- posAttrib,
- 2,
- GL_FLOAT,
- GL_FALSE,
- 4*sizeof(float),
- 0);
- glEnableVertexAttribArray(posAttrib);
-
- GLint texAttrib = glGetAttribLocation(gl->shader, "texcoord");
- glVertexAttribPointer(
- texAttrib,
- 2,
- GL_FLOAT,
- GL_FALSE,
- 4*sizeof(float),
- (void *)(2*sizeof(float)));
- glEnableVertexAttribArray(texAttrib);
-
- glBindVertexArray(0);
-
- /*
- * Create the element buffer object that will actually be drawn via
- * glDrawElements().
- */
- GLubyte elements[] = {
- 0, 1, 2,
- 2, 3, 0
- };
-
- glGenBuffers(1, &gl->ebo);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl->ebo);
- glBufferData(
- GL_ELEMENT_ARRAY_BUFFER,
- sizeof(elements),
- elements,
- GL_STATIC_DRAW);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- glBindBuffer(GL_ARRAY_BUFFER, 0);
-
- /* Create the texture we'll draw to */
- glGenTextures(1, &gl->texture);
- glBindTexture(GL_TEXTURE_2D, gl->texture);
- glTexImage2D(
- GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- texture->width,
- texture->height,
- 0,
- /*
- * On little-endian processors, textures from Cairo
- * have to have their red and blue channels swapped.
- */
- texture->swizzle ? GL_BGRA : GL_RGBA,
- GL_UNSIGNED_BYTE,
- (GLvoid *)texture->buffer);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
- /* Bind the actual bits we'll be using to render */
- glBindVertexArray(gl->vao);
- glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gl->ebo);
-}
-
-void gl_destroy(struct gl *gl)
-{
- glDeleteProgram(gl->shader);
- glDeleteTextures(1, &gl->texture);
- glDeleteBuffers(1, &gl->ebo);
- glDeleteVertexArrays(1, &gl->vao);
- glDeleteBuffers(1, &gl->vbo);
-}
-
-void gl_clear(struct gl *gl, struct color *color)
-{
- glClearColor(color->r, color->g, color->b, color->a);
- glClear(GL_COLOR_BUFFER_BIT);
-}
-
-void gl_draw_texture(
- struct gl *gl,
- struct image *texture,
- int32_t x,
- int32_t y,
- int32_t width,
- int32_t height)
-{
- if (texture->redraw) {
- glTexSubImage2D(
- GL_TEXTURE_2D,
- 0,
- 0,
- 0,
- texture->width,
- texture->height,
- texture->swizzle ? GL_BGRA : GL_RGBA,
- GL_UNSIGNED_BYTE,
- (GLvoid *)texture->buffer);
- texture->redraw = false;
- }
-
- glViewport(x, y, width, height);
- glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, NULL);
-}
-
-void load_shader(GLuint shader, const char *filename)
-{
- errno = 0;
- FILE *fp = fopen(filename, "rb");
- if (!fp) {
- log_error("Failed to load shader %s: %s.\n",
- filename, strerror(errno));
- exit(EXIT_FAILURE);
- }
- if (fseek(fp, 0, SEEK_END) != 0) {
- log_error("Failed to load shader %s: %s.\n",
- filename, strerror(errno));
- fclose(fp);
- exit(EXIT_FAILURE);
- }
- long size = ftell(fp);
- if (size <= 0) {
- log_error("Failed to load shader %s: %s.\n",
- filename, strerror(errno));
- fclose(fp);
- exit(EXIT_FAILURE);
- }
- unsigned long usize = (unsigned long) size;
- GLchar *source = xmalloc(usize + 1);
- rewind(fp);
- if (fread(source, 1, usize, fp) != usize) {
- log_error("Failed to load shader %s: %s.\n",
- filename, strerror(errno));
- fclose(fp);
- exit(EXIT_FAILURE);
- }
- fclose(fp);
- source[usize] = '\0';
- glShaderSource(shader, 1, (const GLchar *const *)&source, NULL);
- free(source);
-
- glCompileShader(shader);
-
- GLint status;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if (status != GL_TRUE) {
- log_error("Failed to compile shader %s!\n", filename);
-
- GLint info_length = 0;
- glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_length);
- if (info_length > 1) {
- char *log = xmalloc((unsigned)info_length * sizeof(*log));
- glGetShaderInfoLog(shader, info_length, NULL, log);
- log_error("\t%s\n", log);
- free(log);
- }
- exit(EXIT_FAILURE);
- }
-}
-
-GLuint create_shader_program(const char *vert, const char *frag)
-{
- GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
- load_shader(vertex_shader, vert);
-
- GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
- load_shader(fragment_shader, frag);
-
- GLuint shader = glCreateProgram();
- glAttachShader(shader, vertex_shader);
- glAttachShader(shader, fragment_shader);
- glLinkProgram(shader);
- glDetachShader(shader, fragment_shader);
- glDetachShader(shader, vertex_shader);
- glDeleteShader(fragment_shader);
- glDeleteShader(vertex_shader);
- return shader;
-}
-
-void GLAPIENTRY MessageCallback(
- GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const GLchar* message,
- const void* userParam)
-{
- log_debug("Message from OpenGL:\n");
- log_debug("\tSource: %s\n", gl_debug_source_string(source));
- log_debug("\tType: %s\n", gl_debug_type_string(type));
- log_debug("\tSeverity: %s\n", gl_debug_severity_string(severity));
- log_debug("\tMessage: %s\n", message);
-}
-
-const char *gl_debug_source_string(GLenum type)
-{
- switch(type) {
- case GL_DEBUG_SOURCE_API:
- return "API";
- case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
- return "Window system";
- case GL_DEBUG_SOURCE_SHADER_COMPILER:
- return "Shader compiler";
- case GL_DEBUG_SOURCE_THIRD_PARTY:
- return "Third party";
- case GL_DEBUG_SOURCE_APPLICATION:
- return "Application";
- case GL_DEBUG_SOURCE_OTHER:
- return "Other";
- }
- return "unknown";
-}
-
-const char *gl_debug_type_string(GLenum type)
-{
- switch(type) {
- case GL_DEBUG_TYPE_ERROR:
- return "Error";
- case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
- return "Deprecated behavior";
- case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
- return "Undefined behavior";
- case GL_DEBUG_TYPE_PORTABILITY:
- return "Portability";
- case GL_DEBUG_TYPE_PERFORMANCE:
- return "Performance";
- case GL_DEBUG_TYPE_MARKER:
- return "Marker";
- case GL_DEBUG_TYPE_PUSH_GROUP:
- return "Push group";
- case GL_DEBUG_TYPE_POP_GROUP:
- return "Pop group";
- case GL_DEBUG_TYPE_OTHER:
- return "Other";
- }
- return "Unknown";
-}
-
-const char *gl_debug_severity_string(GLenum type)
-{
- switch(type) {
- case GL_DEBUG_SEVERITY_HIGH:
- return "High";
- case GL_DEBUG_SEVERITY_MEDIUM:
- return "Medium";
- case GL_DEBUG_SEVERITY_LOW:
- return "Low";
- case GL_DEBUG_SEVERITY_NOTIFICATION:
- return "Notification";
- }
- return "Unknown";
-}
diff --git a/src/gl.h b/src/gl.h
deleted file mode 100644
index 8d4b6f9..0000000
--- a/src/gl.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef GL_H
-#define GL_H
-
-#include <epoxy/gl.h>
-#include "color.h"
-#include "image.h"
-
-struct gl {
- GLuint vbo;
- GLuint vao;
- GLuint ebo;
- GLuint texture;
- GLuint shader;
-};
-
-void gl_initialise(struct gl *gl, struct image *texture);
-void gl_destroy(struct gl *gl);
-void gl_clear(struct gl *gl, struct color *color);
-void gl_draw_texture(
- struct gl *gl,
- struct image *texture,
- int32_t x,
- int32_t y,
- int32_t width,
- int32_t height);
-
-#endif /* GL_H */
diff --git a/src/image.h b/src/image.h
index a66e0cb..2afaa4d 100644
--- a/src/image.h
+++ b/src/image.h
@@ -8,7 +8,6 @@ struct image {
uint8_t *buffer;
uint32_t width;
uint32_t height;
- bool swizzle;
bool redraw;
struct {
uint32_t x;
diff --git a/src/ipc.c b/src/ipc.c
deleted file mode 100644
index 2af5dbf..0000000
--- a/src/ipc.c
+++ /dev/null
@@ -1,121 +0,0 @@
-#include <json-c/json_object.h>
-#include <json-c/json_tokener.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-#include "ipc.h"
-#include "log.h"
-#include "xmalloc.h"
-
-static int ipc_open(void);
-static int ipc_send(int socket, struct json_object *request);
-static struct json_object *ipc_receive(int socket);
-
-struct json_object *ipc_submit(struct json_object *request)
-{
- int sock = ipc_open();
- if (sock == -1) {
- return NULL;
- }
-
- if (ipc_send(sock, request) == -1) {
- close(sock);
- return NULL;
- }
-
- struct json_object *resp = ipc_receive(sock);
- close(sock);
- return resp;
-}
-
-/*
- * Open a connection to the UNIX socket specified by
- * the environment variable GREETD_SOCK.
- *
- * Returns the socket file descriptor on success, or -1 on failure.
- */
-int ipc_open(void)
-{
- char *greetd_sock = getenv("GREETD_SOCK");
-
- if (greetd_sock == NULL) {
- log_error("GREETD_SOCK not set.\n");
- return -1;
- }
-
- int sock = socket(AF_UNIX, SOCK_STREAM, 0);
- if (sock == -1) {
- log_error("Unable to create socket: %s\n", strerror(errno));
- return -1;
- }
-
- struct sockaddr_un remote = { .sun_family = AF_UNIX };
- strncpy(remote.sun_path, greetd_sock, sizeof(remote.sun_path));
-
- if (connect(sock, (struct sockaddr *)&remote, sizeof(remote)) == -1) {
- log_error("Unable to connect to greetd: %s\n", strerror(errno));
- close(sock);
- return -1;
- }
- return sock;
-}
-
-/*
- * Send an IPC request to the specified socket.
- *
- * Returns 0 on success, or -1 on failure.
- */
-int ipc_send(int sock, struct json_object *request)
-{
- const char *str = json_object_to_json_string(request);
- uint32_t len = strlen(str);
-
- if (send(sock, &len, sizeof(len), 0) == -1) {
- log_error("Error sending request size: %s\n", strerror(errno));
- return -1;
- }
-
- if (send(sock, str, len, 0) == -1) {
- log_error("Error sending request: %s\n", strerror(errno));
- return -1;
- }
- return 0;
-}
-
-/*
- * Receive an IPC response on the specified socket.
- *
- * Returns the response on success, or NULL on failure.
- */
-struct json_object *ipc_receive(int sock)
-{
- uint32_t len = 0;
-
- if (recv(sock, &len, sizeof(len), 0) != sizeof(len)) {
- log_error("Error receiving response size: %s\n", strerror(errno));
- return NULL;
- }
-
- char *buf = xmalloc(len + 1);
- if (recv(sock, buf, len, 0) != len) {
- log_error("Error receiving response: %s\n", strerror(errno));
- free(buf);
- return NULL;
- }
-
- buf[len] = '\0';
-
- enum json_tokener_error error;
- struct json_object *resp = json_tokener_parse_verbose(buf, &error);
- free(buf);
-
- if (resp == NULL) {
- log_error("Error parsing response: %s\n", json_tokener_error_desc(error));
- }
- return resp;
-
-}
diff --git a/src/ipc.h b/src/ipc.h
deleted file mode 100644
index 30a953a..0000000
--- a/src/ipc.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef IPC_H
-#define IPC_H
-
-#include <json-c/json_object.h>
-
-/*
- * Submit an IPC request to greetd.
- *
- * Returns the response on success, or NULL on failure.
- */
-struct json_object *ipc_submit(struct json_object *request);
-
-#endif /* IPC_H */
diff --git a/src/log.c b/src/log.c
index a6c9a75..065d5be 100644
--- a/src/log.c
+++ b/src/log.c
@@ -1,6 +1,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
+#include <sys/resource.h>
#include <time.h>
#define SECOND 1000000000ul
@@ -34,7 +35,7 @@ void log_debug(const char *const fmt, ...)
#endif
static struct timespec start_time;
if (start_time.tv_nsec == 0) {
- fprintf(stderr, "[ real, cpu]\n");
+ fprintf(stderr, "[ real, cpu, maxRSS]\n");
clock_gettime(CLOCK_REALTIME, &start_time);
}
struct timespec real_time;
@@ -42,15 +43,21 @@ void log_debug(const char *const fmt, ...)
clock_gettime(CLOCK_REALTIME, &real_time);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &cpu_time);
real_time = time_diff(real_time, start_time);
+
+ struct rusage usage;
+ getrusage(RUSAGE_SELF, &usage);
+
va_list args;
va_start(args, fmt);
fprintf(
stderr,
- "[%ld.%03ld, %ld.%03ld][DEBUG]: ",
+ "[%ld.%03ld, %ld.%03ld, %ld KB][DEBUG]: ",
real_time.tv_sec,
real_time.tv_nsec / 1000000,
cpu_time.tv_sec,
- cpu_time.tv_nsec / 1000000);
+ cpu_time.tv_nsec / 1000000,
+ usage.ru_maxrss
+ );
vfprintf(stderr, fmt, args);
va_end(args);
}
diff --git a/src/main.c b/src/main.c
index 514d6f2..d59f747 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,6 +1,4 @@
#include <assert.h>
-#include <wayland-egl.h>
-#include <epoxy/gl.h>
#include <errno.h>
#include <getopt.h>
#include <locale.h>
@@ -14,16 +12,14 @@
#include <wayland-client.h>
#include <wchar.h>
#include <wctype.h>
-#include <xdg-shell.h>
#include <xkbcommon/xkbcommon.h>
#include "tofi.h"
#include "compgen.h"
-#include "egl.h"
#include "entry.h"
#include "image.h"
-#include "gl.h"
#include "log.h"
#include "nelem.h"
+#include "shm.h"
#include "string_vec.h"
#undef MAX
@@ -49,7 +45,7 @@ static void zwlr_layer_surface_configure(
/*
* Resize the main window.
- * EGL wants actual pixel width / height, so we have to scale the
+ * We want actual pixel width / height, so we have to scale the
* values provided by Wayland.
*/
tofi->window.surface.width =
@@ -57,9 +53,13 @@ static void zwlr_layer_surface_configure(
tofi->window.surface.height =
tofi->window.height * tofi->window.scale;
+ /* Assume 4 bytes per pixel for WL_SHM_FORMAT_XRGB8888 */
+ tofi->window.surface.stride =
+ tofi->window.surface.width * 4;
+
/*
- * Need to redraw the background at the new size. This entails a
- * wl_surface_commit, so no need to do so explicitly here.
+ * Need to redraw the background at the new size. This entails
+ * a wl_surface_commit, so no need to do so explicitly here.
*/
tofi->window.surface.redraw = true;
}
@@ -443,7 +443,7 @@ static void registry_global(
uint32_t version)
{
struct tofi *tofi = data;
- //log_debug("Registry %s %u.\n", interface, name);
+ log_debug("Registry %u: %s v%u.\n", name, interface, version);
if (!strcmp(interface, wl_compositor_interface.name)) {
tofi->wl_compositor = wl_registry_bind(
wl_registry,
@@ -473,12 +473,19 @@ static void registry_global(
&wl_output_listener,
tofi);
log_debug("Bound to output %u.\n", name);
+ } else if (!strcmp(interface, wl_shm_interface.name)) {
+ tofi->wl_shm = wl_registry_bind(
+ wl_registry,
+ name,
+ &wl_shm_interface,
+ 1);
+ log_debug("Bound to shm %u.\n", name);
} else if (!strcmp(interface, zwlr_layer_shell_v1_interface.name)) {
tofi->zwlr_layer_shell = wl_registry_bind(
wl_registry,
name,
&zwlr_layer_shell_v1_interface,
- 1);
+ 4);
log_debug("Bound to zwlr_layer_shell_v1 %u.\n", name);
}
}
@@ -797,19 +804,21 @@ int main(int argc, char *argv[])
log_debug("Pango / Cairo initialised.\n");
/*
- * Create the various EGL and GL structures for each surface, and
+ * Create the various structures for each surface, and
* perform an initial render of everything.
*/
log_debug("Initialising main window surface.\n");
+
surface_initialise(
&tofi.window.surface,
- tofi.wl_display,
+ tofi.wl_shm,
&tofi.window.entry.image);
surface_draw(
&tofi.window.surface,
&tofi.window.entry.background_color,
&tofi.window.entry.image);
+
/* We've just rendered, so we don't need to do it again right now. */
tofi.window.surface.redraw = false;
@@ -842,11 +851,10 @@ int main(int argc, char *argv[])
/*
* For debug builds, try to cleanup as much as possible, to make using
* e.g. Valgrind easier. There's still a few unavoidable leaks though,
- * mostly from OpenGL libs and Pango.
+ * mostly from Pango.
*/
- entry_destroy(&tofi.window.entry);
surface_destroy(&tofi.window.surface);
- eglTerminate(tofi.window.surface.egl.display);
+ entry_destroy(&tofi.window.entry);
wl_surface_destroy(tofi.window.surface.wl_surface);
if (tofi.wl_keyboard != NULL) {
wl_keyboard_release(tofi.wl_keyboard);
diff --git a/src/shm.c b/src/shm.c
new file mode 100644
index 0000000..e145d4a
--- /dev/null
+++ b/src/shm.c
@@ -0,0 +1,49 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <time.h>
+#include <unistd.h>
+#include "shm.h"
+
+static void randname(char *buf)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ long r = ts.tv_nsec;
+ for (int i = 0; i < 6; ++i) {
+ buf[i] = 'A'+(r&15)+(r&16)*2;
+ r >>= 5;
+ }
+}
+
+static int create_shm_file(void)
+{
+ int retries = 100;
+ do {
+ char name[] = "/wl_shm-XXXXXX";
+ randname(name + sizeof(name) - 7);
+ --retries;
+ int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (fd >= 0) {
+ shm_unlink(name);
+ return fd;
+ }
+ } while (retries > 0 && errno == EEXIST);
+ return -1;
+}
+
+int shm_allocate_file(size_t size)
+{
+ int fd = create_shm_file();
+ if (fd < 0)
+ return -1;
+ int ret;
+ do {
+ ret = ftruncate(fd, size);
+ } while (ret < 0 && errno == EINTR);
+ if (ret < 0) {
+ close(fd);
+ return -1;
+ }
+ return fd;
+}
diff --git a/src/shm.h b/src/shm.h
new file mode 100644
index 0000000..559ff5c
--- /dev/null
+++ b/src/shm.h
@@ -0,0 +1,8 @@
+#ifndef SHM_H
+#define SHM_H
+
+#include <stddef.h>
+
+int shm_allocate_file(size_t size);
+
+#endif /* SHM_H */
diff --git a/src/string_vec.c b/src/string_vec.c
index 3c77f6f..0bcd7f2 100644
--- a/src/string_vec.c
+++ b/src/string_vec.c
@@ -23,7 +23,7 @@ static int cmpstringp(const void *restrict a, const void *restrict b)
if (str2 == NULL) {
return -1;
}
- return strcasecmp(str1, str2);
+ return strcmp(str1, str2);
}
struct string_vec string_vec_create(void)
diff --git a/src/surface.c b/src/surface.c
index 8052d5e..90e7bb0 100644
--- a/src/surface.c
+++ b/src/surface.c
@@ -1,4 +1,8 @@
-#include "gl.h"
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include "log.h"
+#include "shm.h"
#include "surface.h"
#undef MAX
@@ -6,23 +10,56 @@
void surface_initialise(
struct surface *surface,
- struct wl_display *wl_display,
+ struct wl_shm *wl_shm,
struct image *texture)
{
- egl_create_window(
- &surface->egl,
- surface->wl_surface,
- surface->width,
- surface->height);
- egl_create_context(&surface->egl, wl_display);
- gl_initialise(&surface->gl, texture);
+
+ const int height = surface->height;
+ const int stride = surface->stride;
+
+ /* Double-buffered pool, so allocate space for two windows */
+ surface->shm_pool_size =
+ height
+ * stride
+ * 2;
+ surface->shm_pool_fd = shm_allocate_file(surface->shm_pool_size);
+ surface->shm_pool_data = mmap(
+ NULL,
+ surface->shm_pool_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED,
+ surface->shm_pool_fd,
+ 0);
+ surface->wl_shm_pool = wl_shm_create_pool(
+ wl_shm,
+ surface->shm_pool_fd,
+ surface->shm_pool_size);
+
+ for (int i = 0; i < 2; i++) {
+ int offset = surface->height * surface->stride * i;
+ surface->buffers[i] = wl_shm_pool_create_buffer(
+ surface->wl_shm_pool,
+ offset,
+ surface->width,
+ surface->height,
+ surface->stride,
+ WL_SHM_FORMAT_XRGB8888);
+ }
+
+ log_debug("Created shm file with size %d KiB.\n",
+ surface->shm_pool_size / 1024);
+
+ surface->index = 0;
}
void surface_destroy(struct surface *surface)
{
- egl_make_current(&surface->egl);
- gl_destroy(&surface->gl);
- egl_destroy(&surface->egl);
+ wl_shm_pool_destroy(surface->wl_shm_pool);
+ munmap(surface->shm_pool_data, surface->shm_pool_size);
+ surface->shm_pool_data = NULL;
+ close(surface->shm_pool_fd);
+ wl_buffer_destroy(surface->buffers[0]);
+ wl_buffer_destroy(surface->buffers[1]);
}
void surface_draw(
@@ -30,29 +67,12 @@ void surface_draw(
struct color *color,
struct image *texture)
{
- wl_egl_window_resize(
- surface->egl.window,
- surface->width,
- surface->height,
- 0,
- 0);
- egl_make_current(&surface->egl);
- gl_clear(&surface->gl, color);
-
- if (texture != NULL && texture->buffer != NULL) {
- double scale = MAX(
- (double)surface->width / texture->width,
- (double)surface->height / texture->height
- );
- int32_t width = (int32_t)(scale * texture->width);
- int32_t height = (int32_t)(scale * texture->height);
- int32_t x = -((int32_t)width - (int32_t)surface->width) / 2;
- int32_t y = -((int32_t)height - (int32_t)surface->height) / 2;
-
- gl_draw_texture(&surface->gl, texture, x, y, width, height);
- }
+ surface->index = !surface->index;
+ int offset = surface->height * surface->stride * surface->index;
+ uint32_t *pixels = (uint32_t *)&surface->shm_pool_data[offset];
+ memcpy(pixels, texture->buffer, surface->height * surface->stride);
+ wl_surface_attach(surface->wl_surface, surface->buffers[surface->index], 0, 0);
wl_surface_damage_buffer(surface->wl_surface, 0, 0, INT32_MAX, INT32_MAX);
-
- egl_swap_buffers(&surface->egl);
+ wl_surface_commit(surface->wl_surface);
}
diff --git a/src/surface.h b/src/surface.h
index b8b132f..8abd1e1 100644
--- a/src/surface.h
+++ b/src/surface.h
@@ -3,21 +3,28 @@
#include <stdbool.h>
#include <stdint.h>
-#include "egl.h"
-#include "gl.h"
+#include <wayland-client.h>
+#include "color.h"
+#include "image.h"
struct surface {
- struct egl egl;
- struct gl gl;
struct wl_surface *wl_surface;
+ struct wl_shm_pool *wl_shm_pool;
int32_t width;
int32_t height;
+ int32_t stride;
+ int index;
+ struct wl_buffer *buffers[2];
+
+ int shm_pool_size;
+ int shm_pool_fd;
+ uint8_t *shm_pool_data;
bool redraw;
};
void surface_initialise(
struct surface *surface,
- struct wl_display *wl_display,
+ struct wl_shm *wl_shm,
struct image *texture);
void surface_destroy(struct surface *surface);
void surface_draw(
diff --git a/src/tofi.h b/src/tofi.h
index 87c0dfe..36869a6 100644
--- a/src/tofi.h
+++ b/src/tofi.h
@@ -3,7 +3,6 @@
#include <stdbool.h>
#include <stdint.h>
-#include <xdg-shell.h>
#include "color.h"
#include "entry.h"
#include "image.h"
@@ -17,6 +16,7 @@ struct tofi {
struct wl_compositor *wl_compositor;
struct wl_seat *wl_seat;
struct wl_output *wl_output;
+ struct wl_shm *wl_shm;
struct zwlr_layer_shell_v1 *zwlr_layer_shell;
uint32_t wl_display_name;
@@ -24,6 +24,7 @@ struct tofi {
uint32_t wl_compositor_name;
uint32_t wl_seat_name;
uint32_t wl_output_name;
+ uint32_t wl_shm_name;
uint32_t zwlr_layer_shell_name;
/* Objects */
diff --git a/src/xmalloc.c b/src/xmalloc.c
index 1c2a9dc..2bb07d2 100644
--- a/src/xmalloc.c
+++ b/src/xmalloc.c
@@ -8,7 +8,7 @@ void *xmalloc(size_t size)
void *ptr = malloc(size);
if (ptr != NULL) {
- //log_debug("Allocated %zu bytes.\n", size);
+ log_debug("Allocated %zu bytes.\n", size);
return ptr;
} else {
log_error("Out of memory, exiting.\n");
@@ -21,7 +21,7 @@ void *xcalloc(size_t nmemb, size_t size)
void *ptr = calloc(nmemb, size);
if (ptr != NULL) {
- //log_debug("Allocated %zux%zu bytes.\n", nmemb, size);
+ log_debug("Allocated %zux%zu bytes.\n", nmemb, size);
return ptr;
} else {
log_error("Out of memory, exiting.\n");
@@ -34,7 +34,7 @@ void *xrealloc(void *ptr, size_t size)
ptr = realloc(ptr, size);
if (ptr != NULL) {
- //log_debug("Reallocated to %zu bytes.\n", size);
+ log_debug("Reallocated to %zu bytes.\n", size);
return ptr;
} else {
log_error("Out of memory, exiting.\n");
@@ -47,7 +47,6 @@ char *xstrdup(const char *s)
char *ptr = strdup(s);
if (ptr != NULL) {
- //log_debug("Allocated %zu bytes.\n", size);
return ptr;
} else {
log_error("Out of memory, exiting.\n");