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,320 @@
1
+ """Byte abstractions of OpenGL Buffer Objects.
2
+
3
+ Use `create_buffer` to create a Buffer Object.
4
+
5
+ Buffers can optionally be created "mappable" (incorporating the
6
+ `AbstractMappable` mix-in). In this case the buffer provides a ``get_region``
7
+ method which provides the most efficient path for updating partial data within
8
+ the buffer.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import ctypes
13
+ import sys
14
+ from functools import lru_cache
15
+ from typing import TYPE_CHECKING, Sequence
16
+
17
+ from ctypes import Array
18
+
19
+ from pyglet.graphics.api.gl import (
20
+ GL_ARRAY_BUFFER,
21
+ GL_DYNAMIC_DRAW,
22
+ GL_ELEMENT_ARRAY_BUFFER,
23
+ GL_MAP_READ_BIT,
24
+ GL_MAP_WRITE_BIT,
25
+ GL_WRITE_ONLY,
26
+ GLubyte,
27
+ GLuint,
28
+ glBindBuffer,
29
+ glBufferData,
30
+ glBufferSubData,
31
+ glDeleteBuffers,
32
+ glGenBuffers,
33
+ glMapBuffer,
34
+ glMapBufferRange,
35
+ glUnmapBuffer, OpenGLSurfaceContext,
36
+ )
37
+ from pyglet.graphics.buffer import AbstractBuffer
38
+
39
+ if TYPE_CHECKING:
40
+ from pyglet.customtypes import CType, CTypesPointer
41
+ from pyglet.graphics.shader import GraphicsAttribute
42
+
43
+
44
+ class BufferObject(AbstractBuffer):
45
+ """Lightweight representation of an OpenGL Buffer Object.
46
+
47
+ The data in the buffer is not replicated in any system memory (unless it
48
+ is done so by the video driver). While this can improve memory usage and
49
+ possibly performance, updates to the buffer are relatively slow.
50
+ The target of the buffer is ``GL_ARRAY_BUFFER`` internally to avoid
51
+ accidentally overriding other states when altering the buffer contents.
52
+ The intended target can be set when binding the buffer.
53
+ """
54
+
55
+ id: int
56
+ size: int
57
+ usage: int
58
+ _context: OpenGLSurfaceContext | None
59
+
60
+ def __init__(self, context: OpenGLSurfaceContext, size: int, usage: int = GL_DYNAMIC_DRAW) -> None:
61
+ """Initialize the BufferObject with the given size and draw usage."""
62
+ super().__init__('b', size)
63
+ self.usage = usage
64
+ self._context = context
65
+
66
+ buffer_id = GLuint()
67
+ glGenBuffers(1, buffer_id)
68
+ self.id = buffer_id.value
69
+
70
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
71
+ data = (GLubyte * self.size)()
72
+ glBufferData(GL_ARRAY_BUFFER, self.size, data, self.usage)
73
+
74
+ def invalidate(self) -> None:
75
+ glBufferData(GL_ARRAY_BUFFER, self.size, None, self.usage)
76
+
77
+ def bind(self, target: int = GL_ARRAY_BUFFER) -> None:
78
+ glBindBuffer(target, self.id)
79
+
80
+ def unbind(self) -> None:
81
+ glBindBuffer(GL_ARRAY_BUFFER, 0)
82
+
83
+ def bind_to_index_buffer(self) -> None:
84
+ """Binds this buffer as an index buffer on the active vertex array."""
85
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
86
+
87
+ def set_data(self, data: Sequence[int] | CTypesPointer) -> None:
88
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
89
+ glBufferData(GL_ARRAY_BUFFER, self.size, data, self.usage)
90
+
91
+ def set_data_region(self, data: Sequence[int] | CTypesPointer, start: int, length: int) -> None:
92
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
93
+ glBufferSubData(GL_ARRAY_BUFFER, start, length, data)
94
+
95
+ def map(self) -> CTypesPointer[ctypes.c_byte]:
96
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
97
+ return ctypes.cast(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY),
98
+ ctypes.POINTER(ctypes.c_byte * self.size)).contents
99
+
100
+ def map_range(self, start: int, size: int, ptr_type: type[CTypesPointer]) -> CTypesPointer:
101
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
102
+ return ctypes.cast(glMapBufferRange(GL_ARRAY_BUFFER, start, size, GL_MAP_WRITE_BIT), ptr_type).contents
103
+
104
+ def unmap(self) -> None:
105
+ glUnmapBuffer(GL_ARRAY_BUFFER)
106
+
107
+ def delete(self) -> None:
108
+ glDeleteBuffers(1, GLuint(self.id))
109
+ self.id = None
110
+
111
+ def __del__(self) -> None:
112
+ if self.id is not None:
113
+ try:
114
+ self._context.delete_buffer(self.id)
115
+ self.id = None
116
+ except (AttributeError, ImportError):
117
+ pass # Interpreter is shutting down
118
+
119
+ def resize(self, size: int) -> None:
120
+ # Map, create a copy, then reinitialize.
121
+ temp = (ctypes.c_byte * size)()
122
+
123
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
124
+ data = glMapBufferRange(GL_ARRAY_BUFFER, 0, self.size, GL_MAP_READ_BIT)
125
+ ctypes.memmove(temp, data, min(size, self.size))
126
+ glUnmapBuffer(GL_ARRAY_BUFFER)
127
+
128
+ self.size = size
129
+ glBufferData(GL_ARRAY_BUFFER, self.size, temp, self.usage)
130
+
131
+ def get_bytes(self) -> bytes:
132
+ ...
133
+
134
+ def get_bytes_region(self, offset: int, length: int) -> bytes:
135
+ ...
136
+
137
+ def get_data(self) -> ctypes.Array[CType]:
138
+ ...
139
+
140
+ def get_data_region(self, start: int, length: int) -> ctypes.Array[CType]:
141
+ ...
142
+
143
+ def set_bytes(self, data: bytes) -> None:
144
+ ...
145
+
146
+ def set_bytes_region(self, start: int, length: int) -> None:
147
+ ...
148
+
149
+ def set_data_ptr(self, offset: int, length: int, ptr: CTypesPointer) -> None:
150
+ ...
151
+
152
+ def __repr__(self) -> str:
153
+ return f"{self.__class__.__name__}(id={self.id}, size={self.size})"
154
+
155
+
156
+ class BackedBufferObject(BufferObject):
157
+ """A buffer with system-memory backed store.
158
+
159
+ Updates to the data via `set_data` and `set_data_region` will be held
160
+ in local memory until `buffer_data` is called. The advantage is that
161
+ fewer OpenGL calls are needed, which can increasing performance at the
162
+ expense of system memory.
163
+ """
164
+ data: CType
165
+ data_ptr: int
166
+ _dirty_min: int
167
+ _dirty_max: int
168
+ _dirty: bool
169
+ stride: int
170
+ element_count: int
171
+ ctype: CType
172
+
173
+ def __init__(self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
174
+ usage: int = GL_DYNAMIC_DRAW) -> None:
175
+ super().__init__(context, size, usage)
176
+
177
+ self.c_type = c_type
178
+ self._ctypes_size = ctypes.sizeof(c_type)
179
+ number = size // self._ctypes_size
180
+ self.data = (c_type * number)()
181
+ self.data_ptr = ctypes.addressof(self.data)
182
+
183
+ self._dirty_min = sys.maxsize
184
+ self._dirty_max = 0
185
+ self._dirty = False
186
+
187
+ self.stride = stride
188
+ self.element_count = element_count
189
+
190
+ def commit(self) -> None:
191
+ """Commits all saved changes to the underlying buffer before drawing.
192
+
193
+ Allows submitting multiple changes at once, rather than having to call glBufferSubData for every change.
194
+ """
195
+ # GL 2.0 we will need to bind it each draw cycle.
196
+ glBindBuffer(GL_ARRAY_BUFFER, self.id)
197
+
198
+ if not self._dirty:
199
+ return
200
+
201
+ size = self._dirty_max - self._dirty_min
202
+ if size > 0:
203
+ if size == self.size:
204
+ glBufferData(GL_ARRAY_BUFFER, self.size, self.data, self.usage)
205
+ else:
206
+ glBufferSubData(GL_ARRAY_BUFFER, self._dirty_min, size, self.data_ptr + self._dirty_min)
207
+
208
+ self._dirty_min = sys.maxsize
209
+ self._dirty_max = 0
210
+ self._dirty = False
211
+
212
+ @lru_cache(maxsize=None) # noqa: B019
213
+ def get_region(self, start: int, count: int) -> Array[CType]:
214
+ byte_start = self.stride * start # byte offset
215
+ array_count = self.element_count * count # number of values
216
+ ptr_type = ctypes.POINTER(self.c_type * array_count)
217
+ return ctypes.cast(self.data_ptr + byte_start, ptr_type).contents
218
+
219
+ def set_region(self, start: int, count: int, data: Sequence[float]) -> None:
220
+ array_start = self.element_count * start
221
+ array_end = self.element_count * count + array_start
222
+
223
+ self.data[array_start:array_end] = data
224
+
225
+ # replicated from self.invalidate_region
226
+ byte_start = self.stride * start
227
+ byte_end = byte_start + self.stride * count
228
+ # As of Python 3.11, this is faster than min/max:
229
+ if byte_start < self._dirty_min:
230
+ self._dirty_min = byte_start
231
+ if byte_end > self._dirty_max:
232
+ self._dirty_max = byte_end
233
+ self._dirty = True
234
+
235
+ def resize(self, size: int) -> None:
236
+ # size is the allocator size * attribute.stride
237
+ number = size // ctypes.sizeof(self.c_type)
238
+ data = (self.c_type * number)()
239
+ ctypes.memmove(data, self.data, min(size, self.size))
240
+ self.data = data
241
+ self.data_ptr = ctypes.addressof(data)
242
+ self.size = size
243
+
244
+ # Set the dirty range to be the entire buffer.
245
+ self._dirty_min = 0
246
+ self._dirty_max = self.size
247
+ self._dirty = True
248
+
249
+ self.get_region.cache_clear()
250
+
251
+ def invalidate(self) -> None:
252
+ super().invalidate()
253
+ self._dirty = True
254
+
255
+ def invalidate_region(self, start: int, count: int) -> None:
256
+ byte_start = self.stride * start
257
+ byte_end = byte_start + self.stride * count
258
+ # As of Python 3.11, this is faster than min/max:
259
+ if byte_start < self._dirty_min:
260
+ self._dirty_min = byte_start
261
+ if byte_end > self._dirty_max:
262
+ self._dirty_max = byte_end
263
+ self._dirty = True
264
+
265
+
266
+ class AttributeBufferObject(BackedBufferObject):
267
+ """A backed buffer used for Shader Program attributes."""
268
+
269
+ def __init__(self, context: OpenGLSurfaceContext, size: int, graphics_attr: GraphicsAttribute) -> None:
270
+ # size is the allocator size * attribute.stride (buffer size)
271
+ super().__init__(context, size, graphics_attr.attribute.c_type,
272
+ graphics_attr.view.stride,
273
+ graphics_attr.attribute.fmt.components)
274
+
275
+
276
+ class IndexedBufferObject(BackedBufferObject):
277
+ """A backed buffer used for indices."""
278
+
279
+ def __init__(self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
280
+ usage: int = GL_DYNAMIC_DRAW) -> None:
281
+ super().__init__(context, size, c_type, stride, element_count, usage)
282
+
283
+ # def bind_to_index_buffer(self) -> None:
284
+ # """Binds this buffer as an index buffer on the active vertex array."""
285
+ # self._context.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
286
+
287
+ def commit(self) -> None:
288
+ """Commits all saved changes to the underlying buffer before drawing.
289
+
290
+ Allows submitting multiple changes at once, rather than having to call glBufferSubData for every change.
291
+ """
292
+ # GL 2.0 we will need to bind it each draw cycle.
293
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
294
+
295
+ if not self._dirty:
296
+ return
297
+
298
+ size = self._dirty_max - self._dirty_min
299
+ if size > 0:
300
+ if size == self.size:
301
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.size, self.data, self.usage)
302
+ else:
303
+ glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, self._dirty_min, size, self.data_ptr + self._dirty_min)
304
+
305
+ self._dirty_min = sys.maxsize
306
+ self._dirty_max = 0
307
+ self._dirty = False
308
+
309
+ class PersistentBufferObject(AbstractBuffer):
310
+ """A persistently mapped buffer.
311
+
312
+ Available in OpenGL 4.3+ contexts. Persistently mapped buffers
313
+ are mapped one time on creation, and can be updated at any time
314
+ without the need to map or unmap.
315
+
316
+ Unsupported by GL2.
317
+ """
318
+
319
+ def __init__(self, context, size, attribute, vao) -> None:
320
+ raise NotImplementedError