~schnwalter

CEE, Earth


#576 Stroke rendering bug 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

Looks like there are more cases that are problematic. I've prepared some tests and a patch.

Here's the new program that I'm using to test all edge cases:

// SPDX-License-Identifier: Unlicense OR MIT

package main

import (
	"gioui.org/app"
	"gioui.org/f32"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"image/color"
	"log"
	"os"
)

func main() {
	go func() {
		var appWindow app.Window
		appWindow.Option(
			app.Title("Render Bug Demo"),
			app.Size(unit.Dp(560), unit.Dp(320)),
		)
		if err := appRun(&appWindow); err != nil {
			log.Fatal(err)
		}
		os.Exit(0)
	}()

	app.Main()
}

func appRun(appWindow *app.Window) error {
	var ops op.Ops
	for {
		switch windowEvent := appWindow.Event().(type) {
		case app.DestroyEvent:
			return windowEvent.Err

		case app.FrameEvent:
			gtx := app.NewContext(&ops, windowEvent)

			strokeWidth := float32(80)

			{
				var lePath clip.Path
				lePath.Begin(gtx.Ops)
				lePath.MoveTo(f32.Point{X: 80, Y: 80})
				lePath.LineTo(f32.Point{X: 80 + strokeWidth, Y: 80})
				pathSpec := lePath.End()

				leShape := clip.Stroke{Path: pathSpec, Width: strokeWidth}
				paint.FillShape(gtx.Ops, color.NRGBA{R: 0xAA, G: 0x33, B: 0x33, A: 0xFF}, leShape.Op())
			}

			{
				var lePath clip.Path
				lePath.Begin(gtx.Ops)
				lePath.MoveTo(f32.Point{X: 80 + strokeWidth, Y: 240})
				lePath.LineTo(f32.Point{X: 80, Y: 240})
				pathSpec := lePath.End()

				leShape := clip.Stroke{Path: pathSpec, Width: strokeWidth}
				paint.FillShape(gtx.Ops, color.NRGBA{R: 0xAA, G: 0x33, B: 0x33, A: 0xFF}, leShape.Op())
			}

			{
				var lePath clip.Path
				lePath.Begin(gtx.Ops)
				lePath.MoveTo(f32.Point{X: 320, Y: 120})
				lePath.LineTo(f32.Point{X: 320, Y: 120 + strokeWidth})
				pathSpec := lePath.End()

				leShape := clip.Stroke{Path: pathSpec, Width: strokeWidth}
				paint.FillShape(gtx.Ops, color.NRGBA{R: 0xAA, G: 0x33, B: 0x33, A: 0xFF}, leShape.Op())
			}

			{
				var lePath clip.Path
				lePath.Begin(gtx.Ops)
				lePath.MoveTo(f32.Point{X: 480, Y: 120 + strokeWidth})
				lePath.LineTo(f32.Point{X: 480, Y: 120})
				pathSpec := lePath.End()

				leShape := clip.Stroke{Path: pathSpec, Width: strokeWidth}
				paint.FillShape(gtx.Ops, color.NRGBA{R: 0xAA, G: 0x33, B: 0x33, A: 0xFF}, leShape.Op())
			}

			windowEvent.Frame(gtx.Ops)
			gtx.Ops.Reset()
		}
	}
}

#579 X11: freeze/crash after hundreds of window resizes 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

I was the impression this was happening also in openSUSE, but it might not be the case. I have just checked this again on Xen and it stops working because of:

xen:grant_table: xen/grant-table: max_grant_frames reached cur=2048 extra=1 limit=2048 gnttab_free_count=0 req_entries=1

And this happens with the app consuming barely any memory and with plenty of free memory to go around.

I'm assuming this will be mitigated by #560, but it's still worth checking, maybe there's some improvement to be had for everybody.

I'll continue to look into this.

#576 Stroke rendering bug 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

Here's a better visual example of the issue. (I've also sent a patch.)

// SPDX-License-Identifier: Unlicense OR MIT
package main

import (
	"gioui.org/app"
	"gioui.org/f32"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"image/color"
	"log"
	"os"
)

func main() {
	go func() {
		var appWindow app.Window
		appWindow.Option(
			app.Title("Stroke Rendering Bug"),
			app.Size(unit.Dp(320), unit.Dp(320)),
		)
		if err := appRun(&appWindow); err != nil {
			log.Fatal(err)
		}
		os.Exit(0)
	}()
	app.Main()
}

func appRun(appWindow *app.Window) error {
	var ops op.Ops
	for {
		switch windowEvent := appWindow.Event().(type) {
		case app.DestroyEvent:
			return windowEvent.Err
		case app.FrameEvent:
			gtx := app.NewContext(&ops, windowEvent)
			strokeWidth := float32(40)
			var p clip.Path
			p.Begin(gtx.Ops)
			p.MoveTo(f32.Point{X: 50, Y: 50})
			p.LineTo(f32.Point{X: 200, Y: 50})
			p.LineTo(f32.Point{X: 200, Y: 50 + strokeWidth})
			p.LineTo(f32.Point{X: 50, Y: 200})
			p.Close()
			paint.FillShape(
				gtx.Ops,
				color.NRGBA{R: 0x33, G: 0x33, B: 0x33, A: 0xFF},
				clip.Stroke{Path: p.End(), Width: strokeWidth}.Op(),
			)
			windowEvent.Frame(gtx.Ops)
		}
	}
}

#565 problem redrawing when doing a window resize 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

From what I can tell, the final commit, 691adf4, has a different effect than the patch I've (51388).

It fixed the white bands, they are now gone, but the EGLSurface refresh is a bit late and you can see the content jumping a lot during vertical window resize, this didn't happen with 51388.

I'll look more into this sometime in the next few days.

#579 X11: freeze/crash after hundreds of window resizes 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

No, I've discovered this while debugging #565.

I've just tested with 691adf4e, the problem persists.

#578 [svg2gio] Nothing output for lucide SVGs 2 months ago

on ~eliasnaur/gio

On Fri Apr 26, 2024 at 12:43 PM CEST, ~schnwalter wrote:

Anyway, it looks like inkeliz did a good job on giosvg and it has support for arcs, so it works with that file.

I think I will use this then, it seems to do the job well !

Thanks for the suggestion. I think that this can be closed then.

-- vigoux

#472 Longer paths converting to horizontal/vertical lines 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

I'm trying to reproduce the bug without Gio. I've got the X11 window, the EGLSurface is there and it should show its background color, but I doesn't show up, here's what I have so far:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>


void paint() {

    GLenum glErrors;

    eglBindAPI(EGL_OPENGL_ES_API);
    glViewport(0, 0, 600, 600);

    glErrors = glGetError();
    if (glErrors != 0) {
        printf("ERROR: glGetError\n");
        exit(1);
    }
    glClearColor(1,1,0,1);
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glFlush();
}

//int argc char **argv;
void main() {
    Display *myDisplay;
    int myScreen;
    int myDepth;
    XSetWindowAttributes myWindowAttributes;
    unsigned long myWindowMask;
    Window myWindow;
    XSizeHints theSizeHints;
    const int x = 200;
    const int y = 150;
    const unsigned int width = 800;
    const unsigned int height = 800;


    myDisplay = XOpenDisplay("");
    if (myDisplay == NULL) {
        fprintf(stderr,
                "ERROR: Could not open a connection to X on display %s\n",
                XDisplayName(NULL)
        );
        exit(0);
    }


    myScreen = DefaultScreen(myDisplay);
    myDepth = DefaultDepth(myDisplay, myScreen);

    myWindowAttributes.background_pixmap = None;
    myWindowAttributes.border_pixel = BlackPixel(myDisplay, myScreen);
    myWindowAttributes.background_pixel = 0xFF808080;
    myWindowAttributes.override_redirect = False;

    myWindowMask = CWBackPixel | CWBackPixmap | CWBorderPixel | CWOverrideRedirect;

    const XID window = RootWindow(myDisplay, myScreen);
    myWindow = XCreateWindow(myDisplay,
                             window,
                             x, y, width, height, 0,
                             myDepth, InputOutput, CopyFromParent,
                             myWindowMask, &myWindowAttributes);

    theSizeHints.flags = PPosition | PSize;
    theSizeHints.x = x;
    theSizeHints.y = y;
    theSizeHints.width = width;
    theSizeHints.height = height;
    XSetWMNormalHints(myDisplay, myWindow, &theSizeHints);
    XMapWindow(myDisplay, myWindow);
    XFlush(myDisplay);


    const EGLDisplay _eglDisplay = eglGetDisplay(myDisplay);
    if( _eglDisplay == EGL_NO_DISPLAY ){
        printf( "ERROR: eglGetDisplay\n" );
        exit(1);
    }
    const EGLBoolean emcRet = eglMakeCurrent(_eglDisplay, NULL, NULL, NULL);
    if (emcRet != EGL_TRUE) {
        printf( "ERROR: eglMakeCurrent\n" );
        exit(1);
    }

    EGLint majorVersion;
    EGLint minorVersion;
    const EGLBoolean eglInitRet = eglInitialize(_eglDisplay, &majorVersion, &minorVersion);
    if (!eglInitRet) {
        printf("ERROR: eglInitialize\n");
        exit(1);
    }

    const XID _eglWindow = window;

    const EGLint defaultAttribList[] = {
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
		EGL_CONFIG_CAVEAT, EGL_NONE,
        EGL_NONE
    };
    EGLConfig eglCfg;
    EGLint ncfg;
    const EGLBoolean eglCfgRet = eglChooseConfig(_eglDisplay, defaultAttribList, &eglCfg, 1, &ncfg);
    if (!eglCfgRet || ncfg != 1) {
        printf("ERROR: eglChooseConfig\n");
        return;
    }

    const EGLint surfAttribs[] = {
        EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB,
        EGL_NONE,
    };
    const EGLSurface _eglSurface = eglCreateWindowSurface(_eglDisplay, eglCfg, _eglWindow, surfAttribs);
    if (_eglSurface == EGL_NO_SURFACE) {
        printf("ERROR: eglCreateWindowSurface\n");
        exit(1);
    }

    const EGLint ctxAttribs[] = {
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE,
    };
    const EGLContext nilEGLContext = 0;
    //EGL_CONTEXT_OPENGL_DEBUG
    const EGLContext _eglCtx = eglCreateContext(_eglDisplay, eglCfg, NULL, ctxAttribs);
    if (_eglCtx == nilEGLContext) {
        printf("ERROR: eglCreateContext\n");
        exit(1);
    }

    EGLBoolean eglMakeCurentRet;
    eglMakeCurentRet = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglCtx);
    if (!eglMakeCurentRet) {
        printf("ERROR: eglMakeCurrent\n");
        exit(1);
    }

    paint();

    const EGLBoolean eglSwapBuffersRet = eglSwapBuffers(_eglDisplay, _eglSurface);
    if (!eglSwapBuffersRet) {
        printf("Error eglSwapBuffers!\n");
        exit(1);
    }

    eglMakeCurentRet = eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglCtx);
    if (!eglMakeCurentRet) {
        printf("ERROR: eglMakeCurrent\n");
        exit(1);
    }

    sleep(10);
    eglDestroySurface(_eglDisplay, _eglSurface);
    XDestroyWindow(myDisplay, myWindow);
    XCloseDisplay(myDisplay);
    exit(0);
}

#579 X11: freeze/crash after hundreds of window resizes 2 months ago

Ticket created by ~schnwalter on ~eliasnaur/gio

If you take a simple window with a background color and resize it continuously for about 30 seconds (just move the mouse in circles), the window will crash with signal: killed if it's executed using go run and the built version will just have a redraw lag of several seconds and the fan will go crazy, might be related to #560

#565 problem redrawing when doing a window resize 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

And... we have a patch, turns out the problem was something else. No need to muck around with XCreateWindow flags, just reuse the EGLSurface:

https://lists.sr.ht/~eliasnaur/gio-patches/patches/51388

#565 problem redrawing when doing a window resize 2 months ago

Comment by ~schnwalter on ~eliasnaur/gio

One more thing... the default value for bit_gravity is ForgetGravity, it indicates that the window contents will always be discarded after a window size change; So, if we make Gio respond in time, we can keep the default bit_gravity.