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,360 @@
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.enums import FramebufferTarget, FramebufferAttachment, ComponentFormat
29
+ from pyglet.graphics.api.webgl import gl
30
+ from pyglet.image.base import ImageData
31
+ from pyglet.graphics.api.webgl.texture import _get_internal_format
32
+
33
+ if TYPE_CHECKING:
34
+ from pyglet.graphics.api.webgl.webgl_js import WebGLFramebuffer, WebGLRenderbuffer
35
+ from pyglet.customtypes import DataTypes
36
+ from pyglet.graphics.api.webgl import OpenGLSurfaceContext
37
+ from pyglet.graphics.api.webgl.texture import Texture
38
+
39
+ _gl_target_map = {
40
+ FramebufferTarget.FRAMEBUFFER: gl.GL_FRAMEBUFFER,
41
+ FramebufferTarget.DRAW: gl.GL_DRAW_FRAMEBUFFER,
42
+ FramebufferTarget.READ: gl.GL_READ_FRAMEBUFFER,
43
+ }
44
+
45
+ _gl_attachment_map = {
46
+ FramebufferAttachment.COLOR0: gl.GL_COLOR_ATTACHMENT0,
47
+ FramebufferAttachment.COLOR1: gl.GL_COLOR_ATTACHMENT1,
48
+ FramebufferAttachment.COLOR2: gl.GL_COLOR_ATTACHMENT2,
49
+ FramebufferAttachment.COLOR3: gl.GL_COLOR_ATTACHMENT3,
50
+ FramebufferAttachment.COLOR4: gl.GL_COLOR_ATTACHMENT4,
51
+ FramebufferAttachment.COLOR5: gl.GL_COLOR_ATTACHMENT5,
52
+ FramebufferAttachment.COLOR6: gl.GL_COLOR_ATTACHMENT6,
53
+ FramebufferAttachment.COLOR7: gl.GL_COLOR_ATTACHMENT7,
54
+ FramebufferAttachment.COLOR8: gl.GL_COLOR_ATTACHMENT8,
55
+ FramebufferAttachment.COLOR9: gl.GL_COLOR_ATTACHMENT9,
56
+ FramebufferAttachment.COLOR10: gl.GL_COLOR_ATTACHMENT10,
57
+ FramebufferAttachment.COLOR11: gl.GL_COLOR_ATTACHMENT11,
58
+ FramebufferAttachment.COLOR12: gl.GL_COLOR_ATTACHMENT12,
59
+ FramebufferAttachment.COLOR13: gl.GL_COLOR_ATTACHMENT13,
60
+ FramebufferAttachment.COLOR14: gl.GL_COLOR_ATTACHMENT14,
61
+ FramebufferAttachment.COLOR15: gl.GL_COLOR_ATTACHMENT15,
62
+
63
+ FramebufferAttachment.DEPTH: gl.GL_DEPTH_ATTACHMENT,
64
+ FramebufferAttachment.STENCIL: gl.GL_STENCIL_ATTACHMENT,
65
+ FramebufferAttachment.DEPTH_STENCIL: gl.GL_DEPTH_STENCIL_ATTACHMENT,
66
+ }
67
+
68
+
69
+ def get_viewport() -> tuple:
70
+ """Get the current OpenGL viewport dimensions (left, bottom, right, top)."""
71
+ ctx = pyglet.graphics.api.core.current_context
72
+ viewport = (gl.GLint * 4)()
73
+ ctx.glGetIntegerv(gl.GL_VIEWPORT, viewport)
74
+ return tuple(viewport)
75
+
76
+ def get_screenshot() -> ImageData:
77
+ """Read the pixel data from the default color buffer into ImageData.
78
+
79
+ This provides a simplistic screenshot of the default frame buffer.
80
+
81
+ This may be inaccurate if you utilize multiple frame buffers in your program.
82
+
83
+ .. versionadded:: 3.0
84
+ """
85
+ # ctx = pyglet.graphics.api.core.current_context
86
+ # fmt = 'RGBA'
87
+ # viewport = get_viewport()
88
+ # width = viewport[2]
89
+ # height = viewport[3]
90
+ #
91
+ # buf = (gl.GLubyte * (len(fmt) * width * height))()
92
+ #
93
+ # ctx.glReadBuffer(gl.GL_BACK)
94
+ # ctx.glPixelStorei(gl.GL_PACK_ALIGNMENT, 1)
95
+ # ctx.glReadPixels(0, 0, width, height, gl.GL_RGBA, gl.GL_UNSIGNED_BYTE, buf)
96
+ # return ImageData(width, height, fmt, buf)
97
+ raise NotImplementedError("Not yet implemented.")
98
+
99
+
100
+
101
+
102
+ def get_max_color_attachments() -> int:
103
+ """Return the maximum number of color attachments supported by the current context."""
104
+ return pyglet.graphics.api.core.current_context.get_info().MAX_COLOR_ATTACHMENTS
105
+
106
+
107
+ class Renderbuffer:
108
+ """OpenGL Renderbuffer Object."""
109
+
110
+ def __init__(self, context: OpenGLSurfaceContext, width: int, height: int,
111
+ component_format: ComponentFormat, bit_size: int, data_type: DataTypes = "I", samples: int = 1) -> None:
112
+ """Create a RenderBuffer instance."""
113
+ self._context = context or pyglet.graphics.api.core.current_context
114
+ self._gl = self._context.gl
115
+ self._width = width
116
+ self._height = height
117
+ self._internal_format = _get_internal_format(component_format, bit_size, data_type)
118
+
119
+ self._id = self._gl.createRenderbuffer()
120
+ self.bind()
121
+
122
+ if samples > 1:
123
+ self._gl.renderbufferStorageMultisample(
124
+ gl.GL_RENDERBUFFER,
125
+ samples,
126
+ self._internal_format,
127
+ width,
128
+ height,
129
+ )
130
+ else:
131
+ self._gl.renderbufferStorage(
132
+ gl.GL_RENDERBUFFER,
133
+ self._internal_format,
134
+ width,
135
+ height,
136
+ )
137
+
138
+ self.unbind()
139
+
140
+ @property
141
+ def id(self) -> WebGLRenderbuffer:
142
+ return self._id
143
+
144
+ @property
145
+ def width(self) -> int:
146
+ return self._width
147
+
148
+ @property
149
+ def height(self) -> int:
150
+ return self._height
151
+
152
+ def bind(self) -> None:
153
+ self._gl.bindRenderbuffer(gl.GL_RENDERBUFFER, self._id)
154
+
155
+ def unbind(self) -> None:
156
+ self._gl.bindRenderbuffer(gl.GL_RENDERBUFFER, None)
157
+
158
+ def delete(self) -> None:
159
+ if self._id is not None:
160
+ self._gl.deleteRenderbuffer(self._id) # FIX for WebGL
161
+ self._id = None
162
+
163
+ def __del__(self) -> None:
164
+ self.delete()
165
+
166
+ def __repr__(self) -> str:
167
+ return f"{self.__class__.__name__}(id={self._id})"
168
+
169
+
170
+ _status_states = {
171
+ gl.GL_FRAMEBUFFER_UNSUPPORTED: "Framebuffer unsupported. Try another format.",
172
+ gl.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: "Framebuffer incomplete attachment.",
173
+ gl.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: "Framebuffer missing attachment.",
174
+ gl.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: "Framebuffer unsupported dimension.",
175
+ gl.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: "Framebuffer incomplete formats.",
176
+ gl.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: "Framebuffer incomplete draw buffer.",
177
+ gl.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: "Framebuffer incomplete read buffer.",
178
+ gl.GL_FRAMEBUFFER_COMPLETE: "Framebuffer is complete.",
179
+ }
180
+
181
+ class Framebuffer:
182
+ """OpenGL Framebuffer Object.
183
+
184
+ .. versionadded:: 2.0
185
+ """
186
+ _id: WebGLFramebuffer | None
187
+
188
+ def __init__(self,
189
+ target: FramebufferTarget = FramebufferTarget.FRAMEBUFFER,
190
+ context: OpenGLSurfaceContext | None = None) -> None:
191
+ self._context = context or pyglet.graphics.api.core.current_context
192
+ self._gl = self._context.gl
193
+ self._id = self._gl.createFramebuffer()
194
+ self._clear_bits = 0
195
+ self._gl_attachment_types = []
196
+ self._width = 0
197
+ self._height = 0
198
+ self.target = target
199
+ self._gl_target = _gl_target_map[target]
200
+
201
+ @property
202
+ def id(self) -> WebGLFramebuffer:
203
+ """The Framebuffer id."""
204
+ return self._id
205
+
206
+ @property
207
+ def width(self) -> int:
208
+ """The width of the widest attachment."""
209
+ return self._width
210
+
211
+ @property
212
+ def height(self) -> int:
213
+ """The height of the tallest attachment."""
214
+ return self._height
215
+
216
+ def bind(self) -> None:
217
+ """Bind the Framebuffer.
218
+
219
+ This activates it as the current drawing target.
220
+ """
221
+ self._gl.bindFramebuffer(self._gl_target, self._id)
222
+
223
+ def unbind(self) -> None:
224
+ """Unbind the Framebuffer.
225
+
226
+ Unbind should be called to prevent further rendering
227
+ to the framebuffer, or if you wish to access data
228
+ from its Texture atachments.
229
+ """
230
+ self._gl.bindFramebuffer(self._gl_target, None)
231
+
232
+ def clear(self) -> None:
233
+ """Clear the attachments."""
234
+ if self._clear_bits:
235
+ self.bind()
236
+ self._gl.clear(self._clear_bits)
237
+ self.unbind()
238
+
239
+ def delete(self) -> None:
240
+ """Explicitly delete the Framebuffer."""
241
+ if self._id is not None:
242
+ self._gl.deleteFramebuffer(self._id)
243
+ self._id = None
244
+
245
+ def __del__(self) -> None:
246
+ self.delete()
247
+
248
+ @property
249
+ def is_complete(self) -> bool:
250
+ """True if the framebuffer is 'complete', else False."""
251
+ return self._gl.checkFramebufferStatus(self._gl_target) == gl.GL_FRAMEBUFFER_COMPLETE
252
+
253
+ def get_status(self) -> str:
254
+ """Get the current Framebuffer status, as a string.
255
+
256
+ If ``Framebuffer.is_complete`` is ``False``, this method
257
+ can be used for more information. It will return a
258
+ string with the OpenGL reported status.
259
+ """
260
+ gl_status = self._gl.checkFramebufferStatus(self._gl_target)
261
+
262
+ return _status_states.get(gl_status, "Unknown error")
263
+
264
+ def attach_texture(self, texture: Texture, attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
265
+ """Attach a Texture to the Framebuffer.
266
+
267
+ Args:
268
+ texture:
269
+ Specifies the texture object to attach to the framebuffer attachment
270
+ point named by attachment.
271
+ attachment:
272
+ Specifies the attachment point of the framebuffer.
273
+ """
274
+ self.bind()
275
+ gl_attachment = _gl_attachment_map[attachment]
276
+ self._gl.framebufferTexture2D(
277
+ self._gl_target,
278
+ gl_attachment,
279
+ gl.GL_TEXTURE_2D,
280
+ texture.id,
281
+ texture.level,
282
+ )
283
+ if "COLOR" in attachment.name:
284
+ self._clear_bits |= gl.GL_COLOR_BUFFER_BIT
285
+ elif "DEPTH" in attachment.name:
286
+ self._clear_bits |= gl.GL_DEPTH_BUFFER_BIT
287
+ elif "STENCIL" in attachment.name:
288
+ self._clear_bits |= gl.GL_STENCIL_BUFFER_BIT
289
+ self._gl_attachment_types.append(gl_attachment)
290
+ self._width = max(texture.width, self._width)
291
+ self._height = max(texture.height, self._height)
292
+ self.unbind()
293
+
294
+ def attach_texture_layer(self, texture: Texture, layer: int, level: int,
295
+ attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
296
+ """Attach a Texture layer to the Framebuffer.
297
+
298
+ Args:
299
+ texture:
300
+ Specifies the texture object to attach to the framebuffer attachment
301
+ point named by attachment.
302
+ layer:
303
+ Specifies the layer of texture to attach.
304
+ level:
305
+ Specifies the mipmap level of texture to attach.
306
+ attachment:
307
+ Specifies the attachment point of the framebuffer.
308
+ """
309
+ self.bind()
310
+ gl_attachment = _gl_attachment_map[attachment]
311
+ self._gl.framebufferTextureLayer(
312
+ self._gl_target,
313
+ gl_attachment,
314
+ texture.id,
315
+ level,
316
+ layer,
317
+ )
318
+ if "COLOR" in attachment.name:
319
+ self._clear_bits |= gl.GL_COLOR_BUFFER_BIT
320
+ self._gl_attachment_types.append(gl_attachment)
321
+ self._width = max(texture.width, self._width)
322
+ self._height = max(texture.height, self._height)
323
+ self.unbind()
324
+
325
+ def attach_renderbuffer(self, renderbuffer: Renderbuffer,
326
+ attachment: FramebufferAttachment = FramebufferAttachment.COLOR0) -> None:
327
+ """Attach a Renderbuffer to the Framebuffer.
328
+
329
+ Args:
330
+ renderbuffer:
331
+ Specifies the Renderbuffer to attach to the framebuffer attachment
332
+ point named by attachment.
333
+ attachment:
334
+ Specifies the attachment point of the framebuffer.
335
+ """
336
+ self.bind()
337
+ gl_attachment = _gl_attachment_map[attachment]
338
+ self._gl.framebufferRenderbuffer(
339
+ self._gl_target,
340
+ gl_attachment,
341
+ gl.GL_RENDERBUFFER,
342
+ renderbuffer.id,
343
+ )
344
+ self._gl_attachment_types.append(gl_attachment)
345
+ if "DEPTH" in attachment.name:
346
+ self._clear_bits |= gl.GL_DEPTH_BUFFER_BIT
347
+ elif "STENCIL" in attachment.name:
348
+ self._clear_bits |= gl.GL_STENCIL_BUFFER_BIT
349
+ self._width = max(renderbuffer.width, self._width)
350
+ self._height = max(renderbuffer.height, self._height)
351
+ self.unbind()
352
+
353
+ def set_draw_buffers(self) -> None:
354
+ """Enable multiple render targets for the FBO (WebGL2)."""
355
+ self.bind()
356
+ self._gl.drawBuffers(self._gl_attachment_types)
357
+ self.unbind()
358
+
359
+ def __repr__(self) -> str:
360
+ return f"{self.__class__.__name__}(id={self._id})"