diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f2a440..83eaef4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,9 @@ The default value is currently 30 fps. This can be disabled by setting the value to 0. This change combats framerate spikes in the thousands when the window is minimized eating up battery life and resources. +* `WindowConfig.init_mgl_context` can now be implemented to completely override context creation. * `run_window_config` was split into `create_window_config_instance` and `run_window_config_instance` making customization easier. `run_window_config` will still behave as before. -* Minimized / iconified windows are now framerate capped * Some doc improvements ## 3.0.0 diff --git a/moderngl_window/__init__.py b/moderngl_window/__init__.py index be975ae..9fbad18 100644 --- a/moderngl_window/__init__.py +++ b/moderngl_window/__init__.py @@ -244,6 +244,7 @@ def create_window_config_instance( samples=values.samples if values.samples is not None else config_cls.samples, cursor=show_cursor if show_cursor is not None else True, backend=values.backend, + context_creation_func=config_cls.init_mgl_context, ) window.print_context_info() activate_context(window=window) diff --git a/moderngl_window/context/base/window.py b/moderngl_window/context/base/window.py index 0dacfc2..e8fc706 100644 --- a/moderngl_window/context/base/window.py +++ b/moderngl_window/context/base/window.py @@ -92,6 +92,7 @@ def __init__( samples: int = 0, cursor: bool = True, backend: Optional[str] = None, + context_creation_func: Optional[Callable] = None, **kwargs: Any, ) -> None: """Initialize a window instance. @@ -118,6 +119,11 @@ def __init__( Number of MSAA samples for the default framebuffer cursor: Enable/disable displaying the cursor inside the window + backend: + The context backend to use. For example ``egl`` for EGL + context_creation_func: + A callable returning a ModernGL context. This can be used to + create a custom context. """ # Window parameters self._title = title @@ -133,6 +139,7 @@ def __init__( self._cursor = cursor self._backend = backend self._headless = False + self._context_creation_func = context_creation_func self._exit_key = self.keys.ESCAPE self._fs_key = self.keys.F11 @@ -183,7 +190,10 @@ def init_mgl_context(self) -> None: Keyword Args: ctx: An optional custom ModernGL context """ - self._ctx = moderngl.create_context(require=self.gl_version_code) + if self._context_creation_func: + self._ctx = self._context_creation_func() + if self._ctx is None: + self._ctx = moderngl.create_context(require=self.gl_version_code) err = self._ctx.error if err != "GL_NO_ERROR": logger.info("Consumed the following error during context creation: %s", err) @@ -420,11 +430,8 @@ def fullscreen(self, value: bool) -> None: @property def config(self) -> Optional["WindowConfig"]: - """Get the current WindowConfig instance + """Get or det the current WindowConfig instance - DEPRECATED PROPERTY. This is not handled in `WindowConfig.__init__` - - This property can also be set. Assigning a WindowConfig instance will automatically set up the necessary event callback methods:: @@ -1165,6 +1172,16 @@ def add_arguments(cls: type["WindowConfig"], parser: ArgumentParser) -> None: """ pass + @classmethod + def init_mgl_context(cls) -> Optional[moderngl.Context]: + """ + Can be implemented to control the creation of the moderngl context. + + The window calls this method first during context creation. + If not context is returned the window will create its own. + """ + return None + def on_render(self, time: float, frame_time: float) -> None: """Renders the assigned effect diff --git a/moderngl_window/opengl/program.py b/moderngl_window/opengl/program.py index 3b2540a..2a424e4 100644 --- a/moderngl_window/opengl/program.py +++ b/moderngl_window/opengl/program.py @@ -427,7 +427,9 @@ def _members(self) -> dict[Any, Any]: def ctx(self) -> moderngl.Context: return self.program.ctx - def __getitem__(self, key: Any) -> Union[ + def __getitem__( + self, key: Any + ) -> Union[ moderngl.Uniform, moderngl.UniformBlock, moderngl.Subroutine,