sync pyglet and lib-not-dr
This commit is contained in:
parent
8857166e67
commit
b28ef5c580
@ -9,26 +9,11 @@ import inspect
|
|||||||
from types import FrameType
|
from types import FrameType
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from .structers import LogMessage
|
from lib_not_dr.logger.structers import LogMessage
|
||||||
|
from lib_not_dr.logger.outstream import BaseOutputStream
|
||||||
from lib_not_dr.types.options import Options
|
from lib_not_dr.types.options import Options
|
||||||
|
|
||||||
|
|
||||||
class BaseOutputStream(Options):
|
|
||||||
name = 'BaseOutputStream'
|
|
||||||
|
|
||||||
level: int = 20
|
|
||||||
enable: bool = True
|
|
||||||
|
|
||||||
def write_stdout(self, message: LogMessage) -> None:
|
|
||||||
raise NotImplementedError(f'{self.__class__.__name__}.write_stdout is not implemented')
|
|
||||||
|
|
||||||
def write_stderr(self, message: LogMessage) -> None:
|
|
||||||
raise NotImplementedError(f'{self.__class__.__name__}.write_stderr is not implemented')
|
|
||||||
|
|
||||||
def flush(self) -> None:
|
|
||||||
raise NotImplementedError(f'{self.__class__.__name__}.flush is not implemented')
|
|
||||||
|
|
||||||
|
|
||||||
class Logger(Options):
|
class Logger(Options):
|
||||||
name = 'Logger-v2'
|
name = 'Logger-v2'
|
||||||
|
|
||||||
|
62
libs/lib_not_dr/logger/outstream.py
Normal file
62
libs/lib_not_dr/logger/outstream.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# -------------------------------
|
||||||
|
# Difficult Rocket
|
||||||
|
# Copyright © 2020-2023 by shenjackyuanjie 3695888@qq.com
|
||||||
|
# All rights reserved
|
||||||
|
# -------------------------------
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from lib_not_dr.types.options import Options
|
||||||
|
from lib_not_dr.logger.structers import LogMessage
|
||||||
|
from lib_not_dr.logger.formatter import BaseFormatter, StdFormatter
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'BaseOutputStream'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class BaseOutputStream(Options):
|
||||||
|
name = 'BaseOutputStream'
|
||||||
|
|
||||||
|
level: int = 20
|
||||||
|
enable: bool = True
|
||||||
|
|
||||||
|
def write_stdout(self, message: LogMessage) -> None:
|
||||||
|
raise NotImplementedError(f'{self.__class__.__name__}.write_stdout is not implemented')
|
||||||
|
|
||||||
|
def write_stderr(self, message: LogMessage) -> None:
|
||||||
|
raise NotImplementedError(f'{self.__class__.__name__}.write_stderr is not implemented')
|
||||||
|
|
||||||
|
def flush(self) -> None:
|
||||||
|
raise NotImplementedError(f'{self.__class__.__name__}.flush is not implemented')
|
||||||
|
|
||||||
|
|
||||||
|
class StdioOutputStream(BaseOutputStream):
|
||||||
|
name = 'StdioOutputStream'
|
||||||
|
|
||||||
|
formatter: BaseFormatter = StdFormatter()
|
||||||
|
|
||||||
|
def write_stdout(self, message: LogMessage) -> None:
|
||||||
|
if not self.enable:
|
||||||
|
return None
|
||||||
|
if message.level < self.level:
|
||||||
|
return None
|
||||||
|
print(self.formatter.format_message(message), end='', flush=message.flush)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def write_stderr(self, message: LogMessage) -> None:
|
||||||
|
if not self.enable:
|
||||||
|
return None
|
||||||
|
if message.level < self.level:
|
||||||
|
return None
|
||||||
|
print(self.formatter.format_message(message), end='', flush=message.flush, file=sys.stderr)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def flush(self) -> None:
|
||||||
|
"""
|
||||||
|
flush stdout and stderr
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
print('', end='', flush=True)
|
||||||
|
print('', end='', flush=True, file=sys.stderr)
|
||||||
|
return None
|
@ -1,6 +1,7 @@
|
|||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
import threading
|
||||||
from typing import Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
import pyglet
|
import pyglet
|
||||||
@ -209,11 +210,12 @@ class CanvasConfig(Config):
|
|||||||
|
|
||||||
class ObjectSpace:
|
class ObjectSpace:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Textures and buffers scheduled for deletion
|
# Objects scheduled for deletion the next time this object space is active.
|
||||||
# the next time this object space is active.
|
|
||||||
self.doomed_textures = []
|
self.doomed_textures = []
|
||||||
self.doomed_buffers = []
|
self.doomed_buffers = []
|
||||||
self.doomed_shader_programs = []
|
self.doomed_shader_programs = []
|
||||||
|
self.doomed_shaders = []
|
||||||
|
self.doomed_renderbuffers = []
|
||||||
|
|
||||||
|
|
||||||
class Context:
|
class Context:
|
||||||
@ -236,6 +238,7 @@ class Context:
|
|||||||
self.canvas = None
|
self.canvas = None
|
||||||
|
|
||||||
self.doomed_vaos = []
|
self.doomed_vaos = []
|
||||||
|
self.doomed_framebuffers = []
|
||||||
|
|
||||||
if context_share:
|
if context_share:
|
||||||
self.object_space = context_share.object_space
|
self.object_space = context_share.object_space
|
||||||
@ -277,28 +280,44 @@ class Context:
|
|||||||
self._info = gl_info.GLInfo()
|
self._info = gl_info.GLInfo()
|
||||||
self._info.set_active_context()
|
self._info.set_active_context()
|
||||||
|
|
||||||
# Release Textures, Buffers, and VAOs on this context scheduled for
|
|
||||||
# deletion. Note that the garbage collector may introduce a race
|
|
||||||
# condition, so operate on a copy, and clear the list afterward.
|
|
||||||
if self.object_space.doomed_textures:
|
if self.object_space.doomed_textures:
|
||||||
textures = self.object_space.doomed_textures[:]
|
self._delete_objects(self.object_space.doomed_textures, gl.glDeleteTextures)
|
||||||
textures = (gl.GLuint * len(textures))(*textures)
|
|
||||||
gl.glDeleteTextures(len(textures), textures)
|
|
||||||
self.object_space.doomed_textures.clear()
|
|
||||||
if self.object_space.doomed_buffers:
|
if self.object_space.doomed_buffers:
|
||||||
buffers = self.object_space.doomed_buffers[:]
|
self._delete_objects(self.object_space.doomed_buffers, gl.glDeleteBuffers)
|
||||||
buffers = (gl.GLuint * len(buffers))(*buffers)
|
|
||||||
gl.glDeleteBuffers(len(buffers), buffers)
|
|
||||||
self.object_space.doomed_buffers.clear()
|
|
||||||
if self.object_space.doomed_shader_programs:
|
if self.object_space.doomed_shader_programs:
|
||||||
for program_id in self.object_space.doomed_shader_programs:
|
self._delete_objects_one_by_one(self.object_space.doomed_shader_programs,
|
||||||
gl.glDeleteProgram(program_id)
|
gl.glDeleteProgram)
|
||||||
self.object_space.doomed_shader_programs.clear()
|
if self.object_space.doomed_shaders:
|
||||||
|
self._delete_objects_one_by_one(self.object_space.doomed_shaders, gl.glDeleteShader)
|
||||||
|
if self.object_space.doomed_renderbuffers:
|
||||||
|
self._delete_objects(self.object_space.doomed_renderbuffers, gl.glDeleteRenderbuffers)
|
||||||
|
|
||||||
if self.doomed_vaos:
|
if self.doomed_vaos:
|
||||||
vaos = self.doomed_vaos[:]
|
self._delete_objects(self.doomed_vaos, gl.glDeleteVertexArrays)
|
||||||
vaos = (gl.GLuint * len(vaos))(*vaos)
|
if self.doomed_framebuffers:
|
||||||
gl.glDeleteVertexArrays(len(vaos), vaos)
|
self._delete_objects(self.doomed_framebuffers, gl.glDeleteFramebuffers)
|
||||||
self.doomed_vaos.clear()
|
|
||||||
|
# For the functions below:
|
||||||
|
# The garbage collector introduces a race condition.
|
||||||
|
# The provided list might be appended to (and only appended to) while this
|
||||||
|
# method runs, as it's a `doomed_*` list either on the context or
|
||||||
|
# its object space. This is why we drain it relying on `pop`s atomicity.
|
||||||
|
def _delete_objects(self, list_, deletion_func):
|
||||||
|
"""Release all OpenGL objects in the given list using the supplied
|
||||||
|
deletion function with the signature ``(GLuint count, GLuint *names)``.
|
||||||
|
"""
|
||||||
|
to_delete = []
|
||||||
|
while list_:
|
||||||
|
to_delete.append(list_.pop())
|
||||||
|
|
||||||
|
deletion_func(len(to_delete), (gl.GLuint * len(to_delete))(*to_delete))
|
||||||
|
|
||||||
|
def _delete_objects_one_by_one(self, list_, deletion_func):
|
||||||
|
"""Similar to ``_delete_objects``, but assumes the deletion functions's
|
||||||
|
signature to be ``(GLuint name)``, calling it once for each object.
|
||||||
|
"""
|
||||||
|
while list_:
|
||||||
|
deletion_func(gl.GLuint(list_.pop()))
|
||||||
|
|
||||||
def destroy(self):
|
def destroy(self):
|
||||||
"""Release the context.
|
"""Release the context.
|
||||||
@ -318,6 +337,27 @@ class Context:
|
|||||||
if gl._shadow_window is not None:
|
if gl._shadow_window is not None:
|
||||||
gl._shadow_window.switch_to()
|
gl._shadow_window.switch_to()
|
||||||
|
|
||||||
|
def _safe_to_operate_on_object_space(self):
|
||||||
|
"""Return whether it is safe to interact with this context's object
|
||||||
|
space.
|
||||||
|
|
||||||
|
This is considered to be the case if the currently active context's
|
||||||
|
object space is the same as this context's object space and this
|
||||||
|
method is called from the main thread.
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
self.object_space is gl.current_context.object_space and
|
||||||
|
threading.current_thread() is threading.main_thread()
|
||||||
|
)
|
||||||
|
|
||||||
|
def _safe_to_operate_on(self):
|
||||||
|
"""Return whether it is safe to interact with this context.
|
||||||
|
|
||||||
|
This is considered to be the case if it's the current context and this
|
||||||
|
method is called from the main thread.
|
||||||
|
"""
|
||||||
|
return gl.current_context is self and threading.current_thread() is threading.main_thread()
|
||||||
|
|
||||||
def create_program(self, *sources: Tuple[str, str], program_class=None):
|
def create_program(self, *sources: Tuple[str, str], program_class=None):
|
||||||
"""Create a ShaderProgram from OpenGL GLSL source.
|
"""Create a ShaderProgram from OpenGL GLSL source.
|
||||||
|
|
||||||
@ -347,25 +387,30 @@ class Context:
|
|||||||
return program
|
return program
|
||||||
|
|
||||||
def delete_texture(self, texture_id):
|
def delete_texture(self, texture_id):
|
||||||
"""Safely delete a Texture belonging to this context.
|
"""Safely delete a Texture belonging to this context's object space.
|
||||||
|
|
||||||
Usually, the Texture is released immediately using
|
This method will delete the texture immediately via
|
||||||
``glDeleteTextures``, however if another context that does not share
|
``glDeleteTextures`` if the current context's object space is the same
|
||||||
this context's object space is currently active, the deletion will
|
as this context's object space and it is called from the main thread.
|
||||||
be deferred until an appropriate context is activated.
|
|
||||||
|
Otherwise, the texture will only be marked for deletion, postponing
|
||||||
|
it until any context with the same object space becomes active again.
|
||||||
|
|
||||||
|
This makes it safe to call from anywhere, including other threads.
|
||||||
|
|
||||||
:Parameters:
|
:Parameters:
|
||||||
`texture_id` : int
|
`texture_id` : int
|
||||||
The OpenGL name of the Texture to delete.
|
The OpenGL name of the Texture to delete.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.object_space is gl.current_context.object_space:
|
if self._safe_to_operate_on_object_space():
|
||||||
gl.glDeleteTextures(1, gl.GLuint(texture_id))
|
gl.glDeleteTextures(1, gl.GLuint(texture_id))
|
||||||
else:
|
else:
|
||||||
self.object_space.doomed_textures.append(texture_id)
|
self.object_space.doomed_textures.append(texture_id)
|
||||||
|
|
||||||
def delete_buffer(self, buffer_id):
|
def delete_buffer(self, buffer_id):
|
||||||
"""Safely delete a Buffer object belonging to this context.
|
"""Safely delete a Buffer object belonging to this context's object
|
||||||
|
space.
|
||||||
|
|
||||||
This method behaves similarly to `delete_texture`, though for
|
This method behaves similarly to `delete_texture`, though for
|
||||||
``glDeleteBuffers`` instead of ``glDeleteTextures``.
|
``glDeleteBuffers`` instead of ``glDeleteTextures``.
|
||||||
@ -376,30 +421,14 @@ class Context:
|
|||||||
|
|
||||||
.. versionadded:: 1.1
|
.. versionadded:: 1.1
|
||||||
"""
|
"""
|
||||||
if self.object_space is gl.current_context.object_space and False:
|
if self._safe_to_operate_on_object_space():
|
||||||
gl.glDeleteBuffers(1, gl.GLuint(buffer_id))
|
gl.glDeleteBuffers(1, gl.GLuint(buffer_id))
|
||||||
else:
|
else:
|
||||||
self.object_space.doomed_buffers.append(buffer_id)
|
self.object_space.doomed_buffers.append(buffer_id)
|
||||||
|
|
||||||
def delete_vao(self, vao_id):
|
|
||||||
"""Safely delete a Vertex Array Object belonging to this context.
|
|
||||||
|
|
||||||
This method behaves similarly to `delete_texture`, though for
|
|
||||||
``glDeleteVertexArrays`` instead of ``glDeleteTextures``.
|
|
||||||
|
|
||||||
:Parameters:
|
|
||||||
`vao_id` : int
|
|
||||||
The OpenGL name of the Vertex Array to delete.
|
|
||||||
|
|
||||||
.. versionadded:: 2.0
|
|
||||||
"""
|
|
||||||
if gl.current_context is self:
|
|
||||||
gl.glDeleteVertexArrays(1, gl.GLuint(vao_id))
|
|
||||||
else:
|
|
||||||
self.doomed_vaos.append(vao_id)
|
|
||||||
|
|
||||||
def delete_shader_program(self, program_id):
|
def delete_shader_program(self, program_id):
|
||||||
"""Safely delete a Shader Program belonging to this context.
|
"""Safely delete a Shader Program belonging to this context's
|
||||||
|
object space.
|
||||||
|
|
||||||
This method behaves similarly to `delete_texture`, though for
|
This method behaves similarly to `delete_texture`, though for
|
||||||
``glDeleteProgram`` instead of ``glDeleteTextures``.
|
``glDeleteProgram`` instead of ``glDeleteTextures``.
|
||||||
@ -410,11 +439,84 @@ class Context:
|
|||||||
|
|
||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
"""
|
"""
|
||||||
if gl.current_context is self:
|
if self._safe_to_operate_on_object_space():
|
||||||
gl.glDeleteProgram(program_id)
|
gl.glDeleteProgram(gl.GLuint(program_id))
|
||||||
else:
|
else:
|
||||||
self.object_space.doomed_shader_programs.append(program_id)
|
self.object_space.doomed_shader_programs.append(program_id)
|
||||||
|
|
||||||
|
def delete_shader(self, shader_id):
|
||||||
|
"""Safely delete a Shader belonging to this context's object space.
|
||||||
|
|
||||||
|
This method behaves similarly to `delete_texture`, though for
|
||||||
|
``glDeleteShader`` instead of ``glDeleteTextures``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`shader_id` : int
|
||||||
|
The OpenGL name of the Shader to delete.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.10
|
||||||
|
"""
|
||||||
|
if self._safe_to_operate_on_object_space():
|
||||||
|
gl.glDeleteShader(gl.GLuint(shader_id))
|
||||||
|
else:
|
||||||
|
self.object_space.doomed_shaders.append(shader_id)
|
||||||
|
|
||||||
|
def delete_renderbuffer(self, rbo_id):
|
||||||
|
"""Safely delete a Renderbuffer Object belonging to this context's
|
||||||
|
object space.
|
||||||
|
|
||||||
|
This method behaves similarly to `delete_texture`, though for
|
||||||
|
``glDeleteRenderbuffers`` instead of ``glDeleteTextures``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`rbo_id` : int
|
||||||
|
The OpenGL name of the Shader Program to delete.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.10
|
||||||
|
"""
|
||||||
|
if self._safe_to_operate_on_object_space():
|
||||||
|
gl.glDeleteRenderbuffers(1, gl.GLuint(rbo_id))
|
||||||
|
else:
|
||||||
|
self.object_space.doomed_renderbuffers.append(rbo_id)
|
||||||
|
|
||||||
|
def delete_vao(self, vao_id):
|
||||||
|
"""Safely delete a Vertex Array Object belonging to this context.
|
||||||
|
|
||||||
|
If this context is not the current context or this method is not
|
||||||
|
called from the main thread, its deletion will be postponed until
|
||||||
|
this context is next made active again.
|
||||||
|
|
||||||
|
Otherwise, this method will immediately delete the VAO via
|
||||||
|
``glDeleteVertexArrays``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`vao_id` : int
|
||||||
|
The OpenGL name of the Vertex Array to delete.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
"""
|
||||||
|
if self._safe_to_operate_on():
|
||||||
|
gl.glDeleteVertexArrays(1, gl.GLuint(vao_id))
|
||||||
|
else:
|
||||||
|
self.doomed_vaos.append(vao_id)
|
||||||
|
|
||||||
|
def delete_framebuffer(self, fbo_id):
|
||||||
|
"""Safely delete a Framebuffer Object belonging to this context.
|
||||||
|
|
||||||
|
This method behaves similarly to `delete_vao`, though for
|
||||||
|
``glDeleteFramebuffers`` instead of ``glDeleteVertexArrays``.
|
||||||
|
|
||||||
|
:Parameters:
|
||||||
|
`fbo_id` : int
|
||||||
|
The OpenGL name of the Framebuffer Object to delete.
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.10
|
||||||
|
"""
|
||||||
|
if self._safe_to_operate_on():
|
||||||
|
gl.glDeleteFramebuffers(1, gl.GLuint(fbo_id))
|
||||||
|
else:
|
||||||
|
self.doomed_framebuffers.append(fbo_id)
|
||||||
|
|
||||||
def get_info(self):
|
def get_info(self):
|
||||||
"""Get the OpenGL information for this context.
|
"""Get the OpenGL information for this context.
|
||||||
|
|
||||||
|
@ -62,8 +62,7 @@ def errcheck(result, func, arguments):
|
|||||||
print(name)
|
print(name)
|
||||||
|
|
||||||
from pyglet import gl
|
from pyglet import gl
|
||||||
context = gl.current_context
|
if not gl.current_context:
|
||||||
if not context:
|
|
||||||
raise GLException('No GL context; create a Window first')
|
raise GLException('No GL context; create a Window first')
|
||||||
error = gl.glGetError()
|
error = gl.glGetError()
|
||||||
if error:
|
if error:
|
||||||
|
@ -674,6 +674,7 @@ class Shader:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, source_string: str, shader_type: str):
|
def __init__(self, source_string: str, shader_type: str):
|
||||||
|
self._context = pyglet.gl.current_context
|
||||||
self._id = None
|
self._id = None
|
||||||
self.type = shader_type
|
self.type = shader_type
|
||||||
|
|
||||||
@ -689,6 +690,7 @@ class Shader:
|
|||||||
source_length = c_int(len(shader_source_utf8))
|
source_length = c_int(len(shader_source_utf8))
|
||||||
|
|
||||||
shader_id = glCreateShader(shader_type)
|
shader_id = glCreateShader(shader_type)
|
||||||
|
self._id = shader_id
|
||||||
glShaderSource(shader_id, 1, byref(source_buffer_pointer), source_length)
|
glShaderSource(shader_id, 1, byref(source_buffer_pointer), source_length)
|
||||||
glCompileShader(shader_id)
|
glCompileShader(shader_id)
|
||||||
|
|
||||||
@ -709,8 +711,6 @@ class Shader:
|
|||||||
elif _debug_gl_shaders:
|
elif _debug_gl_shaders:
|
||||||
print(self._get_shader_log(shader_id))
|
print(self._get_shader_log(shader_id))
|
||||||
|
|
||||||
self._id = shader_id
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def id(self):
|
def id(self):
|
||||||
return self._id
|
return self._id
|
||||||
@ -735,16 +735,19 @@ class Shader:
|
|||||||
glGetShaderSource(shader_id, source_length, None, source_str)
|
glGetShaderSource(shader_id, source_length, None, source_str)
|
||||||
return source_str.value.decode('utf8')
|
return source_str.value.decode('utf8')
|
||||||
|
|
||||||
def __del__(self):
|
def delete(self):
|
||||||
try:
|
glDeleteShader(self._id)
|
||||||
glDeleteShader(self._id)
|
self._id = None
|
||||||
if _debug_gl_shaders:
|
|
||||||
print(f"Destroyed {self.type} Shader '{self._id}'")
|
|
||||||
|
|
||||||
except Exception:
|
def __del__(self):
|
||||||
# Interpreter is shutting down,
|
if self._id is not None:
|
||||||
# or Shader failed to compile.
|
try:
|
||||||
pass
|
self._context.delete_shader(self._id)
|
||||||
|
if _debug_gl_shaders:
|
||||||
|
print(f"Destroyed {self.type} Shader '{self._id}'")
|
||||||
|
self._id = None
|
||||||
|
except (AttributeError, ImportError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{0}(id={1}, type={2})".format(self.__class__.__name__, self.id, self.type)
|
return "{0}(id={1}, type={2})".format(self.__class__.__name__, self.id, self.type)
|
||||||
@ -756,6 +759,8 @@ class ShaderProgram:
|
|||||||
__slots__ = '_id', '_context', '_attributes', '_uniforms', '_uniform_blocks', '__weakref__'
|
__slots__ = '_id', '_context', '_attributes', '_uniforms', '_uniform_blocks', '__weakref__'
|
||||||
|
|
||||||
def __init__(self, *shaders: Shader):
|
def __init__(self, *shaders: Shader):
|
||||||
|
self._id = None
|
||||||
|
|
||||||
assert shaders, "At least one Shader object is required."
|
assert shaders, "At least one Shader object is required."
|
||||||
self._id = _link_program(*shaders)
|
self._id = _link_program(*shaders)
|
||||||
self._context = pyglet.gl.current_context
|
self._context = pyglet.gl.current_context
|
||||||
@ -799,13 +804,17 @@ class ShaderProgram:
|
|||||||
def __exit__(self, *_):
|
def __exit__(self, *_):
|
||||||
glUseProgram(0)
|
glUseProgram(0)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
glDeleteProgram(self._id)
|
||||||
|
self._id = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
if self._id is not None:
|
||||||
self._context.delete_shader_program(self.id)
|
try:
|
||||||
except Exception:
|
self._context.delete_shader_program(self._id)
|
||||||
# Interpreter is shutting down,
|
self._id = None
|
||||||
# or ShaderProgram failed to link.
|
except (AttributeError, ImportError):
|
||||||
pass
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
try:
|
try:
|
||||||
@ -930,6 +939,8 @@ class ComputeShaderProgram:
|
|||||||
|
|
||||||
def __init__(self, source: str):
|
def __init__(self, source: str):
|
||||||
"""Create an OpenGL ComputeShaderProgram from source."""
|
"""Create an OpenGL ComputeShaderProgram from source."""
|
||||||
|
self._id = None
|
||||||
|
|
||||||
if not (gl_info.have_version(4, 3) or gl_info.have_extension("GL_ARB_compute_shader")):
|
if not (gl_info.have_version(4, 3) or gl_info.have_extension("GL_ARB_compute_shader")):
|
||||||
raise ShaderException("Compute Shader not supported. OpenGL Context version must be at least "
|
raise ShaderException("Compute Shader not supported. OpenGL Context version must be at least "
|
||||||
"4.3 or higher, or 4.2 with the 'GL_ARB_compute_shader' extension.")
|
"4.3 or higher, or 4.2 with the 'GL_ARB_compute_shader' extension.")
|
||||||
@ -1002,13 +1013,17 @@ class ComputeShaderProgram:
|
|||||||
def __exit__(self, *_):
|
def __exit__(self, *_):
|
||||||
glUseProgram(0)
|
glUseProgram(0)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
glDeleteProgram(self._id)
|
||||||
|
self._id = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
if self._id is not None:
|
||||||
self._context.delete_shader_program(self.id)
|
try:
|
||||||
except Exception:
|
self._context.delete_shader_program(self._id)
|
||||||
# Interpreter is shutting down,
|
self._id = None
|
||||||
# or ShaderProgram failed to link.
|
except (AttributeError, ImportError):
|
||||||
pass
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
try:
|
try:
|
||||||
|
@ -27,10 +27,8 @@ class VertexArray:
|
|||||||
glBindVertexArray(0)
|
glBindVertexArray(0)
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
try:
|
glDeleteVertexArrays(1, self._id)
|
||||||
glDeleteVertexArrays(1, self._id)
|
self._id = None
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
__enter__ = bind
|
__enter__ = bind
|
||||||
|
|
||||||
@ -38,11 +36,12 @@ class VertexArray:
|
|||||||
glBindVertexArray(0)
|
glBindVertexArray(0)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
if self._id is not None:
|
||||||
self._context.delete_vao(self.id)
|
try:
|
||||||
# Python interpreter is shutting down:
|
self._context.delete_vao(self.id)
|
||||||
except ImportError:
|
self._id = None
|
||||||
pass
|
except (ImportError, AttributeError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
||||||
|
@ -164,21 +164,18 @@ class BufferObject(AbstractBuffer):
|
|||||||
def unmap(self):
|
def unmap(self):
|
||||||
glUnmapBuffer(GL_ARRAY_BUFFER)
|
glUnmapBuffer(GL_ARRAY_BUFFER)
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
try:
|
|
||||||
if self.id is not None:
|
|
||||||
self._context.delete_buffer(self.id)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
buffer_id = GLuint(self.id)
|
glDeleteBuffers(1, self.id)
|
||||||
try:
|
|
||||||
glDeleteBuffers(1, buffer_id)
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
self.id = None
|
self.id = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
if self.id is not None:
|
||||||
|
try:
|
||||||
|
self._context.delete_buffer(self.id)
|
||||||
|
self.id = None
|
||||||
|
except (AttributeError, ImportError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def resize(self, size):
|
def resize(self, size):
|
||||||
# Map, create a copy, then reinitialize.
|
# Map, create a copy, then reinitialize.
|
||||||
temp = (ctypes.c_byte * size)()
|
temp = (ctypes.c_byte * size)()
|
||||||
|
@ -452,7 +452,7 @@ class TextEntry(WidgetBase):
|
|||||||
self._height = value
|
self._height = value
|
||||||
self._layout.height = value
|
self._layout.height = value
|
||||||
self._outline.height = value
|
self._outline.height = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def focus(self) -> bool:
|
def focus(self) -> bool:
|
||||||
return self._focus
|
return self._focus
|
||||||
|
@ -1220,11 +1220,20 @@ class Texture(AbstractImage):
|
|||||||
self.id = tex_id
|
self.id = tex_id
|
||||||
self._context = pyglet.gl.current_context
|
self._context = pyglet.gl.current_context
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""Delete this texture and the memory it occupies.
|
||||||
|
After this, it may not be used anymore.
|
||||||
|
"""
|
||||||
|
glDeleteTextures(1, self.id)
|
||||||
|
self.id = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
if self.id is not None:
|
||||||
self._context.delete_texture(self.id)
|
try:
|
||||||
except Exception:
|
self._context.delete_texture(self.id)
|
||||||
pass
|
self.id = None
|
||||||
|
except (AttributeError, ImportError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def bind(self, texture_unit: int = 0):
|
def bind(self, texture_unit: int = 0):
|
||||||
"""Bind to a specific Texture Unit by number."""
|
"""Bind to a specific Texture Unit by number."""
|
||||||
@ -1479,8 +1488,13 @@ class TextureRegion(Texture):
|
|||||||
return "{}(id={}, size={}x{}, owner={}x{})".format(self.__class__.__name__, self.id, self.width, self.height,
|
return "{}(id={}, size={}x{}, owner={}x{})".format(self.__class__.__name__, self.id, self.width, self.height,
|
||||||
self.owner.width, self.owner.height)
|
self.owner.width, self.owner.height)
|
||||||
|
|
||||||
|
def delete(self):
|
||||||
|
"""Deleting a TextureRegion has no effect. Operate on the owning
|
||||||
|
texture instead.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
# only the owner Texture should handle deletion
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ class Renderbuffer:
|
|||||||
|
|
||||||
def __init__(self, width, height, internal_format, samples=1):
|
def __init__(self, width, height, internal_format, samples=1):
|
||||||
"""Create an instance of a Renderbuffer object."""
|
"""Create an instance of a Renderbuffer object."""
|
||||||
|
self._context = pyglet.gl.current_context
|
||||||
self._id = GLuint()
|
self._id = GLuint()
|
||||||
self._width = width
|
self._width = width
|
||||||
self._height = height
|
self._height = height
|
||||||
@ -49,13 +50,15 @@ class Renderbuffer:
|
|||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
glDeleteRenderbuffers(1, self._id)
|
glDeleteRenderbuffers(1, self._id)
|
||||||
|
self._id = None
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
try:
|
if self._id is not None:
|
||||||
glDeleteRenderbuffers(1, self._id)
|
try:
|
||||||
# Python interpreter is shutting down:
|
self._context.delete_renderbuffer(self._id.value)
|
||||||
except Exception:
|
self._id = None
|
||||||
pass
|
except (AttributeError, ImportError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
||||||
@ -71,6 +74,7 @@ class Framebuffer:
|
|||||||
|
|
||||||
.. versionadded:: 2.0
|
.. versionadded:: 2.0
|
||||||
"""
|
"""
|
||||||
|
self._context = pyglet.gl.current_context
|
||||||
self._id = GLuint()
|
self._id = GLuint()
|
||||||
glGenFramebuffers(1, self._id)
|
glGenFramebuffers(1, self._id)
|
||||||
self._attachment_types = 0
|
self._attachment_types = 0
|
||||||
@ -105,10 +109,16 @@ class Framebuffer:
|
|||||||
self.unbind()
|
self.unbind()
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
try:
|
glDeleteFramebuffers(1, self._id)
|
||||||
glDeleteFramebuffers(1, self._id)
|
self._id = None
|
||||||
except Exception:
|
|
||||||
pass
|
def __del__(self):
|
||||||
|
if self._id is not None:
|
||||||
|
try:
|
||||||
|
self._context.delete_framebuffer(self._id.value)
|
||||||
|
self._id = None
|
||||||
|
except (AttributeError, ImportError):
|
||||||
|
pass # Interpreter is shutting down
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_complete(self):
|
def is_complete(self):
|
||||||
@ -203,12 +213,5 @@ class Framebuffer:
|
|||||||
self._height = max(renderbuffer.height, self._height)
|
self._height = max(renderbuffer.height, self._height)
|
||||||
self.unbind()
|
self.unbind()
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
try:
|
|
||||||
glDeleteFramebuffers(1, self._id)
|
|
||||||
# Python interpreter is shutting down:
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
return "{}(id={})".format(self.__class__.__name__, self._id.value)
|
||||||
|
@ -4,7 +4,6 @@ import fcntl
|
|||||||
import ctypes
|
import ctypes
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from os import readv
|
|
||||||
from ctypes import c_uint16 as _u16
|
from ctypes import c_uint16 as _u16
|
||||||
from ctypes import c_int16 as _s16
|
from ctypes import c_int16 as _s16
|
||||||
from ctypes import c_uint32 as _u32
|
from ctypes import c_uint32 as _u32
|
||||||
@ -22,6 +21,8 @@ from pyglet.input.base import Device, RelativeAxis, AbsoluteAxis, Button, Joysti
|
|||||||
from pyglet.input.base import DeviceOpenException, ControllerManager
|
from pyglet.input.base import DeviceOpenException, ControllerManager
|
||||||
from pyglet.input.controller import get_mapping, Relation, create_guid
|
from pyglet.input.controller import get_mapping, Relation, create_guid
|
||||||
|
|
||||||
|
c = pyglet.lib.load_library('c')
|
||||||
|
|
||||||
_IOC_NRBITS = 8
|
_IOC_NRBITS = 8
|
||||||
_IOC_TYPEBITS = 8
|
_IOC_TYPEBITS = 8
|
||||||
_IOC_SIZEBITS = 14
|
_IOC_SIZEBITS = 14
|
||||||
@ -408,7 +409,7 @@ class EvdevDevice(XlibSelectDevice, Device):
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bytes_read = readv(self._fileno, self._event_buffer)
|
bytes_read = c.read(self._fileno, self._event_buffer, self._event_size)
|
||||||
except OSError:
|
except OSError:
|
||||||
self.close()
|
self.close()
|
||||||
return
|
return
|
||||||
|
@ -273,9 +273,10 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
conventions. This will ensure it is not obscured by other windows,
|
conventions. This will ensure it is not obscured by other windows,
|
||||||
and appears on an appropriate screen for the user.
|
and appears on an appropriate screen for the user.
|
||||||
|
|
||||||
To render into a window, you must first call `switch_to`, to make
|
To render into a window, you must first call its :py:meth:`.switch_to`
|
||||||
it the current OpenGL context. If you use only one window in the
|
method to make it the active OpenGL context. If you use only one
|
||||||
application, there is no need to do this.
|
window in your application, you can skip this step as it will always
|
||||||
|
be the active context.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Filled in by metaclass with the names of all methods on this (sub)class
|
# Filled in by metaclass with the names of all methods on this (sub)class
|
||||||
@ -638,7 +639,8 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
"""Clear the window.
|
"""Clear the window.
|
||||||
|
|
||||||
This is a convenience method for clearing the color and depth
|
This is a convenience method for clearing the color and depth
|
||||||
buffer. The window must be the active context (see `switch_to`).
|
buffer. The window must be the active context (see
|
||||||
|
:py:meth:`.switch_to`).
|
||||||
"""
|
"""
|
||||||
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
|
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
|
||||||
|
|
||||||
@ -646,10 +648,12 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
"""Close the window.
|
"""Close the window.
|
||||||
|
|
||||||
After closing the window, the GL context will be invalid. The
|
After closing the window, the GL context will be invalid. The
|
||||||
window instance cannot be reused once closed (see also `set_visible`).
|
window instance cannot be reused once closed. To re-use windows,
|
||||||
|
see :py:meth:`.set_visible` instead.
|
||||||
|
|
||||||
The `pyglet.app.EventLoop.on_window_close` event is dispatched on
|
The :py:meth:`pyglet.app.EventLoop.on_window_close` event is
|
||||||
`pyglet.app.event_loop` when this method is called.
|
dispatched by the :py:attr:`pyglet.app.event_loop` when this method
|
||||||
|
is called.
|
||||||
"""
|
"""
|
||||||
from pyglet import app
|
from pyglet import app
|
||||||
if not self._context:
|
if not self._context:
|
||||||
@ -676,7 +680,7 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
and advanced applications that must integrate their event loop
|
and advanced applications that must integrate their event loop
|
||||||
into another framework.
|
into another framework.
|
||||||
|
|
||||||
Typical applications should use `pyglet.app.run`.
|
Typical applications should use :py:func:`pyglet.app.run`.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('abstract')
|
raise NotImplementedError('abstract')
|
||||||
|
|
||||||
@ -715,11 +719,14 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
"""Swap the OpenGL front and back buffers.
|
"""Swap the OpenGL front and back buffers.
|
||||||
|
|
||||||
Call this method on a double-buffered window to update the
|
Call this method on a double-buffered window to update the
|
||||||
visible display with the back buffer. The contents of the back buffer
|
visible display with the back buffer. Windows are
|
||||||
is undefined after this operation.
|
double-buffered by default unless you turn this feature off.
|
||||||
|
|
||||||
Windows are double-buffered by default. This method is called
|
The contents of the back buffer are undefined after this operation.
|
||||||
automatically by `EventLoop` after the :py:meth:`~pyglet.window.Window.on_draw` event.
|
|
||||||
|
The default :py:attr:`~pyglet.app.event_loop` automatically
|
||||||
|
calls this method after the window's
|
||||||
|
:py:meth:`~pyglet.window.Window.on_draw` event.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('abstract')
|
raise NotImplementedError('abstract')
|
||||||
|
|
||||||
@ -1158,10 +1165,13 @@ class BaseWindow(EventDispatcher, metaclass=_WindowMetaclass):
|
|||||||
def switch_to(self):
|
def switch_to(self):
|
||||||
"""Make this window the current OpenGL rendering context.
|
"""Make this window the current OpenGL rendering context.
|
||||||
|
|
||||||
Only one OpenGL context can be active at a time. This method sets
|
Only one OpenGL context can be active at a time. This method
|
||||||
the current window's context to be current. You should use this
|
sets the current window context as the active one.
|
||||||
method in preference to `pyglet.gl.Context.set_current`, as it may
|
|
||||||
perform additional initialisation functions.
|
In most cases, you should use this method instead of directly
|
||||||
|
calling :py:meth:`pyglet.gl.Context.set_current`. The latter
|
||||||
|
will not perform platform-specific state management tasks for
|
||||||
|
you.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('abstract')
|
raise NotImplementedError('abstract')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user