pyglet 2.1.13__py3-none-any.whl → 3.0.dev1__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 (267) hide show
  1. pyglet/__init__.py +67 -61
  2. pyglet/__init__.pyi +15 -8
  3. pyglet/app/__init__.py +22 -13
  4. pyglet/app/async_app.py +212 -0
  5. pyglet/app/base.py +2 -1
  6. pyglet/app/{xlib.py → linux.py} +3 -3
  7. pyglet/config/__init__.py +101 -0
  8. pyglet/config/gl/__init__.py +30 -0
  9. pyglet/config/gl/egl.py +120 -0
  10. pyglet/config/gl/macos.py +262 -0
  11. pyglet/config/gl/windows.py +267 -0
  12. pyglet/config/gl/x11.py +142 -0
  13. pyglet/customtypes.py +43 -2
  14. pyglet/display/__init__.py +8 -6
  15. pyglet/display/base.py +3 -63
  16. pyglet/display/cocoa.py +12 -17
  17. pyglet/display/emscripten.py +39 -0
  18. pyglet/display/headless.py +23 -30
  19. pyglet/display/wayland.py +157 -0
  20. pyglet/display/win32.py +5 -21
  21. pyglet/display/xlib.py +19 -27
  22. pyglet/display/xlib_vidmoderestore.py +2 -2
  23. pyglet/enums.py +183 -0
  24. pyglet/event.py +0 -1
  25. pyglet/experimental/geoshader_sprite.py +15 -13
  26. pyglet/experimental/hidraw.py +6 -15
  27. pyglet/experimental/multitexture_sprite.py +31 -19
  28. pyglet/experimental/particles.py +13 -35
  29. pyglet/font/__init__.py +251 -85
  30. pyglet/font/base.py +116 -61
  31. pyglet/font/dwrite/__init__.py +349 -204
  32. pyglet/font/dwrite/dwrite_lib.py +27 -5
  33. pyglet/font/fontconfig.py +14 -6
  34. pyglet/font/freetype.py +138 -87
  35. pyglet/font/freetype_lib.py +19 -0
  36. pyglet/font/group.py +179 -0
  37. pyglet/font/harfbuzz/__init__.py +3 -3
  38. pyglet/font/pyodide_js.py +310 -0
  39. pyglet/font/quartz.py +319 -126
  40. pyglet/font/ttf.py +45 -3
  41. pyglet/font/user.py +14 -19
  42. pyglet/font/win32.py +45 -21
  43. pyglet/graphics/__init__.py +8 -787
  44. pyglet/graphics/allocation.py +115 -1
  45. pyglet/graphics/api/__init__.py +77 -0
  46. pyglet/graphics/api/base.py +299 -0
  47. pyglet/graphics/api/gl/__init__.py +58 -0
  48. pyglet/graphics/api/gl/base.py +24 -0
  49. pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
  50. pyglet/graphics/api/gl/cocoa/context.py +76 -0
  51. pyglet/graphics/api/gl/context.py +391 -0
  52. pyglet/graphics/api/gl/default_shaders.py +0 -0
  53. pyglet/graphics/api/gl/draw.py +627 -0
  54. pyglet/graphics/api/gl/egl/__init__.py +0 -0
  55. pyglet/graphics/api/gl/egl/context.py +92 -0
  56. pyglet/graphics/api/gl/enums.py +76 -0
  57. pyglet/graphics/api/gl/framebuffer.py +315 -0
  58. pyglet/graphics/api/gl/gl.py +5463 -0
  59. pyglet/graphics/api/gl/gl_info.py +188 -0
  60. pyglet/graphics/api/gl/global_opengl.py +226 -0
  61. pyglet/{gl → graphics/api/gl}/lib.py +34 -18
  62. pyglet/graphics/api/gl/shader.py +1476 -0
  63. pyglet/graphics/api/gl/shapes.py +55 -0
  64. pyglet/graphics/api/gl/sprite.py +102 -0
  65. pyglet/graphics/api/gl/state.py +219 -0
  66. pyglet/graphics/api/gl/text.py +190 -0
  67. pyglet/graphics/api/gl/texture.py +1526 -0
  68. pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
  69. pyglet/graphics/api/gl/vertexdomain.py +751 -0
  70. pyglet/graphics/api/gl/win32/__init__.py +0 -0
  71. pyglet/graphics/api/gl/win32/context.py +108 -0
  72. pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
  73. pyglet/graphics/api/gl/xlib/__init__.py +0 -0
  74. pyglet/graphics/api/gl/xlib/context.py +174 -0
  75. pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
  76. pyglet/graphics/api/gl1/__init__.py +0 -0
  77. pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
  78. pyglet/graphics/api/gl2/__init__.py +0 -0
  79. pyglet/graphics/api/gl2/buffer.py +320 -0
  80. pyglet/graphics/api/gl2/draw.py +600 -0
  81. pyglet/graphics/api/gl2/global_opengl.py +122 -0
  82. pyglet/graphics/api/gl2/shader.py +200 -0
  83. pyglet/graphics/api/gl2/shapes.py +51 -0
  84. pyglet/graphics/api/gl2/sprite.py +79 -0
  85. pyglet/graphics/api/gl2/text.py +175 -0
  86. pyglet/graphics/api/gl2/vertexdomain.py +364 -0
  87. pyglet/graphics/api/webgl/__init__.py +233 -0
  88. pyglet/graphics/api/webgl/buffer.py +302 -0
  89. pyglet/graphics/api/webgl/context.py +234 -0
  90. pyglet/graphics/api/webgl/draw.py +590 -0
  91. pyglet/graphics/api/webgl/enums.py +76 -0
  92. pyglet/graphics/api/webgl/framebuffer.py +360 -0
  93. pyglet/graphics/api/webgl/gl.py +1537 -0
  94. pyglet/graphics/api/webgl/gl_info.py +130 -0
  95. pyglet/graphics/api/webgl/shader.py +1346 -0
  96. pyglet/graphics/api/webgl/shapes.py +92 -0
  97. pyglet/graphics/api/webgl/sprite.py +102 -0
  98. pyglet/graphics/api/webgl/state.py +227 -0
  99. pyglet/graphics/api/webgl/text.py +187 -0
  100. pyglet/graphics/api/webgl/texture.py +1227 -0
  101. pyglet/graphics/api/webgl/vertexarray.py +54 -0
  102. pyglet/graphics/api/webgl/vertexdomain.py +616 -0
  103. pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
  104. pyglet/{image → graphics}/atlas.py +33 -32
  105. pyglet/graphics/base.py +10 -0
  106. pyglet/graphics/buffer.py +245 -0
  107. pyglet/graphics/draw.py +578 -0
  108. pyglet/graphics/framebuffer.py +26 -0
  109. pyglet/graphics/instance.py +178 -69
  110. pyglet/graphics/shader.py +267 -1553
  111. pyglet/graphics/state.py +83 -0
  112. pyglet/graphics/texture.py +703 -0
  113. pyglet/graphics/vertexdomain.py +695 -538
  114. pyglet/gui/ninepatch.py +10 -10
  115. pyglet/gui/widgets.py +120 -10
  116. pyglet/image/__init__.py +20 -1973
  117. pyglet/image/animation.py +12 -12
  118. pyglet/image/base.py +730 -0
  119. pyglet/image/codecs/__init__.py +9 -0
  120. pyglet/image/codecs/bmp.py +53 -30
  121. pyglet/image/codecs/dds.py +53 -31
  122. pyglet/image/codecs/gdiplus.py +38 -14
  123. pyglet/image/codecs/gdkpixbuf2.py +0 -2
  124. pyglet/image/codecs/js_image.py +99 -0
  125. pyglet/image/codecs/ktx2.py +161 -0
  126. pyglet/image/codecs/pil.py +1 -1
  127. pyglet/image/codecs/png.py +1 -1
  128. pyglet/image/codecs/wic.py +11 -2
  129. pyglet/info.py +26 -24
  130. pyglet/input/__init__.py +8 -0
  131. pyglet/input/base.py +163 -105
  132. pyglet/input/controller.py +13 -19
  133. pyglet/input/controller_db.py +39 -24
  134. pyglet/input/emscripten/__init__.py +18 -0
  135. pyglet/input/emscripten/gamepad_js.py +397 -0
  136. pyglet/input/linux/__init__.py +11 -5
  137. pyglet/input/linux/evdev.py +10 -11
  138. pyglet/input/linux/x11_xinput.py +2 -2
  139. pyglet/input/linux/x11_xinput_tablet.py +1 -1
  140. pyglet/input/macos/__init__.py +7 -2
  141. pyglet/input/macos/darwin_gc.py +559 -0
  142. pyglet/input/win32/__init__.py +1 -1
  143. pyglet/input/win32/directinput.py +34 -29
  144. pyglet/input/win32/xinput.py +11 -61
  145. pyglet/lib.py +3 -3
  146. pyglet/libs/__init__.py +1 -1
  147. pyglet/{gl → libs/darwin}/agl.py +1 -1
  148. pyglet/libs/darwin/cocoapy/__init__.py +2 -2
  149. pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
  150. pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
  151. pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
  152. pyglet/libs/darwin/cocoapy/runtime.py +81 -45
  153. pyglet/libs/darwin/coreaudio.py +4 -4
  154. pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
  155. pyglet/libs/darwin/quartzkey.py +1 -3
  156. pyglet/libs/egl/__init__.py +2 -0
  157. pyglet/libs/egl/egl_lib.py +576 -0
  158. pyglet/libs/egl/eglext.py +51 -5
  159. pyglet/libs/linux/__init__.py +0 -0
  160. pyglet/libs/linux/egl/__init__.py +0 -0
  161. pyglet/libs/linux/egl/eglext.py +22 -0
  162. pyglet/libs/linux/glx/__init__.py +0 -0
  163. pyglet/{gl → libs/linux/glx}/glx.py +13 -14
  164. pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
  165. pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
  166. pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
  167. pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
  168. pyglet/libs/linux/wayland/__init__.py +0 -0
  169. pyglet/libs/linux/wayland/client.py +1068 -0
  170. pyglet/libs/linux/wayland/lib_wayland.py +207 -0
  171. pyglet/libs/linux/wayland/wayland_egl.py +38 -0
  172. pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
  173. pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
  174. pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
  175. pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
  176. pyglet/libs/linux/x11/xrandr.py +0 -0
  177. pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
  178. pyglet/libs/shared/__init__.py +0 -0
  179. pyglet/libs/shared/spirv/__init__.py +0 -0
  180. pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
  181. pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
  182. pyglet/libs/win32/__init__.py +28 -8
  183. pyglet/libs/win32/constants.py +59 -48
  184. pyglet/libs/win32/context_managers.py +20 -3
  185. pyglet/libs/win32/dinput.py +105 -88
  186. pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
  187. pyglet/libs/win32/types.py +58 -23
  188. pyglet/{gl → libs/win32}/wgl.py +32 -25
  189. pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
  190. pyglet/media/__init__.py +9 -10
  191. pyglet/media/codecs/__init__.py +12 -1
  192. pyglet/media/codecs/base.py +99 -96
  193. pyglet/media/codecs/ffmpeg.py +2 -2
  194. pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
  195. pyglet/media/codecs/webaudio_pyodide.py +111 -0
  196. pyglet/media/drivers/__init__.py +9 -4
  197. pyglet/media/drivers/base.py +4 -4
  198. pyglet/media/drivers/openal/__init__.py +1 -1
  199. pyglet/media/drivers/openal/adaptation.py +3 -3
  200. pyglet/media/drivers/pulse/__init__.py +1 -1
  201. pyglet/media/drivers/pulse/adaptation.py +3 -3
  202. pyglet/media/drivers/pyodide_js/__init__.py +8 -0
  203. pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
  204. pyglet/media/drivers/xaudio2/adaptation.py +3 -3
  205. pyglet/media/player.py +276 -193
  206. pyglet/media/player_worker_thread.py +1 -1
  207. pyglet/model/__init__.py +39 -29
  208. pyglet/model/codecs/base.py +4 -4
  209. pyglet/model/codecs/gltf.py +3 -3
  210. pyglet/model/codecs/obj.py +71 -43
  211. pyglet/resource.py +129 -78
  212. pyglet/shapes.py +154 -194
  213. pyglet/sprite.py +47 -164
  214. pyglet/text/__init__.py +44 -54
  215. pyglet/text/caret.py +12 -7
  216. pyglet/text/document.py +19 -17
  217. pyglet/text/formats/html.py +2 -2
  218. pyglet/text/formats/structured.py +10 -40
  219. pyglet/text/layout/__init__.py +20 -13
  220. pyglet/text/layout/base.py +176 -287
  221. pyglet/text/layout/incremental.py +9 -10
  222. pyglet/text/layout/scrolling.py +7 -95
  223. pyglet/window/__init__.py +183 -172
  224. pyglet/window/cocoa/__init__.py +62 -51
  225. pyglet/window/cocoa/pyglet_delegate.py +2 -25
  226. pyglet/window/cocoa/pyglet_view.py +9 -8
  227. pyglet/window/dialog/__init__.py +184 -0
  228. pyglet/window/dialog/base.py +99 -0
  229. pyglet/window/dialog/darwin.py +121 -0
  230. pyglet/window/dialog/linux.py +72 -0
  231. pyglet/window/dialog/windows.py +194 -0
  232. pyglet/window/emscripten/__init__.py +779 -0
  233. pyglet/window/headless/__init__.py +44 -28
  234. pyglet/window/key.py +2 -0
  235. pyglet/window/mouse.py +2 -2
  236. pyglet/window/wayland/__init__.py +377 -0
  237. pyglet/window/win32/__init__.py +101 -46
  238. pyglet/window/xlib/__init__.py +104 -66
  239. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
  240. pyglet-3.0.dev1.dist-info/RECORD +322 -0
  241. {pyglet-2.1.13.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
  242. pyglet/gl/__init__.py +0 -208
  243. pyglet/gl/base.py +0 -499
  244. pyglet/gl/cocoa.py +0 -309
  245. pyglet/gl/gl.py +0 -4625
  246. pyglet/gl/gl.pyi +0 -2320
  247. pyglet/gl/gl_compat.pyi +0 -3097
  248. pyglet/gl/gl_info.py +0 -190
  249. pyglet/gl/headless.py +0 -166
  250. pyglet/gl/wgl_info.py +0 -36
  251. pyglet/gl/wglext_nv.py +0 -1096
  252. pyglet/gl/win32.py +0 -268
  253. pyglet/gl/xlib.py +0 -295
  254. pyglet/image/buffer.py +0 -274
  255. pyglet/image/codecs/s3tc.py +0 -354
  256. pyglet/libs/x11/xrandr.py +0 -166
  257. pyglet-2.1.13.dist-info/RECORD +0 -234
  258. /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
  259. /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
  260. /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
  261. /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
  262. /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
  263. /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
  264. /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
  265. /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
  266. /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
  267. {pyglet-2.1.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
@@ -0,0 +1,54 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ import pyglet
6
+
7
+ if TYPE_CHECKING:
8
+ from pyglet.graphics.api.webgl import OpenGLSurfaceContext
9
+ from pyglet.graphics.api.webgl.webgl_js import WebGLVertexArrayObject
10
+
11
+ __all__ = ['VertexArray']
12
+
13
+
14
+ class VertexArray:
15
+ """OpenGL Vertex Array Object."""
16
+
17
+ _context: OpenGLSurfaceContext | None
18
+ _id: WebGLVertexArrayObject
19
+
20
+ def __init__(self, context: OpenGLSurfaceContext) -> None:
21
+ """Create an instance of a Vertex Array object."""
22
+ self._context = context
23
+ self._gl = self._context.gl
24
+ self._id = self._gl.createVertexArray()
25
+
26
+ @property
27
+ def id(self) -> WebGLVertexArrayObject | int:
28
+ return self._id
29
+
30
+ def bind(self) -> None:
31
+ self._gl.bindVertexArray(self._id)
32
+
33
+ def unbind(self) -> None:
34
+ self._gl.bindVertexArray(None)
35
+
36
+ def delete(self) -> None:
37
+ self._gl.deleteVertexArray(self._id)
38
+ self._id = None
39
+
40
+ __enter__ = bind
41
+
42
+ def __exit__(self, *_) -> None: # noqa: ANN002
43
+ self._gl.bindVertexArray(None)
44
+
45
+ def __del__(self) -> None:
46
+ if self._id is not None:
47
+ try:
48
+ self._context.delete_vao(self.id)
49
+ self._id = None
50
+ except (ImportError, AttributeError):
51
+ pass # Interpreter is shutting down
52
+
53
+ def __repr__(self) -> str:
54
+ return f"{self.__class__.__name__}(id={self._id})"
@@ -0,0 +1,616 @@
1
+ """Manage related vertex attributes within a single vertex domain.
2
+
3
+ A vertex "domain" consists of a set of attribute descriptions that together
4
+ describe the layout of one or more vertex buffers which are used together to
5
+ specify the vertices in a primitive. Additionally, the domain manages the
6
+ buffers used to store the data and will resize them as necessary to accommodate
7
+ new vertices.
8
+
9
+ Domains can optionally be indexed, in which case they also manage a buffer
10
+ containing vertex indices. This buffer is grown separately and has no size
11
+ relation to the attribute buffers.
12
+
13
+ Applications can create vertices (and optionally, indices) within a domain
14
+ with the :py:meth:`VertexDomain.create` method. This returns a
15
+ :py:class:`VertexList` representing the list of vertices created. The vertex
16
+ attribute data within the group can be modified, and the changes will be made
17
+ to the underlying buffers automatically.
18
+
19
+ The entire domain can be efficiently drawn in one step with the
20
+ :py:meth:`VertexDomain.draw` method, assuming all the vertices comprise
21
+ primitives of the same OpenGL primitive mode.
22
+ """
23
+ from __future__ import annotations
24
+
25
+ import ctypes
26
+ from typing import TYPE_CHECKING, Any, Sequence
27
+
28
+ from pyglet.graphics.api.base import SurfaceContext
29
+ from pyglet.graphics.api.webgl import vertexarray
30
+ from pyglet.graphics.api.webgl.gl import (
31
+ GL_BYTE,
32
+ GL_DOUBLE,
33
+ GL_FLOAT,
34
+ GL_INT,
35
+ GL_SHORT,
36
+ GL_UNSIGNED_BYTE,
37
+ GL_UNSIGNED_INT,
38
+ GL_UNSIGNED_SHORT,
39
+ GLint,
40
+ GLintptr,
41
+ GLsizei,
42
+ GLvoid,
43
+ )
44
+ from pyglet.graphics.api.webgl.enums import geometry_map
45
+ from pyglet.graphics.api.webgl.shader import GLAttribute
46
+ from pyglet.graphics.api.webgl.buffer import AttributeBufferObject, IndexedBufferObject
47
+ from pyglet.graphics.instance import InstanceBucket, BaseInstanceDomain, VertexInstanceBase
48
+ from pyglet.graphics.vertexdomain import (
49
+ VertexArrayBinding,
50
+ VertexArrayProtocol,
51
+ InstanceStream,
52
+ VertexStream,
53
+ IndexStream,
54
+ VertexListBase,
55
+ IndexedVertexListBase,
56
+ VertexDomainBase,
57
+ IndexedVertexDomainBase,
58
+ VertexGroupBucket,
59
+ _RunningIndexSupport,
60
+ InstanceIndexedVertexListBase,
61
+ InstancedIndexedVertexDomainBase,
62
+ InstancedVertexDomainBase,
63
+ InstanceVertexListBase,
64
+ )
65
+
66
+ if TYPE_CHECKING:
67
+ from pyglet.graphics.shader import AttributeView
68
+ from pyglet.customtypes import CType, DataTypes
69
+ from pyglet.graphics import GeometryMode
70
+ from pyglet.graphics.shader import Attribute
71
+ from pyglet.graphics.api.webgl.context import OpenGLSurfaceContext
72
+
73
+ _c_types = {
74
+ GL_BYTE: ctypes.c_byte,
75
+ GL_UNSIGNED_BYTE: ctypes.c_ubyte,
76
+ GL_SHORT: ctypes.c_short,
77
+ GL_UNSIGNED_SHORT: ctypes.c_ushort,
78
+ GL_INT: ctypes.c_int,
79
+ GL_UNSIGNED_INT: ctypes.c_uint,
80
+ GL_FLOAT: ctypes.c_float,
81
+ GL_DOUBLE: ctypes.c_double,
82
+ }
83
+
84
+ _gl_types = {
85
+ 'b': GL_BYTE,
86
+ 'B': GL_UNSIGNED_BYTE,
87
+ 'h': GL_SHORT,
88
+ 'H': GL_UNSIGNED_SHORT,
89
+ 'i': GL_INT,
90
+ 'I': GL_UNSIGNED_INT,
91
+ 'f': GL_FLOAT,
92
+ 'd': GL_DOUBLE,
93
+ }
94
+
95
+
96
+ def _make_attribute_property(name: str) -> property:
97
+ def _attribute_getter(self: VertexList) -> ctypes.Array[float | int]:
98
+ buffer = self.domain.attrib_name_buffers[name]
99
+ region = buffer.get_region(self.start, self.count)
100
+ buffer.invalidate_region(self.start, self.count)
101
+ return region
102
+
103
+ def _attribute_setter(self: VertexList, data: Any) -> None:
104
+ buffer = self.domain.attrib_name_buffers[name]
105
+ buffer.set_region(self.start, self.count, data)
106
+
107
+ return property(_attribute_getter, _attribute_setter)
108
+
109
+
110
+ class _GLVertexStreamMix(VertexStream):
111
+ _ctx: OpenGLSurfaceContext
112
+ attrib_name_buffers: dict[str, AttributeBufferObject]
113
+
114
+ def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute], *, divisor: int = 0):
115
+ super().__init__(ctx, initial_size, attrs, divisor=divisor)
116
+
117
+ def get_graphics_attribute(self, attribute: Attribute, view: AttributeView) -> GLAttribute:
118
+ return GLAttribute(attribute, view)
119
+
120
+ def get_buffer(self, size: int, attribute) -> AttributeBufferObject:
121
+ return AttributeBufferObject(self._ctx, size, attribute)
122
+
123
+ def bind_into(self, vao) -> None:
124
+ for attribute, buffer in zip(self.attribute_names.values(), self.buffers):
125
+ buffer.bind()
126
+ attribute.enable()
127
+ attribute.set_pointer()
128
+ attribute.set_divisor()
129
+
130
+ class GLVertexStream(_GLVertexStreamMix, VertexStream): # noqa: D101
131
+ def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute]) -> None:
132
+ """Contains data for vertex stream.
133
+
134
+ Args:
135
+ ctx:
136
+ The core context that owns this stream.
137
+ initial_size:
138
+ Initial buffer size.
139
+ attrs:
140
+ Attributes that will be used.
141
+ """
142
+ super().__init__(ctx, initial_size, attrs)
143
+
144
+ class GLInstanceStream(_GLVertexStreamMix, InstanceStream): # noqa: D101
145
+ _ctx: OpenGLSurfaceContext
146
+
147
+ def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute], # noqa: D107
148
+ *, divisor: int = 0) -> None:
149
+ super().__init__(ctx, initial_size, attrs, divisor=divisor)
150
+
151
+ class GLVertexArrayBinding(VertexArrayBinding): # noqa: D101
152
+
153
+ def _create_vao(self) -> VertexArrayProtocol:
154
+ return vertexarray.VertexArray(self._ctx)
155
+
156
+ def _link(self) -> None:
157
+ self.vao.bind()
158
+ for stream in self.streams:
159
+ stream.bind_into(self.vao)
160
+ self.vao.unbind()
161
+
162
+ def bind(self) -> None:
163
+ self.vao.bind()
164
+
165
+ def unbind(self) -> None:
166
+ self.vao.unbind()
167
+
168
+
169
+ class VertexList(VertexListBase):
170
+ ...
171
+
172
+ class InstanceVertexList(InstanceVertexListBase):
173
+ ...
174
+
175
+ class IndexedVertexList(IndexedVertexListBase):
176
+ ...
177
+
178
+ class InstanceIndexedVertexList(InstanceIndexedVertexListBase):
179
+ ...
180
+
181
+ class GLIndexStream(IndexStream): # noqa: D101
182
+ index_element_size: int
183
+ index_c_type: CType
184
+ gl_type: int
185
+
186
+ def __init__(self, ctx: OpenGLSurfaceContext, data_type: DataTypes, initial_elems: int) -> None: # noqa: D107
187
+ self.gl_type = _gl_types[data_type]
188
+ self.index_c_type = _c_types[self.gl_type]
189
+ self.index_element_size = ctypes.sizeof(self.index_c_type)
190
+ super().__init__(ctx, data_type, initial_elems)
191
+
192
+ def _create_buffer(self) -> IndexedBufferObject:
193
+ return IndexedBufferObject(self.ctx, self.allocator.capacity * self.index_element_size,
194
+ self.index_c_type,
195
+ self.index_element_size,
196
+ 1)
197
+
198
+ def bind_into(self, vao: VertexArrayBinding) -> None:
199
+ self.buffer.bind_to_index_buffer()
200
+
201
+
202
+ class VertexDomain(VertexDomainBase):
203
+ """Management of a set of vertex lists.
204
+
205
+ Construction of a vertex domain is usually done with the
206
+ :py:func:`create_domain` function.
207
+ """
208
+
209
+ def __init__(self, context: SurfaceContext, initial_count: int, attribute_meta: dict[str, Attribute]) -> None:
210
+ super().__init__(context, initial_count, attribute_meta)
211
+ self._gl = context.gl
212
+ if self._supports_multi_draw:
213
+ self._multi_draw_array = self._gl.getExtension("WEBGL_multi_draw").multiDrawArraysWEBGL
214
+ else:
215
+ self._multi_draw_array = None
216
+
217
+ def draw_bucket(self, mode: int, bucket) -> None:
218
+ bucket.draw(self, mode)
219
+
220
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
221
+ regions = []
222
+ for bucket in buckets:
223
+ regions.extend(bucket.merged_ranges)
224
+
225
+ start_list = [region[0] for region in regions]
226
+ size_list = [region[1] for region in regions]
227
+ primcount = len(regions)
228
+ if self._supports_multi_draw:
229
+ starts = (GLint * primcount)(*start_list)
230
+ sizes = (GLsizei * primcount)(*size_list)
231
+ self._multi_draw_array(starts[:], 0, sizes[:], 0, primcount)
232
+ else:
233
+ for start, size in zip(start_list, size_list):
234
+ self._gl.drawArrays(mode, start, size)
235
+
236
+ def _create_vertex_class(self) -> type:
237
+ return type(self._vertex_class.__name__, (self._vertex_class,), self.vertex_buffers._property_dict)
238
+
239
+ def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
240
+ return ctx.gl.getExtension("WEBGL_multi_draw")
241
+
242
+ def _create_vao(self) -> GLVertexArrayBinding:
243
+ return GLVertexArrayBinding(self._context, self._streams)
244
+
245
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
246
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
247
+ return [self.vertex_buffers]
248
+
249
+ def draw(self, mode: int) -> None:
250
+ """Draw all vertices in the domain.
251
+
252
+ All vertices in the domain are drawn at once. This is the
253
+ most efficient way to render primitives.
254
+
255
+ Args:
256
+ mode:
257
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
258
+
259
+ """
260
+ self.vao.bind()
261
+ self.vertex_buffers.commit()
262
+
263
+ starts, sizes = self.vertex_buffers.allocator.get_allocated_regions()
264
+ primcount = len(starts)
265
+ if primcount == 0:
266
+ pass
267
+ elif primcount == 1:
268
+ # Common case
269
+ self._gl.drawArrays(mode, starts[0], sizes[0])
270
+ else:
271
+ if self._multi_draw_array:
272
+ starts = (GLint * primcount)(*starts)
273
+ sizes = (GLsizei * primcount)(*sizes)
274
+ self._multi_draw_array(starts[:], 0, sizes[:], 0, primcount)
275
+ else:
276
+ # If not available, draw separately.
277
+ for start, size in zip(starts, sizes):
278
+ self._gl.drawArrays(mode, start, size)
279
+
280
+ def draw_subset(self, mode: GeometryMode, vertex_list: VertexList) -> None:
281
+ """Draw a specific VertexList in the domain.
282
+
283
+ The `vertex_list` parameter specifies a :py:class:`VertexList`
284
+ to draw. Only primitives in that list will be drawn.
285
+
286
+ Args:
287
+ mode:
288
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
289
+ vertex_list:
290
+ Vertex list to draw.
291
+
292
+ """
293
+ self.vao.bind()
294
+ self.vertex_buffers.commit()
295
+ self._gl.drawArrays(geometry_map[mode], vertex_list.start, vertex_list.count)
296
+
297
+ @property
298
+ def is_empty(self) -> bool:
299
+ return not self.vertex_buffers.allocator.starts
300
+
301
+ def __repr__(self) -> str:
302
+ return f'<{self.__class__.__name__}@{id(self):x} vertex_alloc={self.vertex_buffers.allocator}>'
303
+
304
+
305
+ class GLInstanceDomainArrays(BaseInstanceDomain): # noqa: D101
306
+ def __init__(self, domain: Any, initial_instances: int) -> None:
307
+ super().__init__(domain, initial_instances)
308
+ self._ctx = domain._context # noqa: SLF001
309
+ self._gl = domain._context.gl # noqa: SLF001
310
+
311
+ def _create_bucket_arrays(self) -> InstanceBucket:
312
+ istream = GLInstanceStream(self._ctx, self._initial, self._domain.per_instance, divisor=1)
313
+ vao = GLVertexArrayBinding(self._ctx, [self._domain.vertex_buffers, istream])
314
+ return InstanceBucket(istream, vao)
315
+
316
+ def _create_bucket_elements(self) -> InstanceBucket:
317
+ raise NotImplementedError("Use GLInstanceDomainElements for indexed draws")
318
+
319
+ def draw(self, mode: int) -> None:
320
+ for key, bucket in self._buckets.items():
321
+ if bucket.instance_count <= 0:
322
+ continue
323
+ first_vertex, vertex_count = self._geom[bucket]
324
+ bucket.vao.bind()
325
+ bucket.stream.commit()
326
+ self._gl.drawArraysInstanced(mode, first_vertex, vertex_count, bucket.instance_count)
327
+
328
+ def draw_subset(self, mode: int, vertex_list: InstanceVertexList):
329
+ """Draw a specific VertexList in the domain."""
330
+ bucket = vertex_list.bucket
331
+ bucket.vao.bind()
332
+ bucket.stream.commit()
333
+ self._gl.drawArraysInstanced(mode, vertex_list.start, vertex_list.count, bucket.instance_count)
334
+
335
+ class GLInstanceDomainElements(BaseInstanceDomain): # noqa: D101
336
+ _ctx: OpenGLSurfaceContext
337
+
338
+ def __init__(self, domain: Any, initial_instances: int, index_stream: GLIndexStream) -> None:
339
+ super().__init__(domain, initial_instances)
340
+ self._ctx = domain._context # noqa: SLF001
341
+ self._gl = domain._context.gl # noqa: SLF001
342
+ self._index_stream = index_stream
343
+ self._index_gl_type = self._index_stream.gl_type
344
+ self._elem_size = index_stream.index_element_size
345
+
346
+ def _create_bucket_elements(self) -> InstanceBucket:
347
+ istream = GLInstanceStream(self._ctx, self._initial, self._domain.per_instance, divisor=1)
348
+ vao = GLVertexArrayBinding(self._ctx, [self._domain.vertex_buffers, istream, self._index_stream])
349
+ return InstanceBucket(istream, vao)
350
+
351
+ def _create_bucket_arrays(self) -> InstanceBucket:
352
+ raise NotImplementedError("Use GLInstanceDomainArrays for non-indexed draws")
353
+
354
+ def draw_bucket(self, mode: int, bucket: InstanceBucket) -> None:
355
+ if bucket.instance_count <= 0:
356
+ return
357
+ first_index, index_count, _, _ = self._geom[bucket]
358
+ byte_offset = first_index * self._elem_size
359
+ bucket.vao.bind()
360
+ bucket.stream.commit()
361
+ self._gl.drawElementsInstanced(
362
+ mode, index_count, self._index_gl_type, byte_offset,
363
+ bucket.instance_count,
364
+ )
365
+
366
+ def draw_subset(self, mode: GeometryMode, vertex_list: InstanceIndexedVertexList) -> None:
367
+ """Draw a specific VertexList in the domain."""
368
+ byte_offset = vertex_list.index_start * self._elem_size
369
+ self._gl.drawElementsInstanced(
370
+ mode, vertex_list.index_count, self._index_gl_type, byte_offset,
371
+ vertex_list.bucket.instance_count,
372
+ )
373
+
374
+ def draw(self, mode: int) -> None:
375
+ for key, bucket in self._buckets.items():
376
+ if bucket.instance_count <= 0:
377
+ continue
378
+ first_index, index_count, _, _ = self._geom[bucket]
379
+ byte_offset = first_index * self._elem_size
380
+ bucket.vao.bind()
381
+ bucket.stream.commit()
382
+ self._gl.drawElementsInstanced(
383
+ mode, index_count, self._index_gl_type, byte_offset,
384
+ bucket.instance_count,
385
+ )
386
+
387
+
388
+ class InstancedVertexDomain(InstancedVertexDomainBase): # noqa: D101
389
+ _vertexinstance_class: type
390
+ _vertex_class = InstanceVertexList
391
+
392
+ def _create_vertex_class(self) -> type:
393
+ return type(self._vertex_class.__name__, (self._vertex_class,), self.vertex_buffers._property_dict)
394
+
395
+ def _has_multi_draw_extension(self, ctx):
396
+ return False
397
+
398
+ def _create_vao(self) -> GLVertexArrayBinding:
399
+ return GLVertexArrayBinding(self._context, self._streams)
400
+
401
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
402
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
403
+ return [self.vertex_buffers]
404
+
405
+ def create_instance_domain(self, size: int) -> BaseInstanceDomain:
406
+ return GLInstanceDomainArrays(self, size)
407
+
408
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
409
+ """Draw a specific VertexGroupBucket in the domain."""
410
+ self.instance_domain.draw(mode)
411
+
412
+ def _create_vao(self) -> None:
413
+ """Handled by buckets."""
414
+
415
+ def draw(self, mode: int) -> None:
416
+ """Draw all vertices in the domain.
417
+
418
+ All vertices in the domain are drawn at once. This is the
419
+ most efficient way to render primitives.
420
+
421
+ Args:
422
+ mode:
423
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
424
+
425
+ """
426
+ self.vertex_buffers.commit()
427
+ self.instance_buckets.draw(mode)
428
+
429
+ def draw_subset(self, mode: GeometryMode, vertex_list: InstanceVertexList) -> None:
430
+ """Draw a specific VertexList in the domain.
431
+
432
+ The `vertex_list` parameter specifies a :py:class:`VertexList`
433
+ to draw. Only primitives in that list will be drawn.
434
+
435
+ Args:
436
+ mode:
437
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
438
+ vertex_list:
439
+ Vertex list to draw.
440
+ """
441
+ self.vertex_buffers.commit()
442
+ self.instance_buckets.draw_subset(geometry_map[mode], vertex_list)
443
+
444
+
445
+
446
+ class IndexedVertexDomain(IndexedVertexDomainBase):
447
+ """Management of a set of indexed vertex lists.
448
+
449
+ Construction of an indexed vertex domain is usually done with the
450
+ :py:func:`create_domain` function.
451
+ """
452
+
453
+ _vertex_class = IndexedVertexList
454
+ _supports_base_vertex: bool = False
455
+
456
+ def __init__(self, context: SurfaceContext, initial_count: int, attribute_meta: dict[str, Attribute],
457
+ index_type: DataTypes = "I") -> None:
458
+ super().__init__(context, initial_count, attribute_meta, index_type)
459
+ self._gl = context.gl
460
+ if self._supports_multi_draw:
461
+ self._multi_draw_elements = self._gl.getExtension("WEBGL_multi_draw").multiDrawElementsWEBGL
462
+ else:
463
+ self._multi_draw_elements = None
464
+
465
+ def _create_vertex_class(self) -> type:
466
+ return type(self._vertex_class.__name__, (_RunningIndexSupport, self._vertex_class),
467
+ self.vertex_buffers._property_dict) # noqa: SLF001
468
+
469
+ def _create_vao(self) -> GLVertexArrayBinding:
470
+ return GLVertexArrayBinding(self._context, self._streams)
471
+
472
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
473
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
474
+ self.index_stream = GLIndexStream(self._context, self.index_type, size)
475
+ return [self.vertex_buffers, self.index_stream]
476
+
477
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
478
+ regions = []
479
+ for bucket in buckets:
480
+ regions.extend(bucket.merged_ranges)
481
+
482
+ start_list = [region[0] for region in regions]
483
+ size_list = [region[1] for region in regions]
484
+ primcount = len(regions)
485
+ if self._supports_multi_draw:
486
+ starts = [s * self.index_stream.index_element_size for s in start_list]
487
+ starts = (ctypes.POINTER(GLvoid) * primcount)(*(GLintptr * primcount)(*starts))
488
+ sizes = (GLsizei * primcount)(*size_list)
489
+ self._multi_draw_elements(mode, sizes[:], 0, self.index_stream.gl_type, starts[:], 0, primcount)
490
+ else:
491
+ for start, size in zip(start_list, size_list):
492
+ self._gl.drawElements(mode, size, self.index_stream.gl_type,
493
+ start * self.index_stream.index_element_size)
494
+
495
+ def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
496
+ return ctx.gl.getExtension("WEBGL_multi_draw")
497
+
498
+ def draw(self, mode: int) -> None:
499
+ """Draw all vertices in the domain.
500
+
501
+ All vertices in the domain are drawn at once. This is the
502
+ most efficient way to render primitives.
503
+
504
+ Args:
505
+ mode:
506
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
507
+
508
+ """
509
+ self.vao.bind()
510
+ self.vertex_buffers.commit()
511
+ self.index_stream.buffer.commit()
512
+
513
+ starts, sizes = self.index_stream.allocator.get_allocated_regions()
514
+ primcount = len(starts)
515
+ if primcount == 0:
516
+ pass
517
+ elif primcount == 1:
518
+ # Common case
519
+ self._gl.drawElements(mode, sizes[0], self.index_stream.gl_type, starts[0] * self.index_stream.index_element_size)
520
+ else:
521
+ if self._multi_draw_elements:
522
+ starts = [s * self.index_stream.index_element_size for s in starts]
523
+ starts = (ctypes.POINTER(GLvoid) * primcount)(*(GLintptr * primcount)(*starts))
524
+ sizes = (GLsizei * primcount)(*sizes)
525
+ self._multi_draw_elements(mode, sizes[:], 0, self.index_stream.gl_type, starts[:], 0, primcount)
526
+ else:
527
+ for start, size in zip(starts, sizes):
528
+ self._gl.drawElements(mode, size, self.index_stream.gl_type,
529
+ start * self.index_stream.index_element_size)
530
+
531
+ def draw_subset(self, mode: GeometryMode, vertex_list: IndexedVertexList) -> None:
532
+ """Draw a specific IndexedVertexList in the domain.
533
+
534
+ The `vertex_list` parameter specifies a :py:class:`IndexedVertexList`
535
+ to draw. Only primitives in that list will be drawn.
536
+
537
+ Args:
538
+ mode:
539
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
540
+ vertex_list:
541
+ Vertex list to draw.
542
+ """
543
+ self.vao.bind()
544
+ self.vertex_buffers.commit()
545
+ self.index_stream.buffer.commit()
546
+
547
+ self._gl.drawElements(geometry_map[mode], vertex_list.index_count, self.index_stream.gl_type,
548
+ vertex_list.index_start * self.index_stream.index_element_size)
549
+
550
+
551
+ class InstancedIndexedVertexDomain(InstancedIndexedVertexDomainBase):
552
+ """Management of a set of indexed vertex lists.
553
+
554
+ Construction of an indexed vertex domain is usually done with the
555
+ :py:func:`create_domain` function.
556
+ """
557
+ _initial_index_count: int = 16
558
+ _vertex_class = InstanceIndexedVertexList
559
+
560
+ def _create_vertex_class(self) -> type:
561
+ return type(self._vertex_class.__name__, (_RunningIndexSupport, self._vertex_class),
562
+ self.vertex_buffers._property_dict) # noqa: SLF001
563
+
564
+ def _create_vao(self) -> GLVertexArrayBinding:
565
+ return GLVertexArrayBinding(self._context, self._streams)
566
+
567
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
568
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
569
+ self.index_stream = GLIndexStream(self._context, self.index_type, size)
570
+ return [self.vertex_buffers, self.index_stream]
571
+
572
+ def create_instance_domain(self, size: int) -> GLInstanceDomainElements:
573
+ return GLInstanceDomainElements(self, size, index_stream=self.index_stream)
574
+
575
+ def _has_multi_draw_extension(self, ctx):
576
+ return False
577
+
578
+ def _create_vao(self) -> None:
579
+ """Handled by buckets."""
580
+
581
+ def draw(self, mode: int) -> None:
582
+ """Draw all vertices in the domain.
583
+
584
+ All vertices in the domain are drawn at once. This is the
585
+ most efficient way to render primitives.
586
+
587
+ Args:
588
+ mode:
589
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
590
+
591
+ """
592
+ self.vertex_buffers.commit()
593
+ self.index_stream.commit()
594
+ self.instance_domain.draw(mode)
595
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
596
+ """Draw a specific VertexGroupBucket in the domain."""
597
+ for bucket in buckets:
598
+ for vl_range in bucket.ranges:
599
+ self.instance_domain.draw_bucket(mode, self._instance_map[vl_range])
600
+
601
+ def draw_subset(self, mode: GeometryMode, vertex_list: InstanceIndexedVertexListBase) -> None:
602
+ """Draw a specific IndexedVertexList in the domain.
603
+
604
+ The ``vertex_list`` parameter specifies a :py:class:`IndexedVertexList`
605
+ to draw. Only primitives in that list will be drawn.
606
+
607
+ Args:
608
+ mode:
609
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
610
+ vertex_list:
611
+ Vertex list to draw.
612
+
613
+ """
614
+ self.vertex_buffers.commit()
615
+ self.index_stream.commit()
616
+ self.instance_domain.draw_subset(geometry_map[mode], vertex_list)