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