wayland flickering/ghosting fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good
This commit is contained in:
parent
f9bbba8af9
commit
1dda7934ce
8 changed files with 82 additions and 46 deletions
|
|
@ -261,6 +261,7 @@ if(MW_USE_WAYLAND)
|
|||
scan_wayland_protocol("unstable" "primary-selection" "-unstable-v1")
|
||||
scan_wayland_protocol("unstable" "pointer-constraints" "-unstable-v1")
|
||||
scan_wayland_protocol("unstable" "relative-pointer" "-unstable-v1")
|
||||
scan_wayland_protocol("staging" "fifo" "-v1")
|
||||
scan_wayland_protocol_from_file("wlr-layer-shell" "wlr-layer-shell-unstable-v1.xml")
|
||||
|
||||
target_sources(
|
||||
|
|
|
|||
|
|
@ -196,6 +196,9 @@ struct _MwLLCairo {
|
|||
/* The cairo to actually use for draw operations. Typically is front_cairo, but wayland's MwLLBeginDraw can change this to the back_cairo so it can be used to draw window decorations. */
|
||||
cairo_t* selected_cairo;
|
||||
|
||||
cairo_surface_t* frontbuffer_cs;
|
||||
cairo_t* frontbuffer_cairo;
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ MwInline int wayland_load_funcs() {
|
|||
#include "Wayland/relative-pointer-client-protocol.h"
|
||||
#include "Wayland/xdg-toplevel-icon-client-protocol.h"
|
||||
#include "Wayland/wlr-layer-shell-client-protocol.h"
|
||||
#include "Wayland/fifo-client-protocol.h"
|
||||
#endif
|
||||
|
||||
typedef struct wayland_protocol {
|
||||
|
|
@ -265,6 +266,7 @@ struct _MwLLWaylandShmBuffer {
|
|||
struct wl_buffer* shm_buffer_back;
|
||||
struct wl_surface* surface;
|
||||
struct wl_output* output;
|
||||
struct wp_fifo_v1* fifo;
|
||||
|
||||
MwU8* buf;
|
||||
MwU8* buf_back;
|
||||
|
|
@ -426,9 +428,13 @@ struct _MwLLWayland {
|
|||
|
||||
MwBool force_render;
|
||||
MwBool did_event_loop_early;
|
||||
MwBool do_cascading_draw;
|
||||
int cascading_child_num;
|
||||
|
||||
MwBool dispatching_resize;
|
||||
|
||||
MwBool is_toplevel_menu;
|
||||
|
||||
struct _MwLLWaylandShmBuffer framebuffer;
|
||||
struct _MwLLWaylandShmBuffer backbuffer;
|
||||
struct _MwLLWaylandShmBuffer cursor;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ if (grep(/^wayland$/, @backends)) {
|
|||
scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1");
|
||||
scan_wayland_protocol("unstable", "pointer-constraints", "-unstable-v1");
|
||||
scan_wayland_protocol("unstable", "relative-pointer", "-unstable-v1");
|
||||
scan_wayland_protocol("staging", "fifo", "-v1");
|
||||
scan_wayland_protocol_from_file("wlr-layer-shell",
|
||||
"wlr-layer-shell-unstable-v1.xml");
|
||||
|
||||
|
|
|
|||
|
|
@ -113,13 +113,16 @@ void MwLLCairoDrawPixmap(struct _MwLLCairo handle, MwRect* rect, MwLLPixmap pixm
|
|||
|
||||
void MwLLCairoFrontSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
|
||||
if(data) {
|
||||
cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
|
||||
cairo->front_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
|
||||
cairo->frontbuffer_cs = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, width * 4);
|
||||
} else {
|
||||
cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cairo->front_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cairo->frontbuffer_cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
}
|
||||
cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cairo->front_cairo_back = cairo_create(cairo->front_cs_back);
|
||||
cairo->front_cairo = cairo_create(cairo->front_cs);
|
||||
cairo->front_cs_back = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
||||
cairo->front_cairo_back = cairo_create(cairo->front_cs_back);
|
||||
cairo->front_cairo = cairo_create(cairo->front_cs);
|
||||
cairo->frontbuffer_cairo = cairo_create(cairo->frontbuffer_cs);
|
||||
}
|
||||
|
||||
void MwLLCairoBackSetup(struct _MwLLCairo* cairo, MwU8* data, MwU32 width, MwU32 height) {
|
||||
|
|
@ -135,6 +138,8 @@ void MwLLCairoFrontDestroy(struct _MwLLCairo* cairo) {
|
|||
cairo_destroy(cairo->front_cairo);
|
||||
cairo_destroy(cairo->front_cairo_back);
|
||||
cairo_surface_destroy(cairo->front_cs);
|
||||
cairo_surface_destroy(cairo->frontbuffer_cs);
|
||||
cairo_destroy(cairo->frontbuffer_cairo);
|
||||
};
|
||||
void MwLLCairoBackDestroy(struct _MwLLCairo* cairo) {
|
||||
cairo_destroy(cairo->back_cairo);
|
||||
|
|
@ -214,8 +219,8 @@ static void MwLLFreeColorImpl(MwLLColor color) {}
|
|||
|
||||
static MwBool lmao = MwFALSE;
|
||||
static int MwLLPendingImpl(MwLL handle) {
|
||||
lmao = !lmao;
|
||||
return lmao;
|
||||
lmao = !lmao;
|
||||
return lmao;
|
||||
}
|
||||
static void MwLLNextEventImpl(MwLL handle) {
|
||||
MwLLDispatch(handle, draw, NULL);
|
||||
|
|
@ -259,10 +264,10 @@ static void MwLLRaiseImpl(MwLL handle) {}
|
|||
static void MwLLClipImpl(MwLL handle, MwRect* rect) {}
|
||||
static void MwLLSetupDragAndDropImpl(MwLL handle) {}
|
||||
static int MwLLCairoCallInitImpl(void) {
|
||||
if(cairo_load_funcs() != 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
if(cairo_load_funcs() != 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#include "call.c"
|
||||
CALL(Cairo);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ void MwLLWaylandFramebufferSetup(struct _MwLLWayland* wayland) {
|
|||
memset(wayland->framebuffer.buf_back, 0, wayland->framebuffer.buf_size);
|
||||
if(wayland->configured)
|
||||
wl_surface_attach(wayland->framebuffer.surface, wayland->framebuffer.shm_buffer, 0, 0);
|
||||
if(wayland->framebuffer.fifo)
|
||||
wp_fifo_v1_set_barrier(wayland->framebuffer.fifo);
|
||||
|
||||
wl_surface_commit(wayland->framebuffer.surface);
|
||||
|
||||
MwLLWaylandHangUntilConfigured((MwLL)wayland);
|
||||
|
|
@ -38,6 +41,8 @@ void MwLLWaylandBackbufferSetup(struct _MwLLWayland* wayland) {
|
|||
memset(wayland->backbuffer.buf_back, 255, wayland->backbuffer.buf_size);
|
||||
if(wayland->configured)
|
||||
wl_surface_attach(wayland->backbuffer.surface, wayland->backbuffer.shm_buffer, 0, 0);
|
||||
// if(wayland->framebuffer.fifo)
|
||||
// wp_fifo_v1_set_barrier(wayland->framebuffer.fifo);
|
||||
wl_surface_commit(wayland->backbuffer.surface);
|
||||
MwLLWaylandHangUntilConfigured((MwLL)wayland);
|
||||
MwLLWaylandBufferUpdate((MwLL)wayland, &wayland->backbuffer);
|
||||
|
|
@ -119,9 +124,11 @@ void MwLLWaylandBufferUpdate(MwLL self, struct _MwLLWaylandShmBuffer* buffer) {
|
|||
memcpy(buffer->buf, buffer->buf_back, buffer->buf_size);
|
||||
if(buffer->surface) {
|
||||
// Yes this is needed every time, it's how we fix weston.
|
||||
if(self->wayland.configured)
|
||||
if(self->wayland.configured) {
|
||||
wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0);
|
||||
|
||||
}
|
||||
if(buffer->fifo)
|
||||
wp_fifo_v1_wait_barrier(buffer->fifo);
|
||||
wl_surface_commit(buffer->surface);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -749,6 +749,7 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time
|
|||
if(self->wayland.backbuffer.surface) {
|
||||
wl_pointer_set_cursor(self->wayland.pointer, self->wayland.pointer_serial, self->wayland.cursor.surface, 0, 0);
|
||||
}
|
||||
|
||||
WAYLAND_EVENT_OP_END(self);
|
||||
};
|
||||
|
||||
|
|
@ -1511,6 +1512,21 @@ static void zwlr_layer_shell_v1_interface_destroy(struct _MwLLWayland* wayland,
|
|||
free(data);
|
||||
}
|
||||
|
||||
static wayland_protocol_t* wp_fifo_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland, MwU32 version) {
|
||||
wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t));
|
||||
|
||||
proto->context = wl_registry_bind(wayland->registry, name, &wp_fifo_manager_v1_interface, version);
|
||||
proto->listener = NULL;
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
static void wp_fifo_manager_v1_interface_destroy(struct _MwLLWayland* wayland, wayland_protocol_t* data) {
|
||||
(void)wayland;
|
||||
|
||||
free(data);
|
||||
}
|
||||
|
||||
/* Function for setting up the callbacks/structs that will be registered upon the relevant interfaces being found. */
|
||||
void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) {
|
||||
/* Convience macro for adding the interface functions to the setup map */
|
||||
|
|
@ -1553,6 +1569,7 @@ void MwLLWaylandSetupCallbacks(struct _MwLLWayland* wayland) {
|
|||
WL_INTERFACE(xdg_toplevel_icon_manager_v1);
|
||||
WL_INTERFACE(wl_subcompositor);
|
||||
WL_INTERFACE(wl_seat);
|
||||
WL_INTERFACE(wp_fifo_manager_v1);
|
||||
} else if(wayland->type == MwLL_WAYLAND_POPUP) {
|
||||
WL_INTERFACE(wl_seat);
|
||||
} else if(wayland->type == MwLL_WAYLAND_LAYER_SURFACE) {
|
||||
|
|
|
|||
|
|
@ -265,6 +265,10 @@ static void setup_toplevel(MwLL r, int x, int y) {
|
|||
r->wayland.toplevel->ssurface = wl_subcompositor_get_subsurface(r->wayland.toplevel->scompositor, r->wayland.framebuffer.surface, r->wayland.backbuffer.surface);
|
||||
wl_subsurface_set_desync(r->wayland.toplevel->ssurface);
|
||||
|
||||
if(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1) != NULL) {
|
||||
r->wayland.framebuffer.fifo = wp_fifo_manager_v1_get_fifo(WAYLAND_GET_INTERFACE(r->wayland, wp_fifo_manager_v1)->context, r->wayland.framebuffer.surface);
|
||||
}
|
||||
|
||||
r->wayland.toplevel->xdg_surface =
|
||||
xdg_wm_base_get_xdg_surface(WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context, r->wayland.backbuffer.surface);
|
||||
r->wayland.toplevel->xdg_top_level = xdg_surface_get_toplevel(r->wayland.toplevel->xdg_surface);
|
||||
|
|
@ -407,10 +411,13 @@ static void popup_configure(void* data,
|
|||
|
||||
if(width < 50) width = 50;
|
||||
if(height < 50) height = 50;
|
||||
self->wayland.x = x;
|
||||
self->wayland.y = y;
|
||||
self->wayland.ww = width;
|
||||
self->wayland.wh = height;
|
||||
self->wayland.x = x;
|
||||
self->wayland.y = y;
|
||||
|
||||
if(!self->wayland.setting_wh) {
|
||||
self->wayland.ww = width;
|
||||
self->wayland.wh = height;
|
||||
}
|
||||
};
|
||||
|
||||
static void popup_done(void* data,
|
||||
|
|
@ -439,10 +446,11 @@ struct xdg_popup_listener popup_listener = {
|
|||
static void setup_popup(MwLL r, int x, int y, MwLL parent) {
|
||||
char* mw_force_csd = getenv("MW_FORCE_CSD");
|
||||
MwLL topmost_parent = r->wayland.parent;
|
||||
r->wayland.type = MwLL_WAYLAND_POPUP;
|
||||
r->wayland.x = x;
|
||||
r->wayland.y = y;
|
||||
r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup));
|
||||
|
||||
r->wayland.type = MwLL_WAYLAND_POPUP;
|
||||
r->wayland.x = x;
|
||||
r->wayland.y = y;
|
||||
r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup));
|
||||
|
||||
if(parent) {
|
||||
MwWidget p = parent->common.user;
|
||||
|
|
@ -908,13 +916,8 @@ static void draw_child(MwLL handle, MwLL child) {
|
|||
cairo_t* c;
|
||||
cairo_surface_t* cs;
|
||||
cairo_t* selected_cairo;
|
||||
MwLL topmost_parent = handle;
|
||||
|
||||
if(topmost_parent->wayland.type != MwLL_WAYLAND_POPUP) {
|
||||
while(topmost_parent->wayland.parent) {
|
||||
topmost_parent = topmost_parent->wayland.parent;
|
||||
}
|
||||
}
|
||||
draw_children(child);
|
||||
|
||||
wl_surface_commit(child->wayland.framebuffer.surface);
|
||||
|
||||
|
|
@ -928,20 +931,18 @@ static void draw_child(MwLL handle, MwLL child) {
|
|||
|
||||
cairo_paint(c);
|
||||
|
||||
// printf("%d %d\n", child->wayland.x, child->wayland.y);
|
||||
|
||||
cairo_set_source_surface(handle->wayland.cairo.front_cairo_back, cs, child->wayland.x, child->wayland.y);
|
||||
cairo_paint(handle->wayland.cairo.front_cairo_back);
|
||||
|
||||
cairo_destroy(c);
|
||||
cairo_surface_destroy(cs);
|
||||
|
||||
draw_children(child);
|
||||
}
|
||||
|
||||
static void draw_children(MwLL handle) {
|
||||
wl_surface_damage(handle->wayland.framebuffer.surface, 0, 0, handle->wayland.ww, handle->wayland.wh);
|
||||
|
||||
cairo_reset_clip(handle->wayland.cairo.front_cairo_back);
|
||||
|
||||
MwLLWaylandChildrenIterate(handle, draw_child);
|
||||
|
||||
if(handle->wayland.configured) MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
|
||||
|
|
@ -949,24 +950,13 @@ static void draw_children(MwLL handle) {
|
|||
}
|
||||
|
||||
static void frontbuffer_draw(MwLL handle) {
|
||||
cairo_t* c;
|
||||
cairo_surface_t* cs;
|
||||
|
||||
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, handle->wayland.ww, handle->wayland.wh);
|
||||
c = cairo_create(cs);
|
||||
cairo_t* c = handle->wayland.cairo.frontbuffer_cairo;
|
||||
|
||||
cairo_set_source_surface(c, handle->wayland.cairo.front_cs_back, 0, 0);
|
||||
cairo_pattern_set_filter(cairo_get_source(c), CAIRO_FILTER_NEAREST);
|
||||
|
||||
cairo_set_operator(handle->wayland.cairo.front_cairo_back, CAIRO_OPERATOR_OVER);
|
||||
|
||||
cairo_paint(c);
|
||||
|
||||
cairo_set_source_surface(handle->wayland.cairo.front_cairo, cs, 0, 0);
|
||||
cairo_paint(handle->wayland.cairo.front_cairo);
|
||||
|
||||
cairo_destroy(c);
|
||||
cairo_surface_destroy(cs);
|
||||
}
|
||||
|
||||
static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
|
||||
|
|
@ -1301,10 +1291,17 @@ static void MwLLBeginDrawImpl(MwLL handle) {
|
|||
}
|
||||
|
||||
static void MwLLEndDrawImpl(MwLL handle) {
|
||||
MwLL root = handle;
|
||||
while(root->wayland.type == MwLL_WAYLAND_SUBLEVEL && root->wayland.parent) {
|
||||
root = root->wayland.parent;
|
||||
}
|
||||
root->wayland.do_cascading_draw = MwTRUE;
|
||||
|
||||
if(handle->wayland.configured) {
|
||||
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
|
||||
MwLLWaylandBufferUpdate(handle, &handle->wayland.backbuffer);
|
||||
}
|
||||
|
||||
MwLLWaylandBufferUpdate(handle, &handle->wayland.framebuffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -1363,9 +1360,10 @@ static int MwLLPendingImpl(MwLL handle) {
|
|||
|
||||
handle->wayland.resizing = 0;
|
||||
|
||||
if(handle->wayland.type != MwLL_WAYLAND_SUBLEVEL) {
|
||||
if(handle->wayland.do_cascading_draw) {
|
||||
draw_children(handle);
|
||||
frontbuffer_draw(handle);
|
||||
handle->wayland.do_cascading_draw = MwFALSE;
|
||||
}
|
||||
|
||||
if(handle->wayland.setting_wh) {
|
||||
|
|
@ -1430,7 +1428,6 @@ static int MwLLPendingImpl(MwLL handle) {
|
|||
}
|
||||
|
||||
static void MwLLNextEventImpl(MwLL handle) {
|
||||
|
||||
if(!MwWaylandVulkan) {
|
||||
if(handle->wayland.did_event_loop_early) {
|
||||
handle->wayland.did_event_loop_early = MwFALSE;
|
||||
|
|
@ -1450,7 +1447,6 @@ static void MwLLNextEventImpl(MwLL handle) {
|
|||
}
|
||||
|
||||
static void MwLLSetTitleImpl(MwLL handle, const char* title) {
|
||||
|
||||
if(handle->wayland.type == MwLL_WAYLAND_TOPLEVEL) {
|
||||
xdg_toplevel_set_title(handle->wayland.toplevel->xdg_top_level, title);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue