pyglet 2.1.13__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 +5 -21
- 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 +28 -8
- 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 +154 -194
- 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.13.dist-info → pyglet-3.0.dev1.dist-info}/METADATA +2 -3
- pyglet-3.0.dev1.dist-info/RECORD +322 -0
- {pyglet-2.1.13.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.13.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.13.dist-info/licenses → pyglet-3.0.dev1.dist-info}/LICENSE +0 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"""Byte abstractions of OpenGL Buffer Objects.
|
|
2
|
+
|
|
3
|
+
Use `create_buffer` to create a Buffer Object.
|
|
4
|
+
|
|
5
|
+
Buffers can optionally be created "mappable" (incorporating the
|
|
6
|
+
`AbstractMappable` mix-in). In this case the buffer provides a ``get_region``
|
|
7
|
+
method which provides the most efficient path for updating partial data within
|
|
8
|
+
the buffer.
|
|
9
|
+
"""
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import ctypes
|
|
13
|
+
import sys
|
|
14
|
+
from functools import lru_cache
|
|
15
|
+
from typing import TYPE_CHECKING, Sequence
|
|
16
|
+
|
|
17
|
+
from ctypes import Array
|
|
18
|
+
|
|
19
|
+
from pyglet.graphics.api.gl import (
|
|
20
|
+
GL_ARRAY_BUFFER,
|
|
21
|
+
GL_DYNAMIC_DRAW,
|
|
22
|
+
GL_ELEMENT_ARRAY_BUFFER,
|
|
23
|
+
GL_MAP_READ_BIT,
|
|
24
|
+
GL_MAP_WRITE_BIT,
|
|
25
|
+
GL_WRITE_ONLY,
|
|
26
|
+
GLubyte,
|
|
27
|
+
GLuint,
|
|
28
|
+
glBindBuffer,
|
|
29
|
+
glBufferData,
|
|
30
|
+
glBufferSubData,
|
|
31
|
+
glDeleteBuffers,
|
|
32
|
+
glGenBuffers,
|
|
33
|
+
glMapBuffer,
|
|
34
|
+
glMapBufferRange,
|
|
35
|
+
glUnmapBuffer, OpenGLSurfaceContext,
|
|
36
|
+
)
|
|
37
|
+
from pyglet.graphics.buffer import AbstractBuffer
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from pyglet.customtypes import CType, CTypesPointer
|
|
41
|
+
from pyglet.graphics.shader import GraphicsAttribute
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class BufferObject(AbstractBuffer):
|
|
45
|
+
"""Lightweight representation of an OpenGL Buffer Object.
|
|
46
|
+
|
|
47
|
+
The data in the buffer is not replicated in any system memory (unless it
|
|
48
|
+
is done so by the video driver). While this can improve memory usage and
|
|
49
|
+
possibly performance, updates to the buffer are relatively slow.
|
|
50
|
+
The target of the buffer is ``GL_ARRAY_BUFFER`` internally to avoid
|
|
51
|
+
accidentally overriding other states when altering the buffer contents.
|
|
52
|
+
The intended target can be set when binding the buffer.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
id: int
|
|
56
|
+
size: int
|
|
57
|
+
usage: int
|
|
58
|
+
_context: OpenGLSurfaceContext | None
|
|
59
|
+
|
|
60
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, usage: int = GL_DYNAMIC_DRAW) -> None:
|
|
61
|
+
"""Initialize the BufferObject with the given size and draw usage."""
|
|
62
|
+
super().__init__('b', size)
|
|
63
|
+
self.usage = usage
|
|
64
|
+
self._context = context
|
|
65
|
+
|
|
66
|
+
buffer_id = GLuint()
|
|
67
|
+
glGenBuffers(1, buffer_id)
|
|
68
|
+
self.id = buffer_id.value
|
|
69
|
+
|
|
70
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
71
|
+
data = (GLubyte * self.size)()
|
|
72
|
+
glBufferData(GL_ARRAY_BUFFER, self.size, data, self.usage)
|
|
73
|
+
|
|
74
|
+
def invalidate(self) -> None:
|
|
75
|
+
glBufferData(GL_ARRAY_BUFFER, self.size, None, self.usage)
|
|
76
|
+
|
|
77
|
+
def bind(self, target: int = GL_ARRAY_BUFFER) -> None:
|
|
78
|
+
glBindBuffer(target, self.id)
|
|
79
|
+
|
|
80
|
+
def unbind(self) -> None:
|
|
81
|
+
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
|
82
|
+
|
|
83
|
+
def bind_to_index_buffer(self) -> None:
|
|
84
|
+
"""Binds this buffer as an index buffer on the active vertex array."""
|
|
85
|
+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
|
|
86
|
+
|
|
87
|
+
def set_data(self, data: Sequence[int] | CTypesPointer) -> None:
|
|
88
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
89
|
+
glBufferData(GL_ARRAY_BUFFER, self.size, data, self.usage)
|
|
90
|
+
|
|
91
|
+
def set_data_region(self, data: Sequence[int] | CTypesPointer, start: int, length: int) -> None:
|
|
92
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
93
|
+
glBufferSubData(GL_ARRAY_BUFFER, start, length, data)
|
|
94
|
+
|
|
95
|
+
def map(self) -> CTypesPointer[ctypes.c_byte]:
|
|
96
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
97
|
+
return ctypes.cast(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY),
|
|
98
|
+
ctypes.POINTER(ctypes.c_byte * self.size)).contents
|
|
99
|
+
|
|
100
|
+
def map_range(self, start: int, size: int, ptr_type: type[CTypesPointer]) -> CTypesPointer:
|
|
101
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
102
|
+
return ctypes.cast(glMapBufferRange(GL_ARRAY_BUFFER, start, size, GL_MAP_WRITE_BIT), ptr_type).contents
|
|
103
|
+
|
|
104
|
+
def unmap(self) -> None:
|
|
105
|
+
glUnmapBuffer(GL_ARRAY_BUFFER)
|
|
106
|
+
|
|
107
|
+
def delete(self) -> None:
|
|
108
|
+
glDeleteBuffers(1, GLuint(self.id))
|
|
109
|
+
self.id = None
|
|
110
|
+
|
|
111
|
+
def __del__(self) -> None:
|
|
112
|
+
if self.id is not None:
|
|
113
|
+
try:
|
|
114
|
+
self._context.delete_buffer(self.id)
|
|
115
|
+
self.id = None
|
|
116
|
+
except (AttributeError, ImportError):
|
|
117
|
+
pass # Interpreter is shutting down
|
|
118
|
+
|
|
119
|
+
def resize(self, size: int) -> None:
|
|
120
|
+
# Map, create a copy, then reinitialize.
|
|
121
|
+
temp = (ctypes.c_byte * size)()
|
|
122
|
+
|
|
123
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
124
|
+
data = glMapBufferRange(GL_ARRAY_BUFFER, 0, self.size, GL_MAP_READ_BIT)
|
|
125
|
+
ctypes.memmove(temp, data, min(size, self.size))
|
|
126
|
+
glUnmapBuffer(GL_ARRAY_BUFFER)
|
|
127
|
+
|
|
128
|
+
self.size = size
|
|
129
|
+
glBufferData(GL_ARRAY_BUFFER, self.size, temp, self.usage)
|
|
130
|
+
|
|
131
|
+
def get_bytes(self) -> bytes:
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
def get_bytes_region(self, offset: int, length: int) -> bytes:
|
|
135
|
+
...
|
|
136
|
+
|
|
137
|
+
def get_data(self) -> ctypes.Array[CType]:
|
|
138
|
+
...
|
|
139
|
+
|
|
140
|
+
def get_data_region(self, start: int, length: int) -> ctypes.Array[CType]:
|
|
141
|
+
...
|
|
142
|
+
|
|
143
|
+
def set_bytes(self, data: bytes) -> None:
|
|
144
|
+
...
|
|
145
|
+
|
|
146
|
+
def set_bytes_region(self, start: int, length: int) -> None:
|
|
147
|
+
...
|
|
148
|
+
|
|
149
|
+
def set_data_ptr(self, offset: int, length: int, ptr: CTypesPointer) -> None:
|
|
150
|
+
...
|
|
151
|
+
|
|
152
|
+
def __repr__(self) -> str:
|
|
153
|
+
return f"{self.__class__.__name__}(id={self.id}, size={self.size})"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class BackedBufferObject(BufferObject):
|
|
157
|
+
"""A buffer with system-memory backed store.
|
|
158
|
+
|
|
159
|
+
Updates to the data via `set_data` and `set_data_region` will be held
|
|
160
|
+
in local memory until `buffer_data` is called. The advantage is that
|
|
161
|
+
fewer OpenGL calls are needed, which can increasing performance at the
|
|
162
|
+
expense of system memory.
|
|
163
|
+
"""
|
|
164
|
+
data: CType
|
|
165
|
+
data_ptr: int
|
|
166
|
+
_dirty_min: int
|
|
167
|
+
_dirty_max: int
|
|
168
|
+
_dirty: bool
|
|
169
|
+
stride: int
|
|
170
|
+
element_count: int
|
|
171
|
+
ctype: CType
|
|
172
|
+
|
|
173
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
|
|
174
|
+
usage: int = GL_DYNAMIC_DRAW) -> None:
|
|
175
|
+
super().__init__(context, size, usage)
|
|
176
|
+
|
|
177
|
+
self.c_type = c_type
|
|
178
|
+
self._ctypes_size = ctypes.sizeof(c_type)
|
|
179
|
+
number = size // self._ctypes_size
|
|
180
|
+
self.data = (c_type * number)()
|
|
181
|
+
self.data_ptr = ctypes.addressof(self.data)
|
|
182
|
+
|
|
183
|
+
self._dirty_min = sys.maxsize
|
|
184
|
+
self._dirty_max = 0
|
|
185
|
+
self._dirty = False
|
|
186
|
+
|
|
187
|
+
self.stride = stride
|
|
188
|
+
self.element_count = element_count
|
|
189
|
+
|
|
190
|
+
def commit(self) -> None:
|
|
191
|
+
"""Commits all saved changes to the underlying buffer before drawing.
|
|
192
|
+
|
|
193
|
+
Allows submitting multiple changes at once, rather than having to call glBufferSubData for every change.
|
|
194
|
+
"""
|
|
195
|
+
# GL 2.0 we will need to bind it each draw cycle.
|
|
196
|
+
glBindBuffer(GL_ARRAY_BUFFER, self.id)
|
|
197
|
+
|
|
198
|
+
if not self._dirty:
|
|
199
|
+
return
|
|
200
|
+
|
|
201
|
+
size = self._dirty_max - self._dirty_min
|
|
202
|
+
if size > 0:
|
|
203
|
+
if size == self.size:
|
|
204
|
+
glBufferData(GL_ARRAY_BUFFER, self.size, self.data, self.usage)
|
|
205
|
+
else:
|
|
206
|
+
glBufferSubData(GL_ARRAY_BUFFER, self._dirty_min, size, self.data_ptr + self._dirty_min)
|
|
207
|
+
|
|
208
|
+
self._dirty_min = sys.maxsize
|
|
209
|
+
self._dirty_max = 0
|
|
210
|
+
self._dirty = False
|
|
211
|
+
|
|
212
|
+
@lru_cache(maxsize=None) # noqa: B019
|
|
213
|
+
def get_region(self, start: int, count: int) -> Array[CType]:
|
|
214
|
+
byte_start = self.stride * start # byte offset
|
|
215
|
+
array_count = self.element_count * count # number of values
|
|
216
|
+
ptr_type = ctypes.POINTER(self.c_type * array_count)
|
|
217
|
+
return ctypes.cast(self.data_ptr + byte_start, ptr_type).contents
|
|
218
|
+
|
|
219
|
+
def set_region(self, start: int, count: int, data: Sequence[float]) -> None:
|
|
220
|
+
array_start = self.element_count * start
|
|
221
|
+
array_end = self.element_count * count + array_start
|
|
222
|
+
|
|
223
|
+
self.data[array_start:array_end] = data
|
|
224
|
+
|
|
225
|
+
# replicated from self.invalidate_region
|
|
226
|
+
byte_start = self.stride * start
|
|
227
|
+
byte_end = byte_start + self.stride * count
|
|
228
|
+
# As of Python 3.11, this is faster than min/max:
|
|
229
|
+
if byte_start < self._dirty_min:
|
|
230
|
+
self._dirty_min = byte_start
|
|
231
|
+
if byte_end > self._dirty_max:
|
|
232
|
+
self._dirty_max = byte_end
|
|
233
|
+
self._dirty = True
|
|
234
|
+
|
|
235
|
+
def resize(self, size: int) -> None:
|
|
236
|
+
# size is the allocator size * attribute.stride
|
|
237
|
+
number = size // ctypes.sizeof(self.c_type)
|
|
238
|
+
data = (self.c_type * number)()
|
|
239
|
+
ctypes.memmove(data, self.data, min(size, self.size))
|
|
240
|
+
self.data = data
|
|
241
|
+
self.data_ptr = ctypes.addressof(data)
|
|
242
|
+
self.size = size
|
|
243
|
+
|
|
244
|
+
# Set the dirty range to be the entire buffer.
|
|
245
|
+
self._dirty_min = 0
|
|
246
|
+
self._dirty_max = self.size
|
|
247
|
+
self._dirty = True
|
|
248
|
+
|
|
249
|
+
self.get_region.cache_clear()
|
|
250
|
+
|
|
251
|
+
def invalidate(self) -> None:
|
|
252
|
+
super().invalidate()
|
|
253
|
+
self._dirty = True
|
|
254
|
+
|
|
255
|
+
def invalidate_region(self, start: int, count: int) -> None:
|
|
256
|
+
byte_start = self.stride * start
|
|
257
|
+
byte_end = byte_start + self.stride * count
|
|
258
|
+
# As of Python 3.11, this is faster than min/max:
|
|
259
|
+
if byte_start < self._dirty_min:
|
|
260
|
+
self._dirty_min = byte_start
|
|
261
|
+
if byte_end > self._dirty_max:
|
|
262
|
+
self._dirty_max = byte_end
|
|
263
|
+
self._dirty = True
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
class AttributeBufferObject(BackedBufferObject):
|
|
267
|
+
"""A backed buffer used for Shader Program attributes."""
|
|
268
|
+
|
|
269
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, graphics_attr: GraphicsAttribute) -> None:
|
|
270
|
+
# size is the allocator size * attribute.stride (buffer size)
|
|
271
|
+
super().__init__(context, size, graphics_attr.attribute.c_type,
|
|
272
|
+
graphics_attr.view.stride,
|
|
273
|
+
graphics_attr.attribute.fmt.components)
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
class IndexedBufferObject(BackedBufferObject):
|
|
277
|
+
"""A backed buffer used for indices."""
|
|
278
|
+
|
|
279
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
|
|
280
|
+
usage: int = GL_DYNAMIC_DRAW) -> None:
|
|
281
|
+
super().__init__(context, size, c_type, stride, element_count, usage)
|
|
282
|
+
|
|
283
|
+
# def bind_to_index_buffer(self) -> None:
|
|
284
|
+
# """Binds this buffer as an index buffer on the active vertex array."""
|
|
285
|
+
# self._context.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
|
|
286
|
+
|
|
287
|
+
def commit(self) -> None:
|
|
288
|
+
"""Commits all saved changes to the underlying buffer before drawing.
|
|
289
|
+
|
|
290
|
+
Allows submitting multiple changes at once, rather than having to call glBufferSubData for every change.
|
|
291
|
+
"""
|
|
292
|
+
# GL 2.0 we will need to bind it each draw cycle.
|
|
293
|
+
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
|
|
294
|
+
|
|
295
|
+
if not self._dirty:
|
|
296
|
+
return
|
|
297
|
+
|
|
298
|
+
size = self._dirty_max - self._dirty_min
|
|
299
|
+
if size > 0:
|
|
300
|
+
if size == self.size:
|
|
301
|
+
glBufferData(GL_ELEMENT_ARRAY_BUFFER, self.size, self.data, self.usage)
|
|
302
|
+
else:
|
|
303
|
+
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, self._dirty_min, size, self.data_ptr + self._dirty_min)
|
|
304
|
+
|
|
305
|
+
self._dirty_min = sys.maxsize
|
|
306
|
+
self._dirty_max = 0
|
|
307
|
+
self._dirty = False
|
|
308
|
+
|
|
309
|
+
class PersistentBufferObject(AbstractBuffer):
|
|
310
|
+
"""A persistently mapped buffer.
|
|
311
|
+
|
|
312
|
+
Available in OpenGL 4.3+ contexts. Persistently mapped buffers
|
|
313
|
+
are mapped one time on creation, and can be updated at any time
|
|
314
|
+
without the need to map or unmap.
|
|
315
|
+
|
|
316
|
+
Unsupported by GL2.
|
|
317
|
+
"""
|
|
318
|
+
|
|
319
|
+
def __init__(self, context, size, attribute, vao) -> None:
|
|
320
|
+
raise NotImplementedError
|