lem-project / lem

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

Black screen on the SDL2 frontend (with Linux and NVIDIA driver?) #833

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

SDL2 lem is normally launched as a black screen, even though any key inputs.

To be

We can use SDL2 Lem as same as ncurses Lem.

Details

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 input we made after resizing Lem's window (or minimizing and restoring) by our hands.

It appears after resolved https://github.com/lem-project/lem/issues/690 with software accelerated options.


My hypothesis

I think this issue occurs because of no redrawing in lem-if:update-window process. In other detailed words, Lem tries to redraw in wrong way in terms of SDL. SDL does double-buffering in rendering so to switch back buffer into front buffer use SDL2's SDL_RenderPresent() function, but I think Lem may not do this.

I checked SDL document and found this:

The backbuffer should be considered invalidated after each present; do not assume that previous contents will exist between frames. You are strongly encouraged to call SDL_RenderClear() to initialize the backbuffer before starting each new frame's drawing, even if you plan to overwrite every pixel.

--- https://wiki.libsdl.org/SDL2/SDL_RenderPresent

This means any rendering process using SDL2 should do like this:

  1. call SDL_RenderClear() to initialize the back buffer
  2. do drawing onto the back buffer
  3. call SDL_RenderPresent() to make the back buffer a current buffer
    • rendering result appears on our display after doing this

Now I'm not familiar with SDL2 Lem's rendering process so I will continue to read frontend codes.

t-sin 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?

--- https://github.com/lem-project/lem/issues/690#issuecomment-1636739038

This mention is about this issue so I replies in here.

I found a SDL error when sdl2:render-present like this:

<INFO> [23:38:42] lem-sdl2 main.lisp (update-display display) -
 <INFO> [23:38:42] lem-sdl2 main.lisp (update-display display) -
  Unable to make GL context current
 <INFO> [23:38:42] lem-sdl2 main.lisp (update-display display) -
  Unable to make GL context current

with this patch:

diff --git a/frontends/sdl2/main.lisp b/frontends/sdl2/main.lisp
index 0311eb7b..2d1ae6ff 100644
--- a/frontends/sdl2/main.lisp
+++ b/frontends/sdl2/main.lisp
@@ -185,7 +185,13 @@
     (floor (* scale-y y) (char-height))))

 (defmethod update-display ((display display))
-  (sdl2:render-present (display-renderer display)))
+  (log:info "update display actually")
+  (sdl2-ffi.functions:sdl-clear-error)
+  (log:info "~a" (sdl2-ffi.functions:sdl-get-error))
+  (sdl2:render-present (display-renderer display))
+  (log:info "~a" (sdl2-ffi.functions:sdl-get-error))
+  (sdl2:render-clear (current-renderer))
+  (log:info "~a" (sdl2-ffi.functions:sdl-get-error)))

 (defmethod display-width ((display display))
   (nth-value 0 (sdl2:get-renderer-output-size (display-renderer display))))

and also found no error occurs on resizing with that diff.

Hmm... Where are these differences coming from...

t-sin commented 1 year ago

This issue is resolved by this PR https://github.com/lem-project/lem/pull/981 ! Thanks!!