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.
- pyglet/__init__.py +67 -61
- pyglet/__init__.pyi +15 -8
- pyglet/app/__init__.py +22 -13
- pyglet/app/async_app.py +212 -0
- pyglet/app/base.py +2 -1
- pyglet/app/{xlib.py → linux.py} +3 -3
- pyglet/config/__init__.py +101 -0
- pyglet/config/gl/__init__.py +30 -0
- pyglet/config/gl/egl.py +120 -0
- pyglet/config/gl/macos.py +262 -0
- pyglet/config/gl/windows.py +267 -0
- pyglet/config/gl/x11.py +142 -0
- pyglet/customtypes.py +43 -2
- pyglet/display/__init__.py +8 -6
- pyglet/display/base.py +3 -63
- pyglet/display/cocoa.py +12 -17
- pyglet/display/emscripten.py +39 -0
- pyglet/display/headless.py +23 -30
- pyglet/display/wayland.py +157 -0
- pyglet/display/win32.py +4 -17
- pyglet/display/xlib.py +19 -27
- pyglet/display/xlib_vidmoderestore.py +2 -2
- pyglet/enums.py +183 -0
- pyglet/event.py +0 -1
- pyglet/experimental/geoshader_sprite.py +15 -13
- pyglet/experimental/hidraw.py +6 -15
- pyglet/experimental/multitexture_sprite.py +31 -19
- pyglet/experimental/particles.py +13 -35
- pyglet/font/__init__.py +251 -85
- pyglet/font/base.py +116 -61
- pyglet/font/dwrite/__init__.py +349 -204
- pyglet/font/dwrite/dwrite_lib.py +27 -5
- pyglet/font/fontconfig.py +14 -6
- pyglet/font/freetype.py +138 -87
- pyglet/font/freetype_lib.py +19 -0
- pyglet/font/group.py +179 -0
- pyglet/font/harfbuzz/__init__.py +3 -3
- pyglet/font/pyodide_js.py +310 -0
- pyglet/font/quartz.py +319 -126
- pyglet/font/ttf.py +45 -3
- pyglet/font/user.py +14 -19
- pyglet/font/win32.py +45 -21
- pyglet/graphics/__init__.py +8 -787
- pyglet/graphics/allocation.py +115 -1
- pyglet/graphics/api/__init__.py +77 -0
- pyglet/graphics/api/base.py +299 -0
- pyglet/graphics/api/gl/__init__.py +58 -0
- pyglet/graphics/api/gl/base.py +24 -0
- pyglet/graphics/{vertexbuffer.py → api/gl/buffer.py} +104 -159
- pyglet/graphics/api/gl/cocoa/context.py +76 -0
- pyglet/graphics/api/gl/context.py +391 -0
- pyglet/graphics/api/gl/default_shaders.py +0 -0
- pyglet/graphics/api/gl/draw.py +627 -0
- pyglet/graphics/api/gl/egl/__init__.py +0 -0
- pyglet/graphics/api/gl/egl/context.py +92 -0
- pyglet/graphics/api/gl/enums.py +76 -0
- pyglet/graphics/api/gl/framebuffer.py +315 -0
- pyglet/graphics/api/gl/gl.py +5463 -0
- pyglet/graphics/api/gl/gl_info.py +188 -0
- pyglet/graphics/api/gl/global_opengl.py +226 -0
- pyglet/{gl → graphics/api/gl}/lib.py +34 -18
- pyglet/graphics/api/gl/shader.py +1476 -0
- pyglet/graphics/api/gl/shapes.py +55 -0
- pyglet/graphics/api/gl/sprite.py +102 -0
- pyglet/graphics/api/gl/state.py +219 -0
- pyglet/graphics/api/gl/text.py +190 -0
- pyglet/graphics/api/gl/texture.py +1526 -0
- pyglet/graphics/{vertexarray.py → api/gl/vertexarray.py} +11 -13
- pyglet/graphics/api/gl/vertexdomain.py +751 -0
- pyglet/graphics/api/gl/win32/__init__.py +0 -0
- pyglet/graphics/api/gl/win32/context.py +108 -0
- pyglet/graphics/api/gl/win32/wgl_info.py +24 -0
- pyglet/graphics/api/gl/xlib/__init__.py +0 -0
- pyglet/graphics/api/gl/xlib/context.py +174 -0
- pyglet/{gl → graphics/api/gl/xlib}/glx_info.py +26 -31
- pyglet/graphics/api/gl1/__init__.py +0 -0
- pyglet/{gl → graphics/api/gl1}/gl_compat.py +3 -2
- pyglet/graphics/api/gl2/__init__.py +0 -0
- pyglet/graphics/api/gl2/buffer.py +320 -0
- pyglet/graphics/api/gl2/draw.py +600 -0
- pyglet/graphics/api/gl2/global_opengl.py +122 -0
- pyglet/graphics/api/gl2/shader.py +200 -0
- pyglet/graphics/api/gl2/shapes.py +51 -0
- pyglet/graphics/api/gl2/sprite.py +79 -0
- pyglet/graphics/api/gl2/text.py +175 -0
- pyglet/graphics/api/gl2/vertexdomain.py +364 -0
- pyglet/graphics/api/webgl/__init__.py +233 -0
- pyglet/graphics/api/webgl/buffer.py +302 -0
- pyglet/graphics/api/webgl/context.py +234 -0
- pyglet/graphics/api/webgl/draw.py +590 -0
- pyglet/graphics/api/webgl/enums.py +76 -0
- pyglet/graphics/api/webgl/framebuffer.py +360 -0
- pyglet/graphics/api/webgl/gl.py +1537 -0
- pyglet/graphics/api/webgl/gl_info.py +130 -0
- pyglet/graphics/api/webgl/shader.py +1346 -0
- pyglet/graphics/api/webgl/shapes.py +92 -0
- pyglet/graphics/api/webgl/sprite.py +102 -0
- pyglet/graphics/api/webgl/state.py +227 -0
- pyglet/graphics/api/webgl/text.py +187 -0
- pyglet/graphics/api/webgl/texture.py +1227 -0
- pyglet/graphics/api/webgl/vertexarray.py +54 -0
- pyglet/graphics/api/webgl/vertexdomain.py +616 -0
- pyglet/graphics/api/webgl/webgl_js.pyi +307 -0
- pyglet/{image → graphics}/atlas.py +33 -32
- pyglet/graphics/base.py +10 -0
- pyglet/graphics/buffer.py +245 -0
- pyglet/graphics/draw.py +578 -0
- pyglet/graphics/framebuffer.py +26 -0
- pyglet/graphics/instance.py +178 -69
- pyglet/graphics/shader.py +267 -1553
- pyglet/graphics/state.py +83 -0
- pyglet/graphics/texture.py +703 -0
- pyglet/graphics/vertexdomain.py +695 -538
- pyglet/gui/ninepatch.py +10 -10
- pyglet/gui/widgets.py +120 -10
- pyglet/image/__init__.py +20 -1973
- pyglet/image/animation.py +12 -12
- pyglet/image/base.py +730 -0
- pyglet/image/codecs/__init__.py +9 -0
- pyglet/image/codecs/bmp.py +53 -30
- pyglet/image/codecs/dds.py +53 -31
- pyglet/image/codecs/gdiplus.py +38 -14
- pyglet/image/codecs/gdkpixbuf2.py +0 -2
- pyglet/image/codecs/js_image.py +99 -0
- pyglet/image/codecs/ktx2.py +161 -0
- pyglet/image/codecs/pil.py +1 -1
- pyglet/image/codecs/png.py +1 -1
- pyglet/image/codecs/wic.py +11 -2
- pyglet/info.py +26 -24
- pyglet/input/__init__.py +8 -0
- pyglet/input/base.py +163 -105
- pyglet/input/controller.py +13 -19
- pyglet/input/controller_db.py +39 -24
- pyglet/input/emscripten/__init__.py +18 -0
- pyglet/input/emscripten/gamepad_js.py +397 -0
- pyglet/input/linux/__init__.py +11 -5
- pyglet/input/linux/evdev.py +10 -11
- pyglet/input/linux/x11_xinput.py +2 -2
- pyglet/input/linux/x11_xinput_tablet.py +1 -1
- pyglet/input/macos/__init__.py +7 -2
- pyglet/input/macos/darwin_gc.py +559 -0
- pyglet/input/win32/__init__.py +1 -1
- pyglet/input/win32/directinput.py +34 -29
- pyglet/input/win32/xinput.py +11 -61
- pyglet/lib.py +3 -3
- pyglet/libs/__init__.py +1 -1
- pyglet/{gl → libs/darwin}/agl.py +1 -1
- pyglet/libs/darwin/cocoapy/__init__.py +2 -2
- pyglet/libs/darwin/cocoapy/cocoahelpers.py +181 -0
- pyglet/libs/darwin/cocoapy/cocoalibs.py +31 -0
- pyglet/libs/darwin/cocoapy/cocoatypes.py +27 -0
- pyglet/libs/darwin/cocoapy/runtime.py +81 -45
- pyglet/libs/darwin/coreaudio.py +4 -4
- pyglet/{gl → libs/darwin}/lib_agl.py +9 -8
- pyglet/libs/darwin/quartzkey.py +1 -3
- pyglet/libs/egl/__init__.py +2 -0
- pyglet/libs/egl/egl_lib.py +576 -0
- pyglet/libs/egl/eglext.py +51 -5
- pyglet/libs/linux/__init__.py +0 -0
- pyglet/libs/linux/egl/__init__.py +0 -0
- pyglet/libs/linux/egl/eglext.py +22 -0
- pyglet/libs/linux/glx/__init__.py +0 -0
- pyglet/{gl → libs/linux/glx}/glx.py +13 -14
- pyglet/{gl → libs/linux/glx}/glxext_arb.py +408 -192
- pyglet/{gl → libs/linux/glx}/glxext_mesa.py +1 -1
- pyglet/{gl → libs/linux/glx}/glxext_nv.py +345 -164
- pyglet/{gl → libs/linux/glx}/lib_glx.py +3 -2
- pyglet/libs/linux/wayland/__init__.py +0 -0
- pyglet/libs/linux/wayland/client.py +1068 -0
- pyglet/libs/linux/wayland/lib_wayland.py +207 -0
- pyglet/libs/linux/wayland/wayland_egl.py +38 -0
- pyglet/libs/{wayland → linux/wayland}/xkbcommon.py +26 -0
- pyglet/libs/{x11 → linux/x11}/xf86vmode.py +4 -4
- pyglet/libs/{x11 → linux/x11}/xinerama.py +2 -2
- pyglet/libs/{x11 → linux/x11}/xinput.py +10 -10
- pyglet/libs/linux/x11/xrandr.py +0 -0
- pyglet/libs/{x11 → linux/x11}/xrender.py +1 -1
- pyglet/libs/shared/__init__.py +0 -0
- pyglet/libs/shared/spirv/__init__.py +0 -0
- pyglet/libs/shared/spirv/lib_shaderc.py +85 -0
- pyglet/libs/shared/spirv/lib_spirv_cross.py +126 -0
- pyglet/libs/win32/__init__.py +27 -5
- pyglet/libs/win32/constants.py +59 -48
- pyglet/libs/win32/context_managers.py +20 -3
- pyglet/libs/win32/dinput.py +105 -88
- pyglet/{gl → libs/win32}/lib_wgl.py +52 -26
- pyglet/libs/win32/types.py +58 -23
- pyglet/{gl → libs/win32}/wgl.py +32 -25
- pyglet/{gl → libs/win32}/wglext_arb.py +364 -2
- pyglet/media/__init__.py +9 -10
- pyglet/media/codecs/__init__.py +12 -1
- pyglet/media/codecs/base.py +99 -96
- pyglet/media/codecs/ffmpeg.py +2 -2
- pyglet/media/codecs/ffmpeg_lib/libavformat.py +3 -8
- pyglet/media/codecs/webaudio_pyodide.py +111 -0
- pyglet/media/drivers/__init__.py +9 -4
- pyglet/media/drivers/base.py +4 -4
- pyglet/media/drivers/openal/__init__.py +1 -1
- pyglet/media/drivers/openal/adaptation.py +3 -3
- pyglet/media/drivers/pulse/__init__.py +1 -1
- pyglet/media/drivers/pulse/adaptation.py +3 -3
- pyglet/media/drivers/pyodide_js/__init__.py +8 -0
- pyglet/media/drivers/pyodide_js/adaptation.py +288 -0
- pyglet/media/drivers/xaudio2/adaptation.py +3 -3
- pyglet/media/player.py +276 -193
- pyglet/media/player_worker_thread.py +1 -1
- pyglet/model/__init__.py +39 -29
- pyglet/model/codecs/base.py +4 -4
- pyglet/model/codecs/gltf.py +3 -3
- pyglet/model/codecs/obj.py +71 -43
- pyglet/resource.py +129 -78
- pyglet/shapes.py +147 -177
- pyglet/sprite.py +47 -164
- pyglet/text/__init__.py +44 -54
- pyglet/text/caret.py +12 -7
- pyglet/text/document.py +19 -17
- pyglet/text/formats/html.py +2 -2
- pyglet/text/formats/structured.py +10 -40
- pyglet/text/layout/__init__.py +20 -13
- pyglet/text/layout/base.py +176 -287
- pyglet/text/layout/incremental.py +9 -10
- pyglet/text/layout/scrolling.py +7 -95
- pyglet/window/__init__.py +183 -172
- pyglet/window/cocoa/__init__.py +62 -51
- pyglet/window/cocoa/pyglet_delegate.py +2 -25
- pyglet/window/cocoa/pyglet_view.py +9 -8
- pyglet/window/dialog/__init__.py +184 -0
- pyglet/window/dialog/base.py +99 -0
- pyglet/window/dialog/darwin.py +121 -0
- pyglet/window/dialog/linux.py +72 -0
- pyglet/window/dialog/windows.py +194 -0
- pyglet/window/emscripten/__init__.py +779 -0
- pyglet/window/headless/__init__.py +44 -28
- pyglet/window/key.py +2 -0
- pyglet/window/mouse.py +2 -2
- pyglet/window/wayland/__init__.py +377 -0
- pyglet/window/win32/__init__.py +101 -46
- pyglet/window/xlib/__init__.py +104 -66
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.12.dist-info → pyglet-3.0.dev1.dist-info}/WHEEL +1 -1
- pyglet/gl/__init__.py +0 -208
- pyglet/gl/base.py +0 -499
- pyglet/gl/cocoa.py +0 -309
- pyglet/gl/gl.py +0 -4625
- pyglet/gl/gl.pyi +0 -2320
- pyglet/gl/gl_compat.pyi +0 -3097
- pyglet/gl/gl_info.py +0 -190
- pyglet/gl/headless.py +0 -166
- pyglet/gl/wgl_info.py +0 -36
- pyglet/gl/wglext_nv.py +0 -1096
- pyglet/gl/win32.py +0 -268
- pyglet/gl/xlib.py +0 -295
- pyglet/image/buffer.py +0 -274
- pyglet/image/codecs/s3tc.py +0 -354
- pyglet/libs/x11/xrandr.py +0 -166
- pyglet-2.1.12.dist-info/RECORD +0 -234
- /pyglet/{libs/wayland → graphics/api/gl/cocoa}/__init__.py +0 -0
- /pyglet/libs/{egl → linux/egl}/egl.py +0 -0
- /pyglet/libs/{egl → linux/egl}/lib.py +0 -0
- /pyglet/libs/{ioctl.py → linux/ioctl.py} +0 -0
- /pyglet/libs/{wayland → linux/wayland}/gbm.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/__init__.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/cursorfont.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xlib.py +0 -0
- /pyglet/libs/{x11 → linux/x11}/xsync.py +0 -0
- {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})"
|