diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..b38b56e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wlroots-lunar"] + path = wlroots-lunar + url = git@github.com:slendidev/wlroots-lunar diff --git a/src/LunarWM_render.c b/src/LunarWM_render.c index 92445d5..4067b83 100644 --- a/src/LunarWM_render.c +++ b/src/LunarWM_render.c @@ -329,12 +329,22 @@ void LunarWM_render_windows(LunarWM *this, bool alpha_check) continue; } if (tl->gles_texture) { - if (alpha_check && tl->gles_texture->has_alpha) { + if (alpha_check && tl->composed_has_alpha) { continue; } + Texture2D tex = tl->rl_texture; + bool y_flip = false; + if (IsRenderTextureValid(tl->surface_rt)) { + tex = tl->surface_rt.texture; + tex.width = tl->rl_texture.width; + tex.height = tl->rl_texture.height; + y_flip = true; + } + if (!tex.id) + continue; float rad = window->coord.r - 0.01f * (float)i; - DrawTextureCyl2(tl->rl_texture, Vector3Zero(), window->coord, rad, - this->cman->cfg.space.window_scale, false); + DrawTextureCyl2(tex, Vector3Zero(), window->coord, rad, + this->cman->cfg.space.window_scale, y_flip); } } } diff --git a/src/LunarWM_types.h b/src/LunarWM_types.h index 65b4c62..36dd835 100644 --- a/src/LunarWM_types.h +++ b/src/LunarWM_types.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -126,6 +127,9 @@ typedef struct { struct wlr_gles2_texture_attribs attribs; struct wlr_gles2_texture *gles_texture; Texture2D rl_texture; + RenderTexture2D surface_rt; + struct wlr_box surface_extents; + bool composed_has_alpha; } LunarWM_Toplevel; typedef struct { diff --git a/src/LunarWM_wayland.c b/src/LunarWM_wayland.c index 9760300..28777d8 100644 --- a/src/LunarWM_wayland.c +++ b/src/LunarWM_wayland.c @@ -26,6 +26,18 @@ static inline SphericalCoord get_forward_spherical_with_nearest( return Vector3ToSpherical(vec); } +static void LunarWM_Toplevel_release_surface_rt(LunarWM_Toplevel *tl) +{ + if (!tl) + return; + if (IsRenderTextureValid(tl->surface_rt)) { + UnloadRenderTexture(tl->surface_rt); + } + tl->surface_rt = (RenderTexture2D) { 0 }; + tl->surface_extents = (struct wlr_box) { 0 }; + tl->composed_has_alpha = false; +} + static void remove_windows_for_tl(LunarWM *wm, LunarWM_Toplevel *tl) { if (!wm || !tl) @@ -126,7 +138,9 @@ static void toplevel_unmap_notify(struct wl_listener *l, void *data) tl->texture = NULL; tl->gles_texture = NULL; tl->rl_texture = (Texture) { 0 }; + LunarWM_Toplevel_release_surface_rt(tl); tl->surface = NULL; + tl->composed_has_alpha = false; focus_fallback(tl->server); } @@ -196,9 +210,63 @@ bool LunarWM_Toplevel_destroy(LunarWM_Toplevel *this) wl_list_remove(&this->destroy.link); if (this->locked_buffer) wlr_buffer_unlock(this->locked_buffer); + LunarWM_Toplevel_release_surface_rt(this); + this->composed_has_alpha = false; return true; } +struct SurfaceComposeCtx { + struct wlr_box extents; + bool *has_alpha; +}; + +static void surface_compose_draw( + struct wlr_surface *surface, int sx, int sy, void *user_data) +{ + struct SurfaceComposeCtx *ctx = user_data; + if (!ctx) + return; + + struct wlr_texture *wlr_tex = wlr_surface_get_texture(surface); + if (!wlr_tex || wlr_tex->width == 0 || wlr_tex->height == 0) + return; + + struct wlr_gles2_texture *gles_tex = gles2_get_texture(wlr_tex); + if (!gles_tex) + return; + if (ctx->has_alpha && gles_tex->has_alpha) + *ctx->has_alpha = true; + + struct wlr_gles2_texture_attribs attribs; + wlr_gles2_texture_get_attribs(wlr_tex, &attribs); + Texture2D tex = { + .id = (unsigned int)attribs.tex, + .width = (int)wlr_tex->width, + .height = (int)wlr_tex->height, + .mipmaps = 1, + .format = gles_tex->has_alpha + ? PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 + : PIXELFORMAT_UNCOMPRESSED_R8G8B8, + }; + + float dest_w = (float)surface->current.width; + float dest_h = (float)surface->current.height; + if (dest_w <= 0.0f || dest_h <= 0.0f) { + dest_w = (float)tex.width; + dest_h = (float)tex.height; + } + + Rectangle src = { 0.0f, 0.0f, (float)tex.width, (float)tex.height }; + Rectangle dst = { + (float)(sx - ctx->extents.x), + (float)(sy - ctx->extents.y), + dest_w, + dest_h, + }; + + DrawTexturePro(tex, src, dst, (Vector2) { 0.0f, 0.0f }, 0.0f, WHITE); +} + bool LunarWM_Toplevel_update(LunarWM_Toplevel *this) { if (!this || !this->surface) @@ -236,6 +304,53 @@ bool LunarWM_Toplevel_update(LunarWM_Toplevel *this) SetTextureFilter(this->rl_texture, TEXTURE_FILTER_BILINEAR); SetTextureWrap(this->rl_texture, TEXTURE_WRAP_CLAMP); + struct wlr_box extents = { 0 }; + wlr_surface_get_extents(this->surface, &extents); + if (extents.width <= 0 || extents.height <= 0) { + LunarWM_Toplevel_release_surface_rt(this); + this->composed_has_alpha = this->gles_texture->has_alpha; + return true; + } + + bool needs_alpha = this->gles_texture->has_alpha; + if (extents.x != 0 || extents.y != 0 + || extents.width != (int)this->texture->width + || extents.height != (int)this->texture->height) { + needs_alpha = true; + } + + bool const size_changed = !IsRenderTextureValid(this->surface_rt) + || this->surface_rt.texture.width != extents.width + || this->surface_rt.texture.height != extents.height; + if (size_changed) { + LunarWM_Toplevel_release_surface_rt(this); + this->surface_rt = LoadRenderTexture(extents.width, extents.height); + if (!IsRenderTextureValid(this->surface_rt)) { + this->composed_has_alpha = needs_alpha; + return true; + } + SetTextureFilter(this->surface_rt.texture, TEXTURE_FILTER_BILINEAR); + SetTextureWrap(this->surface_rt.texture, TEXTURE_WRAP_CLAMP); + } + + BeginTextureMode(this->surface_rt); + ClearBackground(BLANK); + BeginBlendMode(BLEND_ALPHA); + struct SurfaceComposeCtx ctx = { + .extents = extents, + .has_alpha = &needs_alpha, + }; + wlr_surface_for_each_surface(this->surface, surface_compose_draw, &ctx); + EndBlendMode(); + EndTextureMode(); + + this->surface_extents = extents; + Texture2D composed = this->surface_rt.texture; + composed.width = extents.width; + composed.height = extents.height; + this->rl_texture = composed; + this->composed_has_alpha = needs_alpha; + return true; } @@ -389,6 +504,7 @@ static void xwl_unmap_toplevel(LunarWM_Toplevel *tl) tl->texture = NULL; tl->gles_texture = NULL; tl->rl_texture = (Texture) { 0 }; + LunarWM_Toplevel_release_surface_rt(tl); tl->surface = NULL; } diff --git a/wlroots-lunar b/wlroots-lunar new file mode 160000 index 0000000..2fd8463 --- /dev/null +++ b/wlroots-lunar @@ -0,0 +1 @@ +Subproject commit 2fd8463ad8c78469744d854b3d155a3b55fc7ae1