pyglet 2.1.12__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 +4 -17
  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 +27 -5
  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 +147 -177
  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.12.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.12.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.12.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.12.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
@@ -0,0 +1,364 @@
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 ctypes import Array
29
+
30
+ from pyglet.graphics.api.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
+ GL_ARRAY_BUFFER, OpenGLSurfaceContext,
44
+
45
+ )
46
+ from pyglet.graphics.api.gl.enums import geometry_map
47
+ from pyglet.graphics.api.gl.shader import GLAttribute
48
+ from pyglet.graphics.api.gl2.buffer import AttributeBufferObject, IndexedBufferObject
49
+ from pyglet.graphics.vertexdomain import (
50
+ VertexStream,
51
+ IndexStream,
52
+ VertexArrayBinding,
53
+ VertexArrayProtocol,
54
+ VertexDomainBase,
55
+ VertexListBase,
56
+ IndexedVertexDomainBase,
57
+ IndexedVertexListBase,
58
+ VertexGroupBucket,
59
+ _RunningIndexSupport,
60
+ )
61
+
62
+ if TYPE_CHECKING:
63
+ from pyglet.graphics.shader import AttributeView
64
+ from pyglet.customtypes import CType, DataTypes
65
+ from pyglet.graphics import GeometryMode
66
+ from pyglet.graphics.shader import Attribute
67
+
68
+ _c_types = {
69
+ GL_BYTE: ctypes.c_byte,
70
+ GL_UNSIGNED_BYTE: ctypes.c_ubyte,
71
+ GL_SHORT: ctypes.c_short,
72
+ GL_UNSIGNED_SHORT: ctypes.c_ushort,
73
+ GL_INT: ctypes.c_int,
74
+ GL_UNSIGNED_INT: ctypes.c_uint,
75
+ GL_FLOAT: ctypes.c_float,
76
+ GL_DOUBLE: ctypes.c_double,
77
+ }
78
+
79
+ _gl_types = {
80
+ 'b': GL_BYTE,
81
+ 'B': GL_UNSIGNED_BYTE,
82
+ 'h': GL_SHORT,
83
+ 'H': GL_UNSIGNED_SHORT,
84
+ 'i': GL_INT,
85
+ 'I': GL_UNSIGNED_INT,
86
+ 'f': GL_FLOAT,
87
+ 'd': GL_DOUBLE,
88
+ }
89
+
90
+
91
+ def _make_attribute_property(name: str) -> property:
92
+ def _attribute_getter(self: VertexList) -> Array[float | int]:
93
+ buffer = self.domain.attrib_name_buffers[name]
94
+ region = buffer.get_region(self.start, self.count)
95
+ buffer.invalidate_region(self.start, self.count)
96
+ return region
97
+
98
+ def _attribute_setter(self: VertexList, data: Any) -> None:
99
+ buffer = self.domain.attrib_name_buffers[name]
100
+ buffer.set_region(self.start, self.count, data)
101
+
102
+ return property(_attribute_getter, _attribute_setter)
103
+
104
+
105
+ class GLVertexArrayBinding(VertexArrayBinding):
106
+ streams: list[GLVertexStream | GLIndexStream]
107
+
108
+ """GL2 doesn't have a real VAO. This just acts as a container."""
109
+ def _create_vao(self) -> VertexArrayProtocol | None:
110
+ return None
111
+
112
+ def _link(self) -> None:
113
+ pass
114
+
115
+ def bind(self) -> None:
116
+ for stream in self.streams:
117
+ stream.bind_into(self.vao)
118
+
119
+ def unbind(self) -> None:
120
+ for stream in self.streams:
121
+ stream.unbind()
122
+
123
+
124
+ class InstancedVertexDomain:
125
+ """Not available in OpenGL 2.0"""
126
+ def __init__(self, *args, **kwargs):
127
+ raise NotImplementedError("InstancedVertexDomain is not available in OpenGL 2.0.")
128
+
129
+
130
+ class InstancedIndexedVertexDomain:
131
+ """Not available in OpenGL 2.0"""
132
+ def __init__(self, *args, **kwargs):
133
+ raise NotImplementedError("InstancedIndexedVertexDomain is not available in OpenGL 2.0.")
134
+
135
+
136
+ class VertexList(VertexListBase):
137
+ ...
138
+
139
+
140
+ class IndexedVertexList(IndexedVertexListBase):
141
+ ...
142
+
143
+
144
+ class GLVertexStream(VertexStream):
145
+ _ctx: OpenGLSurfaceContext
146
+
147
+ def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute], *, divisor: int = 0):
148
+ super().__init__(ctx, initial_size, attrs, divisor=divisor)
149
+
150
+ def get_graphics_attribute(self, attribute: Attribute, view: AttributeView) -> GLAttribute:
151
+ return GLAttribute(attribute, view)
152
+
153
+ def get_buffer(self, size: int, attribute) -> AttributeBufferObject:
154
+ # TODO: use persistent buffer if we have GL support for it:
155
+ # attribute.buffer = PersistentBufferObject(attribute.stride * self.allocator.capacity, attribute, self.vao)
156
+ return AttributeBufferObject(self._ctx, size, attribute)
157
+
158
+ def bind_into(self, _vao: None) -> None:
159
+ for attribute, buffer in zip(self.attribute_names.values(), self.buffers):
160
+ buffer.commit()
161
+ attribute.enable()
162
+ attribute.set_pointer()
163
+
164
+ def unbind(self) -> None:
165
+ for attribute in self.attribute_names.values():
166
+ attribute.disable()
167
+
168
+
169
+ class GLIndexStream(IndexStream):
170
+ index_element_size: int
171
+ index_c_type: CType
172
+ gl_type: int
173
+
174
+ def __init__(self, ctx: OpenGLSurfaceContext, data_type: DataTypes, initial_elems: int) -> None:
175
+ self.gl_type = _gl_types[data_type]
176
+ self.index_c_type = _c_types[self.gl_type]
177
+ self.index_element_size = ctypes.sizeof(self.index_c_type)
178
+ super().__init__(ctx, data_type, initial_elems)
179
+
180
+ def _create_buffer(self) -> IndexedBufferObject:
181
+ return IndexedBufferObject(self.ctx, self.allocator.capacity * self.index_element_size,
182
+ self.index_c_type,
183
+ self.index_element_size,
184
+ 1)
185
+
186
+ def bind_into(self, vao: VertexArrayBinding) -> None:
187
+ #self.buffer.bind_to_index_buffer()
188
+ pass
189
+
190
+ def unbind(self):
191
+ self.buffer.unbind()
192
+
193
+
194
+ class VertexDomain(VertexDomainBase):
195
+ """Management of a set of vertex lists.
196
+
197
+ Construction of a vertex domain is usually done with the
198
+ :py:func:`create_domain` function.
199
+ """
200
+ def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
201
+ return ctx.get_info().have_extension("GL_EXT_multi_draw_arrays")
202
+
203
+ def _create_vertex_class(self) -> type:
204
+ return type(self._vertex_class.__name__, (self._vertex_class,), self.vertex_buffers._property_dict)
205
+
206
+ def _create_vao(self) -> GLVertexArrayBinding:
207
+ return GLVertexArrayBinding(self._context, self._streams)
208
+
209
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream]:
210
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
211
+ return [self.vertex_buffers]
212
+
213
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
214
+ regions = []
215
+ for bucket in buckets:
216
+ regions.extend(bucket.merged_ranges)
217
+
218
+ start_list = [region[0] for region in regions]
219
+ size_list = [region[1] for region in regions]
220
+
221
+ if self._supports_multi_draw:
222
+ primcount = len(regions)
223
+ starts = (GLint * primcount)(*start_list)
224
+ sizes = (GLsizei * primcount)(*size_list)
225
+ self._context.glMultiDrawArrays(mode, starts, sizes, primcount)
226
+ else:
227
+ for start, size in zip(start_list, size_list):
228
+ self._context.glDrawArrays(mode, start, size)
229
+
230
+ def draw(self, mode: int) -> None:
231
+ """Draw all vertices in the domain.
232
+
233
+ All vertices in the domain are drawn at once. This is the
234
+ most efficient way to render primitives.
235
+
236
+ Args:
237
+ mode:
238
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
239
+
240
+ """
241
+ self.vao.bind()
242
+ self.vertex_buffers.commit()
243
+
244
+ starts, sizes = self.vertex_buffers.allocator.get_allocated_regions()
245
+ primcount = len(starts)
246
+ if primcount == 0:
247
+ pass
248
+ elif primcount == 1:
249
+ # Common case
250
+ self._context.glDrawArrays(mode, starts[0], sizes[0])
251
+ else:
252
+ starts = (GLint * primcount)(*starts)
253
+ sizes = (GLsizei * primcount)(*sizes)
254
+ self._context.glMultiDrawArrays(mode, starts, sizes, primcount)
255
+
256
+ for _, attribute in self.vertex_buffers.attribute_names.items():
257
+ attribute.disable()
258
+
259
+ def draw_subset(self, mode: GeometryMode, vertex_list: VertexList) -> None:
260
+ """Draw a specific VertexList in the domain.
261
+
262
+ The `vertex_list` parameter specifies a :py:class:`VertexList`
263
+ to draw. Only primitives in that list will be drawn.
264
+
265
+ Args:
266
+ mode:
267
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
268
+ vertex_list:
269
+ Vertex list to draw.
270
+
271
+ """
272
+ for buffer, attribute in self.buffer_attributes:
273
+ buffer.commit()
274
+ attribute.enable()
275
+ attribute.set_pointer(0)
276
+
277
+ self._context.glDrawArrays(geometry_map[mode], vertex_list.start, vertex_list.count)
278
+
279
+ for _, attribute in self.buffer_attributes:
280
+ attribute.disable()
281
+
282
+ @property
283
+ def is_empty(self) -> bool:
284
+ return not self.vertex_buffers.allocator.starts
285
+
286
+ def __repr__(self) -> str:
287
+ return f'<{self.__class__.__name__}@{id(self):x} {self.allocator}>'
288
+
289
+
290
+
291
+ class IndexedVertexDomain(IndexedVertexDomainBase):
292
+ """Management of a set of indexed vertex lists.
293
+
294
+ Construction of an indexed vertex domain is usually done with the
295
+ :py:func:`create_domain` function.
296
+ """
297
+
298
+ _vertex_class = IndexedVertexList
299
+ index_stream: GLIndexStream
300
+
301
+ def _create_vertex_class(self) -> type:
302
+ # Make a custom VertexList class w/ properties for each attribute in the ShaderProgram:
303
+ return type(self._vertex_class.__name__, (_RunningIndexSupport, self._vertex_class),
304
+ self.vertex_buffers._property_dict) # noqa: SLF001
305
+
306
+ def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
307
+ return ctx.get_info().have_extension("GL_EXT_multi_draw_arrays")
308
+
309
+ def _create_vao(self) -> GLVertexArrayBinding:
310
+ return GLVertexArrayBinding(self._context, self._streams)
311
+
312
+ def _create_streams(self, size: int) -> list[VertexStream | IndexStream]:
313
+ self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
314
+ self.index_stream = GLIndexStream(self._context, self.index_type, size)
315
+ return [self.vertex_buffers, self.index_stream]
316
+
317
+ def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
318
+ self.vao.bind()
319
+ regions = []
320
+ for bucket in buckets:
321
+ regions.extend(bucket.merged_ranges)
322
+
323
+ start_list = [region[0] for region in regions]
324
+ size_list = [region[1] for region in regions]
325
+ primcount = len(regions)
326
+
327
+ if self._supports_multi_draw:
328
+ starts = [s * self.index_stream.index_element_size for s in start_list]
329
+ starts = (ctypes.POINTER(GLvoid) * primcount)(*(GLintptr * primcount)(*starts))
330
+ sizes = (GLsizei * primcount)(*size_list)
331
+ self._context.glMultiDrawElements(mode, sizes, self.index_stream.gl_type, starts, primcount)
332
+ else:
333
+ for start, size in zip(start_list, size_list):
334
+ self._context.glDrawElements(
335
+ mode, size, self.index_stream.gl_type, start * self.index_stream.index_element_size)
336
+
337
+ self.vao.unbind()
338
+
339
+ def draw_subset(self, mode: GeometryMode, vertex_list: IndexedVertexList) -> None:
340
+ """Draw a specific IndexedVertexList in the domain.
341
+
342
+ The `vertex_list` parameter specifies a :py:class:`IndexedVertexList`
343
+ to draw. Only primitives in that list will be drawn.
344
+
345
+ Args:
346
+ mode:
347
+ OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
348
+ vertex_list:
349
+ Vertex list to draw.
350
+ """
351
+ for buffer, attribute in self.buffer_attributes:
352
+ buffer.commit()
353
+ attribute.enable()
354
+ attribute.set_pointer(0)
355
+
356
+ self.index_buffer.commit()
357
+
358
+ self._context.glDrawElements(geometry_map[mode], vertex_list.index_count, self.index_gl_type,
359
+ vertex_list.index_start * self.index_element_size)
360
+
361
+ for _, attribute in self.buffer_attributes:
362
+ attribute.disable()
363
+
364
+ self._context.glBindBuffer(GL_ARRAY_BUFFER, 0)
@@ -0,0 +1,233 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import warnings
5
+ from typing import TYPE_CHECKING, Sequence
6
+
7
+ import js
8
+
9
+ import pyglet
10
+ from pyglet.graphics.api.webgl.context import OpenGLSurfaceContext
11
+ from pyglet.graphics.api.base import BackendGlobalObject, SurfaceContext, UBOMatrixTransformations
12
+ from pyglet.graphics.api.webgl.shader import Shader, ShaderProgram
13
+ from pyglet.math import Mat4
14
+
15
+ if TYPE_CHECKING:
16
+
17
+ from pyglet.config import SurfaceConfig
18
+ from pyglet.graphics.shader import ShaderType
19
+ from pyglet.window import Window
20
+
21
+ _is_pyglet_doc_run = hasattr(sys, "is_pyglet_doc_run") and sys.is_pyglet_doc_run
22
+
23
+
24
+ class OpenGL3_Matrices(UBOMatrixTransformations):
25
+ # Create a default ShaderProgram, so the Window instance can
26
+ # update the `WindowBlock` UBO shared by all default shaders.
27
+ _default_vertex_source = """#version 300 es
28
+ in vec4 position;
29
+
30
+ uniform WindowBlock
31
+ {
32
+ mat4 projection;
33
+ mat4 view;
34
+ } window;
35
+
36
+ void main()
37
+ {
38
+ gl_Position = window.projection * window.view * position;
39
+ }
40
+ """
41
+ _default_fragment_source = """#version 300 es
42
+ out vec4 color;
43
+
44
+ void main()
45
+ {
46
+ color = vec4(1.0, 0.0, 0.0, 1.0);
47
+ }
48
+ """
49
+
50
+ def __init__(self, window: Window, backend: WebGLBackend):
51
+ self._default_program = backend.create_shader_program(
52
+ backend.create_shader(self._default_vertex_source, 'vertex'),
53
+ backend.create_shader(self._default_fragment_source, 'fragment'),
54
+ )
55
+
56
+ window_block = self._default_program.uniform_blocks['WindowBlock']
57
+ self.ubo = window_block.create_ubo()
58
+ window_block.bind(self.ubo)
59
+
60
+ self._viewport = (0, 0, *window.get_framebuffer_size())
61
+
62
+ width, height = window.get_size()
63
+
64
+ super().__init__(window, Mat4.orthogonal_projection(0, width, 0, height, -255, 255), Mat4(), Mat4())
65
+
66
+ with self.ubo as window_block:
67
+ window_block.view[:] = self._view
68
+ window_block.projection[:] = self._projection
69
+
70
+ @property
71
+ def projection(self) -> Mat4:
72
+ return self._projection
73
+
74
+ @projection.setter
75
+ def projection(self, projection: Mat4):
76
+ with self.ubo as window_block:
77
+ window_block.projection[:] = projection
78
+
79
+ self._projection = projection
80
+
81
+ @property
82
+ def view(self) -> Mat4:
83
+ return self._view
84
+
85
+ @view.setter
86
+ def view(self, view: Mat4):
87
+ with self.ubo as window_block:
88
+ window_block.view[:] = view
89
+
90
+ self._view = view
91
+
92
+ @property
93
+ def model(self) -> Mat4:
94
+ return self._model
95
+
96
+ @model.setter
97
+ def model(self, model: Mat4):
98
+ with self.ubo as window_block:
99
+ window_block.model[:] = model
100
+
101
+ self._model = model
102
+
103
+
104
+ class ObjectSpace:
105
+ """A container to store shared objects that are to be removed."""
106
+
107
+ def __init__(self) -> None:
108
+ """Initialize the context object space."""
109
+ # Objects scheduled for deletion the next time this object space is active.
110
+ self.doomed_textures = []
111
+ self.doomed_buffers = []
112
+ self.doomed_shader_programs = []
113
+ self.doomed_shaders = []
114
+ self.doomed_renderbuffers = []
115
+
116
+
117
+ class WebGLBackend(BackendGlobalObject):
118
+ current_context: OpenGLSurfaceContext | None
119
+ _have_context: bool = False
120
+
121
+ def __init__(self) -> None:
122
+ self.initialized = False
123
+ self.current_context = None
124
+
125
+ # When the shadow window is created, a context is made. This is used to help the "real" context to utilize
126
+ # its full capabilities; however, the two contexts have no relationship normally. This is used for the purpose
127
+ # of sharing basic information between contexts. However, in usage, the user or internals should use the
128
+ # "real" context's information to prevent any discrepencies.
129
+ # self.gl_info = GLInfo() # GL Info is a shared info space.
130
+ super().__init__()
131
+
132
+ @property
133
+ def object_space(self) -> ObjectSpace:
134
+ assert self.current_context is not None, "Context has not been created."
135
+ return self.current_context.object_space
136
+
137
+ def create_context(self, config: SurfaceConfig, shared: OpenGLSurfaceContext | None) -> OpenGLSurfaceContext:
138
+ return OpenGLSurfaceContext(self, config._window, config, shared)
139
+
140
+ def get_surface_context(self, window: Window, config: SurfaceConfig) -> SurfaceContext:
141
+ context = self.windows[window] = self.create_context(config, self.current_context)
142
+ self.current_context = context
143
+ self._have_context = True
144
+ return context
145
+
146
+ # def get_window_backend_context(self, window: Window, config: OpenGLWindowConfig) -> SurfaceContext:
147
+ # """We will always only have one context in this Backend."""
148
+ # assert self.current_context is None
149
+ # context = self.windows[window] = self.create_context(config, self.current_context)
150
+ # self.current_context = context
151
+ # self._have_context = True
152
+ # return context
153
+
154
+ def get_default_configs(self) -> Sequence[pyglet.config.OpenGLConfig]:
155
+ """A sequence of configs to use if the user does not specify any.
156
+
157
+ These will be used during Window creation.
158
+ """
159
+ return [
160
+ pyglet.config.OpenGLConfig(double_buffer=True, depth_size=24, major_version=3, minor_version=3),
161
+ pyglet.config.OpenGLConfig(double_buffer=True, depth_size=16, major_version=3, minor_version=3),
162
+ ]
163
+
164
+ def get_config(self, **kwargs: float | str | None) -> pyglet.config.OpenGLConfig:
165
+ return pyglet.config.OpenGLConfig(**kwargs)
166
+
167
+ def get_info(self):
168
+ return self.current_context.get_info()
169
+
170
+ def have_extension(self, extension_name: str) -> bool:
171
+ if not self.current_context:
172
+ warnings.warn('No GL context created yet or current context not set.')
173
+ return False
174
+
175
+ return self.current_context.get_info().have_extension(extension_name)
176
+
177
+ def have_version(self, major: int, minor: int = 0) -> bool:
178
+ if not self.current_context:
179
+ warnings.warn('No GL context created yet or current context not set.')
180
+ return False
181
+
182
+ return self.current_context.get_info().have_version(major, minor)
183
+
184
+ def get_cached_shader(self, name: str, *sources: tuple[str, ShaderType]) -> ShaderProgram:
185
+ """Create a ShaderProgram from OpenGL GLSL source.
186
+
187
+ This is a convenience method that takes one or more tuples of
188
+ (source_string, shader_type), and returns a
189
+ :py:class:`~pyglet.graphics.shader.ShaderProgram` instance.
190
+
191
+ ``source_string`` is OpenGL GLSL source code as a str, and ``shader_type``
192
+ is the OpenGL shader type, such as "vertex" or "fragment". See
193
+ :py:class:`~pyglet.graphics.shader.Shader` for more information.
194
+
195
+ .. note:: This method is cached. Given the same shader sources, the
196
+ same ShaderProgram instance will be returned. For more
197
+ control over the ShaderProgram lifecycle, it is recommended
198
+ to manually create Shaders and link ShaderPrograms.
199
+
200
+ .. versionadded:: 2.0.10
201
+ """
202
+ assert self.current_context
203
+ assert isinstance(name, str), "First argument must be a string name for the shader."
204
+ if program := self.current_context.cached_programs.get(name):
205
+ return program
206
+
207
+ shaders = (Shader(src, srctype) for (src, srctype) in sources)
208
+ program = ShaderProgram(*shaders)
209
+ self.current_context.cached_programs[name] = program
210
+ return program
211
+
212
+ def create_shader_program(self, *shaders: Shader) -> ShaderProgram:
213
+ return ShaderProgram(*shaders)
214
+
215
+ def create_shader(self, source_string: str, shader_type: ShaderType) -> Shader:
216
+ return Shader(source_string, shader_type)
217
+
218
+ def get_default_batch(self) -> pyglet.graphics.Batch:
219
+ assert self.current_context
220
+ if not hasattr(self.current_context, "default_batch"):
221
+ self.current_context.default_batch = pyglet.graphics.Batch()
222
+
223
+ return self.current_context.default_batch
224
+
225
+ @property
226
+ def have_context(self) -> bool:
227
+ return self._have_context
228
+
229
+ def initialize_matrices(self, window):
230
+ return OpenGL3_Matrices(window, self)
231
+
232
+ def set_viewport(self, window, x: int, y: int, width: int, height: int) -> None:
233
+ self.current_context.gl.viewport(x, y, width, height)