Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions examples/example-blur-plugin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
#include <string.h>
#include "example-blur-plugin.h"

#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <GLES2/gl2.h>
#include <wlr/util/log.h>

#include "scenefx/render/pass.h"
#include "scenefx/render/fx_renderer/fx_blur.h"
#include "scenefx/render/fx_renderer/fx_renderer.h"

struct invert_data
{
struct fx_blur_plugin_base_shader base;
GLint target_offset;
GLint target_size;
GLint source_size;
};

static char* invert_gles3_src =
"#version 300 es\n"
"\n"
"precision highp float;\n"
"\n"
"in vec2 v_texcoord;\n"
"uniform sampler2D tex;\n"
"uniform vec2 target_offset;\n"
"uniform vec2 target_size;\n"
"uniform vec2 source_size;\n"
"out vec4 fragColor;\n"
"\n"
"void main() {\n"
" vec2 full = v_texcoord;\n"
" vec2 offset = target_offset / source_size;\n"
" vec2 limit = target_size / source_size;\n"
" vec2 inverted_coord = (limit - (v_texcoord - offset)) + offset;\n"
" fragColor = texture(tex, inverted_coord);\n"
"}\n";

static bool invert_init(int client_version, char *id, void** user_data)
{
struct invert_data* v = malloc(sizeof(struct invert_data));
if (!v)
{
return false;
}

if (!fx_link_blur_plugin_base_shader_program(&v->base, invert_gles3_src, client_version))
{
wlr_log(WLR_ERROR, "failed to link blur plugin");
free(v);
return false;
}

v->source_size = glGetUniformLocation(v->base.program, "source_size");
v->target_size = glGetUniformLocation(v->base.program, "target_size");
v->target_offset = glGetUniformLocation(v->base.program, "target_offset");
*user_data = v;

return true;
}

static void invert_execute(pixman_region32_t* damage, struct wlr_box* box,
struct fx_gles_render_pass* pass,
struct fx_render_blur_pass_options* fx_options,
void* data)
{
fx_options->tex_options.base.clip = damage;

struct fx_render_texture_options* tex_options = &fx_options->tex_options;
struct wlr_render_texture_options* options = &tex_options->base;
struct fx_texture* texture = fx_get_texture(options->texture);

struct invert_data shader = *(struct invert_data*)data;

struct wlr_box dst_box;
struct wlr_fbox src_fbox;
wlr_render_texture_options_get_src_box(options, &src_fbox);
wlr_render_texture_options_get_dst_box(options, &dst_box);

src_fbox.x /= options->texture->width;
src_fbox.y /= options->texture->height;
src_fbox.width /= options->texture->width;
src_fbox.height /= options->texture->height;

glDisable(GL_BLEND);
glDisable(GL_STENCIL_TEST);

glUseProgram(shader.base.program);

glActiveTexture(GL_TEXTURE0);

GLuint tex_target = fx_texture_get_target(texture);
GLuint tex_tex = fx_texture_get_texture(texture);

glBindTexture(tex_target, tex_tex);

switch (options->filter_mode)
{
case WLR_SCALE_FILTER_BILINEAR:
glTexParameteri(tex_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(tex_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
break;
case WLR_SCALE_FILTER_NEAREST:
abort();
}

glUniform1i(shader.base.tex, 0);

glUniform2f(shader.target_size, box->width, box->height);
glUniform2f(shader.target_offset, box->x, box->y);
glUniform2f(shader.source_size, options->texture->width,
options->texture->height);

fx_set_proj_matrix(shader.base.proj, pass->projection_matrix, &dst_box);
fx_set_tex_matrix(shader.base.tex_proj, options->transform, &src_fbox);

fx_render(&dst_box, options->clip, shader.base.pos_attrib);

glBindTexture(tex_target, 0);

wlr_texture_destroy(options->texture);
}

static void invert_destroy(void* data)
{
struct invert_data shader = *(struct invert_data*)data;
free(data);
glDeleteProgram(shader.base.program);
}

static const struct fx_blur_impl invert = {
.name = "invert",
.init = invert_init,
.get_expansion = NULL,
.prepare = NULL,
.execute = invert_execute,
.destroy = invert_destroy,
};

const struct fx_blur_impl* fx_blur_by_id(char* name)
{
if (strcmp(invert.name, name) == 0)
{
return &invert;
}

return NULL;
}
8 changes: 8 additions & 0 deletions examples/example-blur-plugin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//
// Created by eater on 11/22/25.
//

#ifndef SWAYFX_EXAMPLE_BLUR_PLUGIN_H
#define SWAYFX_EXAMPLE_BLUR_PLUGIN_H
const struct fx_blur_impl *fx_blur_by_id(char *name);
#endif //SWAYFX_EXAMPLE_BLUR_PLUGIN_H
5 changes: 5 additions & 0 deletions examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,8 @@ foreach name, info : compositors
)
endforeach

library(
'example-blur-plugin',
['example-blur-plugin.c'],
dependencies: [scenefx]
)
3 changes: 1 addition & 2 deletions include/render/fx_renderer/fx_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,6 @@ bool wlr_renderer_is_fx(struct wlr_renderer *wlr_renderer);

struct fx_render_timer *fx_get_render_timer(struct wlr_render_timer *timer);

struct fx_texture *fx_get_texture(struct wlr_texture *wlr_texture);

struct wlr_renderer *fx_renderer_create_egl(struct wlr_egl *egl);

struct wlr_egl *wlr_fx_renderer_get_egl(struct wlr_renderer *renderer);
Expand Down Expand Up @@ -191,6 +189,7 @@ struct fx_renderer {
struct wl_list buffers; // fx_framebuffer.link
struct wl_list textures; // fx_texture.link
struct wl_list effect_fbos; // fx_effect_framebuffers.link
struct wl_list blur_shader_data; // fx_blur_plugin_info.link

// Set to true when 'wlr_renderer_begin_buffer_pass' is called instead of
// our custom 'fx_renderer_begin_buffer_pass' function
Expand Down
53 changes: 53 additions & 0 deletions include/scenefx/render/fx_renderer/fx_blur.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#ifndef SWAYFX_FX_BLUR_H
#define SWAYFX_FX_BLUR_H
#include <stdbool.h>
#include <wayland-util.h>
#include <GLES2/gl2.h>

enum fx_blur_shader_state {
BLUR_NONE = 0,
BLUR_LOADED = 1,
BLUR_LINKED = 2,
BLUR_READY = BLUR_LINKED | BLUR_LOADED,
};

struct fx_blur_plugin_info {
struct wl_list link;
enum fx_blur_shader_state state;
void *handle;
char *path;
char *id;
const struct fx_blur_impl *blur_impl;
void *user_data;
};


struct fx_blur_plugin_base_shader {
GLuint program;
GLint proj;
GLint tex_proj;
GLint tex;
GLint pos_attrib;
};

bool fx_link_blur_plugin_base_shader_program(
struct fx_blur_plugin_base_shader *shader,
char *shader_src,
GLint client_version
);

struct wlr_renderer;
struct fx_blur_plugin_info *fx_blur_plugin_create(char *path, char *id);
void fx_blur_plugin_destroy(struct fx_blur_plugin_info *info);
bool fx_blur_plugin_load(struct fx_blur_plugin_info *info);
bool fx_blur_plugin_link(struct wlr_renderer *renderer, struct fx_blur_plugin_info *info);
// TODO:
// void blur_plugin_reload(struct fx_blur_shader_info *info);

struct fx_blur_plugin_info *fx_renderer_get_plugin(struct wlr_renderer *renderer, char *id);
void fx_renderer_add_plugin(struct wlr_renderer *renderer, struct fx_blur_plugin_info *info);
void fx_renderer_remove_plugin(struct wlr_renderer *renderer, struct fx_blur_plugin_info *info);

typedef const struct fx_blur_impl *(*fx_blur_get_by_id_func)(char *);

#endif //SWAYFX_FX_BLUR_H
5 changes: 5 additions & 0 deletions include/scenefx/render/fx_renderer/fx_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <wlr/types/wlr_buffer.h>

struct fx_renderer;
struct fx_framebuffer;

struct wlr_renderer *fx_renderer_create_with_drm_fd(int drm_fd);
struct wlr_renderer *fx_renderer_create(struct wlr_backend *backend);
Expand All @@ -17,6 +18,10 @@ struct fx_renderer *fx_get_renderer(struct wlr_renderer *wlr_renderer);
bool fx_renderer_check_ext(struct wlr_renderer *renderer, const char *ext);
GLuint fx_renderer_get_buffer_fbo(struct wlr_renderer *renderer, struct wlr_buffer *buffer);

struct fx_renderer * fx_framebuffer_get_renderer(struct fx_framebuffer* framebuffer);
struct fx_texture *fx_get_texture(struct wlr_texture *wlr_texture);
GLuint fx_texture_get_target(struct fx_texture *fx_texture);
GLuint fx_texture_get_texture(struct fx_texture *fx_texture);
//
// fx_texture
//
Expand Down
15 changes: 15 additions & 0 deletions include/scenefx/render/pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,23 @@ struct fx_render_blur_pass_options {
int corner_radius;
enum corner_location corners;
struct clipped_region clipped_region;
char* blur_id;
};

struct fx_blur_impl {
char *name;
bool (*init)(int client_version, char *id, void ** data);
bool (*supports_optimized_blur)(void *);
int (*get_expansion)(struct fx_gles_render_pass *, struct fx_render_blur_pass_options *, void *);
bool (*prepare)(pixman_region32_t *damage, struct fx_gles_render_pass *, struct fx_render_blur_pass_options *, void *);
void (*execute)(pixman_region32_t *damage, struct wlr_box *box, struct fx_gles_render_pass *, struct fx_render_blur_pass_options *, void *);
void (*destroy)(void *);
};

void fx_set_tex_matrix(GLint loc, enum wl_output_transform trans,
const struct wlr_fbox *box);
void fx_set_proj_matrix(GLint loc, float proj[9], const struct wlr_box *box);
void fx_render(const struct wlr_box *box, const pixman_region32_t *clip, GLint attrib);
/**
* Render a fx texture.
*/
Expand Down
1 change: 1 addition & 0 deletions include/scenefx/types/fx/blur_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <wlr/util/addon.h>

struct blur_data {
char *id;
int num_passes;
float radius;
float noise;
Expand Down
2 changes: 2 additions & 0 deletions include/scenefx/types/wlr_scene.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@ void wlr_scene_set_blur_contrast(struct wlr_scene *scene, float contrast);
// Sets the global blur saturation parameter
void wlr_scene_set_blur_saturation(struct wlr_scene *scene, float saturation);

void wlr_scene_set_blur_id(struct wlr_scene *scene, char * id);

/**
* Handles linux_dmabuf_v1 feedback for all surfaces in the scene.
*
Expand Down
Loading