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,54 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
import pyglet
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from pyglet.graphics.api.webgl import OpenGLSurfaceContext
|
|
9
|
+
from pyglet.graphics.api.webgl.webgl_js import WebGLVertexArrayObject
|
|
10
|
+
|
|
11
|
+
__all__ = ['VertexArray']
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class VertexArray:
|
|
15
|
+
"""OpenGL Vertex Array Object."""
|
|
16
|
+
|
|
17
|
+
_context: OpenGLSurfaceContext | None
|
|
18
|
+
_id: WebGLVertexArrayObject
|
|
19
|
+
|
|
20
|
+
def __init__(self, context: OpenGLSurfaceContext) -> None:
|
|
21
|
+
"""Create an instance of a Vertex Array object."""
|
|
22
|
+
self._context = context
|
|
23
|
+
self._gl = self._context.gl
|
|
24
|
+
self._id = self._gl.createVertexArray()
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def id(self) -> WebGLVertexArrayObject | int:
|
|
28
|
+
return self._id
|
|
29
|
+
|
|
30
|
+
def bind(self) -> None:
|
|
31
|
+
self._gl.bindVertexArray(self._id)
|
|
32
|
+
|
|
33
|
+
def unbind(self) -> None:
|
|
34
|
+
self._gl.bindVertexArray(None)
|
|
35
|
+
|
|
36
|
+
def delete(self) -> None:
|
|
37
|
+
self._gl.deleteVertexArray(self._id)
|
|
38
|
+
self._id = None
|
|
39
|
+
|
|
40
|
+
__enter__ = bind
|
|
41
|
+
|
|
42
|
+
def __exit__(self, *_) -> None: # noqa: ANN002
|
|
43
|
+
self._gl.bindVertexArray(None)
|
|
44
|
+
|
|
45
|
+
def __del__(self) -> None:
|
|
46
|
+
if self._id is not None:
|
|
47
|
+
try:
|
|
48
|
+
self._context.delete_vao(self.id)
|
|
49
|
+
self._id = None
|
|
50
|
+
except (ImportError, AttributeError):
|
|
51
|
+
pass # Interpreter is shutting down
|
|
52
|
+
|
|
53
|
+
def __repr__(self) -> str:
|
|
54
|
+
return f"{self.__class__.__name__}(id={self._id})"
|
|
@@ -0,0 +1,616 @@
|
|
|
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 pyglet.graphics.api.base import SurfaceContext
|
|
29
|
+
from pyglet.graphics.api.webgl import vertexarray
|
|
30
|
+
from pyglet.graphics.api.webgl.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
|
+
)
|
|
44
|
+
from pyglet.graphics.api.webgl.enums import geometry_map
|
|
45
|
+
from pyglet.graphics.api.webgl.shader import GLAttribute
|
|
46
|
+
from pyglet.graphics.api.webgl.buffer import AttributeBufferObject, IndexedBufferObject
|
|
47
|
+
from pyglet.graphics.instance import InstanceBucket, BaseInstanceDomain, VertexInstanceBase
|
|
48
|
+
from pyglet.graphics.vertexdomain import (
|
|
49
|
+
VertexArrayBinding,
|
|
50
|
+
VertexArrayProtocol,
|
|
51
|
+
InstanceStream,
|
|
52
|
+
VertexStream,
|
|
53
|
+
IndexStream,
|
|
54
|
+
VertexListBase,
|
|
55
|
+
IndexedVertexListBase,
|
|
56
|
+
VertexDomainBase,
|
|
57
|
+
IndexedVertexDomainBase,
|
|
58
|
+
VertexGroupBucket,
|
|
59
|
+
_RunningIndexSupport,
|
|
60
|
+
InstanceIndexedVertexListBase,
|
|
61
|
+
InstancedIndexedVertexDomainBase,
|
|
62
|
+
InstancedVertexDomainBase,
|
|
63
|
+
InstanceVertexListBase,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
if TYPE_CHECKING:
|
|
67
|
+
from pyglet.graphics.shader import AttributeView
|
|
68
|
+
from pyglet.customtypes import CType, DataTypes
|
|
69
|
+
from pyglet.graphics import GeometryMode
|
|
70
|
+
from pyglet.graphics.shader import Attribute
|
|
71
|
+
from pyglet.graphics.api.webgl.context import OpenGLSurfaceContext
|
|
72
|
+
|
|
73
|
+
_c_types = {
|
|
74
|
+
GL_BYTE: ctypes.c_byte,
|
|
75
|
+
GL_UNSIGNED_BYTE: ctypes.c_ubyte,
|
|
76
|
+
GL_SHORT: ctypes.c_short,
|
|
77
|
+
GL_UNSIGNED_SHORT: ctypes.c_ushort,
|
|
78
|
+
GL_INT: ctypes.c_int,
|
|
79
|
+
GL_UNSIGNED_INT: ctypes.c_uint,
|
|
80
|
+
GL_FLOAT: ctypes.c_float,
|
|
81
|
+
GL_DOUBLE: ctypes.c_double,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_gl_types = {
|
|
85
|
+
'b': GL_BYTE,
|
|
86
|
+
'B': GL_UNSIGNED_BYTE,
|
|
87
|
+
'h': GL_SHORT,
|
|
88
|
+
'H': GL_UNSIGNED_SHORT,
|
|
89
|
+
'i': GL_INT,
|
|
90
|
+
'I': GL_UNSIGNED_INT,
|
|
91
|
+
'f': GL_FLOAT,
|
|
92
|
+
'd': GL_DOUBLE,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _make_attribute_property(name: str) -> property:
|
|
97
|
+
def _attribute_getter(self: VertexList) -> ctypes.Array[float | int]:
|
|
98
|
+
buffer = self.domain.attrib_name_buffers[name]
|
|
99
|
+
region = buffer.get_region(self.start, self.count)
|
|
100
|
+
buffer.invalidate_region(self.start, self.count)
|
|
101
|
+
return region
|
|
102
|
+
|
|
103
|
+
def _attribute_setter(self: VertexList, data: Any) -> None:
|
|
104
|
+
buffer = self.domain.attrib_name_buffers[name]
|
|
105
|
+
buffer.set_region(self.start, self.count, data)
|
|
106
|
+
|
|
107
|
+
return property(_attribute_getter, _attribute_setter)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class _GLVertexStreamMix(VertexStream):
|
|
111
|
+
_ctx: OpenGLSurfaceContext
|
|
112
|
+
attrib_name_buffers: dict[str, AttributeBufferObject]
|
|
113
|
+
|
|
114
|
+
def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute], *, divisor: int = 0):
|
|
115
|
+
super().__init__(ctx, initial_size, attrs, divisor=divisor)
|
|
116
|
+
|
|
117
|
+
def get_graphics_attribute(self, attribute: Attribute, view: AttributeView) -> GLAttribute:
|
|
118
|
+
return GLAttribute(attribute, view)
|
|
119
|
+
|
|
120
|
+
def get_buffer(self, size: int, attribute) -> AttributeBufferObject:
|
|
121
|
+
return AttributeBufferObject(self._ctx, size, attribute)
|
|
122
|
+
|
|
123
|
+
def bind_into(self, vao) -> None:
|
|
124
|
+
for attribute, buffer in zip(self.attribute_names.values(), self.buffers):
|
|
125
|
+
buffer.bind()
|
|
126
|
+
attribute.enable()
|
|
127
|
+
attribute.set_pointer()
|
|
128
|
+
attribute.set_divisor()
|
|
129
|
+
|
|
130
|
+
class GLVertexStream(_GLVertexStreamMix, VertexStream): # noqa: D101
|
|
131
|
+
def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute]) -> None:
|
|
132
|
+
"""Contains data for vertex stream.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
ctx:
|
|
136
|
+
The core context that owns this stream.
|
|
137
|
+
initial_size:
|
|
138
|
+
Initial buffer size.
|
|
139
|
+
attrs:
|
|
140
|
+
Attributes that will be used.
|
|
141
|
+
"""
|
|
142
|
+
super().__init__(ctx, initial_size, attrs)
|
|
143
|
+
|
|
144
|
+
class GLInstanceStream(_GLVertexStreamMix, InstanceStream): # noqa: D101
|
|
145
|
+
_ctx: OpenGLSurfaceContext
|
|
146
|
+
|
|
147
|
+
def __init__(self, ctx: OpenGLSurfaceContext, initial_size: int, attrs: Sequence[Attribute], # noqa: D107
|
|
148
|
+
*, divisor: int = 0) -> None:
|
|
149
|
+
super().__init__(ctx, initial_size, attrs, divisor=divisor)
|
|
150
|
+
|
|
151
|
+
class GLVertexArrayBinding(VertexArrayBinding): # noqa: D101
|
|
152
|
+
|
|
153
|
+
def _create_vao(self) -> VertexArrayProtocol:
|
|
154
|
+
return vertexarray.VertexArray(self._ctx)
|
|
155
|
+
|
|
156
|
+
def _link(self) -> None:
|
|
157
|
+
self.vao.bind()
|
|
158
|
+
for stream in self.streams:
|
|
159
|
+
stream.bind_into(self.vao)
|
|
160
|
+
self.vao.unbind()
|
|
161
|
+
|
|
162
|
+
def bind(self) -> None:
|
|
163
|
+
self.vao.bind()
|
|
164
|
+
|
|
165
|
+
def unbind(self) -> None:
|
|
166
|
+
self.vao.unbind()
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class VertexList(VertexListBase):
|
|
170
|
+
...
|
|
171
|
+
|
|
172
|
+
class InstanceVertexList(InstanceVertexListBase):
|
|
173
|
+
...
|
|
174
|
+
|
|
175
|
+
class IndexedVertexList(IndexedVertexListBase):
|
|
176
|
+
...
|
|
177
|
+
|
|
178
|
+
class InstanceIndexedVertexList(InstanceIndexedVertexListBase):
|
|
179
|
+
...
|
|
180
|
+
|
|
181
|
+
class GLIndexStream(IndexStream): # noqa: D101
|
|
182
|
+
index_element_size: int
|
|
183
|
+
index_c_type: CType
|
|
184
|
+
gl_type: int
|
|
185
|
+
|
|
186
|
+
def __init__(self, ctx: OpenGLSurfaceContext, data_type: DataTypes, initial_elems: int) -> None: # noqa: D107
|
|
187
|
+
self.gl_type = _gl_types[data_type]
|
|
188
|
+
self.index_c_type = _c_types[self.gl_type]
|
|
189
|
+
self.index_element_size = ctypes.sizeof(self.index_c_type)
|
|
190
|
+
super().__init__(ctx, data_type, initial_elems)
|
|
191
|
+
|
|
192
|
+
def _create_buffer(self) -> IndexedBufferObject:
|
|
193
|
+
return IndexedBufferObject(self.ctx, self.allocator.capacity * self.index_element_size,
|
|
194
|
+
self.index_c_type,
|
|
195
|
+
self.index_element_size,
|
|
196
|
+
1)
|
|
197
|
+
|
|
198
|
+
def bind_into(self, vao: VertexArrayBinding) -> None:
|
|
199
|
+
self.buffer.bind_to_index_buffer()
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class VertexDomain(VertexDomainBase):
|
|
203
|
+
"""Management of a set of vertex lists.
|
|
204
|
+
|
|
205
|
+
Construction of a vertex domain is usually done with the
|
|
206
|
+
:py:func:`create_domain` function.
|
|
207
|
+
"""
|
|
208
|
+
|
|
209
|
+
def __init__(self, context: SurfaceContext, initial_count: int, attribute_meta: dict[str, Attribute]) -> None:
|
|
210
|
+
super().__init__(context, initial_count, attribute_meta)
|
|
211
|
+
self._gl = context.gl
|
|
212
|
+
if self._supports_multi_draw:
|
|
213
|
+
self._multi_draw_array = self._gl.getExtension("WEBGL_multi_draw").multiDrawArraysWEBGL
|
|
214
|
+
else:
|
|
215
|
+
self._multi_draw_array = None
|
|
216
|
+
|
|
217
|
+
def draw_bucket(self, mode: int, bucket) -> None:
|
|
218
|
+
bucket.draw(self, mode)
|
|
219
|
+
|
|
220
|
+
def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
|
|
221
|
+
regions = []
|
|
222
|
+
for bucket in buckets:
|
|
223
|
+
regions.extend(bucket.merged_ranges)
|
|
224
|
+
|
|
225
|
+
start_list = [region[0] for region in regions]
|
|
226
|
+
size_list = [region[1] for region in regions]
|
|
227
|
+
primcount = len(regions)
|
|
228
|
+
if self._supports_multi_draw:
|
|
229
|
+
starts = (GLint * primcount)(*start_list)
|
|
230
|
+
sizes = (GLsizei * primcount)(*size_list)
|
|
231
|
+
self._multi_draw_array(starts[:], 0, sizes[:], 0, primcount)
|
|
232
|
+
else:
|
|
233
|
+
for start, size in zip(start_list, size_list):
|
|
234
|
+
self._gl.drawArrays(mode, start, size)
|
|
235
|
+
|
|
236
|
+
def _create_vertex_class(self) -> type:
|
|
237
|
+
return type(self._vertex_class.__name__, (self._vertex_class,), self.vertex_buffers._property_dict)
|
|
238
|
+
|
|
239
|
+
def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
|
|
240
|
+
return ctx.gl.getExtension("WEBGL_multi_draw")
|
|
241
|
+
|
|
242
|
+
def _create_vao(self) -> GLVertexArrayBinding:
|
|
243
|
+
return GLVertexArrayBinding(self._context, self._streams)
|
|
244
|
+
|
|
245
|
+
def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
|
|
246
|
+
self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
|
|
247
|
+
return [self.vertex_buffers]
|
|
248
|
+
|
|
249
|
+
def draw(self, mode: int) -> None:
|
|
250
|
+
"""Draw all vertices in the domain.
|
|
251
|
+
|
|
252
|
+
All vertices in the domain are drawn at once. This is the
|
|
253
|
+
most efficient way to render primitives.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
mode:
|
|
257
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
258
|
+
|
|
259
|
+
"""
|
|
260
|
+
self.vao.bind()
|
|
261
|
+
self.vertex_buffers.commit()
|
|
262
|
+
|
|
263
|
+
starts, sizes = self.vertex_buffers.allocator.get_allocated_regions()
|
|
264
|
+
primcount = len(starts)
|
|
265
|
+
if primcount == 0:
|
|
266
|
+
pass
|
|
267
|
+
elif primcount == 1:
|
|
268
|
+
# Common case
|
|
269
|
+
self._gl.drawArrays(mode, starts[0], sizes[0])
|
|
270
|
+
else:
|
|
271
|
+
if self._multi_draw_array:
|
|
272
|
+
starts = (GLint * primcount)(*starts)
|
|
273
|
+
sizes = (GLsizei * primcount)(*sizes)
|
|
274
|
+
self._multi_draw_array(starts[:], 0, sizes[:], 0, primcount)
|
|
275
|
+
else:
|
|
276
|
+
# If not available, draw separately.
|
|
277
|
+
for start, size in zip(starts, sizes):
|
|
278
|
+
self._gl.drawArrays(mode, start, size)
|
|
279
|
+
|
|
280
|
+
def draw_subset(self, mode: GeometryMode, vertex_list: VertexList) -> None:
|
|
281
|
+
"""Draw a specific VertexList in the domain.
|
|
282
|
+
|
|
283
|
+
The `vertex_list` parameter specifies a :py:class:`VertexList`
|
|
284
|
+
to draw. Only primitives in that list will be drawn.
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
mode:
|
|
288
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
289
|
+
vertex_list:
|
|
290
|
+
Vertex list to draw.
|
|
291
|
+
|
|
292
|
+
"""
|
|
293
|
+
self.vao.bind()
|
|
294
|
+
self.vertex_buffers.commit()
|
|
295
|
+
self._gl.drawArrays(geometry_map[mode], vertex_list.start, vertex_list.count)
|
|
296
|
+
|
|
297
|
+
@property
|
|
298
|
+
def is_empty(self) -> bool:
|
|
299
|
+
return not self.vertex_buffers.allocator.starts
|
|
300
|
+
|
|
301
|
+
def __repr__(self) -> str:
|
|
302
|
+
return f'<{self.__class__.__name__}@{id(self):x} vertex_alloc={self.vertex_buffers.allocator}>'
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
class GLInstanceDomainArrays(BaseInstanceDomain): # noqa: D101
|
|
306
|
+
def __init__(self, domain: Any, initial_instances: int) -> None:
|
|
307
|
+
super().__init__(domain, initial_instances)
|
|
308
|
+
self._ctx = domain._context # noqa: SLF001
|
|
309
|
+
self._gl = domain._context.gl # noqa: SLF001
|
|
310
|
+
|
|
311
|
+
def _create_bucket_arrays(self) -> InstanceBucket:
|
|
312
|
+
istream = GLInstanceStream(self._ctx, self._initial, self._domain.per_instance, divisor=1)
|
|
313
|
+
vao = GLVertexArrayBinding(self._ctx, [self._domain.vertex_buffers, istream])
|
|
314
|
+
return InstanceBucket(istream, vao)
|
|
315
|
+
|
|
316
|
+
def _create_bucket_elements(self) -> InstanceBucket:
|
|
317
|
+
raise NotImplementedError("Use GLInstanceDomainElements for indexed draws")
|
|
318
|
+
|
|
319
|
+
def draw(self, mode: int) -> None:
|
|
320
|
+
for key, bucket in self._buckets.items():
|
|
321
|
+
if bucket.instance_count <= 0:
|
|
322
|
+
continue
|
|
323
|
+
first_vertex, vertex_count = self._geom[bucket]
|
|
324
|
+
bucket.vao.bind()
|
|
325
|
+
bucket.stream.commit()
|
|
326
|
+
self._gl.drawArraysInstanced(mode, first_vertex, vertex_count, bucket.instance_count)
|
|
327
|
+
|
|
328
|
+
def draw_subset(self, mode: int, vertex_list: InstanceVertexList):
|
|
329
|
+
"""Draw a specific VertexList in the domain."""
|
|
330
|
+
bucket = vertex_list.bucket
|
|
331
|
+
bucket.vao.bind()
|
|
332
|
+
bucket.stream.commit()
|
|
333
|
+
self._gl.drawArraysInstanced(mode, vertex_list.start, vertex_list.count, bucket.instance_count)
|
|
334
|
+
|
|
335
|
+
class GLInstanceDomainElements(BaseInstanceDomain): # noqa: D101
|
|
336
|
+
_ctx: OpenGLSurfaceContext
|
|
337
|
+
|
|
338
|
+
def __init__(self, domain: Any, initial_instances: int, index_stream: GLIndexStream) -> None:
|
|
339
|
+
super().__init__(domain, initial_instances)
|
|
340
|
+
self._ctx = domain._context # noqa: SLF001
|
|
341
|
+
self._gl = domain._context.gl # noqa: SLF001
|
|
342
|
+
self._index_stream = index_stream
|
|
343
|
+
self._index_gl_type = self._index_stream.gl_type
|
|
344
|
+
self._elem_size = index_stream.index_element_size
|
|
345
|
+
|
|
346
|
+
def _create_bucket_elements(self) -> InstanceBucket:
|
|
347
|
+
istream = GLInstanceStream(self._ctx, self._initial, self._domain.per_instance, divisor=1)
|
|
348
|
+
vao = GLVertexArrayBinding(self._ctx, [self._domain.vertex_buffers, istream, self._index_stream])
|
|
349
|
+
return InstanceBucket(istream, vao)
|
|
350
|
+
|
|
351
|
+
def _create_bucket_arrays(self) -> InstanceBucket:
|
|
352
|
+
raise NotImplementedError("Use GLInstanceDomainArrays for non-indexed draws")
|
|
353
|
+
|
|
354
|
+
def draw_bucket(self, mode: int, bucket: InstanceBucket) -> None:
|
|
355
|
+
if bucket.instance_count <= 0:
|
|
356
|
+
return
|
|
357
|
+
first_index, index_count, _, _ = self._geom[bucket]
|
|
358
|
+
byte_offset = first_index * self._elem_size
|
|
359
|
+
bucket.vao.bind()
|
|
360
|
+
bucket.stream.commit()
|
|
361
|
+
self._gl.drawElementsInstanced(
|
|
362
|
+
mode, index_count, self._index_gl_type, byte_offset,
|
|
363
|
+
bucket.instance_count,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
def draw_subset(self, mode: GeometryMode, vertex_list: InstanceIndexedVertexList) -> None:
|
|
367
|
+
"""Draw a specific VertexList in the domain."""
|
|
368
|
+
byte_offset = vertex_list.index_start * self._elem_size
|
|
369
|
+
self._gl.drawElementsInstanced(
|
|
370
|
+
mode, vertex_list.index_count, self._index_gl_type, byte_offset,
|
|
371
|
+
vertex_list.bucket.instance_count,
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
def draw(self, mode: int) -> None:
|
|
375
|
+
for key, bucket in self._buckets.items():
|
|
376
|
+
if bucket.instance_count <= 0:
|
|
377
|
+
continue
|
|
378
|
+
first_index, index_count, _, _ = self._geom[bucket]
|
|
379
|
+
byte_offset = first_index * self._elem_size
|
|
380
|
+
bucket.vao.bind()
|
|
381
|
+
bucket.stream.commit()
|
|
382
|
+
self._gl.drawElementsInstanced(
|
|
383
|
+
mode, index_count, self._index_gl_type, byte_offset,
|
|
384
|
+
bucket.instance_count,
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
|
|
388
|
+
class InstancedVertexDomain(InstancedVertexDomainBase): # noqa: D101
|
|
389
|
+
_vertexinstance_class: type
|
|
390
|
+
_vertex_class = InstanceVertexList
|
|
391
|
+
|
|
392
|
+
def _create_vertex_class(self) -> type:
|
|
393
|
+
return type(self._vertex_class.__name__, (self._vertex_class,), self.vertex_buffers._property_dict)
|
|
394
|
+
|
|
395
|
+
def _has_multi_draw_extension(self, ctx):
|
|
396
|
+
return False
|
|
397
|
+
|
|
398
|
+
def _create_vao(self) -> GLVertexArrayBinding:
|
|
399
|
+
return GLVertexArrayBinding(self._context, self._streams)
|
|
400
|
+
|
|
401
|
+
def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
|
|
402
|
+
self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
|
|
403
|
+
return [self.vertex_buffers]
|
|
404
|
+
|
|
405
|
+
def create_instance_domain(self, size: int) -> BaseInstanceDomain:
|
|
406
|
+
return GLInstanceDomainArrays(self, size)
|
|
407
|
+
|
|
408
|
+
def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
|
|
409
|
+
"""Draw a specific VertexGroupBucket in the domain."""
|
|
410
|
+
self.instance_domain.draw(mode)
|
|
411
|
+
|
|
412
|
+
def _create_vao(self) -> None:
|
|
413
|
+
"""Handled by buckets."""
|
|
414
|
+
|
|
415
|
+
def draw(self, mode: int) -> None:
|
|
416
|
+
"""Draw all vertices in the domain.
|
|
417
|
+
|
|
418
|
+
All vertices in the domain are drawn at once. This is the
|
|
419
|
+
most efficient way to render primitives.
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
mode:
|
|
423
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
self.vertex_buffers.commit()
|
|
427
|
+
self.instance_buckets.draw(mode)
|
|
428
|
+
|
|
429
|
+
def draw_subset(self, mode: GeometryMode, vertex_list: InstanceVertexList) -> None:
|
|
430
|
+
"""Draw a specific VertexList in the domain.
|
|
431
|
+
|
|
432
|
+
The `vertex_list` parameter specifies a :py:class:`VertexList`
|
|
433
|
+
to draw. Only primitives in that list will be drawn.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
mode:
|
|
437
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
438
|
+
vertex_list:
|
|
439
|
+
Vertex list to draw.
|
|
440
|
+
"""
|
|
441
|
+
self.vertex_buffers.commit()
|
|
442
|
+
self.instance_buckets.draw_subset(geometry_map[mode], vertex_list)
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
class IndexedVertexDomain(IndexedVertexDomainBase):
|
|
447
|
+
"""Management of a set of indexed vertex lists.
|
|
448
|
+
|
|
449
|
+
Construction of an indexed vertex domain is usually done with the
|
|
450
|
+
:py:func:`create_domain` function.
|
|
451
|
+
"""
|
|
452
|
+
|
|
453
|
+
_vertex_class = IndexedVertexList
|
|
454
|
+
_supports_base_vertex: bool = False
|
|
455
|
+
|
|
456
|
+
def __init__(self, context: SurfaceContext, initial_count: int, attribute_meta: dict[str, Attribute],
|
|
457
|
+
index_type: DataTypes = "I") -> None:
|
|
458
|
+
super().__init__(context, initial_count, attribute_meta, index_type)
|
|
459
|
+
self._gl = context.gl
|
|
460
|
+
if self._supports_multi_draw:
|
|
461
|
+
self._multi_draw_elements = self._gl.getExtension("WEBGL_multi_draw").multiDrawElementsWEBGL
|
|
462
|
+
else:
|
|
463
|
+
self._multi_draw_elements = None
|
|
464
|
+
|
|
465
|
+
def _create_vertex_class(self) -> type:
|
|
466
|
+
return type(self._vertex_class.__name__, (_RunningIndexSupport, self._vertex_class),
|
|
467
|
+
self.vertex_buffers._property_dict) # noqa: SLF001
|
|
468
|
+
|
|
469
|
+
def _create_vao(self) -> GLVertexArrayBinding:
|
|
470
|
+
return GLVertexArrayBinding(self._context, self._streams)
|
|
471
|
+
|
|
472
|
+
def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
|
|
473
|
+
self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
|
|
474
|
+
self.index_stream = GLIndexStream(self._context, self.index_type, size)
|
|
475
|
+
return [self.vertex_buffers, self.index_stream]
|
|
476
|
+
|
|
477
|
+
def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
|
|
478
|
+
regions = []
|
|
479
|
+
for bucket in buckets:
|
|
480
|
+
regions.extend(bucket.merged_ranges)
|
|
481
|
+
|
|
482
|
+
start_list = [region[0] for region in regions]
|
|
483
|
+
size_list = [region[1] for region in regions]
|
|
484
|
+
primcount = len(regions)
|
|
485
|
+
if self._supports_multi_draw:
|
|
486
|
+
starts = [s * self.index_stream.index_element_size for s in start_list]
|
|
487
|
+
starts = (ctypes.POINTER(GLvoid) * primcount)(*(GLintptr * primcount)(*starts))
|
|
488
|
+
sizes = (GLsizei * primcount)(*size_list)
|
|
489
|
+
self._multi_draw_elements(mode, sizes[:], 0, self.index_stream.gl_type, starts[:], 0, primcount)
|
|
490
|
+
else:
|
|
491
|
+
for start, size in zip(start_list, size_list):
|
|
492
|
+
self._gl.drawElements(mode, size, self.index_stream.gl_type,
|
|
493
|
+
start * self.index_stream.index_element_size)
|
|
494
|
+
|
|
495
|
+
def _has_multi_draw_extension(self, ctx: OpenGLSurfaceContext) -> bool:
|
|
496
|
+
return ctx.gl.getExtension("WEBGL_multi_draw")
|
|
497
|
+
|
|
498
|
+
def draw(self, mode: int) -> None:
|
|
499
|
+
"""Draw all vertices in the domain.
|
|
500
|
+
|
|
501
|
+
All vertices in the domain are drawn at once. This is the
|
|
502
|
+
most efficient way to render primitives.
|
|
503
|
+
|
|
504
|
+
Args:
|
|
505
|
+
mode:
|
|
506
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
507
|
+
|
|
508
|
+
"""
|
|
509
|
+
self.vao.bind()
|
|
510
|
+
self.vertex_buffers.commit()
|
|
511
|
+
self.index_stream.buffer.commit()
|
|
512
|
+
|
|
513
|
+
starts, sizes = self.index_stream.allocator.get_allocated_regions()
|
|
514
|
+
primcount = len(starts)
|
|
515
|
+
if primcount == 0:
|
|
516
|
+
pass
|
|
517
|
+
elif primcount == 1:
|
|
518
|
+
# Common case
|
|
519
|
+
self._gl.drawElements(mode, sizes[0], self.index_stream.gl_type, starts[0] * self.index_stream.index_element_size)
|
|
520
|
+
else:
|
|
521
|
+
if self._multi_draw_elements:
|
|
522
|
+
starts = [s * self.index_stream.index_element_size for s in starts]
|
|
523
|
+
starts = (ctypes.POINTER(GLvoid) * primcount)(*(GLintptr * primcount)(*starts))
|
|
524
|
+
sizes = (GLsizei * primcount)(*sizes)
|
|
525
|
+
self._multi_draw_elements(mode, sizes[:], 0, self.index_stream.gl_type, starts[:], 0, primcount)
|
|
526
|
+
else:
|
|
527
|
+
for start, size in zip(starts, sizes):
|
|
528
|
+
self._gl.drawElements(mode, size, self.index_stream.gl_type,
|
|
529
|
+
start * self.index_stream.index_element_size)
|
|
530
|
+
|
|
531
|
+
def draw_subset(self, mode: GeometryMode, vertex_list: IndexedVertexList) -> None:
|
|
532
|
+
"""Draw a specific IndexedVertexList in the domain.
|
|
533
|
+
|
|
534
|
+
The `vertex_list` parameter specifies a :py:class:`IndexedVertexList`
|
|
535
|
+
to draw. Only primitives in that list will be drawn.
|
|
536
|
+
|
|
537
|
+
Args:
|
|
538
|
+
mode:
|
|
539
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
540
|
+
vertex_list:
|
|
541
|
+
Vertex list to draw.
|
|
542
|
+
"""
|
|
543
|
+
self.vao.bind()
|
|
544
|
+
self.vertex_buffers.commit()
|
|
545
|
+
self.index_stream.buffer.commit()
|
|
546
|
+
|
|
547
|
+
self._gl.drawElements(geometry_map[mode], vertex_list.index_count, self.index_stream.gl_type,
|
|
548
|
+
vertex_list.index_start * self.index_stream.index_element_size)
|
|
549
|
+
|
|
550
|
+
|
|
551
|
+
class InstancedIndexedVertexDomain(InstancedIndexedVertexDomainBase):
|
|
552
|
+
"""Management of a set of indexed vertex lists.
|
|
553
|
+
|
|
554
|
+
Construction of an indexed vertex domain is usually done with the
|
|
555
|
+
:py:func:`create_domain` function.
|
|
556
|
+
"""
|
|
557
|
+
_initial_index_count: int = 16
|
|
558
|
+
_vertex_class = InstanceIndexedVertexList
|
|
559
|
+
|
|
560
|
+
def _create_vertex_class(self) -> type:
|
|
561
|
+
return type(self._vertex_class.__name__, (_RunningIndexSupport, self._vertex_class),
|
|
562
|
+
self.vertex_buffers._property_dict) # noqa: SLF001
|
|
563
|
+
|
|
564
|
+
def _create_vao(self) -> GLVertexArrayBinding:
|
|
565
|
+
return GLVertexArrayBinding(self._context, self._streams)
|
|
566
|
+
|
|
567
|
+
def _create_streams(self, size: int) -> list[VertexStream | IndexStream | InstanceStream]:
|
|
568
|
+
self.vertex_buffers = GLVertexStream(self._context, size, self.per_vertex)
|
|
569
|
+
self.index_stream = GLIndexStream(self._context, self.index_type, size)
|
|
570
|
+
return [self.vertex_buffers, self.index_stream]
|
|
571
|
+
|
|
572
|
+
def create_instance_domain(self, size: int) -> GLInstanceDomainElements:
|
|
573
|
+
return GLInstanceDomainElements(self, size, index_stream=self.index_stream)
|
|
574
|
+
|
|
575
|
+
def _has_multi_draw_extension(self, ctx):
|
|
576
|
+
return False
|
|
577
|
+
|
|
578
|
+
def _create_vao(self) -> None:
|
|
579
|
+
"""Handled by buckets."""
|
|
580
|
+
|
|
581
|
+
def draw(self, mode: int) -> None:
|
|
582
|
+
"""Draw all vertices in the domain.
|
|
583
|
+
|
|
584
|
+
All vertices in the domain are drawn at once. This is the
|
|
585
|
+
most efficient way to render primitives.
|
|
586
|
+
|
|
587
|
+
Args:
|
|
588
|
+
mode:
|
|
589
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
590
|
+
|
|
591
|
+
"""
|
|
592
|
+
self.vertex_buffers.commit()
|
|
593
|
+
self.index_stream.commit()
|
|
594
|
+
self.instance_domain.draw(mode)
|
|
595
|
+
def draw_buckets(self, mode: int, buckets: list[VertexGroupBucket]) -> None:
|
|
596
|
+
"""Draw a specific VertexGroupBucket in the domain."""
|
|
597
|
+
for bucket in buckets:
|
|
598
|
+
for vl_range in bucket.ranges:
|
|
599
|
+
self.instance_domain.draw_bucket(mode, self._instance_map[vl_range])
|
|
600
|
+
|
|
601
|
+
def draw_subset(self, mode: GeometryMode, vertex_list: InstanceIndexedVertexListBase) -> None:
|
|
602
|
+
"""Draw a specific IndexedVertexList in the domain.
|
|
603
|
+
|
|
604
|
+
The ``vertex_list`` parameter specifies a :py:class:`IndexedVertexList`
|
|
605
|
+
to draw. Only primitives in that list will be drawn.
|
|
606
|
+
|
|
607
|
+
Args:
|
|
608
|
+
mode:
|
|
609
|
+
OpenGL drawing mode, e.g. ``GL_POINTS``, ``GL_LINES``, etc.
|
|
610
|
+
vertex_list:
|
|
611
|
+
Vertex list to draw.
|
|
612
|
+
|
|
613
|
+
"""
|
|
614
|
+
self.vertex_buffers.commit()
|
|
615
|
+
self.index_stream.commit()
|
|
616
|
+
self.instance_domain.draw_subset(geometry_map[mode], vertex_list)
|