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,92 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pyglet.graphics.api.gl import OpenGLSurfaceContext
6
+ from pyglet.graphics.api.gl.base import ContextException
7
+ from pyglet.libs import egl
8
+
9
+ if TYPE_CHECKING:
10
+ from pyglet.config.gl.egl import EGLSurfaceConfig
11
+ from pyglet.graphics.api.gl.base import OpenGLBackend
12
+ from pyglet.window.wayland import WaylandWindow
13
+ from pyglet.window.headless import HeadlessWindow
14
+
15
+
16
+ class EGLContext(OpenGLSurfaceContext):
17
+ display_connection: egl.EGLDisplay
18
+ config: EGLSurfaceConfig
19
+
20
+ def __init__(self,
21
+ opengl_backend: OpenGLBackend,
22
+ window: HeadlessWindow | WaylandWindow,
23
+ config: EGLSurfaceConfig,
24
+ share: EGLContext | None) -> None:
25
+ super().__init__(opengl_backend, window, config=config, context_share=share)
26
+
27
+ self.display_connection = window.egl_display_connection # noqa: SLF001
28
+ self._extensions = []
29
+
30
+ self.egl_context = self._create_egl_context(share)
31
+ if not self.egl_context:
32
+ msg = 'Could not create GL context'
33
+ raise ContextException(msg)
34
+
35
+ def _create_egl_context(self, share: EGLContext | None) -> egl.EGLContext:
36
+ if share:
37
+ share_context = share.egl_context
38
+ else:
39
+ share_context = None
40
+
41
+ user_config = self.config.config
42
+
43
+ if user_config.opengl_api == "gl":
44
+ egl.eglBindAPI(egl.EGL_OPENGL_API)
45
+ elif user_config.opengl_api == "gles":
46
+ egl.eglBindAPI(egl.EGL_OPENGL_ES_API)
47
+ return egl.eglCreateContext(
48
+ self.window.egl_display_connection, # noqa: SLF001
49
+ self.config._egl_config,
50
+ share_context,
51
+ self.config._context_attrib_array,
52
+ )
53
+
54
+ def get_extensions(self) -> list[str]:
55
+ if not self._extensions:
56
+ self._extensions = egl.eglQueryString(self.window._egl_display_connection, egl.EGL_EXTENSIONS).decode().split()
57
+ return self._extensions
58
+
59
+ def attach(self, window: HeadlessWindow | WaylandWindow) -> None:
60
+ super().attach(window)
61
+
62
+ self.egl_surface = window.egl_surface # noqa: SLF001
63
+ self.set_current()
64
+
65
+ def set_current(self) -> None:
66
+ success = egl.eglMakeCurrent(self.display_connection, self.egl_surface, self.egl_surface, self.egl_context)
67
+ super().set_current()
68
+
69
+ def detach(self) -> None:
70
+ if not self.window:
71
+ return
72
+
73
+ self.set_current()
74
+ #gl.glFlush() # needs to be in try/except?
75
+
76
+ super().detach()
77
+
78
+ egl.eglMakeCurrent(self.display_connection, 0, 0, None)
79
+
80
+ self.egl_surface = None
81
+
82
+ def destroy(self) -> None:
83
+ super().destroy()
84
+ if self.egl_context:
85
+ egl.eglDestroyContext(self.display_connection, self.egl_context)
86
+ self.egl_context = None
87
+
88
+ def flip(self) -> None:
89
+ if not self.egl_surface:
90
+ return
91
+
92
+ egl.eglSwapBuffers(self.display_connection, self.egl_surface)
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ from pyglet.graphics import GeometryMode
4
+ from pyglet.graphics.api.gl import (
5
+ GL_LINEAR, GL_NEAREST, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D, \
6
+ GL_TEXTURE_CUBE_MAP, \
7
+ GL_TEXTURE_1D_ARRAY, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_TEXTURE_WRAP_S, \
8
+ GL_TEXTURE_WRAP_T,
9
+ GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP,
10
+ GL_TRIANGLE_FAN,
11
+ GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR,
12
+ GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, \
13
+ GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR,
14
+ GL_ONE_MINUS_CONSTANT_COLOR, \
15
+ GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_NEVER, GL_LESS, GL_EQUAL, GL_LEQUAL, GL_GREATER, GL_NOTEQUAL,
16
+ GL_GEQUAL, GL_ALWAYS)
17
+
18
+ from pyglet.enums import BlendFactor, TextureFilter, TextureType, TextureWrapping, CompareOp
19
+
20
+ geometry_map = {
21
+ GeometryMode.POINTS: GL_POINTS,
22
+ GeometryMode.LINES: GL_LINES,
23
+ GeometryMode.LINE_STRIP: GL_LINE_STRIP,
24
+ GeometryMode.TRIANGLES: GL_TRIANGLES,
25
+ GeometryMode.TRIANGLE_STRIP: GL_TRIANGLE_STRIP,
26
+ GeometryMode.TRIANGLE_FAN: GL_TRIANGLE_FAN,
27
+ }
28
+
29
+ blend_factor_map = {
30
+ BlendFactor.ZERO: GL_ZERO,
31
+ BlendFactor.ONE: GL_ONE,
32
+ BlendFactor.SRC_COLOR: GL_SRC_COLOR,
33
+ BlendFactor.ONE_MINUS_SRC_COLOR: GL_ONE_MINUS_SRC_COLOR,
34
+ BlendFactor.DST_COLOR: GL_DST_COLOR,
35
+ BlendFactor.ONE_MINUS_DST_COLOR: GL_ONE_MINUS_DST_COLOR,
36
+ BlendFactor.SRC_ALPHA: GL_SRC_ALPHA,
37
+ BlendFactor.ONE_MINUS_SRC_ALPHA: GL_ONE_MINUS_SRC_ALPHA,
38
+ BlendFactor.DST_ALPHA: GL_DST_ALPHA,
39
+ BlendFactor.ONE_MINUS_DST_ALPHA: GL_ONE_MINUS_DST_ALPHA,
40
+ BlendFactor.CONSTANT_COLOR: GL_CONSTANT_COLOR,
41
+ BlendFactor.ONE_MINUS_CONSTANT_COLOR: GL_ONE_MINUS_CONSTANT_COLOR,
42
+ BlendFactor.CONSTANT_ALPHA: GL_CONSTANT_ALPHA,
43
+ BlendFactor.ONE_MINUS_CONSTANT_ALPHA: GL_ONE_MINUS_CONSTANT_ALPHA,
44
+ }
45
+
46
+ texture_map = {
47
+ # Filters
48
+ TextureFilter.LINEAR: GL_LINEAR,
49
+ TextureFilter.NEAREST: GL_NEAREST,
50
+
51
+ # Texture Types
52
+ TextureType.TYPE_1D: GL_TEXTURE_1D,
53
+ TextureType.TYPE_2D: GL_TEXTURE_2D,
54
+ TextureType.TYPE_3D: GL_TEXTURE_3D,
55
+ TextureType.TYPE_CUBE_MAP: GL_TEXTURE_CUBE_MAP,
56
+ TextureType.TYPE_1D_ARRAY: GL_TEXTURE_1D_ARRAY,
57
+ TextureType.TYPE_2D_ARRAY: GL_TEXTURE_2D_ARRAY,
58
+ TextureType.TYPE_CUBE_MAP_ARRAY: GL_TEXTURE_CUBE_MAP_ARRAY,
59
+
60
+ # Wrapping
61
+ TextureWrapping.WRAP_R: GL_TEXTURE_WRAP_R,
62
+ TextureWrapping.WRAP_S: GL_TEXTURE_WRAP_S,
63
+ TextureWrapping.WRAP_T: GL_TEXTURE_WRAP_T,
64
+ }
65
+
66
+
67
+ compare_op_map = {
68
+ CompareOp.NEVER: GL_NEVER,
69
+ CompareOp.LESS: GL_LESS,
70
+ CompareOp.EQUAL: GL_EQUAL,
71
+ CompareOp.LESS_OR_EQUAL: GL_LEQUAL,
72
+ CompareOp.GREATER: GL_GREATER,
73
+ CompareOp.NOT_EQUAL: GL_NOTEQUAL,
74
+ CompareOp.GREATER_OR_EQUAL: GL_GEQUAL,
75
+ CompareOp.ALWAYS: GL_ALWAYS,
76
+ }
@@ -0,0 +1,315 @@
1
+ """OpenGL Framebuffer abstractions.
2
+
3
+ This module provides classes for working with Framebuffers & Renderbuffers
4
+ and their attachments. Attachments can be pyglet Texture objects, which allows
5
+ easily accessing their data, saving to disk, etc. Renderbuffers can be used
6
+ if you don't need to access their data at a later time. For example::
7
+
8
+ # Create two objects to use as attachments for our Framebuffer.
9
+ color_buffer = pyglet.graphics.Texture.create(width, height, min_filter=GL_NEAREST, mag_filter=GL_NEAREST)
10
+ depth_buffer = pyglet.image.buffer.Renderbuffer(width, height, GL_DEPTH_COMPONENT)
11
+
12
+ # Create a framebuffer object, and attach the two buffers:
13
+ framebuffer = pyglet.image.Framebuffer()
14
+ framebuffer.attach_texture(color_buffer, attachment=GL_COLOR_ATTACHMENT0)
15
+ framebuffer.attach_renderbuffer(depth_buffer, attachment=GL_DEPTH_ATTACHMENT)
16
+
17
+ # Bind the Framebuffer, which sets it as the active render target:
18
+ framebuffer.bind()
19
+
20
+ See the OpenGL documentation for more information on valid attachment types and targets.
21
+ """
22
+ from __future__ import annotations
23
+
24
+
25
+ import pyglet
26
+ from typing import TYPE_CHECKING
27
+
28
+ from pyglet.customtypes import DataTypes
29
+ from pyglet.enums import FramebufferTarget, FramebufferAttachment, ComponentFormat
30
+ from pyglet.graphics.api.gl import gl, GL_RGBA, GL_UNSIGNED_BYTE, GLuint
31
+ from pyglet.image.base import ImageData
32
+ from pyglet.graphics.api.gl.texture import _get_internal_format
33
+
34
+ if TYPE_CHECKING:
35
+ from pyglet.graphics.api.gl import OpenGLSurfaceContext
36
+ from pyglet.graphics.api.gl.texture import Texture
37
+
38
+ _gl_target_map = {
39
+ FramebufferTarget.FRAMEBUFFER: gl.GL_FRAMEBUFFER,
40
+ FramebufferTarget.DRAW: gl.GL_DRAW_FRAMEBUFFER,
41
+ FramebufferTarget.READ: gl.GL_READ_FRAMEBUFFER,
42
+ }
43
+
44
+ _gl_attachment_map = {
45
+ FramebufferAttachment.COLOR0: gl.GL_COLOR_ATTACHMENT0,
46
+ FramebufferAttachment.COLOR1: gl.GL_COLOR_ATTACHMENT1,
47
+ FramebufferAttachment.COLOR2: gl.GL_COLOR_ATTACHMENT2,
48
+ FramebufferAttachment.COLOR3: gl.GL_COLOR_ATTACHMENT3,
49
+ FramebufferAttachment.COLOR4: gl.GL_COLOR_ATTACHMENT4,
50
+ FramebufferAttachment.COLOR5: gl.GL_COLOR_ATTACHMENT5,
51
+ FramebufferAttachment.COLOR6: gl.GL_COLOR_ATTACHMENT6,
52
+ FramebufferAttachment.COLOR7: gl.GL_COLOR_ATTACHMENT7,
53
+ FramebufferAttachment.COLOR8: gl.GL_COLOR_ATTACHMENT8,
54
+ FramebufferAttachment.COLOR9: gl.GL_COLOR_ATTACHMENT9,
55
+ FramebufferAttachment.COLOR10: gl.GL_COLOR_ATTACHMENT10,
56
+ FramebufferAttachment.COLOR11: gl.GL_COLOR_ATTACHMENT11,
57
+ FramebufferAttachment.COLOR12: gl.GL_COLOR_ATTACHMENT12,
58
+ FramebufferAttachment.COLOR13: gl.GL_COLOR_ATTACHMENT13,
59
+ FramebufferAttachment.COLOR14: gl.GL_COLOR_ATTACHMENT14,
60
+ FramebufferAttachment.COLOR15: gl.GL_COLOR_ATTACHMENT15,
61
+
62
+ FramebufferAttachment.DEPTH: gl.GL_DEPTH_ATTACHMENT,
63
+ FramebufferAttachment.STENCIL: gl.GL_STENCIL_ATTACHMENT,
64
+ FramebufferAttachment.DEPTH_STENCIL: gl.GL_DEPTH_STENCIL_ATTACHMENT,
65
+ }
66
+
67
+
68
+ def get_viewport() -> tuple:
69
+ """Get the current OpenGL viewport dimensions (left, bottom, right, top)."""
70
+ ctx = pyglet.graphics.api.core.current_context
71
+ viewport = (gl.GLint * 4)()
72
+ ctx.glGetIntegerv(gl.GL_VIEWPORT, viewport)
73
+ return tuple(viewport)
74
+
75
+ def get_screenshot() -> ImageData:
76
+ """Read the pixel data from the default color buffer into ImageData.
77
+
78
+ This provides a simplistic screenshot of the default frame buffer.
79
+
80
+ This may be inaccurate if you utilize multiple frame buffers in your program.
81
+
82
+ .. versionadded:: 3.0
83
+ """
84
+ ctx = pyglet.graphics.api.core.current_context
85
+ fmt = 'RGBA'
86
+ viewport = get_viewport()
87
+ width = viewport[2]
88
+ height = viewport[3]
89
+
90
+ buf = (gl.GLubyte * (len(fmt) * width * height))()
91
+
92
+ ctx.glReadBuffer(gl.GL_BACK)
93
+ ctx.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
94
+ ctx.glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf)
95
+ return ImageData(width, height, fmt, buf)
96
+
97
+
98
+
99
+
100
+ def get_max_color_attachments() -> int:
101
+ """Return the maximum number of color attachments supported by the current context."""
102
+ return pyglet.graphics.api.core.current_context.get_info().MAX_COLOR_ATTACHMENTS
103
+
104
+
105
+ class Renderbuffer:
106
+ """OpenGL Renderbuffer Object."""
107
+
108
+ def __init__(self, context: OpenGLSurfaceContext, width: int, height: int,
109
+ component_format: ComponentFormat, bit_size: int, data_type: DataTypes = "I", samples: int = 1) -> None:
110
+ """Create a RenderBuffer instance."""
111
+ self._context = context or pyglet.graphics.api.core.current_context
112
+ self._id = GLuint()
113
+ self._width = width
114
+ self._height = height
115
+ self._internal_format = _get_internal_format(component_format, bit_size, data_type)
116
+
117
+ self._context.glGenRenderbuffers(1, self._id)
118
+ self._context.glBindRenderbuffer(gl.GL_RENDERBUFFER, self._id)
119
+
120
+ if samples > 1:
121
+ self._context.glRenderbufferStorageMultisample(gl.GL_RENDERBUFFER, samples, self._internal_format, width, height)
122
+ else:
123
+ self._context.glRenderbufferStorage(gl.GL_RENDERBUFFER, self._internal_format, width, height)
124
+
125
+ self._context.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0)
126
+
127
+ @property
128
+ def id(self) -> int:
129
+ return self._id.value
130
+
131
+ @property
132
+ def width(self) -> int:
133
+ return self._width
134
+
135
+ @property
136
+ def height(self) -> int:
137
+ return self._height
138
+
139
+ def bind(self) -> None:
140
+ self._context.glBindRenderbuffer(gl.GL_RENDERBUFFER, self._id)
141
+
142
+ def unbind(self) -> None:
143
+ self._context.glBindRenderbuffer(gl.GL_RENDERBUFFER, 0)
144
+
145
+ def delete(self) -> None:
146
+ self._context.glDeleteRenderbuffers(1, self._id)
147
+ self._id = None
148
+
149
+ def __del__(self) -> None:
150
+ if self._id is not None:
151
+ try:
152
+ self._context.delete_renderbuffer(self._id.value)
153
+ self._id = None
154
+ except (AttributeError, ImportError):
155
+ pass # Interpreter is shutting down
156
+
157
+ def __repr__(self) -> str:
158
+ return f"{self.__class__.__name__}(id={self._id.value})"
159
+
160
+
161
+ _status_states = {
162
+ gl.GL_FRAMEBUFFER_UNSUPPORTED: "Framebuffer unsupported. Try another format.",
163
+ gl.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: "Framebuffer incomplete attachment.",
164
+ gl.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: "Framebuffer missing attachment.",
165
+ gl.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: "Framebuffer unsupported dimension.",
166
+ gl.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: "Framebuffer incomplete formats.",
167
+ gl.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: "Framebuffer incomplete draw buffer.",
168
+ gl.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: "Framebuffer incomplete read buffer.",
169
+ gl.GL_FRAMEBUFFER_COMPLETE: "Framebuffer is complete.",
170
+ }
171
+
172
+ class Framebuffer:
173
+ """OpenGL Framebuffer Object.
174
+
175
+ .. versionadded:: 2.0
176
+ """
177
+ def __init__(self, target: FramebufferTarget = FramebufferTarget.FRAMEBUFFER, context: OpenGLSurfaceContext | None = None) -> None:
178
+ self._context = context or pyglet.graphics.api.core.current_context
179
+ self._id = GLuint()
180
+ self._context.glGenFramebuffers(1, self._id)
181
+ self._attachment_types = 0
182
+ self._width = 0
183
+ self._height = 0
184
+ self.target = target
185
+ self._gl_target = _gl_target_map[target]
186
+
187
+ @property
188
+ def id(self) -> int:
189
+ """The Framebuffer id."""
190
+ return self._id.value
191
+
192
+ @property
193
+ def width(self) -> int:
194
+ """The width of the widest attachment."""
195
+ return self._width
196
+
197
+ @property
198
+ def height(self) -> int:
199
+ """The height of the tallest attachment."""
200
+ return self._height
201
+
202
+ def bind(self) -> None:
203
+ """Bind the Framebuffer.
204
+
205
+ This activates it as the current drawing target.
206
+ """
207
+ self._context.glBindFramebuffer(self._gl_target, self._id)
208
+
209
+ def unbind(self) -> None:
210
+ """Unbind the Framebuffer.
211
+
212
+ Unbind should be called to prevent further rendering
213
+ to the framebuffer, or if you wish to access data
214
+ from its Texture atachments.
215
+ """
216
+ self._context.glBindFramebuffer(self._gl_target, 0)
217
+
218
+ def clear(self) -> None:
219
+ """Clear the attachments."""
220
+ if self._attachment_types:
221
+ self.bind()
222
+ self._context.glClear(self._attachment_types)
223
+ self.unbind()
224
+
225
+ def delete(self) -> None:
226
+ """Explicitly delete the Framebuffer."""
227
+ self._context.glDeleteFramebuffers(1, self._id)
228
+ self._id = None
229
+
230
+ def __del__(self) -> None:
231
+ if self._id is not None:
232
+ try:
233
+ self._context.delete_framebuffer(self._id.value)
234
+ self._id = None
235
+ except (AttributeError, ImportError):
236
+ pass # Interpreter is shutting down
237
+
238
+ @property
239
+ def is_complete(self) -> bool:
240
+ """True if the framebuffer is 'complete', else False."""
241
+ return self._context.glCheckFramebufferStatus(gl.GL_FRAMEBUFFER) == gl.GL_FRAMEBUFFER_COMPLETE
242
+
243
+ def get_status(self) -> str:
244
+ """Get the current Framebuffer status, as a string.
245
+
246
+ If ``Framebuffer.is_complete`` is ``False``, this method
247
+ can be used for more information. It will return a
248
+ string with the OpenGL reported status.
249
+ """
250
+ gl_status = self._context.glCheckFramebufferStatus(self._gl_target)
251
+
252
+ return _status_states.get(gl_status, "Unknown error")
253
+
254
+ def attach_texture(self, texture: Texture, attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
255
+ """Attach a Texture to the Framebuffer.
256
+
257
+ Args:
258
+ texture:
259
+ Specifies the texture object to attach to the framebuffer attachment
260
+ point named by attachment.
261
+ attachment:
262
+ Specifies the attachment point of the framebuffer.
263
+ """
264
+ self.bind()
265
+ gl_attachment = _gl_attachment_map[attachment]
266
+ self._context.glFramebufferTexture(self._gl_target, gl_attachment, texture.id, texture.level)
267
+ self._attachment_types |= gl_attachment
268
+ self._width = max(texture.width, self._width)
269
+ self._height = max(texture.height, self._height)
270
+ self.unbind()
271
+
272
+ def attach_texture_layer(self, texture: Texture, layer: int, level: int,
273
+ attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
274
+ """Attach a Texture layer to the Framebuffer.
275
+
276
+ Args:
277
+ texture:
278
+ Specifies the texture object to attach to the framebuffer attachment
279
+ point named by attachment.
280
+ layer:
281
+ Specifies the layer of texture to attach.
282
+ level:
283
+ Specifies the mipmap level of texture to attach.
284
+ attachment:
285
+ Specifies the attachment point of the framebuffer.
286
+ """
287
+ self.bind()
288
+ gl_attachment = _gl_attachment_map[attachment]
289
+ self._context.glFramebufferTextureLayer(self._gl_target, gl_attachment, texture.id, level, layer)
290
+ self._attachment_types |= gl_attachment
291
+ self._width = max(texture.width, self._width)
292
+ self._height = max(texture.height, self._height)
293
+ self.unbind()
294
+
295
+ def attach_renderbuffer(self, renderbuffer: Renderbuffer,
296
+ attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
297
+ """Attach a Renderbuffer to the Framebuffer.
298
+
299
+ Args:
300
+ renderbuffer:
301
+ Specifies the Renderbuffer to attach to the framebuffer attachment
302
+ point named by attachment.
303
+ attachment:
304
+ Specifies the attachment point of the framebuffer.
305
+ """
306
+ self.bind()
307
+ gl_attachment = _gl_attachment_map[attachment]
308
+ self._context.glFramebufferRenderbuffer(self._gl_target, gl_attachment, gl.GL_RENDERBUFFER, renderbuffer.id)
309
+ self._attachment_types |= gl_attachment
310
+ self._width = max(renderbuffer.width, self._width)
311
+ self._height = max(renderbuffer.height, self._height)
312
+ self.unbind()
313
+
314
+ def __repr__(self) -> str:
315
+ return f"{self.__class__.__name__}(id={self._id.value})"