lem-project / lem

Common Lisp editor/IDE with high expansibility
http://lem-project.github.io/
MIT License
2.37k stars 173 forks source link

SDL2 frontend crushes with an SDL error #690

Closed t-sin closed 1 year ago

t-sin commented 1 year ago

Environment

$ uname -a
Linux timberwolf 5.19.0-43-generic #44~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Mon May 22 13:39:36 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
$ glxinfo | grep -i opengl
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce GTX 1050 Ti/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 510.108.03
OpenGL core profile shading language version string: 4.60 NVIDIA
OpenGL core profile context flags: (none)
OpenGL core profile profile mask: core profile
OpenGL core profile extensions:
OpenGL version string: 4.6.0 NVIDIA 510.108.03
OpenGL shading language version string: 4.60 NVIDIA
OpenGL context flags: (none)
OpenGL profile mask: (none)
OpenGL extensions:
OpenGL ES profile version string: OpenGL ES 3.2 NVIDIA 510.108.03
OpenGL ES profile shading language version string: OpenGL ES GLSL ES 3.20
OpenGL ES profile extensions:

Steps

  1. ros install lem-project/lem
  2. lem -f sdl2

As is

Black painted SDL2 frontend window appears and it crushes with these logs:

crush logs with `(lem:lem "--debug" "--log-filename" "lem.log")` ``` [17:22:08] lem-core lem.lisp (lem) - Starting Lem [17:22:09] lem-sdl2 main.lisp (display-width sdl2) - lem-if:display-width [17:22:09] lem-sdl2 main.lisp (display-height sdl2) - lem-if:display-height [17:22:09] lem-sdl2 main.lisp (make-view sdl2) - lem-if:make-view LEM-SDL2::WINDOW: # LEM-SDL2::X: 0 LEM-SDL2::Y: 0 LEM-SDL2::WIDTH: 28 LEM-SDL2::HEIGHT: 11 LEM-SDL2::USE-MODELINE: T [17:22:09] lem-sdl2 main.lisp (update-foreground sdl2) - lem-if:update-foreground LEM-SDL2::COLOR: "#cccccc" [17:22:09] lem-sdl2 main.lisp (update-background sdl2) - lem-if:update-background LEM-SDL2::COLOR: "#2d2d2d" [17:22:09] lem-sdl2 main.lisp (will-update-display sdl2) - will-update-display ;; begin my debugging stuff [17:22:09] lem-sdl2 main.lisp (will-update-display sdl2) - renderer-info: # [17:22:09] lem-sdl2 main.lisp (will-update-display sdl2) - texture-info: (370546692 2 900 840) ;; end of my debugging stuff [17:22:09] lem-sdl2 main.lisp (call-with-debug h0) - SDL Error (-1): glFramebufferTexture2DEXT() failed Backtrace for: # 0: ((LAMBDA NIL :IN UIOP/IMAGE:PRINT-BACKTRACE)) 1: ((FLET "THUNK" :IN UIOP/STREAM:CALL-WITH-SAFE-IO-SYNTAX)) 2: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #) 3: (UIOP/STREAM:CALL-WITH-SAFE-IO-SYNTAX # :PACKAGE :CL) 4: ((FLET "log-stmt1" :IN LEM-SDL2::CALL-WITH-DEBUG) #) 5: ((LAMBDA (STREAM LOG4CL-IMPL::FMT-INFO LOG4CL-IMPL::LOGGER LOG4CL-IMPL::LOG-LEVEL LOG4CL-IMPL::LOG-FUNC) :IN "/home/grey/.roswell/lisp/quicklisp/dists/quicklisp/software/log4cl-20211209-git/src/appender/pattern-layout.lisp") # # # # #) 6: ((LAMBDA (STREAM LOG4CL-IMPL::LOGGER LOG4CL-IMPL::LEVEL LOG4CL-IMPL::LOG-FUNC) :IN LOG4CL-IMPL::COMPILE-PATTERN-FORMAT) # # 4 #) 7: ((FLET "WITH-PRETTY-STREAM0" :IN SB-PRETTY::CALL-LOGICAL-BLOCK-PRINTER) #) 8: (SB-PRETTY::CALL-LOGICAL-BLOCK-PRINTER # # NIL NIL "" NIL) 9: ((LAMBDA (STREAM LOG4CL-IMPL::FMT-INFO LOG4CL-IMPL::LOGGER LOG4CL-IMPL::LOG-LEVEL LOG4CL-IMPL::LOG-FUNC LOG4CL-IMPL::WRAP) :IN "/home/grey/.roswell/lisp/quicklisp/dists/quicklisp/software/log4cl-20211209-git/src/appender/pattern-layout.lisp") # # # 4 # #) 10: ((LAMBDA (STREAM LOG4CL-IMPL::LOGGER LOG4CL-IMPL::LEVEL LOG4CL-IMPL::LOG-FUNC) :IN LOG4CL-IMPL::COMPILE-PATTERN-FORMAT) # # 4 #) 11: ((:METHOD LOG4CL-IMPL:LAYOUT-TO-STREAM (LOG4CL-IMPL:PATTERN-LAYOUT T T T T)) # # # 4 #) [fast-method] 12: ((:METHOD LOG4CL-IMPL:APPENDER-DO-APPEND (LOG4CL-IMPL::FIXED-STREAM-APPENDER-BASE T T T)) # # 4 #) [fast-method] 13: ((SB-PCL::EMF LOG4CL-IMPL:APPENDER-DO-APPEND) # # # # 4 #) 14: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK)) 15: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK # # T NIL) 16: ((:METHOD LOG4CL-IMPL:APPENDER-DO-APPEND :AROUND (LOG4CL-IMPL:SERIALIZED-APPENDER T T T)) # # 4 #) [fast-method] 17: ((LABELS LOG4CL-IMPL::LOG-TO-LOGGER-APPENDERS :IN LOG4CL-IMPL::LOG-WITH-LOGGER) # # 4 #) 18: ((LABELS LOG4CL-IMPL::LOG-TO-LOGGER-APPENDERS :IN LOG4CL-IMPL::LOG-WITH-LOGGER) # # 4 #) 19: ((LABELS LOG4CL-IMPL::LOG-TO-LOGGER-APPENDERS :IN LOG4CL-IMPL::LOG-WITH-LOGGER) # # 4 #) 20: ((LABELS LOG4CL-IMPL::LOG-TO-LOGGER-APPENDERS :IN LOG4CL-IMPL::LOG-WITH-LOGGER) # # 4 #) 21: (LOG4CL-IMPL::LOG-WITH-LOGGER # 4 # #) 22: ((FLET "H0" :IN LEM-SDL2::CALL-WITH-DEBUG) #) 23: (SB-KERNEL::%SIGNAL #) 24: (ERROR SDL2::SDL-RC-ERROR :RC -1 :STRING "glFramebufferTexture2DEXT() failed") 25: (SDL2:SET-RENDER-TARGET # #) 26: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK)) 27: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK # # T NIL) 28: (LEM-SDL2::CALL-WITH-RENDERER #) 29: (LEM-SDL2::CALL-WITH-DEBUG # #) 30: (LEM-CORE:REDRAW-DISPLAY T) 31: (LEM-CORE:LOAD-THEME "decaf" NIL) 32: ((:METHOD LEM-BASE:RUN-HOOKS (LIST)) ((LEM-SCHEME-MODE::DISABLE-SCHEME-SLIME-COMMANDS . 0) (LEM-SCHEME-MODE::DISABLE-SCHEME-PROCESS-COMMANDS . 0) (LEM/FRAME-MULTIPLEXER::ENABLE-FRAME-MULTIPLEXER . 0) (# . 0) (# . 0) (LEM-CORE::INITIALIZE-COLOR-THEME . 0))) [fast-method] 33: (LEM-CORE::INIT #S(LEM-CORE::COMMAND-LINE-ARGUMENTS :ARGS (T #1="~/lem.log") :DEBUG T :LOG-FILENAME #1# :NO-INIT-FILE NIL)) 34: (LEM-CORE::TOPLEVEL-COMMAND-LOOP #) 35: ((LAMBDA NIL :IN LEM-CORE::RUN-EDITOR-THREAD)) 36: ((LAMBDA NIL :IN LEM-CORE::RUN-EDITOR-THREAD)) 37: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)) 38: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 39: ((FLET "WITHOUT-INTERRUPTS-BODY-156" :IN SB-THREAD::RUN)) 40: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 41: ((FLET "WITHOUT-INTERRUPTS-BODY-149" :IN SB-THREAD::RUN)) 42: (SB-THREAD::RUN) 43: ("foreign function: call_into_lisp_") 44: ("foreign function: funcall1") [17:22:09] lem-sdl2 main.lisp (display-height sdl2) - lem-if:display-height [17:22:09] lem-sdl2 main.lisp (display-width sdl2) - lem-if:display-width [17:22:09] lem-sdl2 main.lisp (set-view-size sdl2) - lem-if:set-view-size LEM-SDL2::VIEW: # LEM-SDL2::WIDTH: 28 LEM-SDL2::HEIGHT: 9 [17:22:09] lem-sdl2 main.lisp (call-with-debug h0) - The value NIL is not of type AUTOWRAP:WRAPPER Backtrace for: # 0: (AUTOWRAP:INVALIDATE NIL) 1: ((:METHOD LEM-SDL2::RESIZE (LEM-SDL2::VIEW T T)) # 28 9) [fast-method] 2: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK)) 3: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK # # T NIL) 4: (LEM-SDL2::CALL-WITH-RENDERER #) 5: (LEM-SDL2::CALL-WITH-DEBUG # #) 6: (LEM-CORE::SCREEN-SET-SIZE #S(LEM-CORE::SCREEN :VIEW # :MODELINE-ELEMENTS ((0 " Press Space to continue " #)) :LEFT-LINES #(NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL ...) :LEFT-WIDTH 0 :OLD-LEFT-WIDTH 0 :LINES #((#1="SDL Error (-1): glFramebufferTexture2DEXT() failed" (0 1 LEM-CORE:CURSOR NIL)) #2=("Backtrace for: #") ("0: ((LAMBDA NIL :IN UIOP/IMAGE:PRINT-BACKTRACE))") ("1: ((FLET \"THUNK\" :IN UIOP/STREAM:CALL-WITH-SAFE-IO-SYNTAX))") ("2: (SB-IMPL::%WITH-STANDARD-IO-SYNTAX #)") ("3: (UIOP/STREAM:CALL-WITH-SAFE-IO-SYNTAX # :PACKAGE :CL)") ("4: (LEM-CORE:POP-UP-BACKTRACE #)") ("5: ((FLET \"H0\" :IN LEM-CORE::TOPLEVEL-COMMAND-LOOP) #)") ("6: (SB-KERNEL::%SIGNAL #)") ("7: (ERROR SDL2::SDL-RC-ERROR :RC -1 :STRING \"glFramebufferTexture2DEXT() failed\")") ("8: (SDL2:SET-RENDER-TARGET # #)") ("9: ((FLET \"WITHOUT-INTERRUPTS-BODY-11\" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK))") ...) :OLD-LINES #((#1# (0 1 LEM-CORE:CURSOR NIL)) #2# NIL NIL NIL NIL NIL NIL NIL NIL NIL NIL ...) :WRAP-LINES NIL :WIDTH 100 :MODIFIED-P T :LAST-BUFFER-NAME "*EDITOR ERROR*" :LAST-BUFFER-MODIFIED-TICK 2 ...) 28 9) 7: (LEM-CORE:POP-UP-TYPEOUT-WINDOW # :FUNCTION # :ERASE T :READ-ONLY T) 8: ((FLET "H0" :IN LEM-CORE::TOPLEVEL-COMMAND-LOOP) #) 9: (SB-KERNEL::%SIGNAL #) 10: (ERROR SDL2::SDL-RC-ERROR :RC -1 :STRING "glFramebufferTexture2DEXT() failed") 11: (SDL2:SET-RENDER-TARGET # #) 12: ((FLET "WITHOUT-INTERRUPTS-BODY-11" :IN SB-THREAD::CALL-WITH-RECURSIVE-LOCK)) 13: (SB-THREAD::CALL-WITH-RECURSIVE-LOCK # # T NIL) 14: (LEM-SDL2::CALL-WITH-RENDERER #) 15: (LEM-SDL2::CALL-WITH-DEBUG # #) 16: (LEM-CORE:REDRAW-DISPLAY T) 17: (LEM-CORE:LOAD-THEME "decaf" NIL) 18: ((:METHOD LEM-BASE:RUN-HOOKS (LIST)) ((LEM-SCHEME-MODE::DISABLE-SCHEME-SLIME-COMMANDS . 0) (LEM-SCHEME-MODE::DISABLE-SCHEME-PROCESS-COMMANDS . 0) (LEM/FRAME-MULTIPLEXER::ENABLE-FRAME-MULTIPLEXER . 0) (# . 0) (# . 0) (LEM-CORE::INITIALIZE-COLOR-THEME . 0))) [fast-method] 19: (LEM-CORE::INIT #S(LEM-CORE::COMMAND-LINE-ARGUMENTS :ARGS (T #1="~/lem.log") :DEBUG T :LOG-FILENAME #1# :NO-INIT-FILE NIL)) 20: (LEM-CORE::TOPLEVEL-COMMAND-LOOP #) 21: ((LAMBDA NIL :IN LEM-CORE::RUN-EDITOR-THREAD)) 22: ((LAMBDA NIL :IN LEM-CORE::RUN-EDITOR-THREAD)) 23: ((LAMBDA NIL :IN BORDEAUX-THREADS::BINDING-DEFAULT-SPECIALS)) 24: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 25: ((FLET "WITHOUT-INTERRUPTS-BODY-156" :IN SB-THREAD::RUN)) 26: ((FLET SB-UNIX::BODY :IN SB-THREAD::RUN)) 27: ((FLET "WITHOUT-INTERRUPTS-BODY-149" :IN SB-THREAD::RUN)) 28: (SB-THREAD::RUN) 29: ("foreign function: call_into_lisp_") 30: ("foreign function: funcall1") ```

This issue does not occur in my laptop (Intel Graphics driver).

To be

SDL2 window appears rendered with Lem editor screen.

My debugging

I saw this error in that log:

  SDL Error (-1): glFramebufferTexture2DEXT() failed

so I think this is caused by SDL2 or graphc driver layer. I found some glFramebufferTexture2DEXT() related articles like these:

  1. GL_INVALID_OPERATION at glFramebufferTexture2DEXT (in WindowsXP, caused by using deprecated pixel format)
  2. glFramebufferTexture2D fails on iPhone for certain texture sizes (in iOS, caused by texture sizes?)

but these are not reasons of this issue.

BTW I found codes to raise this error in SDL2 codes:

// https://github.com/libsdl-org/SDL/blob/d032492aaba19c108dfd5e52866573bd02bf6148/src/render/opengl/SDL_render_gl.c#L887
    /* TODO: check if texture pixel format allows this operation */
    data->glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, data->textype, texturedata->texture, 0);
    /* Check FBO status */
    status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
    if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
        return SDL_SetError("glFramebufferTexture2DEXT() failed");
    }
    return 0;

I think this issue may be caused by illegal pixel format on this environment but I cannot know how different each texture formats between renderer and (lem-sdl2:create-texture).

t-sin commented 1 year ago

This issue is caused by that TODO. I patched to SDL2 the error does not occurs and the Lem frontend window is shown. The window is shown but redrawing has done only when the window is resized, in my environment.

My patch to resolve this issue. I patched to SDL2 tagged [release-2.0.20](https://github.com/libsdl-org/SDL/releases/tag/release-2.0.20)) like this: ```diff diff --git a/src/render/opengl/SDL_render_gl.c b/src/render/opengl/SDL_render_gl.c index 47d5ae8a1..37b78dc9e 100644 --- a/src/render/opengl/SDL_render_gl.c +++ b/src/render/opengl/SDL_render_gl.c @@ -887,6 +889,7 @@ GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) GL_RenderData *data = (GL_RenderData *) renderer->driverdata; GL_TextureData *texturedata; GLenum status; + GLenum err; GL_ActivateRenderer(renderer); @@ -908,7 +911,16 @@ GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) /* Check FBO status */ status = data->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { - return SDL_SetError("glFramebufferTexture2DEXT() failed"); + if ((err = data->glGetError()) != GL_NO_ERROR) { + switch (err) { + case GL_INVALID_ENUM: + return SDL_SetError("glFramebufferTexture2DEXT() failed because of GL_INVALID_EMUM"); + case GL_INVALID_OPERATION: + return SDL_SetError("glFramebufferTexture2DEXT() failed because of GL_INVALID_OPERATION"); + } + + return SDL_SetError("glFramebufferTexture2DEXT() failed with (err, status) = (%d, %d)", err, status); + } } return 0; } ```

@cxxxr What do you think about next actions for it? It's a problem of SDL2 so there is no quick workarounds. This needs updating libSDL2 in package manager after PR merged or patching to SDL2 by users, but these ways may weather not be easy or have done with waiting...

cxxxr commented 1 year ago

Thank you very much for the detailed report.

I got the impression that finding a fundamental solution for the bug in the SDL2 frontend might be difficult. Perhaps, I could avoid the problem by avoiding the use of SetRenderTarget. This might be worth trying. However, in the long term, I think it might be better to consider implementing the frontend using a different GUI toolkit.

t-sin commented 1 year ago

This comment https://github.com/lem-project/lem/issues/690#issuecomment-1580248353 missed why that error occurs.

Because of that TODO code SDL2 does not check glGetError() before glCheckFramebufferStatusEXT() even though glGetError() tells there is no error. The case like no GL errors, return value of glCheckFramebufferStatusEXT() is maybe undefined, so TODO code raise that SDL error.

t-sin commented 1 year ago

Progress: I made a PR to SDL https://github.com/libsdl-org/SDL/pull/7938 about that TODO.

t-sin commented 1 year ago

This issue's error now does not occur by this software accelerated PR https://github.com/lem-project/lem/pull/787. And I think this problem issued here entirely solved by that SDL2 PR https://github.com/libsdl-org/SDL/pull/7938, even SDL with hardware accelerated option.

And now new problem occurred like this: SDL2 Lem launched without any conditions but with black screen. This black screen Lem is normally processing key events but simply no redrawing occurs, because we can see the string we made after manual resizing Lem's window (or minimizing and restoring).

I'm thinking about this issue:

  1. when this issue is closed?
    • now: because of software accelerated option
    • when Lem has no conditions with hardware accelerated option after merging that SDL2 PR
  2. should that new problem be a new issue?

@cxxxr What do you think about these above?

cxxxr commented 1 year ago

Hmmm, I don't know, so I'm just guessing. The lem-if:set-view-size is called when the window size is changed. Doesn't this behavior affect the display?

t-sin commented 1 year ago

@cxxxr I found this issue is resolved by https://github.com/lem-project/lem/pull/981 with this patch:

diff --git a/frontends/sdl2/main.lisp b/frontends/sdl2/main.lisp
index 1f982687..62865ecc 100644
--- a/frontends/sdl2/main.lisp
+++ b/frontends/sdl2/main.lisp
@@ -822,7 +822,8 @@
                                        :w window-width
                                        :h window-height
                                        :flags '(:shown :resizable #+darwin :allow-highdpi))
-               (sdl2:with-renderer (renderer window :index -1 :flags '(#-darwin :software #+darwin :accelerated))
+               (sdl2:with-renderer (renderer window :index -1 :flags '(:accelerated))
                  (let* ((renderer-size (multiple-value-list (sdl2:get-renderer-output-size renderer)))
                         (renderer-width (first renderer-size))
                         (renderer-height (second renderer-size))

Off course in Linux with NVIDIA card.

So I think that the hardware acceleration can be used in Linux.

cxxxr commented 1 year ago

Thank you. Also, there must have been a problem with the radeon, so we need to check that out.