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,302 @@
|
|
|
1
|
+
"""OpenGL Buffer Objects.
|
|
2
|
+
|
|
3
|
+
:py:class:`~BufferObject` and a :py:class:`~BackedBufferObject` are provied.
|
|
4
|
+
The first is a lightweight abstraction over an OpenGL buffer, as created
|
|
5
|
+
with ``glGenBuffers``. The backed buffer object is similar, but provides a
|
|
6
|
+
full mirror of the data in CPU memory. This allows for delayed uploading of
|
|
7
|
+
changes to GPU memory, which can improve performance is some cases.
|
|
8
|
+
"""
|
|
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
|
+
import js
|
|
18
|
+
import pyodide.ffi
|
|
19
|
+
|
|
20
|
+
import pyglet
|
|
21
|
+
from pyglet.customtypes import CType, CTypesPointer
|
|
22
|
+
from pyglet.graphics.api.webgl.gl import (
|
|
23
|
+
GL_ARRAY_BUFFER,
|
|
24
|
+
GL_BUFFER_SIZE,
|
|
25
|
+
GL_DYNAMIC_DRAW,
|
|
26
|
+
GL_ELEMENT_ARRAY_BUFFER,
|
|
27
|
+
GL_MAP_COHERENT_BIT,
|
|
28
|
+
GL_MAP_PERSISTENT_BIT,
|
|
29
|
+
GL_MAP_READ_BIT,
|
|
30
|
+
GL_MAP_WRITE_BIT,
|
|
31
|
+
GL_WRITE_ONLY,
|
|
32
|
+
)
|
|
33
|
+
from pyglet.graphics.buffer import AbstractBuffer
|
|
34
|
+
|
|
35
|
+
if TYPE_CHECKING:
|
|
36
|
+
from _ctypes import Array
|
|
37
|
+
|
|
38
|
+
from pyglet.graphics.api.webgl import OpenGLSurfaceContext
|
|
39
|
+
from pyglet.graphics.api.webgl.webgl_js import WebGLBuffer
|
|
40
|
+
from pyglet.graphics.shader import Attribute, GraphicsAttribute
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class BufferObject(AbstractBuffer):
|
|
44
|
+
"""Lightweight representation of an OpenGL Buffer Object.
|
|
45
|
+
|
|
46
|
+
The data in the buffer is not replicated in any system memory (unless it
|
|
47
|
+
is done so by the video driver). While this can reduce system memory usage,
|
|
48
|
+
performing multiple small updates to the buffer can be relatively slow.
|
|
49
|
+
The target of the buffer is ``GL_ARRAY_BUFFER`` internally to avoid
|
|
50
|
+
accidentally overriding other states when altering the buffer contents.
|
|
51
|
+
The intended target can be set when binding the buffer.
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
id: WebGLBuffer
|
|
55
|
+
usage: int
|
|
56
|
+
target: int
|
|
57
|
+
_context: OpenGLSurfaceContext | None
|
|
58
|
+
|
|
59
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, target: int = GL_ARRAY_BUFFER,
|
|
60
|
+
usage: int = GL_DYNAMIC_DRAW) -> None:
|
|
61
|
+
"""Initialize the BufferObject with the given size and draw usage.
|
|
62
|
+
|
|
63
|
+
JS does not allow to directly map memory, so all of them must be backed.
|
|
64
|
+
"""
|
|
65
|
+
super().__init__('b', size)
|
|
66
|
+
self.usage = usage
|
|
67
|
+
self.target = target
|
|
68
|
+
self._context = context
|
|
69
|
+
self._gl = self._context.gl
|
|
70
|
+
|
|
71
|
+
self.id = self._gl.createBuffer()
|
|
72
|
+
|
|
73
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
74
|
+
self._gl.bufferData(self.target, self.size, self.usage)
|
|
75
|
+
|
|
76
|
+
def get_bytes(self) -> bytes: ...
|
|
77
|
+
|
|
78
|
+
def get_bytes_region(self, offset: int, length: int) -> bytes: ...
|
|
79
|
+
|
|
80
|
+
def get_data_region(self, start: int, length: int) -> ctypes.Array[CType]: ...
|
|
81
|
+
|
|
82
|
+
def set_bytes(self, data: bytes) -> None: ...
|
|
83
|
+
|
|
84
|
+
def set_bytes_region(self, start: int, length: int) -> None: ...
|
|
85
|
+
|
|
86
|
+
def set_data_ptr(self, offset: int, length: int, ptr: CTypesPointer) -> None: ...
|
|
87
|
+
|
|
88
|
+
def get_buffer_size(self):
|
|
89
|
+
return self._gl.getBufferParameter(self.target, GL_BUFFER_SIZE)
|
|
90
|
+
|
|
91
|
+
def invalidate(self) -> None:
|
|
92
|
+
self._gl.bufferData(self.target, None, self.usage)
|
|
93
|
+
|
|
94
|
+
def bind(self) -> None:
|
|
95
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
96
|
+
|
|
97
|
+
def unbind(self) -> None:
|
|
98
|
+
self._gl.bindBuffer(self.target, 0)
|
|
99
|
+
|
|
100
|
+
def get_data(self) -> ctypes.Array[CType]:
|
|
101
|
+
data = js.Uint8Array.new(self.size)
|
|
102
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
103
|
+
self._gl.getBufferSubData(self.target, 0, data)
|
|
104
|
+
py_buffer = data.buffer.to_py(depth=1)
|
|
105
|
+
return bytes(py_buffer)
|
|
106
|
+
|
|
107
|
+
def set_data(self, data: Sequence[int] | CTypesPointer) -> None:
|
|
108
|
+
byte_data = ctypes.string_at(data, ctypes.sizeof(data.contents))
|
|
109
|
+
buffer = pyodide.ffi.to_js(memoryview(byte_data))
|
|
110
|
+
js_array = js.Uint8Array.new(buffer)
|
|
111
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
112
|
+
self._gl.bufferData(self.target, js_array, self.usage)
|
|
113
|
+
|
|
114
|
+
def set_data_region(self, data: Sequence[int] | CTypesPointer, start: int, length: int) -> None:
|
|
115
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
116
|
+
self._gl.bufferSubData(self.target, start, data)
|
|
117
|
+
|
|
118
|
+
def map(self, bits=GL_WRITE_ONLY) -> CTypesPointer[ctypes.c_byte]:
|
|
119
|
+
raise NotImplementedError()
|
|
120
|
+
|
|
121
|
+
def map_range(self, start: int, size: int, ptr_type: type[CTypesPointer], bits=GL_MAP_WRITE_BIT) -> CTypesPointer:
|
|
122
|
+
raise NotImplementedError()
|
|
123
|
+
|
|
124
|
+
def unmap(self) -> None:
|
|
125
|
+
raise NotImplementedError()
|
|
126
|
+
|
|
127
|
+
def delete(self) -> None:
|
|
128
|
+
self._gl.deleteBuffer(self.id)
|
|
129
|
+
self.id = None
|
|
130
|
+
|
|
131
|
+
def __del__(self) -> None:
|
|
132
|
+
if self.id is not None:
|
|
133
|
+
try:
|
|
134
|
+
self._context.delete_buffer(self.id)
|
|
135
|
+
self.id = None
|
|
136
|
+
except (AttributeError, ImportError):
|
|
137
|
+
pass # Interpreter is shutting down
|
|
138
|
+
|
|
139
|
+
def resize(self, size: int) -> None:
|
|
140
|
+
# Map, create a copy, then reinitialize.
|
|
141
|
+
temp = (ctypes.c_byte * size)()
|
|
142
|
+
|
|
143
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
144
|
+
data = glMapBufferRange(self.target, 0, self.size, GL_MAP_READ_BIT)
|
|
145
|
+
ctypes.memmove(temp, data, min(size, self.size))
|
|
146
|
+
glUnmapBuffer(self.target)
|
|
147
|
+
|
|
148
|
+
self.size = size
|
|
149
|
+
self._gl.bufferData(self.target, self.size, temp, self.usage)
|
|
150
|
+
|
|
151
|
+
def __repr__(self) -> str:
|
|
152
|
+
return f"{self.__class__.__name__}(id={self.id}, data_type={self.data_type}, size={self.size})"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class BackedBufferObject(BufferObject):
|
|
156
|
+
"""A buffer with system-memory backed store.
|
|
157
|
+
|
|
158
|
+
Updates to the data via ``set_data`` and ``set_data_region`` will be held
|
|
159
|
+
in system memory until ``commit`` is called. The advantage is that fewer
|
|
160
|
+
OpenGL calls are needed, which can increase performance at the expense of
|
|
161
|
+
system memory.
|
|
162
|
+
"""
|
|
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__(
|
|
174
|
+
self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
|
|
175
|
+
usage: int = GL_DYNAMIC_DRAW, target: int=GL_ARRAY_BUFFER,
|
|
176
|
+
) -> None:
|
|
177
|
+
super().__init__(context, size, target, usage)
|
|
178
|
+
|
|
179
|
+
self.c_type = c_type
|
|
180
|
+
self._ctypes_size = ctypes.sizeof(c_type)
|
|
181
|
+
number = size // self._ctypes_size
|
|
182
|
+
self.data = (c_type * number)()
|
|
183
|
+
self.data_ptr = ctypes.addressof(self.data)
|
|
184
|
+
|
|
185
|
+
self._dirty_min = sys.maxsize
|
|
186
|
+
self._dirty_max = 0
|
|
187
|
+
self._dirty = False
|
|
188
|
+
|
|
189
|
+
self.stride = stride
|
|
190
|
+
self.element_count = element_count
|
|
191
|
+
|
|
192
|
+
def commit(self) -> None:
|
|
193
|
+
"""Commits all saved changes to the underlying buffer before drawing.
|
|
194
|
+
|
|
195
|
+
Allows submitting multiple changes at once, rather than having to call glBufferSubData for every change.
|
|
196
|
+
"""
|
|
197
|
+
if not self._dirty:
|
|
198
|
+
return
|
|
199
|
+
|
|
200
|
+
self._gl.bindBuffer(self.target, self.id)
|
|
201
|
+
size = self._dirty_max - self._dirty_min
|
|
202
|
+
if size > 0:
|
|
203
|
+
if size == self.size:
|
|
204
|
+
byte_data = ctypes.string_at(self.data_ptr, self.size)
|
|
205
|
+
buffer = pyodide.ffi.to_js(memoryview(byte_data))
|
|
206
|
+
js_array = js.Uint8Array.new(buffer)
|
|
207
|
+
self._gl.bufferData(self.target, js_array, self.usage)
|
|
208
|
+
else:
|
|
209
|
+
byte_data = ctypes.string_at(self.data_ptr + self._dirty_min, size)
|
|
210
|
+
buffer = pyodide.ffi.to_js(memoryview(byte_data))
|
|
211
|
+
js_array = js.Uint8Array.new(buffer)
|
|
212
|
+
|
|
213
|
+
self._gl.bufferSubData(self.target, self._dirty_min, js_array)
|
|
214
|
+
|
|
215
|
+
self._dirty_min = sys.maxsize
|
|
216
|
+
self._dirty_max = 0
|
|
217
|
+
self._dirty = False
|
|
218
|
+
|
|
219
|
+
@lru_cache(maxsize=None) # noqa: B019
|
|
220
|
+
def get_region(self, start: int, count: int) -> Array[CType]:
|
|
221
|
+
byte_start = self.stride * start # byte offset
|
|
222
|
+
array_count = self.element_count * count # number of values
|
|
223
|
+
ptr_type = ctypes.POINTER(self.c_type * array_count)
|
|
224
|
+
return ctypes.cast(self.data_ptr + byte_start, ptr_type).contents
|
|
225
|
+
|
|
226
|
+
def set_region(self, start: int, count: int, data: Sequence[float]) -> None:
|
|
227
|
+
array_start = self.element_count * start
|
|
228
|
+
array_end = self.element_count * count + array_start
|
|
229
|
+
|
|
230
|
+
self.data[array_start:array_end] = data
|
|
231
|
+
|
|
232
|
+
# replicated from self.invalidate_region
|
|
233
|
+
byte_start = self.stride * start
|
|
234
|
+
byte_end = byte_start + self.stride * count
|
|
235
|
+
# As of Python 3.11, this is faster than min/max:
|
|
236
|
+
if byte_start < self._dirty_min:
|
|
237
|
+
self._dirty_min = byte_start
|
|
238
|
+
if byte_end > self._dirty_max:
|
|
239
|
+
self._dirty_max = byte_end
|
|
240
|
+
self._dirty = True
|
|
241
|
+
|
|
242
|
+
def resize(self, size: int) -> None:
|
|
243
|
+
# size is the allocator size * attribute.stride
|
|
244
|
+
number = size // ctypes.sizeof(self.c_type)
|
|
245
|
+
data = (self.c_type * number)()
|
|
246
|
+
ctypes.memmove(data, self.data, min(size, self.size))
|
|
247
|
+
self.data = data
|
|
248
|
+
self.data_ptr = ctypes.addressof(data)
|
|
249
|
+
self.size = size
|
|
250
|
+
|
|
251
|
+
# Set the dirty range to be the entire buffer.
|
|
252
|
+
self._dirty_min = 0
|
|
253
|
+
self._dirty_max = self.size
|
|
254
|
+
self._dirty = True
|
|
255
|
+
|
|
256
|
+
self.get_region.cache_clear()
|
|
257
|
+
|
|
258
|
+
def invalidate(self) -> None:
|
|
259
|
+
super().invalidate()
|
|
260
|
+
self._dirty = True
|
|
261
|
+
|
|
262
|
+
def invalidate_region(self, start: int, count: int) -> None:
|
|
263
|
+
byte_start = self.stride * start
|
|
264
|
+
byte_end = byte_start + self.stride * count
|
|
265
|
+
# As of Python 3.11, this is faster than min/max:
|
|
266
|
+
if byte_start < self._dirty_min:
|
|
267
|
+
self._dirty_min = byte_start
|
|
268
|
+
if byte_end > self._dirty_max:
|
|
269
|
+
self._dirty_max = byte_end
|
|
270
|
+
self._dirty = True
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class AttributeBufferObject(BackedBufferObject):
|
|
274
|
+
"""A backed buffer used for Shader Program attributes."""
|
|
275
|
+
|
|
276
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, graphics_attr: GraphicsAttribute) -> None:
|
|
277
|
+
# size is the allocator size * attribute.stride (buffer size)
|
|
278
|
+
super().__init__(context, size, graphics_attr.attribute.c_type,
|
|
279
|
+
graphics_attr.view.stride,
|
|
280
|
+
graphics_attr.attribute.fmt.components)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
class IndexedBufferObject(BackedBufferObject):
|
|
285
|
+
"""A backed buffer used for indices."""
|
|
286
|
+
|
|
287
|
+
def __init__(self, context: OpenGLSurfaceContext, size: int, c_type: CType, stride: int, element_count: int,
|
|
288
|
+
usage: int = GL_DYNAMIC_DRAW) -> None:
|
|
289
|
+
super().__init__(context, size, c_type, stride, element_count, usage, GL_ELEMENT_ARRAY_BUFFER)
|
|
290
|
+
|
|
291
|
+
def bind_to_index_buffer(self) -> None:
|
|
292
|
+
"""Binds this buffer as an index buffer on the active vertex array."""
|
|
293
|
+
self._gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, self.id)
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
class PersistentBufferObject(BackedBufferObject):
|
|
297
|
+
"""A persistently mapped buffer.
|
|
298
|
+
|
|
299
|
+
Available in OpenGL 4.3+ contexts. Persistently mapped buffers
|
|
300
|
+
are mapped one time on creation, and can be updated at any time
|
|
301
|
+
without the need to map or unmap.
|
|
302
|
+
"""
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import weakref
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Callable
|
|
5
|
+
|
|
6
|
+
import js
|
|
7
|
+
from pyodide.ffi import create_proxy
|
|
8
|
+
|
|
9
|
+
from pyglet.graphics.api.base import SurfaceContext
|
|
10
|
+
from pyglet.graphics.api.webgl import gl
|
|
11
|
+
from pyglet.graphics.api.webgl.gl import GL_COLOR_BUFFER_BIT
|
|
12
|
+
from pyglet.graphics.api.webgl.gl_info import GLInfo
|
|
13
|
+
from pyglet.graphics.api.webgl.shader import GLDataType
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from pyglet.graphics.api import WebGLBackend
|
|
17
|
+
from pyglet.graphics.api.webgl.config import OpenGLWindowConfig
|
|
18
|
+
from pyglet.graphics.api.webgl.webgl_js import WebGL2RenderingContext
|
|
19
|
+
from pyglet.window import Window
|
|
20
|
+
from pyglet.window.emscripten import EmscriptenWindow
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ObjectSpace:
|
|
24
|
+
"""A container to store shared objects that are to be removed."""
|
|
25
|
+
|
|
26
|
+
def __init__(self) -> None:
|
|
27
|
+
"""Initialize the context object space."""
|
|
28
|
+
# Objects scheduled for deletion the next time this object space is active.
|
|
29
|
+
self.doomed_textures = []
|
|
30
|
+
self.doomed_buffers = []
|
|
31
|
+
self.doomed_shader_programs = []
|
|
32
|
+
self.doomed_shaders = []
|
|
33
|
+
self.doomed_renderbuffers = []
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class OpenGLSurfaceContext(SurfaceContext):
|
|
37
|
+
"""A base OpenGL context for drawing.
|
|
38
|
+
|
|
39
|
+
Use ``DisplayConfig.create_context`` to create a context.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
gl: WebGL2RenderingContext
|
|
43
|
+
config: OpenGLWindowConfig
|
|
44
|
+
context_share: OpenGLSurfaceContext | None
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
global_ctx: WebGLBackend,
|
|
49
|
+
window: EmscriptenWindow,
|
|
50
|
+
config: OpenGLWindowConfig, # noqa: D417
|
|
51
|
+
context_share: OpenGLSurfaceContext | None = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Initialize a context.
|
|
54
|
+
|
|
55
|
+
This should only be created through the ``DisplayConfig.create_context`` method.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
config:
|
|
59
|
+
An operating system specific config.
|
|
60
|
+
context_share:
|
|
61
|
+
A context to share objects with. Use ``None`` to disable sharing.
|
|
62
|
+
"""
|
|
63
|
+
super().__init__(global_ctx, window, config)
|
|
64
|
+
self.global_ctx = global_ctx
|
|
65
|
+
self.window = window
|
|
66
|
+
self.config = config
|
|
67
|
+
self.context_share = context_share
|
|
68
|
+
self.is_current = False
|
|
69
|
+
|
|
70
|
+
# The GL Context.
|
|
71
|
+
self.gl = self.window.canvas.getContext("webgl2")
|
|
72
|
+
|
|
73
|
+
self._info = GLInfo()
|
|
74
|
+
self._info.query(self.gl)
|
|
75
|
+
self.object_space = ObjectSpace()
|
|
76
|
+
|
|
77
|
+
self._draw_proxy = create_proxy(self.window.draw)
|
|
78
|
+
|
|
79
|
+
self._clear_color = (0.0, 0.0, 0.0, 1.0)
|
|
80
|
+
|
|
81
|
+
self.doomed_vaos = []
|
|
82
|
+
self.doomed_framebuffers = []
|
|
83
|
+
|
|
84
|
+
self.cached_programs = weakref.WeakValueDictionary()
|
|
85
|
+
self._create_uniform_dicts()
|
|
86
|
+
|
|
87
|
+
def get_info(self) -> GLInfo:
|
|
88
|
+
"""Get the :py:class:`~GLInfo` instance for this context."""
|
|
89
|
+
return self._info
|
|
90
|
+
|
|
91
|
+
def resized(self, width, height): ...
|
|
92
|
+
|
|
93
|
+
def detach(self):
|
|
94
|
+
self.context = None
|
|
95
|
+
|
|
96
|
+
def __repr__(self) -> str:
|
|
97
|
+
return f"{self.__class__.__name__}(id={id(self)}, share={self.context_share})"
|
|
98
|
+
|
|
99
|
+
def __enter__(self) -> None:
|
|
100
|
+
self.set_current()
|
|
101
|
+
|
|
102
|
+
def __exit__(self, *_args) -> None: # noqa: ANN002
|
|
103
|
+
return
|
|
104
|
+
|
|
105
|
+
def set_clear_color(self, r: float, g: float, b: float, a: float) -> None:
|
|
106
|
+
self._clear_color = (r, g, b, a)
|
|
107
|
+
|
|
108
|
+
def clear(self) -> None:
|
|
109
|
+
self.gl.clear(GL_COLOR_BUFFER_BIT)
|
|
110
|
+
|
|
111
|
+
def flip(self):
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
def destroy(self) -> None:
|
|
115
|
+
"""Release the Context.
|
|
116
|
+
|
|
117
|
+
The context will not be useable after being destroyed. Each platform
|
|
118
|
+
has its own convention for releasing the context and the buffer(s)
|
|
119
|
+
that depend on it in the correct order; this should never be called
|
|
120
|
+
by an application.
|
|
121
|
+
"""
|
|
122
|
+
# self.detach()
|
|
123
|
+
#
|
|
124
|
+
if self.core.current_context is self:
|
|
125
|
+
self.core.current_context = None
|
|
126
|
+
# #gl_info.remove_active_context()
|
|
127
|
+
|
|
128
|
+
def attach(self, window: Window) -> None:
|
|
129
|
+
# if not self.config.compatible(canvas):
|
|
130
|
+
# msg = f'Cannot attach {canvas} to {self}'
|
|
131
|
+
# raise RuntimeError(msg)
|
|
132
|
+
self.window = window
|
|
133
|
+
|
|
134
|
+
def before_draw(self) -> None:
|
|
135
|
+
self.gl.clearColor(*self._clear_color)
|
|
136
|
+
self.gl.clear(GL_COLOR_BUFFER_BIT)
|
|
137
|
+
|
|
138
|
+
def set_current(self) -> None:
|
|
139
|
+
return
|
|
140
|
+
"""Make this the active Context.
|
|
141
|
+
|
|
142
|
+
Setting the Context current will also delete any OpenGL
|
|
143
|
+
objects that have been queued for deletion. IE: any objects
|
|
144
|
+
that were created in this Context, but have been called for
|
|
145
|
+
deletion while another Context was active.
|
|
146
|
+
"""
|
|
147
|
+
assert self.window is not None, "Window has not been attached."
|
|
148
|
+
|
|
149
|
+
# Not per-thread
|
|
150
|
+
self.global_ctx.current_context = self
|
|
151
|
+
gl.current_context = self
|
|
152
|
+
|
|
153
|
+
# Set active context.
|
|
154
|
+
# gl_info.set_active_context()
|
|
155
|
+
|
|
156
|
+
if not self._info.was_queried:
|
|
157
|
+
self._info.query()
|
|
158
|
+
|
|
159
|
+
if self.object_space.doomed_textures:
|
|
160
|
+
self._delete_objects(self.object_space.doomed_textures, gl.glDeleteTextures)
|
|
161
|
+
if self.object_space.doomed_buffers:
|
|
162
|
+
self._delete_objects(self.object_space.doomed_buffers, gl.glDeleteBuffers)
|
|
163
|
+
if self.object_space.doomed_shader_programs:
|
|
164
|
+
self._delete_objects_one_by_one(self.object_space.doomed_shader_programs, gl.glDeleteProgram)
|
|
165
|
+
if self.object_space.doomed_shaders:
|
|
166
|
+
self._delete_objects_one_by_one(self.object_space.doomed_shaders, gl.glDeleteShader)
|
|
167
|
+
if self.object_space.doomed_renderbuffers:
|
|
168
|
+
self._delete_objects(self.object_space.doomed_renderbuffers, gl.glDeleteRenderbuffers)
|
|
169
|
+
|
|
170
|
+
if self.doomed_vaos:
|
|
171
|
+
self._delete_objects(self.doomed_vaos, gl.glDeleteVertexArrays)
|
|
172
|
+
if self.doomed_framebuffers:
|
|
173
|
+
self._delete_objects(self.doomed_framebuffers, gl.glDeleteFramebuffers)
|
|
174
|
+
|
|
175
|
+
def _create_uniform_dicts(self) -> None:
|
|
176
|
+
self._uniform_setters: dict[int, tuple[GLDataType, Callable, int]] = {
|
|
177
|
+
# uniform: gl_type, setter, length
|
|
178
|
+
gl.GL_BOOL: (gl.GLint, self.gl.uniform1i, 1),
|
|
179
|
+
gl.GL_BOOL_VEC2: (gl.GLint, self.gl.uniform2iv, 2),
|
|
180
|
+
gl.GL_BOOL_VEC3: (gl.GLint, self.gl.uniform3iv, 3),
|
|
181
|
+
gl.GL_BOOL_VEC4: (gl.GLint, self.gl.uniform4iv, 4),
|
|
182
|
+
gl.GL_INT: (gl.GLint, self.gl.uniform1i, 1),
|
|
183
|
+
gl.GL_INT_VEC2: (gl.GLint, self.gl.uniform2iv, 2),
|
|
184
|
+
gl.GL_INT_VEC3: (gl.GLint, self.gl.uniform3iv, 3),
|
|
185
|
+
gl.GL_INT_VEC4: (gl.GLint, self.gl.uniform4iv, 4),
|
|
186
|
+
gl.GL_FLOAT: (gl.GLfloat, self.gl.uniform1f, 1),
|
|
187
|
+
gl.GL_FLOAT_VEC2: (gl.GLfloat, self.gl.uniform2fv, 2),
|
|
188
|
+
gl.GL_FLOAT_VEC3: (gl.GLfloat, self.gl.uniform3fv, 3),
|
|
189
|
+
gl.GL_FLOAT_VEC4: (gl.GLfloat, self.gl.uniform4fv, 4),
|
|
190
|
+
# 1D Samplers
|
|
191
|
+
gl.GL_SAMPLER_1D: (gl.GLint, self.gl.uniform1i, 1),
|
|
192
|
+
gl.GL_SAMPLER_1D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
193
|
+
gl.GL_INT_SAMPLER_1D: (gl.GLint, self.gl.uniform1i, 1),
|
|
194
|
+
gl.GL_INT_SAMPLER_1D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
195
|
+
gl.GL_UNSIGNED_INT_SAMPLER_1D: (gl.GLint, self.gl.uniform1i, 1),
|
|
196
|
+
gl.GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
197
|
+
# 2D Samplers
|
|
198
|
+
gl.GL_SAMPLER_2D: (gl.GLint, self.gl.uniform1i, 1),
|
|
199
|
+
gl.GL_SAMPLER_2D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
200
|
+
gl.GL_INT_SAMPLER_2D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
201
|
+
gl.GL_INT_SAMPLER_2D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
202
|
+
gl.GL_UNSIGNED_INT_SAMPLER_2D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
203
|
+
gl.GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
204
|
+
# Multisample
|
|
205
|
+
gl.GL_SAMPLER_2D_MULTISAMPLE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
206
|
+
gl.GL_INT_SAMPLER_2D_MULTISAMPLE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
207
|
+
gl.GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
208
|
+
# Cube Samplers
|
|
209
|
+
gl.GL_SAMPLER_CUBE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
210
|
+
gl.GL_INT_SAMPLER_CUBE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
211
|
+
gl.GL_UNSIGNED_INT_SAMPLER_CUBE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
212
|
+
gl.GL_SAMPLER_CUBE_MAP_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
213
|
+
gl.GL_INT_SAMPLER_CUBE_MAP_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
214
|
+
gl.GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
215
|
+
# 3D Samplers
|
|
216
|
+
gl.GL_SAMPLER_3D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
217
|
+
gl.GL_INT_SAMPLER_3D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
218
|
+
gl.GL_UNSIGNED_INT_SAMPLER_3D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
219
|
+
gl.GL_FLOAT_MAT2: (gl.GLfloat, self.gl.uniformMatrix2fv, 4),
|
|
220
|
+
gl.GL_FLOAT_MAT3: (gl.GLfloat, self.gl.uniformMatrix3fv, 6),
|
|
221
|
+
gl.GL_FLOAT_MAT4: (gl.GLfloat, self.gl.uniformMatrix4fv, 16),
|
|
222
|
+
# Images
|
|
223
|
+
gl.GL_IMAGE_1D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
224
|
+
gl.GL_IMAGE_2D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
225
|
+
gl.GL_IMAGE_2D_RECT: (gl.GLint, self.gl.uniform1iv, 1),
|
|
226
|
+
gl.GL_IMAGE_3D: (gl.GLint, self.gl.uniform1iv, 1),
|
|
227
|
+
gl.GL_IMAGE_1D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
228
|
+
gl.GL_IMAGE_2D_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
229
|
+
gl.GL_IMAGE_2D_MULTISAMPLE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
230
|
+
gl.GL_IMAGE_2D_MULTISAMPLE_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
231
|
+
gl.GL_IMAGE_BUFFER: (gl.GLint, self.gl.uniform1iv, 1),
|
|
232
|
+
gl.GL_IMAGE_CUBE: (gl.GLint, self.gl.uniform1iv, 1),
|
|
233
|
+
gl.GL_IMAGE_CUBE_MAP_ARRAY: (gl.GLint, self.gl.uniform1iv, 1),
|
|
234
|
+
}
|