Skip to content

Commit

Permalink
Make the QGlPicamera2 widget work through XWayland
Browse files Browse the repository at this point in the history
Signed-off-by: David Plowman <[email protected]>
  • Loading branch information
davidplowman committed Jul 25, 2023
1 parent cab033c commit a8f623e
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 10 deletions.
2 changes: 1 addition & 1 deletion apps/app_capture2.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
QVBoxLayout, QWidget)

from picamera2 import Picamera2
from picamera2.previews.qt import QGlPicamera2
from picamera2.previews.qt import QGlPicamera2, QPicamera2


def post_callback(request):
Expand Down
4 changes: 4 additions & 0 deletions picamera2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
from .picamera2 import Picamera2, Preview
from .request import CompletedRequest, MappedArray

if os.environ.get("XDG_SESSION_TYPE", None) == "wayland":
# The code here works through the X wayland layer, but not otherwise.
os.environ["QT_QPA_PLATFORM"] = "xcb"


def _set_configuration_file(filename):
dirs = [
Expand Down
22 changes: 14 additions & 8 deletions picamera2/previews/q_gl_picamera2.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
import threading
import time

from libcamera import Transform
from PyQt5.QtCore import QSocketNotifier, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QWidget

os.environ["PYOPENGL_PLATFORM"] = "egl"

from libcamera import Transform
from OpenGL.EGL.EXT.image_dma_buf_import import *
from OpenGL.EGL.KHR.image import *
from OpenGL.EGL.VERSION.EGL_1_0 import *
Expand All @@ -18,6 +15,8 @@
from OpenGL.GLES2.OES.EGL_image_external import *
from OpenGL.GLES2.VERSION.GLES2_2_0 import *
from OpenGL.GLES3.VERSION.GLES3_3_0 import *
from PyQt5.QtCore import QSocketNotifier, Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import QWidget

from picamera2.previews.gl_helpers import *

Expand Down Expand Up @@ -201,10 +200,13 @@ def init_gl(self):
}
"""

self.program_image = shaders.compileProgram(
shaders.compileShader(vertShaderSrc_image, GL_VERTEX_SHADER),
shaders.compileShader(fragShaderSrc_image, GL_FRAGMENT_SHADER)
)
vertex_shader = shaders.compileShader(vertShaderSrc_image, GL_VERTEX_SHADER),
# For some reason I seem to be getting a 1 element tuple back. Absolutely no clue why.
if isinstance(vertex_shader, tuple):
vertex_shader = vertex_shader[0]
fragment_shader = shaders.compileShader(fragShaderSrc_image, GL_FRAGMENT_SHADER)
self.program_image = shaders.compileProgram(vertex_shader, fragment_shader)

self.program_overlay = shaders.compileProgram(
shaders.compileShader(vertShaderSrc_overlay, GL_VERTEX_SHADER),
shaders.compileShader(fragShaderSrc_overlay, GL_FRAGMENT_SHADER)
Expand Down Expand Up @@ -369,6 +371,10 @@ def repaint(self, completed_request, update_viewport=False):

def render_request(self, completed_request):
"""Draw the camera image using Qt and OpenGL/GLES."""
# For reasons not terribly well understood, eglMakeCurrent hangs in the X-Wayland world if the
# window is being closed. This appears to stop it.
if not self.isVisible():
return
if self.title_function is not None:
self.setWindowTitle(self.title_function(completed_request.get_metadata()))
with self.lock:
Expand Down
2 changes: 1 addition & 1 deletion picamera2/previews/qt.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
_log = getLogger(__name__)

try:
from .q_gl_picamera2 import EglState, QGlPicamera2
from .q_gl_picamera2 import QGlPicamera2
except Exception:
_log.warning("OpenGL will not be available")

0 comments on commit a8f623e

Please sign in to comment.