From d2d750d9c466bbcb5d1b3d0c6fe40206ae49b853 Mon Sep 17 00:00:00 2001 From: "Lex Darlog (DRL)" <3897975+Lex-DRL@users.noreply.github.com> Date: Mon, 23 Feb 2026 01:37:25 -0300 Subject: [PATCH] globals -> concrete backend attribs --- comfy_extras/nodes_glsl.py | 189 +++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 102 deletions(-) diff --git a/comfy_extras/nodes_glsl.py b/comfy_extras/nodes_glsl.py index dcf5b2e1e..6f9e804b5 100644 --- a/comfy_extras/nodes_glsl.py +++ b/comfy_extras/nodes_glsl.py @@ -18,8 +18,6 @@ logger = logging.getLogger(__name__) # OpenGL modules - initialized lazily when context is created gl = None -glfw = None -EGL = None def _check_opengl_availability(): @@ -322,49 +320,47 @@ class _GLContextGLFW(GLContext): return "GLFW" def _init_backend_concrete(self): - global glfw - self._window, glfw = self.__init_glfw() - - def _make_current_concrete(self): - glfw.make_context_current(self._window) - - @staticmethod - def __init_glfw(): - """Initialize GLFW. Returns (window, glfw_module). Raises RuntimeError on failure.""" - logger.debug("__init_glfw: starting") + """Initialize GLFW. Raises RuntimeError on failure.""" + logger.debug("_init_backend_concrete (GLFW): starting") # On macOS, glfw.init() must be called from main thread or it hangs forever if sys.platform == "darwin": - logger.debug("__init_glfw: skipping on macOS") + logger.debug("_init_backend_concrete (GLFW): skipping on macOS") raise RuntimeError("GLFW backend not supported on macOS") - logger.debug("__init_glfw: importing glfw module") - import glfw as _glfw + logger.debug("_init_backend_concrete (GLFW): importing glfw module") + import glfw - logger.debug("__init_glfw: calling glfw.init()") - if not _glfw.init(): + logger.debug("_init_backend_concrete (GLFW): calling glfw.init()") + if not glfw.init(): raise RuntimeError("glfw.init() failed") try: - logger.debug("__init_glfw: setting window hints") - _glfw.window_hint(_glfw.VISIBLE, _glfw.FALSE) - _glfw.window_hint(_glfw.CONTEXT_VERSION_MAJOR, 3) - _glfw.window_hint(_glfw.CONTEXT_VERSION_MINOR, 3) - _glfw.window_hint(_glfw.OPENGL_PROFILE, _glfw.OPENGL_CORE_PROFILE) + logger.debug("_init_backend_concrete (GLFW): setting window hints") + glfw.window_hint(glfw.VISIBLE, glfw.FALSE) + glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3) + glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3) + glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE) - logger.debug("__init_glfw: calling create_window()") - window = _glfw.create_window(64, 64, "ComfyUI GLSL", None, None) + logger.debug("_init_backend_concrete (GLFW): calling create_window()") + window = glfw.create_window(64, 64, "ComfyUI GLSL", None, None) if not window: raise RuntimeError("glfw.create_window() failed") - logger.debug("__init_glfw: calling make_context_current()") - _glfw.make_context_current(window) - logger.debug("__init_glfw: completed successfully") - return window, _glfw + logger.debug("_init_backend_concrete (GLFW): calling make_context_current()") + glfw.make_context_current(window) except Exception: - logger.debug("__init_glfw: failed, terminating glfw") - _glfw.terminate() + logger.debug("_init_backend_concrete (GLFW): failed, terminating glfw") + glfw.terminate() raise + self._window = window + self._glfw = glfw + + logger.debug("_init_backend_concrete (GLFW): completed successfully") + + def _make_current_concrete(self): + self._glfw.make_context_current(self._window) + ########## class _GLContextEGL(GLContext): @@ -374,97 +370,88 @@ class _GLContextEGL(GLContext): return "EGL" def _init_backend_concrete(self): - global EGL - self._egl_display, self._egl_context, self._egl_surface, EGL = self.__init_egl() - - def _make_current_concrete(self): - from OpenGL.EGL import eglMakeCurrent - eglMakeCurrent(self._egl_display, self._egl_surface, self._egl_surface, self._egl_context) - - @staticmethod - def __init_egl(): - """Initialize EGL for headless rendering. Returns (display, context, surface, EGL_module). Raises RuntimeError on failure.""" - logger.debug("__init_egl: starting") - from OpenGL import EGL as _EGL - from OpenGL.EGL import ( - eglGetDisplay, eglInitialize, eglChooseConfig, eglCreateContext, - eglMakeCurrent, eglCreatePbufferSurface, eglBindAPI, - eglTerminate, eglDestroyContext, eglDestroySurface, - EGL_DEFAULT_DISPLAY, EGL_NO_CONTEXT, EGL_NONE, - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_ALPHA_SIZE, EGL_DEPTH_SIZE, - EGL_WIDTH, EGL_HEIGHT, EGL_OPENGL_API, - ) - logger.debug("__init_egl: imports completed") + """Initialize EGL for headless rendering. Raises RuntimeError on failure.""" + logger.debug("_init_backend_concrete (EGL): starting") + from OpenGL import EGL + logger.debug("_init_backend_concrete (EGL): imports completed") display = None context = None surface = None try: - logger.debug("__init_egl: calling eglGetDisplay()") - display = eglGetDisplay(EGL_DEFAULT_DISPLAY) - if display == _EGL.EGL_NO_DISPLAY: + logger.debug("_init_backend_concrete (EGL): calling eglGetDisplay()") + display = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY) + if display == EGL.EGL_NO_DISPLAY: raise RuntimeError("eglGetDisplay() failed") - logger.debug("__init_egl: calling eglInitialize()") - major, minor = _EGL.EGLint(), _EGL.EGLint() - if not eglInitialize(display, major, minor): + logger.debug("_init_backend_concrete (EGL): calling eglInitialize()") + major, minor = EGL.EGLint(), EGL.EGLint() + if not EGL.eglInitialize(display, major, minor): display = None # Not initialized, don't terminate raise RuntimeError("eglInitialize() failed") - logger.debug(f"__init_egl: EGL version {major.value}.{minor.value}") + logger.debug(f"_init_backend_concrete (EGL): EGL version {major.value}.{minor.value}") config_attribs = [ - EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 0, EGL_NONE + EGL.EGL_SURFACE_TYPE, EGL.EGL_PBUFFER_BIT, + EGL.EGL_RENDERABLE_TYPE, EGL.EGL_OPENGL_BIT, + EGL.EGL_RED_SIZE, 8, EGL.EGL_GREEN_SIZE, 8, EGL.EGL_BLUE_SIZE, 8, EGL.EGL_ALPHA_SIZE, 8, + EGL.EGL_DEPTH_SIZE, 0, EGL.EGL_NONE ] - configs = (_EGL.EGLConfig * 1)() - num_configs = _EGL.EGLint() - if not eglChooseConfig(display, config_attribs, configs, 1, num_configs) or num_configs.value == 0: + configs = (EGL.EGLConfig * 1)() + num_configs = EGL.EGLint() + if not EGL.eglChooseConfig(display, config_attribs, configs, 1, num_configs) or num_configs.value == 0: raise RuntimeError("eglChooseConfig() failed") config = configs[0] - logger.debug(f"__init_egl: config chosen, num_configs={num_configs.value}") + logger.debug(f"_init_backend_concrete (EGL): config chosen, num_configs={num_configs.value}") - if not eglBindAPI(EGL_OPENGL_API): + if not EGL.eglBindAPI(EGL.EGL_OPENGL_API): raise RuntimeError("eglBindAPI() failed") - logger.debug("__init_egl: calling eglCreateContext()") + logger.debug("_init_backend_concrete (EGL): calling eglCreateContext()") context_attribs = [ - _EGL.EGL_CONTEXT_MAJOR_VERSION, 3, - _EGL.EGL_CONTEXT_MINOR_VERSION, 3, - _EGL.EGL_CONTEXT_OPENGL_PROFILE_MASK, _EGL.EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, - EGL_NONE + EGL.EGL_CONTEXT_MAJOR_VERSION, 3, + EGL.EGL_CONTEXT_MINOR_VERSION, 3, + EGL.EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL.EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT, + EGL.EGL_NONE ] - context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs) - if context == EGL_NO_CONTEXT: + context = EGL.eglCreateContext(display, config, EGL.EGL_NO_CONTEXT, context_attribs) + if context == EGL.EGL_NO_CONTEXT: raise RuntimeError("eglCreateContext() failed") - logger.debug("__init_egl: calling eglCreatePbufferSurface()") - pbuffer_attribs = [EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE] - surface = eglCreatePbufferSurface(display, config, pbuffer_attribs) - if surface == _EGL.EGL_NO_SURFACE: + logger.debug("_init_backend_concrete (EGL): calling eglCreatePbufferSurface()") + pbuffer_attribs = [EGL.EGL_WIDTH, 64, EGL.EGL_HEIGHT, 64, EGL.EGL_NONE] + surface = EGL.eglCreatePbufferSurface(display, config, pbuffer_attribs) + if surface == EGL.EGL_NO_SURFACE: raise RuntimeError("eglCreatePbufferSurface() failed") - logger.debug("__init_egl: calling eglMakeCurrent()") - if not eglMakeCurrent(display, surface, surface, context): + logger.debug("_init_backend_concrete (EGL): calling eglMakeCurrent()") + if not EGL.eglMakeCurrent(display, surface, surface, context): raise RuntimeError("eglMakeCurrent() failed") - logger.debug("__init_egl: completed successfully") - return display, context, surface, _EGL - except Exception: - logger.debug("__init_egl: failed, cleaning up") + logger.debug("_init_backend_concrete (EGL): failed, cleaning up") # Clean up any resources on failure if surface is not None: - eglDestroySurface(display, surface) + EGL.eglDestroySurface(display, surface) if context is not None: - eglDestroyContext(display, context) + EGL.eglDestroyContext(display, context) if display is not None: - eglTerminate(display) + EGL.eglTerminate(display) raise + self._egl_display = display + self._egl_context = context + self._egl_surface = surface + + self._EGL = EGL + self._eglMakeCurrent = EGL.eglMakeCurrent + + logger.debug("_init_backend_concrete (EGL): completed successfully") + + def _make_current_concrete(self): + self._eglMakeCurrent(self._egl_display, self._egl_surface, self._egl_surface, self._egl_context) + ########## class _GLContextOSMesa(GLContext): @@ -474,27 +461,19 @@ class _GLContextOSMesa(GLContext): return "OSMesa" def _init_backend_concrete(self): - self._osmesa_ctx, self._osmesa_buffer = self.__init_osmesa() - - def _make_current_concrete(self): - from OpenGL.osmesa import OSMesaMakeCurrent - OSMesaMakeCurrent(self._osmesa_ctx, self._osmesa_buffer, gl.GL_UNSIGNED_BYTE, 64, 64) - - @staticmethod - def __init_osmesa(): """Initialize OSMesa for software rendering. Returns (context, buffer). Raises RuntimeError on failure.""" import ctypes - logger.debug("__init_osmesa: starting") + logger.debug("_init_backend_concrete (OSMesa): starting") os.environ["PYOPENGL_PLATFORM"] = "osmesa" - logger.debug("__init_osmesa: importing OpenGL.osmesa") + logger.debug("_init_backend_concrete (OSMesa): importing OpenGL.osmesa") from OpenGL import GL as _gl from OpenGL.osmesa import ( OSMesaCreateContextExt, OSMesaMakeCurrent, OSMesaDestroyContext, OSMESA_RGBA, ) - logger.debug("__init_osmesa: imports completed") + logger.debug("_init_backend_concrete (OSMesa): imports completed") ctx = OSMesaCreateContextExt(OSMESA_RGBA, 24, 0, 0, None) if not ctx: @@ -503,13 +482,19 @@ class _GLContextOSMesa(GLContext): width, height = 64, 64 buffer = (ctypes.c_ubyte * (width * height * 4))() - logger.debug("__init_osmesa: calling OSMesaMakeCurrent()") + logger.debug("_init_backend_concrete (OSMesa): calling OSMesaMakeCurrent()") if not OSMesaMakeCurrent(ctx, buffer, _gl.GL_UNSIGNED_BYTE, width, height): OSMesaDestroyContext(ctx) raise RuntimeError("OSMesaMakeCurrent() failed") - logger.debug("__init_osmesa: completed successfully") - return ctx, buffer + self._osmesa_ctx = ctx + self._osmesa_buffer = buffer + + logger.debug("_init_backend_concrete (OSMesa): completed successfully") + + def _make_current_concrete(self): + from OpenGL.osmesa import OSMesaMakeCurrent + OSMesaMakeCurrent(self._osmesa_ctx, self._osmesa_buffer, self._gl.GL_UNSIGNED_BYTE, 64, 64) # ----------------------------------------------------------