From 1dde83e05ee142e8a10a9acecb341be176dbcba1 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Tue, 31 Mar 2026 13:31:06 +0200 Subject: [PATCH] =?UTF-8?q?wayland:=20Phase=2029=20=E2=80=94=20pixman=20SH?= =?UTF-8?q?M=20surface=20primitives?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add wm_shm_surface: a compositor-owned pixel buffer that bridges pixman software rendering to the wlroots scene graph. The struct embeds a wlr_buffer (wl_container_of compatible) so wlroots can reference-count and GPU-upload the pixel data on demand via the wlr_buffer_impl vtable (begin_data_ptr_access / end_data_ptr_access / destroy). A pixman_image_t wrapping the same malloc memory provides the drawing API. Four entry points: wm_shm_surface_create — alloc + wlr_buffer_init + pixman_image_create wm_shm_surface_fill — pixman_image_composite32(PIXMAN_OP_SRC, ...) wm_shm_surface_commit — wlr_scene_buffer_create / set_position wm_shm_surface_destroy — scene node + wlr_buffer_drop (async free) A 64×64 steel-blue (0xFF4080C0) test surface is committed to the root scene node at (16,16) inside wl_screen_create_internals, proving the pixman → wlr_scene_buffer upload pipeline works end-to-end. Build fixes: - Add pixman-1 to PKG_CHECK_MODULES in configure.ac so -lpixman-1 appears in WLROOTS_LIBS (linker was missing the symbol). - Add -I$(srcdir)/backend/wayland to AM_CPPFLAGS in Makefile.am so generated Wayland protocol headers are found during compilation. Smoke test: PASS (all existing checks continue to pass; Phase 29 log line "Phase 29 test surface committed" confirms the pipeline fires). Co-Authored-By: Claude Sonnet 4.6 --- configure | 177 +++++++++++++++++++++----- configure.ac | 2 +- src/Makefile.am | 1 + src/Makefile.in | 89 ++++++++++++-- src/backend/wayland/wl_backend.c | 205 +++++++++++++++++++++++++++++++ 5 files changed, 432 insertions(+), 42 deletions(-) diff --git a/configure b/configure index ffba7fb..8b03c36 100755 --- a/configure +++ b/configure @@ -680,6 +680,10 @@ XFT_LIBS XFT_CFLAGS FCLIBS LIBM +USE_WAYLAND_BACKEND_FALSE +USE_WAYLAND_BACKEND_TRUE +WLROOTS_LIBS +WLROOTS_CFLAGS LIBXRANDR LIBXINERAMA LIBXMU @@ -880,6 +884,7 @@ enable_shape enable_shm enable_xinerama enable_randr +enable_wayland_backend enable_pango enable_xpm enable_png @@ -909,6 +914,8 @@ PKG_CONFIG_PATH PKG_CONFIG_LIBDIR LINGUAS XMKMF +WLROOTS_CFLAGS +WLROOTS_LIBS XFT_CFLAGS XFT_LIBS PANGO_CFLAGS @@ -1565,6 +1572,9 @@ Optional Features: --enable-xinerama enable Xinerama extension support --enable-randr enable RandR extension support (NOT recommended, buggy) + --enable-wayland-backend + build the wlroots-based Wayland compositor backend + [default=auto] --disable-pango disable Pango text layout support [default=auto] --disable-xpm disable use of XPM pixmaps through libXpm --disable-png disable PNG support through libpng @@ -1622,6 +1632,10 @@ Some influential environment variables: LINGUAS list of language translations to support (I18N), use 'list' to get the list of supported languages, default: none XMKMF Path to xmkmf, Makefile generator for X Window System + WLROOTS_CFLAGS + C compiler flags for WLROOTS, overriding pkg-config + WLROOTS_LIBS + linker flags for WLROOTS, overriding pkg-config XFT_CFLAGS C compiler flags for XFT, overriding pkg-config XFT_LIBS linker flags for XFT, overriding pkg-config PANGO_CFLAGS @@ -2614,6 +2628,18 @@ else enable_randr=no fi +# Check whether --enable-wayland-backend was given. +if test "${enable_wayland_backend+set}" = set; then : + enableval=$enable_wayland_backend; case "$enableval" in #( + yes|no|auto) : + ;; #( + *) : + as_fn_error $? "bad value $enableval for --enable-wayland-backend" "$LINENO" 5 ;; +esac +else + enable_wayland_backend=auto +fi + # Check whether --enable-pango was given. if test "${enable_pango+set}" = set; then : enableval=$enable_pango; case $enableval in #( @@ -6048,7 +6074,7 @@ linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; -netbsd* | netbsdelf*-gnu) +netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else @@ -6410,7 +6436,7 @@ esac fi : ${AR=ar} -: ${AR_FLAGS=cr} +: ${AR_FLAGS=cru} @@ -6911,8 +6937,11 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - $ECHO "$as_me:$LINENO: $NM conftest.$ac_objext | $lt_cv_sys_global_symbol_pipe > $nlist" >&5 - if eval "$NM" conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist 2>&5 && test -s "$nlist"; then + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -8131,8 +8160,8 @@ int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 - echo "$AR cr libconftest.a conftest.o" >&5 - $AR cr libconftest.a conftest.o 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF @@ -8164,11 +8193,11 @@ $as_echo "$lt_cv_ld_force_load" >&6; } # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[912]*) + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; - 10.*|11.*) + 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; @@ -9123,12 +9152,6 @@ lt_prog_compiler_static= lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; - # flang / f18. f95 an alias for gfortran or flang on Debian - flang* | f18* | f95*) - lt_prog_compiler_wl='-Wl,' - lt_prog_compiler_pic='-fPIC' - lt_prog_compiler_static='-static' - ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) @@ -9605,9 +9628,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie openbsd* | bitrig*) with_gnu_ld=no ;; - linux* | k*bsd*-gnu | gnu*) - link_all_deplibs=no - ;; esac ld_shlibs=yes @@ -9862,7 +9882,7 @@ _LT_EOF fi ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -10532,7 +10552,6 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi - link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -10554,7 +10573,7 @@ $as_echo "$lt_cv_irix_exported_symbol" >&6; } esac ;; - netbsd* | netbsdelf*-gnu) + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -11669,18 +11688,6 @@ fi dynamic_linker='GNU/Linux ld.so' ;; -netbsdelf*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='NetBSD ld.elf_so' - ;; - netbsd*) version_type=sunos need_lib_prefix=no @@ -17633,6 +17640,107 @@ fi + +if test "x$enable_wayland_backend" != "xno"; then : + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for wlroots >= 0.15 wayland-server xkbcommon pixman-1" >&5 +$as_echo_n "checking for wlroots >= 0.15 wayland-server xkbcommon pixman-1... " >&6; } + +if test -n "$WLROOTS_CFLAGS"; then + pkg_cv_WLROOTS_CFLAGS="$WLROOTS_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wlroots >= 0.15 wayland-server xkbcommon pixman-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wlroots >= 0.15 wayland-server xkbcommon pixman-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WLROOTS_CFLAGS=`$PKG_CONFIG --cflags "wlroots >= 0.15 wayland-server xkbcommon pixman-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$WLROOTS_LIBS"; then + pkg_cv_WLROOTS_LIBS="$WLROOTS_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"wlroots >= 0.15 wayland-server xkbcommon pixman-1\""; } >&5 + ($PKG_CONFIG --exists --print-errors "wlroots >= 0.15 wayland-server xkbcommon pixman-1") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_WLROOTS_LIBS=`$PKG_CONFIG --libs "wlroots >= 0.15 wayland-server xkbcommon pixman-1" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + WLROOTS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "wlroots >= 0.15 wayland-server xkbcommon pixman-1" 2>&1` + else + WLROOTS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "wlroots >= 0.15 wayland-server xkbcommon pixman-1" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$WLROOTS_PKG_ERRORS" >&5 + + have_wlroots=no +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + have_wlroots=no +else + WLROOTS_CFLAGS=$pkg_cv_WLROOTS_CFLAGS + WLROOTS_LIBS=$pkg_cv_WLROOTS_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_wlroots=yes +fi + if test "x$have_wlroots" = "xyes"; then : + +$as_echo "#define USE_WAYLAND_BACKEND 1" >>confdefs.h + + WLROOTS_CFLAGS="$WLROOTS_CFLAGS -DWLR_USE_UNSTABLE" + supported_core="$supported_core WaylandBackend" +else + if test "x$enable_wayland_backend" = "xyes"; then : + as_fn_error $? "wlroots >= 0.15, wayland-server, or xkbcommon not found" "$LINENO" 5 +fi + unsupported="$unsupported WaylandBackend" +fi +else + have_wlroots=no + unsupported="$unsupported WaylandBackend" +fi + if test "x$have_wlroots" = "xyes"; then + USE_WAYLAND_BACKEND_TRUE= + USE_WAYLAND_BACKEND_FALSE='#' +else + USE_WAYLAND_BACKEND_TRUE='#' + USE_WAYLAND_BACKEND_FALSE= +fi + + + + + ac_fn_c_check_header_mongrel "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default" if test "x$ac_cv_header_math_h" = xyes; then : @@ -19013,6 +19121,10 @@ if test -z "${USE_DOCK_XDND_TRUE}" && test -z "${USE_DOCK_XDND_FALSE}"; then as_fn_error $? "conditional \"USE_DOCK_XDND\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${USE_WAYLAND_BACKEND_TRUE}" && test -z "${USE_WAYLAND_BACKEND_FALSE}"; then + as_fn_error $? "conditional \"USE_WAYLAND_BACKEND\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${USE_XPM_TRUE}" && test -z "${USE_XPM_FALSE}"; then as_fn_error $? "conditional \"USE_XPM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -20674,6 +20786,7 @@ See \`config.log' for more details" "$LINENO" 5; } cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. diff --git a/configure.ac b/configure.ac index 4cfe877..fd253c3 100644 --- a/configure.ac +++ b/configure.ac @@ -665,7 +665,7 @@ m4_divert_pop([INIT_PREPARE])dnl AS_IF([test "x$enable_wayland_backend" != "xno"], [PKG_CHECK_MODULES([WLROOTS], - [wlroots >= 0.15 wayland-server xkbcommon], + [wlroots >= 0.15 wayland-server xkbcommon pixman-1], [have_wlroots=yes], [have_wlroots=no]) AS_IF([test "x$have_wlroots" = "xyes"], diff --git a/src/Makefile.am b/src/Makefile.am index 9a96f4b..5793eae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -172,6 +172,7 @@ AM_CFLAGS = @PANGO_CFLAGS@ @WLROOTS_CFLAGS@ AM_CPPFLAGS = $(DFLAGS) \ -I$(top_builddir)/wrlib \ -I$(top_srcdir)/WINGs -I$(top_builddir)/WINGs \ + -I$(srcdir)/backend/wayland \ @HEADER_SEARCH_PATH@ diff --git a/src/Makefile.in b/src/Makefile.in index 06171d7..e5365aa 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -95,7 +95,11 @@ bin_PROGRAMS = wmaker$(EXEEXT) @WM_OSDEP_DARWIN_TRUE@am__append_4 = osdep_darwin.c @WM_OSDEP_LINUX_TRUE@am__append_5 = osdep_linux.c @WM_OSDEP_GENERIC_TRUE@am__append_6 = osdep_stub.c -@USE_NESTED_FUNC_TRUE@am__append_7 = misc.c \ +@USE_WAYLAND_BACKEND_TRUE@am__append_7 = \ +@USE_WAYLAND_BACKEND_TRUE@ backend/wayland/wl_backend.h \ +@USE_WAYLAND_BACKEND_TRUE@ backend/wayland/wl_backend.c + +@USE_NESTED_FUNC_TRUE@am__append_8 = misc.c \ @USE_NESTED_FUNC_TRUE@ xmodifier.c subdir = src @@ -148,8 +152,9 @@ am__wmaker_SOURCES_DIST = GNUstep.h WindowMaker.h actions.c actions.h \ wcore.h wdefaults.c wdefaults.h window.c window.h winmenu.c \ winmenu.h winspector.h winspector.c wmspec.h wmspec.c \ workspace.c workspace.h wsmap.c wsmap.h xdnd.c motif.h motif.c \ - osdep_bsd.c osdep_darwin.c osdep_linux.c osdep_stub.c misc.c \ - xmodifier.c + osdep_bsd.c osdep_darwin.c osdep_linux.c osdep_stub.c \ + backend/wayland/wl_backend.h backend/wayland/wl_backend.c \ + misc.c xmodifier.c am__dirstamp = $(am__leading_dot)dirstamp @USE_DOCK_XDND_TRUE@am__objects_1 = xdnd.$(OBJEXT) @USE_MWM_HINTS_TRUE@am__objects_2 = motif.$(OBJEXT) @@ -157,7 +162,8 @@ am__dirstamp = $(am__leading_dot)dirstamp @WM_OSDEP_DARWIN_TRUE@am__objects_4 = osdep_darwin.$(OBJEXT) @WM_OSDEP_LINUX_TRUE@am__objects_5 = osdep_linux.$(OBJEXT) @WM_OSDEP_GENERIC_TRUE@am__objects_6 = osdep_stub.$(OBJEXT) -@USE_NESTED_FUNC_TRUE@am__objects_7 = misc.$(OBJEXT) \ +@USE_WAYLAND_BACKEND_TRUE@am__objects_7 = backend/wayland/wl_backend.$(OBJEXT) +@USE_NESTED_FUNC_TRUE@am__objects_8 = misc.$(OBJEXT) \ @USE_NESTED_FUNC_TRUE@ xmodifier.$(OBJEXT) am_wmaker_OBJECTS = actions.$(OBJEXT) appicon.$(OBJEXT) \ application.$(OBJEXT) appmenu.$(OBJEXT) balloon.$(OBJEXT) \ @@ -180,7 +186,8 @@ am_wmaker_OBJECTS = actions.$(OBJEXT) appicon.$(OBJEXT) \ winmenu.$(OBJEXT) winspector.$(OBJEXT) wmspec.$(OBJEXT) \ workspace.$(OBJEXT) wsmap.$(OBJEXT) $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ - $(am__objects_5) $(am__objects_6) $(am__objects_7) + $(am__objects_5) $(am__objects_6) $(am__objects_7) \ + $(am__objects_8) @USE_NESTED_FUNC_FALSE@nodist_wmaker_OBJECTS = misc.hack_nf.$(OBJEXT) \ @USE_NESTED_FUNC_FALSE@ xmodifier.hack_nf.$(OBJEXT) wmaker_OBJECTS = $(am_wmaker_OBJECTS) $(nodist_wmaker_OBJECTS) @@ -233,7 +240,8 @@ am__depfiles_remade = ./$(DEPDIR)/actions.Po ./$(DEPDIR)/appicon.Po \ ./$(DEPDIR)/workspace.Po ./$(DEPDIR)/wsmap.Po \ ./$(DEPDIR)/xdnd.Po ./$(DEPDIR)/xinerama.Po \ ./$(DEPDIR)/xmodifier.Po ./$(DEPDIR)/xmodifier.hack_nf.Po \ - ./$(DEPDIR)/xutil.Po backend/x11/$(DEPDIR)/x11_backend.Po \ + ./$(DEPDIR)/xutil.Po backend/wayland/$(DEPDIR)/wl_backend.Po \ + backend/x11/$(DEPDIR)/x11_backend.Po \ backend/x11/$(DEPDIR)/x11_event.Po \ backend/x11/$(DEPDIR)/x11_monitor.Po \ backend/x11/$(DEPDIR)/x11_props.Po @@ -378,6 +386,8 @@ VERSION = @VERSION@ WEB_REPO_ROOT = @WEB_REPO_ROOT@ WINGSMOFILES = @WINGSMOFILES@ WINGS_VERSION = @WINGS_VERSION@ +WLROOTS_CFLAGS = @WLROOTS_CFLAGS@ +WLROOTS_LIBS = @WLROOTS_LIBS@ WMAKERMOFILES = @WMAKERMOFILES@ WPREFSMOFILES = @WPREFSMOFILES@ WRASTERMOFILES = @WRASTERMOFILES@ @@ -484,15 +494,17 @@ wmaker_SOURCES = GNUstep.h WindowMaker.h actions.c actions.h appicon.c \ winmenu.h winspector.h winspector.c wmspec.h wmspec.c \ workspace.c workspace.h wsmap.c wsmap.h $(am__append_1) \ $(am__append_2) $(am__append_3) $(am__append_4) \ - $(am__append_5) $(am__append_6) $(am__append_7) + $(am__append_5) $(am__append_6) $(am__append_7) \ + $(am__append_8) @USE_NESTED_FUNC_FALSE@nodist_wmaker_SOURCES = misc.hack_nf.c \ @USE_NESTED_FUNC_FALSE@ xmodifier.hack_nf.c @USE_NESTED_FUNC_FALSE@CLEANFILES = $(nodist_wmaker_SOURCES) -AM_CFLAGS = @PANGO_CFLAGS@ +AM_CFLAGS = @PANGO_CFLAGS@ @WLROOTS_CFLAGS@ AM_CPPFLAGS = $(DFLAGS) \ -I$(top_builddir)/wrlib \ -I$(top_srcdir)/WINGs -I$(top_builddir)/WINGs \ + -I$(srcdir)/backend/wayland \ @HEADER_SEARCH_PATH@ wmaker_LDADD = \ @@ -503,6 +515,7 @@ wmaker_LDADD = \ @LIBXRANDR@ \ @LIBXINERAMA@ \ @XLIBS@ \ + @WLROOTS_LIBS@ \ @LIBM@ \ @INTLIBS@ @@ -522,7 +535,51 @@ am__v_CHKOPTS_1 = WM_POLICY_CLEAN_FILES = \ $(srcdir)/xinerama.c \ $(srcdir)/stacking.c \ - $(srcdir)/placement.c + $(srcdir)/placement.c \ + $(srcdir)/cycling.c \ + $(srcdir)/workspace.c \ + $(srcdir)/actions.c \ + $(srcdir)/moveres.c \ + $(srcdir)/window.c \ + $(srcdir)/screen.c \ + $(srcdir)/event.c \ + $(srcdir)/colormap.c \ + $(srcdir)/switchmenu.c \ + $(srcdir)/superfluous.c \ + $(srcdir)/balloon.c \ + $(srcdir)/wsmap.c \ + $(srcdir)/switchpanel.c \ + $(srcdir)/properties.c \ + $(srcdir)/wmspec.c \ + $(srcdir)/application.c \ + $(srcdir)/appicon.c \ + $(srcdir)/dock.c \ + $(srcdir)/dockedapp.c \ + $(srcdir)/icon.c \ + $(srcdir)/motif.c \ + $(srcdir)/pixmap.c \ + $(srcdir)/resources.c \ + $(srcdir)/session.c \ + $(srcdir)/shutdown.c \ + $(srcdir)/texture.c \ + $(srcdir)/winspector.c \ + $(srcdir)/xdnd.c \ + $(srcdir)/rootmenu.c \ + $(srcdir)/xutil.c \ + $(srcdir)/misc.c \ + $(srcdir)/winmenu.c \ + $(srcdir)/appmenu.c \ + $(srcdir)/monitor.c \ + $(srcdir)/usermenu.c \ + $(srcdir)/main.c \ + $(srcdir)/defaults.c \ + $(srcdir)/dialog.c \ + $(srcdir)/menu.c \ + $(srcdir)/wdefaults.c \ + $(srcdir)/xmodifier.c \ + $(srcdir)/framewin.c \ + $(srcdir)/client.c \ + $(srcdir)/startup.c all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am @@ -623,6 +680,14 @@ backend/x11/x11_props.$(OBJEXT): backend/x11/$(am__dirstamp) \ backend/x11/$(DEPDIR)/$(am__dirstamp) backend/x11/x11_monitor.$(OBJEXT): backend/x11/$(am__dirstamp) \ backend/x11/$(DEPDIR)/$(am__dirstamp) +backend/wayland/$(am__dirstamp): + @$(MKDIR_P) backend/wayland + @: > backend/wayland/$(am__dirstamp) +backend/wayland/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) backend/wayland/$(DEPDIR) + @: > backend/wayland/$(DEPDIR)/$(am__dirstamp) +backend/wayland/wl_backend.$(OBJEXT): backend/wayland/$(am__dirstamp) \ + backend/wayland/$(DEPDIR)/$(am__dirstamp) wmaker$(EXEEXT): $(wmaker_OBJECTS) $(wmaker_DEPENDENCIES) $(EXTRA_wmaker_DEPENDENCIES) @rm -f wmaker$(EXEEXT) @@ -630,6 +695,7 @@ wmaker$(EXEEXT): $(wmaker_OBJECTS) $(wmaker_DEPENDENCIES) $(EXTRA_wmaker_DEPENDE mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f backend/wayland/*.$(OBJEXT) -rm -f backend/x11/*.$(OBJEXT) distclean-compile: @@ -691,6 +757,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmodifier.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xmodifier.hack_nf.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xutil.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@backend/wayland/$(DEPDIR)/wl_backend.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@backend/x11/$(DEPDIR)/x11_backend.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@backend/x11/$(DEPDIR)/x11_event.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@backend/x11/$(DEPDIR)/x11_monitor.Po@am__quote@ # am--include-marker @@ -854,6 +921,8 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f backend/wayland/$(DEPDIR)/$(am__dirstamp) + -rm -f backend/wayland/$(am__dirstamp) -rm -f backend/x11/$(DEPDIR)/$(am__dirstamp) -rm -f backend/x11/$(am__dirstamp) @@ -922,6 +991,7 @@ distclean: distclean-am -rm -f ./$(DEPDIR)/xmodifier.Po -rm -f ./$(DEPDIR)/xmodifier.hack_nf.Po -rm -f ./$(DEPDIR)/xutil.Po + -rm -f backend/wayland/$(DEPDIR)/wl_backend.Po -rm -f backend/x11/$(DEPDIR)/x11_backend.Po -rm -f backend/x11/$(DEPDIR)/x11_event.Po -rm -f backend/x11/$(DEPDIR)/x11_monitor.Po @@ -1027,6 +1097,7 @@ maintainer-clean: maintainer-clean-am -rm -f ./$(DEPDIR)/xmodifier.Po -rm -f ./$(DEPDIR)/xmodifier.hack_nf.Po -rm -f ./$(DEPDIR)/xutil.Po + -rm -f backend/wayland/$(DEPDIR)/wl_backend.Po -rm -f backend/x11/$(DEPDIR)/x11_backend.Po -rm -f backend/x11/$(DEPDIR)/x11_event.Po -rm -f backend/x11/$(DEPDIR)/x11_monitor.Po diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 3969356..ac99a42 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -129,6 +129,8 @@ #include /* Phase 18: multi-backend */ #include /* Phase 18: scene graph compositing */ #include /* Phase 18: buffer allocator */ +#include /* Phase 29+: WM-owned SHM surface buffers */ +#include /* Phase 29+: software pixel rendering */ #include /* Phase 23: hardware cursor tracking */ #include /* Phase 23: xcursor theme */ #include /* Phase 25: clipboard / selection */ @@ -2361,6 +2363,198 @@ wl_event_loop_terminate(void) } } +/* ================================================================== */ +/* Phase 29: WM-owned SHM surfaces (pixman rendering → wlroots scene) */ +/* ================================================================== */ + +/* + * wm_shm_surface — a compositor-owned pixel buffer that plugs into the + * wlroots scene graph. + * + * Memory layout: + * wm_shm_surface embeds a wlr_buffer so wlroots can reference-count and + * upload its pixels as a GPU texture. The pixel array (ARGB8888) is + * malloc'd and wrapped by a pixman_image_t for drawing. + * + * Lifecycle: + * wm_shm_surface_create — alloc + pixman init + * wm_shm_surface_fill — draw into the pixman image (no upload yet) + * wm_shm_surface_commit — create/reposition the wlr_scene_buffer node + * wm_shm_surface_destroy — tear down scene node + drop wlr_buffer ref + * (shm_buf_destroy frees memory when ref = 0) + * + * Update model (Phase 29): surfaces are static after first commit. + * A re-draw path (drop + recreate scene node) will be added in Phase 30 + * once the dock and title-bar code drives it. + */ + +struct wm_shm_surface { + /* wlr_buffer interface — MUST be first so wl_container_of works */ + struct wlr_buffer wlr_buf; + /* Pixel store */ + uint32_t *data; /* ARGB8888, row-major */ + int width; + int height; + size_t stride; /* bytes per row = width * 4 */ + /* pixman drawing surface wrapping data[] */ + pixman_image_t *image; + /* scene graph presence */ + struct wlr_scene_buffer *scene_buf; /* NULL until first commit */ +}; + +/* ---------- wlr_buffer implementation -------------------------------- */ + +static void +shm_buf_destroy(struct wlr_buffer *buf) +{ + struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); + if (s->image) + pixman_image_unref(s->image); + free(s->data); + free(s); +} + +static bool +shm_buf_begin_data_ptr(struct wlr_buffer *buf, uint32_t flags, + void **out_data, uint32_t *out_fmt, size_t *out_stride) +{ + struct wm_shm_surface *s = wl_container_of(buf, s, wlr_buf); + (void)flags; + *out_data = s->data; + *out_fmt = WL_SHM_FORMAT_ARGB8888; + *out_stride = s->stride; + return true; +} + +static void +shm_buf_end_data_ptr(struct wlr_buffer *buf) +{ + (void)buf; +} + +static const struct wlr_buffer_impl wm_shm_buf_impl = { + .destroy = shm_buf_destroy, + .begin_data_ptr_access = shm_buf_begin_data_ptr, + .end_data_ptr_access = shm_buf_end_data_ptr, +}; + +/* ---------- surface API ---------------------------------------------- */ + +static struct wm_shm_surface * +wm_shm_surface_create(int width, int height) +{ + if (width <= 0 || height <= 0) + return NULL; + + struct wm_shm_surface *s = calloc(1, sizeof(*s)); + if (!s) + return NULL; + + s->width = width; + s->height = height; + s->stride = (size_t)width * 4; + s->data = calloc(1, (size_t)height * s->stride); + if (!s->data) { + free(s); + return NULL; + } + + /* wlr_buffer init — producer holds one reference */ + wlr_buffer_init(&s->wlr_buf, &wm_shm_buf_impl, width, height); + + /* pixman image wrapping the same memory */ + s->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, + width, height, + (uint32_t *)s->data, + (int)s->stride); + if (!s->image) { + /* wlr_buffer_drop triggers shm_buf_destroy → frees data + s */ + wlr_buffer_drop(&s->wlr_buf); + return NULL; + } + + return s; +} + +/* + * Fill a rectangle with a solid ARGB colour. + * argb: 0xAARRGGBB — e.g. 0xFF4080C0 for opaque steel-blue. + */ +static void +wm_shm_surface_fill(struct wm_shm_surface *s, + int x, int y, int w, int h, + uint32_t argb) +{ + if (!s || !s->image) + return; + /* clamp to surface bounds */ + if (x < 0) { w += x; x = 0; } + if (y < 0) { h += y; y = 0; } + if (x + w > s->width) w = s->width - x; + if (y + h > s->height) h = s->height - y; + if (w <= 0 || h <= 0) + return; + + pixman_color_t c = { + .alpha = (uint16_t)(((argb >> 24) & 0xff) * 0x0101), + .red = (uint16_t)(((argb >> 16) & 0xff) * 0x0101), + .green = (uint16_t)(((argb >> 8) & 0xff) * 0x0101), + .blue = (uint16_t)(((argb >> 0) & 0xff) * 0x0101), + }; + pixman_image_t *fill = pixman_image_create_solid_fill(&c); + if (!fill) + return; + pixman_image_composite32(PIXMAN_OP_SRC, fill, NULL, s->image, + 0, 0, 0, 0, x, y, w, h); + pixman_image_unref(fill); +} + +/* + * Commit the surface to the scene graph. + * + * parent — scene-graph parent node (e.g. &wl_state.scene->node) + * x, y — position in the compositor coordinate space + * + * First call creates the scene_buffer node; subsequent calls just + * reposition it (pixel updates are uploaded lazily by wlroots on the + * next wlr_scene_output_commit). + */ +static void +wm_shm_surface_commit(struct wm_shm_surface *s, + struct wlr_scene_node *parent, + int x, int y) +{ + if (!s) + return; + if (!s->scene_buf) { + s->scene_buf = wlr_scene_buffer_create(parent, &s->wlr_buf); + if (!s->scene_buf) { + wwarning("wm_shm_surface_commit: wlr_scene_buffer_create failed"); + return; + } + wwarning("wl_backend: SHM surface %dx%d committed to scene at %d,%d", + s->width, s->height, x, y); + } + wlr_scene_node_set_position(&s->scene_buf->node, x, y); +} + +/* + * Destroy a surface and remove it from the scene graph. + * After this call s is invalid — the memory is freed asynchronously + * by shm_buf_destroy once the scene node releases its lock. + */ +static void +wm_shm_surface_destroy(struct wm_shm_surface *s) +{ + if (!s) + return; + if (s->scene_buf) { + wlr_scene_node_destroy(&s->scene_buf->node); + s->scene_buf = NULL; + } + wlr_buffer_drop(&s->wlr_buf); /* producer done; shm_buf_destroy frees s */ +} + /* ------------------------------------------------------------------ */ /* Screen open/close */ /* ------------------------------------------------------------------ */ @@ -3866,6 +4060,17 @@ wl_screen_create_internals(WScreen *scr) wPreferences.flags.noclip = 1; wPreferences.flags.nodock = 1; wwarning("wl_backend: dock/clip disabled pending native Wayland rendering"); + + /* Phase 29 smoke test: create a 64×64 steel-blue surface at (16,16) to + * verify the pixman → wlr_scene_buffer pipeline produces visible pixels. */ + if (wl_state.scene) { + struct wm_shm_surface *test_surf = wm_shm_surface_create(64, 64); + if (test_surf) { + wm_shm_surface_fill(test_surf, 0, 0, 64, 64, 0xFF4080C0); /* steel-blue */ + wm_shm_surface_commit(test_surf, &wl_state.scene->node, 16, 16); + wwarning("wl_backend: Phase 29 test surface committed (64x64 steel-blue at 16,16)"); + } + } } static void wl_screen_create_pixmaps(WScreen *scr) { (void)scr; } static void wl_screen_load_tech_font(WScreen *scr) { (void)scr; }