pyglet 3.0.dev1__py3-none-any.whl → 3.0.dev3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. pyglet/__init__.py +11 -2
  2. pyglet/__init__.pyi +2 -0
  3. pyglet/app/__init__.py +3 -1
  4. pyglet/app/base.py +5 -2
  5. pyglet/config/__init__.py +26 -86
  6. pyglet/config/base.py +48 -0
  7. pyglet/config/gl/__init__.py +101 -3
  8. pyglet/config/gl/egl.py +11 -8
  9. pyglet/config/gl/macos.py +6 -7
  10. pyglet/config/gl/webgl.py +24 -0
  11. pyglet/config/gl/windows.py +6 -6
  12. pyglet/config/gl/x11.py +4 -4
  13. pyglet/customtypes.py +3 -0
  14. pyglet/display/base.py +1 -1
  15. pyglet/display/win32.py +7 -1
  16. pyglet/display/xlib.py +2 -0
  17. pyglet/enums.py +54 -7
  18. pyglet/experimental/geoshader_sprite.py +1 -1
  19. pyglet/experimental/particles.py +26 -34
  20. pyglet/font/dwrite/__init__.py +33 -27
  21. pyglet/font/dwrite/dwrite_lib.py +12 -12
  22. pyglet/font/freetype.py +2 -0
  23. pyglet/font/{harfbuzz/__init__.py → harfbuzz.py} +4 -3
  24. pyglet/font/pyodide_js.py +5 -9
  25. pyglet/font/quartz.py +1 -1
  26. pyglet/graphics/__init__.py +0 -2
  27. pyglet/graphics/api/__init__.py +26 -15
  28. pyglet/graphics/api/base.py +190 -4
  29. pyglet/graphics/api/gl/__init__.py +1 -1
  30. pyglet/graphics/api/gl/buffer.py +470 -248
  31. pyglet/graphics/api/gl/cocoa/context.py +1 -1
  32. pyglet/graphics/api/gl/context.py +31 -21
  33. pyglet/graphics/api/gl/draw.py +17 -17
  34. pyglet/graphics/api/gl/egl/context.py +7 -2
  35. pyglet/graphics/api/gl/enums.py +1 -2
  36. pyglet/graphics/api/gl/framebuffer.py +11 -8
  37. pyglet/graphics/api/gl/gl_info.py +55 -92
  38. pyglet/graphics/api/gl/global_opengl.py +45 -36
  39. pyglet/graphics/api/gl/lib.py +19 -6
  40. pyglet/graphics/api/gl/shader.py +349 -434
  41. pyglet/graphics/api/gl/state.py +2 -2
  42. pyglet/graphics/api/gl/texture.py +152 -503
  43. pyglet/graphics/api/gl/vertexarray.py +2 -1
  44. pyglet/graphics/api/gl/vertexdomain.py +108 -87
  45. pyglet/graphics/api/gl/win32/context.py +12 -9
  46. pyglet/graphics/api/gl/xlib/context.py +8 -2
  47. pyglet/graphics/api/gl1/gl_compat.py +3 -1
  48. pyglet/graphics/api/gl2/buffer.py +111 -292
  49. pyglet/graphics/api/gl2/draw.py +7 -6
  50. pyglet/graphics/api/gl2/global_opengl.py +9 -6
  51. pyglet/graphics/api/gl2/shader.py +5 -14
  52. pyglet/graphics/api/gl2/vertexdomain.py +53 -67
  53. pyglet/graphics/api/webgl/__init__.py +25 -22
  54. pyglet/graphics/api/webgl/buffer.py +282 -190
  55. pyglet/graphics/api/webgl/context.py +18 -14
  56. pyglet/graphics/api/webgl/draw.py +17 -17
  57. pyglet/graphics/api/webgl/enums.py +1 -2
  58. pyglet/graphics/api/webgl/framebuffer.py +29 -26
  59. pyglet/graphics/api/webgl/gl_info.py +28 -83
  60. pyglet/graphics/api/webgl/shader.py +99 -395
  61. pyglet/graphics/api/webgl/state.py +3 -3
  62. pyglet/graphics/api/webgl/texture.py +184 -460
  63. pyglet/graphics/api/webgl/vertexarray.py +2 -1
  64. pyglet/graphics/api/webgl/vertexdomain.py +55 -63
  65. pyglet/graphics/api/webgl/webgl_js.pyi +9 -1
  66. pyglet/graphics/atlas.py +1 -1
  67. pyglet/graphics/buffer.py +473 -164
  68. pyglet/graphics/draw.py +11 -12
  69. pyglet/graphics/framebuffer.py +8 -4
  70. pyglet/graphics/instance.py +10 -11
  71. pyglet/graphics/shader.py +405 -28
  72. pyglet/graphics/state.py +24 -14
  73. pyglet/graphics/texture.py +490 -140
  74. pyglet/graphics/vertexdomain.py +76 -84
  75. pyglet/gui/ninepatch.py +2 -2
  76. pyglet/gui/widgets.py +1 -1
  77. pyglet/image/animation.py +2 -2
  78. pyglet/image/base.py +32 -44
  79. pyglet/image/codecs/__init__.py +22 -9
  80. pyglet/info.py +2 -2
  81. pyglet/input/base.py +3 -2
  82. pyglet/input/win32/directinput.py +14 -12
  83. pyglet/input/win32/xinput.py +0 -2
  84. pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -3
  85. pyglet/libs/darwin/cocoapy/runtime.py +28 -0
  86. pyglet/libs/linux/glx/glxext_arb.py +4 -2
  87. pyglet/libs/linux/glx/glxext_nv.py +15 -13
  88. pyglet/libs/linux/x11/xlib.py +2 -178
  89. pyglet/{font/harfbuzz/harfbuzz_lib.py → libs/shared/lib_harfbuzz.py} +1 -2
  90. pyglet/libs/shared/vulkan_lib/__init__.py +164 -0
  91. pyglet/libs/shared/vulkan_lib/exceptions.py +271 -0
  92. pyglet/libs/shared/vulkan_lib/func.py +2891 -0
  93. pyglet/libs/shared/vulkan_lib/func_helpers.py +138 -0
  94. pyglet/libs/shared/vulkan_lib/vk_video.py +1485 -0
  95. pyglet/libs/shared/vulkan_lib/vk_video.pyi +2369 -0
  96. pyglet/libs/shared/vulkan_lib/vulkan_core.py +15540 -0
  97. pyglet/libs/shared/vulkan_lib/vulkan_core.pyi +22937 -0
  98. pyglet/libs/shared/vulkan_lib/vulkan_ios.py +29 -0
  99. pyglet/libs/shared/vulkan_lib/vulkan_ios.pyi +24 -0
  100. pyglet/libs/shared/vulkan_lib/vulkan_macos.py +29 -0
  101. pyglet/libs/shared/vulkan_lib/vulkan_macos.pyi +25 -0
  102. pyglet/libs/shared/vulkan_lib/vulkan_metal.py +136 -0
  103. pyglet/libs/shared/vulkan_lib/vulkan_metal.pyi +198 -0
  104. pyglet/libs/shared/vulkan_lib/vulkan_wayland.py +37 -0
  105. pyglet/libs/shared/vulkan_lib/vulkan_wayland.pyi +32 -0
  106. pyglet/libs/shared/vulkan_lib/vulkan_win32.py +245 -0
  107. pyglet/libs/shared/vulkan_lib/vulkan_win32.pyi +371 -0
  108. pyglet/libs/shared/vulkan_lib/vulkan_xcb.py +38 -0
  109. pyglet/libs/shared/vulkan_lib/vulkan_xcb.pyi +33 -0
  110. pyglet/libs/shared/vulkan_lib/vulkan_xlib.py +38 -0
  111. pyglet/libs/shared/vulkan_lib/vulkan_xlib.pyi +31 -0
  112. pyglet/libs/shared/vulkan_lib/vulkan_xlib_xrandr.py +24 -0
  113. pyglet/libs/shared/vulkan_lib/vulkan_xlib_xrandr.pyi +16 -0
  114. pyglet/libs/win32/__init__.py +3 -1
  115. pyglet/libs/win32/lib_wgl.py +1 -1
  116. pyglet/libs/win32/wglext_arb.py +3 -1
  117. pyglet/math.py +2 -2
  118. pyglet/media/__init__.py +84 -11
  119. pyglet/media/codecs/__init__.py +36 -31
  120. pyglet/media/codecs/base.py +3 -3
  121. pyglet/media/codecs/coreaudio.py +7 -6
  122. pyglet/media/codecs/ffmpeg.py +29 -11
  123. pyglet/media/codecs/ffmpeg_lib/compat.py +52 -26
  124. pyglet/media/codecs/ffmpeg_lib/libavformat.py +71 -26
  125. pyglet/media/codecs/ffmpeg_lib/libswresample.py +1 -1
  126. pyglet/media/codecs/webaudio_pyodide.py +3 -4
  127. pyglet/media/codecs/wmf.py +8 -0
  128. pyglet/media/synthesis.py +13 -7
  129. pyglet/model/__init__.py +10 -36
  130. pyglet/model/codecs/base.py +68 -51
  131. pyglet/model/codecs/gltf.py +181 -60
  132. pyglet/model/codecs/obj.py +60 -57
  133. pyglet/resource.py +46 -16
  134. pyglet/shapes.py +24 -13
  135. pyglet/sprite.py +24 -20
  136. pyglet/text/__init__.py +2 -2
  137. pyglet/text/caret.py +1 -1
  138. pyglet/text/document.py +1 -1
  139. pyglet/text/formats/html.py +136 -6
  140. pyglet/text/formats/structured.py +1 -2
  141. pyglet/text/layout/base.py +21 -19
  142. pyglet/text/layout/incremental.py +1 -1
  143. pyglet/text/layout/scrolling.py +1 -1
  144. pyglet/text/runlist.py +6 -3
  145. pyglet/util.py +157 -66
  146. pyglet/window/__init__.py +58 -55
  147. pyglet/window/cocoa/__init__.py +6 -1
  148. pyglet/window/emscripten/__init__.py +1 -1
  149. pyglet/window/headless/__init__.py +2 -1
  150. pyglet/window/win32/__init__.py +32 -1
  151. pyglet/window/xlib/__init__.py +6 -4
  152. {pyglet-3.0.dev1.dist-info → pyglet-3.0.dev3.dist-info}/METADATA +3 -2
  153. {pyglet-3.0.dev1.dist-info → pyglet-3.0.dev3.dist-info}/RECORD +155 -130
  154. {pyglet-3.0.dev1.dist-info → pyglet-3.0.dev3.dist-info}/WHEEL +1 -1
  155. pyglet/graphics/base.py +0 -10
  156. {pyglet-3.0.dev1.dist-info → pyglet-3.0.dev3.dist-info/licenses}/LICENSE +0 -0
pyglet/__init__.py CHANGED
@@ -11,12 +11,14 @@ import warnings
11
11
  from dataclasses import dataclass, field
12
12
  from typing import TYPE_CHECKING, Literal, Sequence
13
13
 
14
+ from .enums import GraphicsAPI
15
+
14
16
  if TYPE_CHECKING:
15
17
  from types import FrameType
16
18
  from typing import Any, Callable, ItemsView, Sized
17
19
 
18
20
  #: The release version
19
- version = '3.0.dev1'
21
+ version = '3.0.dev3'
20
22
  __version__ = version
21
23
 
22
24
  MIN_PYTHON_VERSION = 3, 8
@@ -286,9 +288,16 @@ class Options:
286
288
  .. versionadded:: 3.0.0
287
289
  """
288
290
 
289
- backend: Literal["opengl", "gl2", "gles3", "gles2", "webgl"] = "opengl"
291
+ backend: Literal["opengl", "gl2", "gles3", "gles2", "webgl"] | GraphicsAPI = GraphicsAPI.OPENGL
290
292
  """Specify the graphics API backend."""
291
293
 
294
+ opengl_persistent_buffers: bool = False
295
+ """If ``True``, the OpenGL backend uses persistent mapped vertex buffers when supported.
296
+
297
+ Requires OpenGL 4.4 or the ``GL_ARB_buffer_storage`` extension. If unavailable or ``False``, pyglet
298
+ falls back to normal backed buffer objects.
299
+ """
300
+
292
301
  optimize_states: bool = True
293
302
  """Runs a second pass on the draw list to remove any redundant states.
294
303
 
pyglet/__init__.pyi CHANGED
@@ -7,6 +7,7 @@ from . import clock as clock
7
7
  from . import config as config
8
8
  from . import customtypes as customtypes
9
9
  from . import display as display
10
+ from . import enums as enums
10
11
  from . import event as event
11
12
  from . import font as font
12
13
  from . import graphics as graphics
@@ -72,6 +73,7 @@ class Options:
72
73
  wayland: bool
73
74
  backend: str | None
74
75
  optimize_states: bool
76
+ opengl_persistent_buffers: bool
75
77
  pyodide: PyodideOptions
76
78
 
77
79
  def get(self, item: str, default: Any = None) -> Any:
pyglet/app/__init__.py CHANGED
@@ -46,8 +46,10 @@ if _is_pyglet_doc_run:
46
46
  else:
47
47
  if compat_platform == 'darwin':
48
48
  from pyglet.app.cocoa import CocoaPlatformEventLoop as PlatformEventLoop
49
+ from pyglet.libs.darwin.cocoapy.runtime import get_chip_model
49
50
 
50
- if platform.machine() == 'arm64' or pyglet.options.osx_alt_loop:
51
+ # Use alternate loop only if forced, or using an M1 chip.
52
+ if (platform.machine() == 'arm64' and "M1" in get_chip_model()) or pyglet.options.osx_alt_loop:
51
53
  from pyglet.app.cocoa import CocoaAlternateEventLoop as EventLoop
52
54
  elif compat_platform in ('win32', 'cygwin'):
53
55
  from pyglet.app.win32 import Win32EventLoop as PlatformEventLoop
pyglet/app/base.py CHANGED
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  import queue
4
4
  import sys
5
5
  import threading
6
+ from queue import Queue
6
7
  from typing import TYPE_CHECKING, Any, Callable
7
8
 
8
9
  from pyglet import app, clock, event
@@ -19,6 +20,8 @@ class PlatformEventLoop:
19
20
 
20
21
  .. versionadded:: 1.2
21
22
  """
23
+ _event_queue: Queue[tuple[EventDispatcher, str, Any]]
24
+
22
25
  def __init__(self) -> None: # noqa: D107
23
26
  self._event_queue = queue.Queue()
24
27
  self._is_running = threading.Event()
@@ -96,8 +99,8 @@ class EventLoop(event.EventDispatcher):
96
99
  this method contains platform-specific code that ensures the application
97
100
  remains responsive to the user while keeping CPU usage to a minimum.
98
101
  """
99
-
100
- _has_exit_condition = None
102
+ _interval: float | None
103
+ _has_exit_condition: threading.Condition
101
104
  _has_exit = False
102
105
 
103
106
  def __init__(self) -> None: # noqa: D107
pyglet/config/__init__.py CHANGED
@@ -1,101 +1,41 @@
1
+ """Configuration options for the Graphics Context."""
2
+
1
3
  from __future__ import annotations
2
4
 
3
- from dataclasses import dataclass
4
- from typing import Any, TYPE_CHECKING
5
+ from typing import TYPE_CHECKING, NamedTuple
6
+
7
+ from pyglet.enums import GraphicsAPI
5
8
 
9
+ from .base import SurfaceConfig, UserConfig # noqa: TC001
10
+ from .gl import OpenGLUserConfig, WebGLUserConfig
6
11
 
7
12
  if TYPE_CHECKING:
8
13
  from pyglet.window import Window
9
14
 
10
15
 
16
+ class Config:
17
+ """A container for backend specific user configuration."""
18
+ opengl: OpenGLUserConfig
19
+ gl2: OpenGLUserConfig
20
+ gles2: OpenGLUserConfig
21
+ gles3: OpenGLUserConfig
22
+ webgl: WebGLUserConfig
11
23
 
12
- class SurfaceConfig:
13
- """Surface configuration information returned by a platform.
14
-
15
- This describes the information a desired surface or window can support.
16
- """
17
- def __init__(self, window: Window, config: UserConfig, handle: Any) -> None:
18
- """A config representing the capabilities of a specific surface.
19
-
20
- This is returned by the platform on a specific window and is not meant to be created by users.
21
-
22
- Args:
23
- window:
24
- The current window or display.
25
- config:
26
- The requested user configuration.
27
- handle:
28
- A handle to the underlying configuration unique to each platform.
29
- """
30
- self._window = window
31
- self.config = config
32
- self.handle = handle
24
+ __slots__ = 'gl2', 'gles2', 'gles3', 'opengl', 'vulkan', 'webgl'
33
25
 
34
- @property
35
- def attributes(self) -> dict[str, Any]:
36
- """The public attributes of this configuration."""
37
- return {attrib: value for attrib, value in self.__dict__.items() if attrib[0] != '_'}
38
-
39
- def is_finalized(self) -> bool:
40
- return True
41
-
42
- class UserConfig:
43
- """User configuration information."""
44
-
45
- @dataclass
46
- class OpenGLConfig(UserConfig):
47
- """An OpenGL Graphics configuration."""
48
- #: Specify the presence of a back-buffer for every color buffer.
49
- double_buffer: bool | None = None
50
- #: Specify the presence of separate left and right buffer sets.
51
- stereo: bool | None = None
52
- #: Total bits per sample per color buffer.
53
- buffer_size: int | None = None
54
- #: The number of auxiliary color buffers.
55
- aux_buffers: int | None = None
56
- #: The number of multisample buffers.
57
- sample_buffers: int | None = None
58
- #: The number of samples per pixel, or 0 if there are no multisample buffers.
59
- samples: int | None = None
60
- #: Bits per sample per buffer devoted to the red component.
61
- red_size: int | None = None
62
- #: Bits per sample per buffer devoted to the green component.
63
- green_size: int | None = None
64
- #: Bits per sample per buffer devoted to the blue component.
65
- blue_size: int | None = None
66
- #: Bits per sample per buffer devoted to the alpha component.
67
- alpha_size: int | None = None
68
- #: Bits per sample in the depth buffer.
69
- depth_size: int | None = None
70
- #: Bits per sample in the stencil buffer.
71
- stencil_size: int | None = None
72
- #: Bits per pixel devoted to the red component in the accumulation buffer. Deprecated.
73
- accum_red_size: int | None = None
74
- #: Bits per pixel devoted to the green component in the accumulation buffer. Deprecated.
75
- accum_green_size: int | None = None
76
- #: Bits per pixel devoted to the blue component in the accumulation buffer. Deprecated.
77
- accum_blue_size: int | None = None
78
- #: Bits per pixel devoted to the alpha component in the accumulation buffer. Deprecated.
79
- accum_alpha_size: int | None = None
80
- #: The OpenGL major version.
81
- major_version: int | None = None
82
- #: The OpenGL minor version.
83
- minor_version: int | None = None
84
- #: Whether to use forward compatibility mode.
85
- forward_compatible: bool | None = None
86
- opengl_api: str | None = "gl"
87
- #: Debug mode.
88
- debug: bool | None = None
89
- #: If the framebuffer should be transparent.
90
- transparent_framebuffer: bool | None = None
91
-
92
- @property
93
- def is_finalized(self) -> bool:
94
- return False
26
+ def __init__(self):
27
+ self.opengl: OpenGLUserConfig = OpenGLUserConfig(major_version=3, minor_version=3, api=GraphicsAPI.OPENGL)
28
+ self.gl2: OpenGLUserConfig = OpenGLUserConfig(major_version=2, minor_version=0, api=GraphicsAPI.OPENGL_2)
29
+ self.gles2: OpenGLUserConfig = OpenGLUserConfig(major_version=2, minor_version=0, api=GraphicsAPI.OPENGL_ES_2)
30
+ self.gles3: OpenGLUserConfig = OpenGLUserConfig(major_version=3, minor_version=2, api=GraphicsAPI.OPENGL_ES_3)
31
+ self.webgl: WebGLUserConfig = WebGLUserConfig()
32
+ # self.vulkan: TBD
95
33
 
96
34
 
97
35
  def match_surface_config(config: UserConfig, surface: Window) -> SurfaceConfig | None:
98
- if isinstance(config, OpenGLConfig):
36
+ if isinstance(config, (OpenGLUserConfig, WebGLUserConfig)):
99
37
  from pyglet.config.gl import get_surface_config # noqa: PLC0415
100
38
  return get_surface_config(config, surface)
101
- return None
39
+
40
+ msg = f"Matching for '{config.__class__}' is not yet implemented."
41
+ raise NotImplementedError(msg)
pyglet/config/base.py ADDED
@@ -0,0 +1,48 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, TYPE_CHECKING
4
+
5
+ if TYPE_CHECKING:
6
+ from pyglet.window import Window
7
+ from pyglet.enums import GraphicsAPI
8
+
9
+
10
+ class UserConfig:
11
+ """User configuration information."""
12
+ api: GraphicsAPI
13
+
14
+ @property
15
+ def is_finalized(self) -> bool:
16
+ return False
17
+
18
+
19
+ class SurfaceConfig:
20
+ """Surface configuration information returned by a platform.
21
+
22
+ This describes the information a desired surface or window can support.
23
+ """
24
+ def __init__(self, window: Window, config: UserConfig, handle: Any) -> None:
25
+ """A config representing the capabilities of a specific surface.
26
+
27
+ This is returned by the platform on a specific window and is not meant to be created by users.
28
+
29
+ Args:
30
+ window:
31
+ The current window or display.
32
+ config:
33
+ The requested user configuration.
34
+ handle:
35
+ A handle to the underlying configuration unique to each platform.
36
+ """
37
+ self._window = window
38
+ self.config = config
39
+ self.handle = handle
40
+
41
+ @property
42
+ def attributes(self) -> dict[str, Any]:
43
+ """The public attributes of this configuration."""
44
+ return {attrib: value for attrib, value in self.__dict__.items() if attrib[0] != '_'}
45
+
46
+ @property
47
+ def is_finalized(self) -> bool:
48
+ return True
@@ -1,30 +1,128 @@
1
1
  from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
2
5
  import pyglet
3
- from pyglet.config import UserConfig, SurfaceConfig, OpenGLConfig
6
+
7
+ from pyglet.enums import GraphicsAPI
8
+ from pyglet.config.base import UserConfig, SurfaceConfig
4
9
 
5
10
 
6
11
  class GLSurfaceConfig(SurfaceConfig):
7
- config: OpenGLConfig
12
+ config: OpenGLUserConfig
13
+
14
+
15
+ # Platform Specific Configurations
16
+
17
+ @dataclass
18
+ class OpenGLUserConfig(UserConfig):
19
+ """An OpenGL Graphics configuration."""
20
+ #: Specify the presence of a back-buffer for every color buffer.
21
+ double_buffer: bool | None = None
22
+ #: Specify the presence of separate left and right buffer sets.
23
+ stereo: bool | None = None
24
+ #: Total bits per sample per color buffer.
25
+ buffer_size: int | None = None
26
+ #: The number of auxiliary color buffers.
27
+ aux_buffers: int | None = None
28
+ #: The number of multisample buffers.
29
+ sample_buffers: int | None = None
30
+ #: The number of samples per pixel, or 0 if there are no multisample buffers.
31
+ samples: int | None = None
32
+ #: Bits per sample per buffer devoted to the red component.
33
+ red_size: int | None = None
34
+ #: Bits per sample per buffer devoted to the green component.
35
+ green_size: int | None = None
36
+ #: Bits per sample per buffer devoted to the blue component.
37
+ blue_size: int | None = None
38
+ #: Bits per sample per buffer devoted to the alpha component.
39
+ alpha_size: int | None = None
40
+ #: Bits per sample in the depth buffer.
41
+ depth_size: int | None = None
42
+ #: Bits per sample in the stencil buffer.
43
+ stencil_size: int | None = None
44
+ #: Bits per pixel devoted to the red component in the accumulation buffer. Deprecated.
45
+ accum_red_size: int | None = None
46
+ #: Bits per pixel devoted to the green component in the accumulation buffer. Deprecated.
47
+ accum_green_size: int | None = None
48
+ #: Bits per pixel devoted to the blue component in the accumulation buffer. Deprecated.
49
+ accum_blue_size: int | None = None
50
+ #: Bits per pixel devoted to the alpha component in the accumulation buffer. Deprecated.
51
+ accum_alpha_size: int | None = None
52
+ #: The OpenGL major version.
53
+ major_version: int | None = None
54
+ #: The OpenGL minor version.
55
+ minor_version: int | None = None
56
+ #: Whether to use forward compatibility mode.
57
+ forward_compatible: bool | None = None
58
+ #: Debug mode.
59
+ debug: bool | None = None
60
+ #: If the framebuffer should be transparent.
61
+ transparent_framebuffer: bool | None = None
62
+ #: Which rendering API is being used (GL, ES, etc.).
63
+ api: GraphicsAPI = GraphicsAPI.OPENGL
64
+
65
+ @property
66
+ def is_finalized(self) -> bool:
67
+ return False
68
+
69
+
70
+ @dataclass
71
+ class WebGLUserConfig(UserConfig):
72
+ """A WebGL Graphics configuration."""
73
+ #: Whether the drawing buffer has an alpha channel (pyglet defaults to False).
74
+ alpha: bool = False
75
+ #: Whether the drawing buffer has a depth buffer (default True).
76
+ depth: bool | None = None
77
+ #: Whether the drawing buffer has a stencil buffer (default False).
78
+ stencil: bool | None = None
79
+ #: Whether antialiasing is enabled (default True).
80
+ antialias: bool | None = None
81
+ #: Whether color values are pre-multiplied by alpha (default True).
82
+ premultipliedAlpha: bool | None = None
83
+ #: Whether the drawing buffer is preserved after rendering (default False).
84
+ preserveDrawingBuffer: bool | None = None
85
+ #: Whether context creation fails if performance is low (default False).
86
+ failIfMajorPerformanceCaveat: bool | None = None
87
+ #: Hints GPU preference: "default", "low-power", or "high-performance" (default "default").
88
+ powerPreference: str | None = None
89
+ #: Hints to reduce latency by desynchronizing canvas painting (default False).
90
+ desynchronized: bool | None = None
91
+
92
+ @property
93
+ def api(self):
94
+ return GraphicsAPI.WEBGL
95
+
96
+ @property
97
+ def is_finalized(self) -> bool:
98
+ return False
8
99
 
9
100
 
10
101
  def get_surface_config(user_config: UserConfig, surface: pyglet.window.Window) -> SurfaceConfig | None:
102
+
11
103
  if pyglet.options.headless or pyglet.options.wayland:
12
104
  from pyglet.config.gl.egl import match
13
105
 
14
106
  return match(user_config, surface)
107
+
15
108
  if pyglet.compat_platform == "win32":
16
109
  from pyglet.config.gl.windows import match # noqa: PLC0415
17
110
 
18
111
  return match(user_config, surface)
112
+
19
113
  if pyglet.compat_platform.startswith("linux"):
20
114
  from pyglet.config.gl.x11 import match # noqa: PLC0415
21
115
 
22
116
  return match(user_config, surface)
117
+
23
118
  if pyglet.compat_platform == "darwin":
24
119
  from pyglet.config.gl.macos import match # noqa: PLC0415
25
120
 
26
121
  return match(user_config, surface)
27
122
 
28
123
  if pyglet.compat_platform == "emscripten":
29
- return GLSurfaceConfig(surface, user_config, None)
124
+ from pyglet.config.gl.webgl import match # noqa: PLC0415
125
+
126
+ return match(user_config, surface)
127
+
30
128
  return None
pyglet/config/gl/egl.py CHANGED
@@ -8,10 +8,11 @@ from pyglet import options
8
8
  from pyglet.graphics.api.gl.egl.context import EGLContext
9
9
  from pyglet.libs import egl
10
10
  from pyglet.config import SurfaceConfig
11
+ from pyglet.enums import GraphicsAPI
11
12
 
12
13
  if TYPE_CHECKING:
13
14
  from pyglet.graphics.api import OpenGLBackend
14
- from pyglet.config import OpenGLConfig
15
+ from pyglet.config import OpenGLUserConfig
15
16
  from pyglet.window.headless import HeadlessWindow
16
17
  from pyglet.window.wayland import WaylandWindow
17
18
 
@@ -26,7 +27,7 @@ _fake_gl_attributes = {
26
27
  }
27
28
 
28
29
 
29
- def match(config: OpenGLConfig, window: HeadlessWindow | WaylandWindow) -> EGLSurfaceConfig:
30
+ def match(config: OpenGLUserConfig, window: HeadlessWindow | WaylandWindow) -> EGLSurfaceConfig:
30
31
  display_connection = window.egl_display_connection # noqa: SLF001
31
32
  assert display_connection is not None
32
33
 
@@ -49,12 +50,14 @@ def match(config: OpenGLConfig, window: HeadlessWindow | WaylandWindow) -> EGLSu
49
50
  attrs.extend([egl.EGL_ALPHA_SIZE, 8])
50
51
  attrs.extend([egl.EGL_DEPTH_SIZE, 8])
51
52
 
52
- if config.opengl_api == "gl":
53
+ if config.api == GraphicsAPI.OPENGL:
53
54
  attrs.extend([egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_BIT])
54
- elif config.opengl_api == "gles":
55
+ elif config.api == GraphicsAPI.OPENGL_ES_2:
56
+ attrs.extend([egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_ES2_BIT])
57
+ elif config.api == GraphicsAPI.OPENGL_ES_3:
55
58
  attrs.extend([egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_ES3_BIT])
56
59
  else:
57
- msg = f"Unknown OpenGL API: {config.opengl_api}"
60
+ msg = f"Unknown OpenGL API: {config.api}"
58
61
  raise ValueError(msg)
59
62
 
60
63
  attrs.extend([egl.EGL_NONE])
@@ -65,7 +68,7 @@ def match(config: OpenGLConfig, window: HeadlessWindow | WaylandWindow) -> EGLSu
65
68
  configs = (egl.EGLConfig * num_config.value)()
66
69
  egl.eglChooseConfig(display_connection, attrs_list, configs, num_config.value, byref(num_config))
67
70
 
68
- result = [EGLSurfaceConfig(window, c, config) for c in configs]
71
+ result = [EGLSurfaceConfig(window, config, c) for c in configs]
69
72
  return result[0]
70
73
 
71
74
 
@@ -85,14 +88,14 @@ class EGLSurfaceConfig(SurfaceConfig):
85
88
  'samples': egl.EGL_SAMPLES,
86
89
  }
87
90
 
88
- def __init__(self, window: HeadlessWindow | WaylandWindow, egl_config: egl.EGLConfig, config: OpenGLConfig) -> None:
91
+ def __init__(self, window: HeadlessWindow | WaylandWindow, config: OpenGLUserConfig, egl_config: egl.EGLConfig) -> None:
89
92
  super().__init__(window, config, egl_config)
90
93
  self._egl_config = egl_config
91
94
 
92
95
  context_attribs = [egl.EGL_CONTEXT_MAJOR_VERSION, config.major_version or 2,
93
96
  egl.EGL_CONTEXT_MINOR_VERSION, config.minor_version or 0]
94
97
 
95
- if config.opengl_api == "gl" and config.forward_compatible:
98
+ if config.api == GraphicsAPI.OPENGL and config.forward_compatible:
96
99
  context_attribs.extend([egl.EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, 1])
97
100
 
98
101
  if config.debug:
pyglet/config/gl/macos.py CHANGED
@@ -6,12 +6,11 @@ from dataclasses import asdict
6
6
  from ctypes import byref, c_uint32, c_int
7
7
 
8
8
  from pyglet.config.gl import GLSurfaceConfig
9
-
10
9
  from pyglet.libs.darwin import cocoapy, quartz
11
10
 
12
11
  from typing import TYPE_CHECKING
13
12
  if TYPE_CHECKING:
14
- from pyglet.config import OpenGLConfig
13
+ from pyglet.config import OpenGLUserConfig
15
14
  from pyglet.graphics.api.gl.cocoa.context import NSOpenGLPixelFormat, CocoaContext
16
15
  from pyglet.window.cocoa import CocoaWindow
17
16
  from pyglet.graphics.api import OpenGLBackend
@@ -41,7 +40,7 @@ catalina: 19.0 -> 19.6
41
40
  big_sur: 20.0 ->
42
41
  """
43
42
 
44
- os_x_release: dict[str, tuple[float] | tuple[float, float] | tuple[float, float, float]] = {
43
+ os_x_release: dict[str, tuple[float, ...]] = {
45
44
  'pre-release': (0, 1),
46
45
  'kodiak': (1, 2, 1),
47
46
  'cheetah': (1, 3, 1),
@@ -64,13 +63,13 @@ os_x_release: dict[str, tuple[float] | tuple[float, float] | tuple[float, float,
64
63
  }
65
64
 
66
65
 
67
- def os_x_version() -> tuple[int, ...] | tuple[tuple[int, ...]]:
66
+ def os_x_version() -> tuple[int, ...]:
68
67
  version = tuple([int(v) for v in platform.release().split('.')])
69
68
 
70
69
  # ensure we return a tuple
71
70
  if len(version) > 0:
72
71
  return version
73
- return (version,)
72
+ return (0,)
74
73
 
75
74
 
76
75
  _os_x_version = os_x_version()
@@ -132,7 +131,7 @@ _fake_gl_attributes = {
132
131
  }
133
132
 
134
133
 
135
- def match(config: OpenGLConfig, window: CocoaWindow) -> CocoaGLSurfaceConfig | None:
134
+ def match(config: OpenGLUserConfig, window: CocoaWindow) -> CocoaGLSurfaceConfig | None:
136
135
  # Construct array of attributes for NSOpenGLPixelFormat
137
136
  attrs = []
138
137
  for name, value in asdict(config).items():
@@ -199,7 +198,7 @@ def match(config: OpenGLConfig, window: CocoaWindow) -> CocoaGLSurfaceConfig | N
199
198
 
200
199
  class CocoaGLSurfaceConfig(GLSurfaceConfig):
201
200
 
202
- def __init__(self, window: CocoaWindow, config: OpenGLConfig, pixel_format: NSOpenGLPixelFormat) -> None:
201
+ def __init__(self, window: CocoaWindow, config: OpenGLUserConfig, pixel_format: NSOpenGLPixelFormat) -> None:
203
202
  super().__init__(window, config, pixel_format)
204
203
  self._pixel_format = pixel_format
205
204
 
@@ -0,0 +1,24 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+ from dataclasses import asdict
5
+ from pyglet.config import SurfaceConfig, WebGLUserConfig
6
+
7
+ if TYPE_CHECKING:
8
+ from pyglet.window import BaseWindow, Any
9
+
10
+
11
+ def match(config: WebGLUserConfig, window: BaseWindow) -> WebGLSurfaceConfig:
12
+ return WebGLSurfaceConfig(window, config, None)
13
+
14
+
15
+ class WebGLSurfaceConfig(SurfaceConfig):
16
+ def __init__(self, window: BaseWindow, config: WebGLUserConfig, handle=None):
17
+ for name, value in asdict(config).items():
18
+ setattr(self, name, value)
19
+ super().__init__(window, config, handle)
20
+
21
+ @property
22
+ def attributes(self) -> dict[str, Any]:
23
+ # Only return the WebGL specific attributes
24
+ return asdict(self.config)
@@ -13,7 +13,7 @@ from pyglet.libs.win32.wgl import WGLFunctions
13
13
  from pyglet.util import asstr
14
14
 
15
15
  if TYPE_CHECKING:
16
- from pyglet.config import OpenGLConfig
16
+ from pyglet.config import OpenGLUserConfig
17
17
  from pyglet.window.win32 import Win32Window
18
18
  from pyglet.graphics.api import OpenGLBackend
19
19
  from pyglet.graphics.api.gl.win32.context import Win32ARBContext, Win32Context
@@ -99,7 +99,7 @@ class _WGL:
99
99
  # A global WGL instance object that has retrieved all the proc addresses for WGL functions.
100
100
  _global_wgl = _WGL()
101
101
 
102
- def match(config: OpenGLConfig, window: Win32Window) -> GLSurfaceConfig | None:
102
+ def match(config: OpenGLUserConfig, window: Win32Window) -> GLSurfaceConfig | None:
103
103
  if not _global_wgl.loaded:
104
104
  _global_wgl.create()
105
105
 
@@ -110,7 +110,7 @@ def match(config: OpenGLConfig, window: Win32Window) -> GLSurfaceConfig | None:
110
110
 
111
111
  return finalized_config
112
112
 
113
- def _get_pixel_format_descriptor_matching_configs(config: OpenGLConfig, window: Win32Window) -> GLLegacyConfig | None:
113
+ def _get_pixel_format_descriptor_matching_configs(config: OpenGLUserConfig, window: Win32Window) -> GLLegacyConfig | None:
114
114
  """Get matching configs using standard PIXELFORMATDESCRIPTOR technique."""
115
115
  pfd = PIXELFORMATDESCRIPTOR()
116
116
  pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR)
@@ -152,7 +152,7 @@ def _get_pixel_format_descriptor_matching_configs(config: OpenGLConfig, window:
152
152
 
153
153
  return None
154
154
 
155
- def _get_arb_pixel_format_matching_configs(config: OpenGLConfig, window: Win32Window) -> GLSurfaceConfig | None:
155
+ def _get_arb_pixel_format_matching_configs(config: OpenGLUserConfig, window: Win32Window) -> GLSurfaceConfig | None:
156
156
  """Get configs using the WGL_ARB_pixel_format extension.
157
157
 
158
158
  This method assumes a (dummy) GL context is already created.
@@ -187,7 +187,7 @@ def _get_arb_pixel_format_matching_configs(config: OpenGLConfig, window: Win32Wi
187
187
 
188
188
 
189
189
  class GLLegacyConfig(GLSurfaceConfig):
190
- def __init__(self, window: Win32Window, pf: int, user_config: OpenGLConfig) -> None:
190
+ def __init__(self, window: Win32Window, pf: int, user_config: OpenGLUserConfig) -> None:
191
191
  super().__init__(window, user_config, pf)
192
192
  self._pf = pf
193
193
  self._pfd = PIXELFORMATDESCRIPTOR()
@@ -239,7 +239,7 @@ class GLSurfaceConfig(GLSurfaceConfig):
239
239
  'accum_alpha_size': wglext_arb.WGL_ACCUM_ALPHA_BITS_ARB,
240
240
  }
241
241
 
242
- def __init__(self, window: Win32Window, pf: int, user_config: OpenGLConfig) -> None:
242
+ def __init__(self, window: Win32Window, pf: int, user_config: OpenGLUserConfig) -> None:
243
243
  super().__init__(window, user_config, pf)
244
244
  self._pf = pf
245
245
 
pyglet/config/gl/x11.py CHANGED
@@ -13,12 +13,12 @@ from pyglet.config import SurfaceConfig
13
13
  if TYPE_CHECKING:
14
14
  from pyglet.graphics.api.gl.xlib.context import XlibContext
15
15
  from pyglet.graphics.api import OpenGLBackend
16
- from pyglet.config import OpenGLConfig
16
+ from pyglet.config import OpenGLUserConfig
17
17
  from pyglet.graphics.api.gl.xlib import glx_info
18
18
  from pyglet.window.xlib import XlibWindow
19
19
 
20
20
 
21
- def match(config: OpenGLConfig, window: XlibWindow) -> XlibGLSurfaceConfig | None:
21
+ def match(config: OpenGLUserConfig, window: XlibWindow) -> XlibGLSurfaceConfig | None:
22
22
  x_display = window._x_display # noqa: SLF001
23
23
  x_screen = window._x_screen_id # noqa: SLF001
24
24
 
@@ -96,7 +96,7 @@ class XlibGLSurfaceConfig(SurfaceConfig):
96
96
  }
97
97
 
98
98
  def __init__(self, window: XlibWindow, fbconfig: glx.GLXFBConfig,
99
- config: OpenGLConfig) -> None:
99
+ config: OpenGLUserConfig) -> None:
100
100
  super().__init__(window, config, fbconfig)
101
101
 
102
102
  self.fbconfig = fbconfig
@@ -122,7 +122,7 @@ class XlibGLSurfaceConfig(SurfaceConfig):
122
122
  if not XRenderFindVisualFormat:
123
123
  return False
124
124
 
125
- xrender_format = XRenderFindVisualFormat(self.canvas.display._display, visual)
125
+ xrender_format = XRenderFindVisualFormat(self.display._display, visual)
126
126
  return xrender_format and xrender_format.contents.direct.alphaMask != 0
127
127
 
128
128
  def get_visual_info(self) -> glx.XVisualInfo:
pyglet/customtypes.py CHANGED
@@ -18,6 +18,8 @@ AnchorX = Literal["left", "center", "right"]
18
18
  AnchorY = Literal["top", "bottom", "center", "baseline"]
19
19
  ContentVAlign = Literal["bottom", "center", "top"]
20
20
 
21
+ MediaTypes = Literal["audio", "video", "image"]
22
+
21
23
  Number = Union[int, float]
22
24
 
23
25
  RGBColor = Tuple[Number, Number, Number]
@@ -59,6 +61,7 @@ __all__ = [
59
61
  "ContentVAlign",
60
62
  "DataTypes",
61
63
  "HorizontalAlign",
64
+ "MediaTypes",
62
65
  "RGBAColor",
63
66
  "RGBColor",
64
67
  ]
pyglet/display/base.py CHANGED
@@ -18,7 +18,7 @@ class Display:
18
18
  x_screen: int = None
19
19
  """The X11 screen number of this display, if applicable."""
20
20
 
21
- def __init__(self, name: str = None, x_screen: int = None) -> None:
21
+ def __init__(self, name: str | None = None, x_screen: int | None = None) -> None:
22
22
  """Create a display connection for the given name and screen.
23
23
 
24
24
  On X11, :attr:`name` is of the form ``"hostname:display"``, where the