feat: pyglet update
This commit is contained in:
parent
fc74a41d70
commit
8be2d655ca
@ -44,7 +44,7 @@ import sys
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
#: The release version
|
#: The release version
|
||||||
version = '2.0.0'
|
version = '2.0.1'
|
||||||
__version__ = version
|
__version__ = version
|
||||||
|
|
||||||
MIN_PYTHON_VERSION = 3, 8
|
MIN_PYTHON_VERSION = 3, 8
|
||||||
|
@ -52,7 +52,6 @@ class PlatformEventLoop:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._event_queue = queue.Queue()
|
self._event_queue = queue.Queue()
|
||||||
self._is_running = threading.Event()
|
self._is_running = threading.Event()
|
||||||
self._is_running.clear()
|
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
"""Return True if the event loop is currently processing, or False
|
"""Return True if the event loop is currently processing, or False
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
# POSSIBILITY OF SUCH DAMAGE.
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import ctypes
|
||||||
|
|
||||||
from .base import PlatformEventLoop
|
from .base import PlatformEventLoop
|
||||||
|
|
||||||
from pyglet.libs.win32 import _kernel32, _user32, types, constants
|
from pyglet.libs.win32 import _kernel32, _user32, types, constants
|
||||||
@ -41,7 +43,7 @@ from pyglet.libs.win32.types import *
|
|||||||
|
|
||||||
class Win32EventLoop(PlatformEventLoop):
|
class Win32EventLoop(PlatformEventLoop):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Win32EventLoop, self).__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._next_idle_time = None
|
self._next_idle_time = None
|
||||||
|
|
||||||
@ -50,7 +52,7 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
# imports pyglet.app _must_ own the main run loop.
|
# imports pyglet.app _must_ own the main run loop.
|
||||||
msg = types.MSG()
|
msg = types.MSG()
|
||||||
_user32.PeekMessageW(ctypes.byref(msg), 0,
|
_user32.PeekMessageW(ctypes.byref(msg), 0,
|
||||||
constants.WM_USER, constants.WM_USER,
|
constants.WM_USER, constants.WM_USER,
|
||||||
constants.PM_NOREMOVE)
|
constants.PM_NOREMOVE)
|
||||||
|
|
||||||
self._event_thread = _kernel32.GetCurrentThreadId()
|
self._event_thread = _kernel32.GetCurrentThreadId()
|
||||||
@ -60,9 +62,15 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
|
|
||||||
self._timer_proc = types.TIMERPROC(self._timer_proc_func)
|
self._timer_proc = types.TIMERPROC(self._timer_proc_func)
|
||||||
self._timer = _user32.SetTimer(0, 0, constants.USER_TIMER_MAXIMUM, self._timer_proc)
|
self._timer = _user32.SetTimer(0, 0, constants.USER_TIMER_MAXIMUM, self._timer_proc)
|
||||||
|
|
||||||
self._timer_func = None
|
self._timer_func = None
|
||||||
|
|
||||||
|
# Windows Multimedia timer precision functions
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
|
||||||
|
self._winmm = ctypes.windll.LoadLibrary('winmm')
|
||||||
|
timecaps = TIMECAPS()
|
||||||
|
self._winmm.timeGetDevCaps(ctypes.byref(timecaps), ctypes.sizeof(timecaps))
|
||||||
|
self._timer_precision = min(max(1, timecaps.wPeriodMin), timecaps.wPeriodMax)
|
||||||
|
|
||||||
def add_wait_object(self, obj, func):
|
def add_wait_object(self, obj, func):
|
||||||
self._wait_objects.append((obj, func))
|
self._wait_objects.append((obj, func))
|
||||||
self._recreate_wait_objects_array()
|
self._recreate_wait_objects_array()
|
||||||
@ -81,8 +89,7 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
return
|
return
|
||||||
|
|
||||||
self._wait_objects_n = len(self._wait_objects)
|
self._wait_objects_n = len(self._wait_objects)
|
||||||
self._wait_objects_array = \
|
self._wait_objects_array = (HANDLE * self._wait_objects_n)(*[o for o, f in self._wait_objects])
|
||||||
(HANDLE * self._wait_objects_n)(*[o for o, f in self._wait_objects])
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
if _kernel32.GetCurrentThreadId() != self._event_thread:
|
if _kernel32.GetCurrentThreadId() != self._event_thread:
|
||||||
@ -90,8 +97,8 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
'thread that imports pyglet.app')
|
'thread that imports pyglet.app')
|
||||||
|
|
||||||
self._timer_func = None
|
self._timer_func = None
|
||||||
self._polling = False
|
|
||||||
self._allow_polling = True
|
self._winmm.timeBeginPeriod(self._timer_precision)
|
||||||
|
|
||||||
def step(self, timeout=None):
|
def step(self, timeout=None):
|
||||||
self.dispatch_posted_events()
|
self.dispatch_posted_events()
|
||||||
@ -100,7 +107,7 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = constants.INFINITE
|
timeout = constants.INFINITE
|
||||||
else:
|
else:
|
||||||
timeout = int(timeout * 1000) # milliseconds
|
timeout = int(timeout * 1000) # milliseconds
|
||||||
|
|
||||||
result = _user32.MsgWaitForMultipleObjects(
|
result = _user32.MsgWaitForMultipleObjects(
|
||||||
self._wait_objects_n,
|
self._wait_objects_n,
|
||||||
@ -122,6 +129,9 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
# Return True if timeout was interrupted.
|
# Return True if timeout was interrupted.
|
||||||
return result <= self._wait_objects_n
|
return result <= self._wait_objects_n
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._winmm.timeEndPeriod(self._timer_precision)
|
||||||
|
|
||||||
def notify(self):
|
def notify(self):
|
||||||
# Nudge the event loop with a message it will discard. Note that only
|
# Nudge the event loop with a message it will discard. Note that only
|
||||||
# user events are actually posted. The posted event will not
|
# user events are actually posted. The posted event will not
|
||||||
@ -133,11 +143,11 @@ class Win32EventLoop(PlatformEventLoop):
|
|||||||
if func is None or interval is None:
|
if func is None or interval is None:
|
||||||
interval = constants.USER_TIMER_MAXIMUM
|
interval = constants.USER_TIMER_MAXIMUM
|
||||||
else:
|
else:
|
||||||
interval = int(interval * 1000) # milliseconds
|
interval = int(interval * 1000) # milliseconds
|
||||||
|
|
||||||
self._timer_func = func
|
self._timer_func = func
|
||||||
_user32.SetTimer(0, self._timer, interval, self._timer_proc)
|
_user32.SetTimer(0, self._timer, interval, self._timer_proc)
|
||||||
|
|
||||||
def _timer_proc_func(self, hwnd, msg, timer, t):
|
def _timer_proc_func(self, hwnd, msg, timer, t):
|
||||||
if self._timer_func:
|
if self._timer_func:
|
||||||
self._timer_func()
|
self._timer_func()
|
||||||
|
@ -98,12 +98,18 @@ class Display:
|
|||||||
raise NotImplementedError('abstract')
|
raise NotImplementedError('abstract')
|
||||||
|
|
||||||
def get_default_screen(self):
|
def get_default_screen(self):
|
||||||
"""Get the default screen as specified by the user's operating system
|
"""Get the default (primary) screen as specified by the user's operating system
|
||||||
preferences.
|
preferences.
|
||||||
|
|
||||||
:rtype: :class:`Screen`
|
:rtype: :class:`Screen`
|
||||||
"""
|
"""
|
||||||
return self.get_screens()[0]
|
screens = self.get_screens()
|
||||||
|
for screen in screens:
|
||||||
|
if screen.x == 0 and screen.y == 0:
|
||||||
|
return screen
|
||||||
|
|
||||||
|
# No Primary screen found?
|
||||||
|
return screens[0]
|
||||||
|
|
||||||
def get_windows(self):
|
def get_windows(self):
|
||||||
"""Get the windows currently attached to this display.
|
"""Get the windows currently attached to this display.
|
||||||
|
@ -120,7 +120,7 @@ class Config:
|
|||||||
major_version = None
|
major_version = None
|
||||||
minor_version = None
|
minor_version = None
|
||||||
forward_compatible = None
|
forward_compatible = None
|
||||||
opengl_api = "gl"
|
opengl_api = None
|
||||||
debug = None
|
debug = None
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@ -137,13 +137,7 @@ class Config:
|
|||||||
else:
|
else:
|
||||||
setattr(self, name, None)
|
setattr(self, name, None)
|
||||||
|
|
||||||
def requires_gl_3(self):
|
self.opengl_api = self.opengl_api or "gl"
|
||||||
# TODO: remove deprecated
|
|
||||||
if self.major_version is not None and self.major_version >= 3:
|
|
||||||
return True
|
|
||||||
if self.forward_compatible or self.debug:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_gl_attributes(self):
|
def get_gl_attributes(self):
|
||||||
"""Return a list of attributes set on this config.
|
"""Return a list of attributes set on this config.
|
||||||
@ -263,15 +257,6 @@ class Context:
|
|||||||
GL objects.
|
GL objects.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#: Context share behaviour indicating that objects should not be
|
|
||||||
#: shared with existing contexts.
|
|
||||||
CONTEXT_SHARE_NONE = None
|
|
||||||
|
|
||||||
#: Context share behaviour indicating that objects are shared with
|
|
||||||
#: the most recently created context (the default).
|
|
||||||
CONTEXT_SHARE_EXISTING = 1
|
|
||||||
|
|
||||||
# gl_info.GLInfo instance, filled in on first set_current
|
# gl_info.GLInfo instance, filled in on first set_current
|
||||||
_info = None
|
_info = None
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ class CocoaContext(Context):
|
|||||||
|
|
||||||
def attach(self, canvas):
|
def attach(self, canvas):
|
||||||
# See if we want OpenGL 3 in a non-Lion OS
|
# See if we want OpenGL 3 in a non-Lion OS
|
||||||
if _os_x_version < os_x_release['lion'] and self.config.requires_gl_3():
|
if _os_x_version < os_x_release['lion']:
|
||||||
raise ContextException('OpenGL 3 not supported')
|
raise ContextException('OpenGL 3 not supported')
|
||||||
|
|
||||||
super(CocoaContext, self).attach(canvas)
|
super(CocoaContext, self).attach(canvas)
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
# POSSIBILITY OF SUCH DAMAGE.
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
import warnings
|
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
|
|
||||||
from pyglet import gl
|
from pyglet import gl
|
||||||
@ -53,6 +52,7 @@ _fake_gl_attributes = {
|
|||||||
'accum_alpha_size': 0
|
'accum_alpha_size': 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class HeadlessConfig(Config):
|
class HeadlessConfig(Config):
|
||||||
def match(self, canvas):
|
def match(self, canvas):
|
||||||
if not isinstance(canvas, HeadlessCanvas):
|
if not isinstance(canvas, HeadlessCanvas):
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
import warnings
|
import warnings
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
|
|
||||||
from .base import Config, CanvasConfig, Context, OpenGLAPI
|
from .base import Config, CanvasConfig, Context
|
||||||
from pyglet.canvas.xlib import XlibCanvas
|
from pyglet.canvas.xlib import XlibCanvas
|
||||||
from pyglet.gl import glx
|
from pyglet.gl import glx
|
||||||
from pyglet.gl import glxext_arb
|
from pyglet.gl import glxext_arb
|
||||||
@ -47,6 +47,7 @@ from pyglet import gl
|
|||||||
|
|
||||||
|
|
||||||
class XlibConfig(Config):
|
class XlibConfig(Config):
|
||||||
|
|
||||||
def match(self, canvas):
|
def match(self, canvas):
|
||||||
if not isinstance(canvas, XlibCanvas):
|
if not isinstance(canvas, XlibCanvas):
|
||||||
raise RuntimeError('Canvas must be an instance of XlibCanvas')
|
raise RuntimeError('Canvas must be an instance of XlibCanvas')
|
||||||
@ -55,51 +56,36 @@ class XlibConfig(Config):
|
|||||||
x_screen = canvas.display.x_screen
|
x_screen = canvas.display.x_screen
|
||||||
|
|
||||||
info = glx_info.GLXInfo(x_display)
|
info = glx_info.GLXInfo(x_display)
|
||||||
have_13 = info.have_version(1, 3)
|
|
||||||
if have_13:
|
|
||||||
config_class = XlibCanvasConfig13
|
|
||||||
else:
|
|
||||||
config_class = XlibCanvasConfig10
|
|
||||||
|
|
||||||
# Construct array of attributes
|
# Construct array of attributes
|
||||||
attrs = []
|
attrs = []
|
||||||
for name, value in self.get_gl_attributes():
|
for name, value in self.get_gl_attributes():
|
||||||
attr = config_class.attribute_ids.get(name, None)
|
attr = XlibCanvasConfig.attribute_ids.get(name, None)
|
||||||
if attr and value is not None:
|
if attr and value is not None:
|
||||||
attrs.extend([attr, int(value)])
|
attrs.extend([attr, int(value)])
|
||||||
|
|
||||||
if have_13:
|
attrs.extend([glx.GLX_X_RENDERABLE, True])
|
||||||
attrs.extend([glx.GLX_X_RENDERABLE, True])
|
|
||||||
else:
|
|
||||||
attrs.extend([glx.GLX_RGBA, True])
|
|
||||||
|
|
||||||
attrs.extend([0, 0]) # attrib_list must be null terminated
|
attrs.extend([0, 0]) # attrib_list must be null terminated
|
||||||
|
|
||||||
attrib_list = (c_int * len(attrs))(*attrs)
|
attrib_list = (c_int * len(attrs))(*attrs)
|
||||||
|
|
||||||
if have_13:
|
elements = c_int()
|
||||||
elements = c_int()
|
configs = glx.glXChooseFBConfig(x_display, x_screen, attrib_list, byref(elements))
|
||||||
configs = glx.glXChooseFBConfig(x_display, x_screen, attrib_list, byref(elements))
|
if not configs:
|
||||||
if not configs:
|
return []
|
||||||
return []
|
|
||||||
|
|
||||||
configs = cast(configs, POINTER(glx.GLXFBConfig * elements.value)).contents
|
configs = cast(configs, POINTER(glx.GLXFBConfig * elements.value)).contents
|
||||||
|
|
||||||
result = [config_class(canvas, info, c, self) for c in configs]
|
result = [XlibCanvasConfig(canvas, info, c, self) for c in configs]
|
||||||
|
|
||||||
# Can't free array until all XlibGLConfig13's are GC'd. Too much
|
# Can't free array until all XlibGLConfig's are GC'd. Too much
|
||||||
# hassle, live with leak. XXX
|
# hassle, live with leak. XXX
|
||||||
# xlib.XFree(configs)
|
# xlib.XFree(configs)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
else:
|
|
||||||
try:
|
|
||||||
return [config_class(canvas, info, attrib_list, self)]
|
|
||||||
except gl.ContextException:
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
class BaseXlibCanvasConfig(CanvasConfig):
|
class XlibCanvasConfig(CanvasConfig):
|
||||||
# Common code shared between GLX 1.0 and GLX 1.3 configs.
|
|
||||||
|
|
||||||
attribute_ids = {
|
attribute_ids = {
|
||||||
'buffer_size': glx.GLX_BUFFER_SIZE,
|
'buffer_size': glx.GLX_BUFFER_SIZE,
|
||||||
@ -117,56 +103,7 @@ class BaseXlibCanvasConfig(CanvasConfig):
|
|||||||
'accum_green_size': glx.GLX_ACCUM_GREEN_SIZE,
|
'accum_green_size': glx.GLX_ACCUM_GREEN_SIZE,
|
||||||
'accum_blue_size': glx.GLX_ACCUM_BLUE_SIZE,
|
'accum_blue_size': glx.GLX_ACCUM_BLUE_SIZE,
|
||||||
'accum_alpha_size': glx.GLX_ACCUM_ALPHA_SIZE,
|
'accum_alpha_size': glx.GLX_ACCUM_ALPHA_SIZE,
|
||||||
}
|
|
||||||
|
|
||||||
def __init__(self, canvas, glx_info, config):
|
|
||||||
super(BaseXlibCanvasConfig, self).__init__(canvas, config)
|
|
||||||
self.glx_info = glx_info
|
|
||||||
|
|
||||||
def compatible(self, canvas):
|
|
||||||
# TODO check more
|
|
||||||
return isinstance(canvas, XlibCanvas)
|
|
||||||
|
|
||||||
def _create_glx_context(self, share):
|
|
||||||
raise NotImplementedError('abstract')
|
|
||||||
|
|
||||||
def is_complete(self):
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_visual_info(self):
|
|
||||||
raise NotImplementedError('abstract')
|
|
||||||
|
|
||||||
|
|
||||||
class XlibCanvasConfig10(BaseXlibCanvasConfig):
|
|
||||||
def __init__(self, canvas, glx_info, attrib_list, config):
|
|
||||||
super(XlibCanvasConfig10, self).__init__(canvas, glx_info, config)
|
|
||||||
x_display = canvas.display._display
|
|
||||||
x_screen = canvas.display.x_screen
|
|
||||||
|
|
||||||
self._visual_info = glx.glXChooseVisual(
|
|
||||||
x_display, x_screen, attrib_list)
|
|
||||||
if not self._visual_info:
|
|
||||||
raise gl.ContextException('No conforming visual exists')
|
|
||||||
|
|
||||||
for name, attr in self.attribute_ids.items():
|
|
||||||
value = c_int()
|
|
||||||
result = glx.glXGetConfig(
|
|
||||||
x_display, self._visual_info, attr, byref(value))
|
|
||||||
if result >= 0:
|
|
||||||
setattr(self, name, value.value)
|
|
||||||
self.sample_buffers = 0
|
|
||||||
self.samples = 0
|
|
||||||
|
|
||||||
def get_visual_info(self):
|
|
||||||
return self._visual_info.contents
|
|
||||||
|
|
||||||
def create_context(self, share):
|
|
||||||
return XlibContext10(self, share)
|
|
||||||
|
|
||||||
|
|
||||||
class XlibCanvasConfig13(BaseXlibCanvasConfig):
|
|
||||||
attribute_ids = BaseXlibCanvasConfig.attribute_ids.copy()
|
|
||||||
attribute_ids.update({
|
|
||||||
'sample_buffers': glx.GLX_SAMPLE_BUFFERS,
|
'sample_buffers': glx.GLX_SAMPLE_BUFFERS,
|
||||||
'samples': glx.GLX_SAMPLES,
|
'samples': glx.GLX_SAMPLES,
|
||||||
|
|
||||||
@ -182,33 +119,40 @@ class XlibCanvasConfig13(BaseXlibCanvasConfig):
|
|||||||
|
|
||||||
# Used internally
|
# Used internally
|
||||||
'x_renderable': glx.GLX_X_RENDERABLE,
|
'x_renderable': glx.GLX_X_RENDERABLE,
|
||||||
})
|
}
|
||||||
|
|
||||||
def __init__(self, canvas, glx_info, fbconfig, config):
|
def __init__(self, canvas, info, fbconfig, config):
|
||||||
super(XlibCanvasConfig13, self).__init__(canvas, glx_info, config)
|
super().__init__(canvas, config)
|
||||||
x_display = canvas.display._display
|
|
||||||
|
self.glx_info = info
|
||||||
|
self.fbconfig = fbconfig
|
||||||
|
|
||||||
self._fbconfig = fbconfig
|
|
||||||
for name, attr in self.attribute_ids.items():
|
for name, attr in self.attribute_ids.items():
|
||||||
value = c_int()
|
value = c_int()
|
||||||
result = glx.glXGetFBConfigAttrib(
|
result = glx.glXGetFBConfigAttrib(canvas.display._display, self.fbconfig, attr, byref(value))
|
||||||
x_display, self._fbconfig, attr, byref(value))
|
|
||||||
if result >= 0:
|
if result >= 0:
|
||||||
setattr(self, name, value.value)
|
setattr(self, name, value.value)
|
||||||
|
|
||||||
def get_visual_info(self):
|
def get_visual_info(self):
|
||||||
return glx.glXGetVisualFromFBConfig(self.canvas.display._display, self._fbconfig).contents
|
return glx.glXGetVisualFromFBConfig(self.canvas.display._display, self.fbconfig).contents
|
||||||
|
|
||||||
def create_context(self, share):
|
def create_context(self, share):
|
||||||
if self.glx_info.have_extension('GLX_ARB_create_context'):
|
return XlibContext(self, share)
|
||||||
return XlibContextARB(self, share)
|
|
||||||
else:
|
def compatible(self, canvas):
|
||||||
return XlibContext13(self, share)
|
# TODO check more
|
||||||
|
return isinstance(canvas, XlibCanvas)
|
||||||
|
|
||||||
|
def _create_glx_context(self, share):
|
||||||
|
raise NotImplementedError('abstract')
|
||||||
|
|
||||||
|
def is_complete(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class BaseXlibContext(Context):
|
class XlibContext(Context):
|
||||||
def __init__(self, config, share):
|
def __init__(self, config, share):
|
||||||
super(BaseXlibContext, self).__init__(config, share)
|
super().__init__(config, share)
|
||||||
|
|
||||||
self.x_display = config.canvas.display._display
|
self.x_display = config.canvas.display._display
|
||||||
|
|
||||||
@ -230,12 +174,81 @@ class BaseXlibContext(Context):
|
|||||||
self._use_video_sync = (self._have_SGI_video_sync and
|
self._use_video_sync = (self._have_SGI_video_sync and
|
||||||
not (self._have_EXT_swap_control or self._have_MESA_swap_control))
|
not (self._have_EXT_swap_control or self._have_MESA_swap_control))
|
||||||
|
|
||||||
# XXX mandate that vsync defaults on across all platforms.
|
# XXX Mandate that vsync defaults on across all platforms.
|
||||||
self._vsync = True
|
self._vsync = True
|
||||||
|
|
||||||
|
self.glx_window = None
|
||||||
|
|
||||||
def is_direct(self):
|
def is_direct(self):
|
||||||
return glx.glXIsDirect(self.x_display, self.glx_context)
|
return glx.glXIsDirect(self.x_display, self.glx_context)
|
||||||
|
|
||||||
|
def _create_glx_context(self, share):
|
||||||
|
if share:
|
||||||
|
share_context = share.glx_context
|
||||||
|
else:
|
||||||
|
share_context = None
|
||||||
|
|
||||||
|
attribs = []
|
||||||
|
if self.config.major_version is not None:
|
||||||
|
attribs.extend([glxext_arb.GLX_CONTEXT_MAJOR_VERSION_ARB, self.config.major_version])
|
||||||
|
if self.config.minor_version is not None:
|
||||||
|
attribs.extend([glxext_arb.GLX_CONTEXT_MINOR_VERSION_ARB, self.config.minor_version])
|
||||||
|
|
||||||
|
if self.config.opengl_api == "gl":
|
||||||
|
attribs.extend([glxext_arb.GLX_CONTEXT_PROFILE_MASK_ARB, glxext_arb.GLX_CONTEXT_CORE_PROFILE_BIT_ARB])
|
||||||
|
elif self.config.opengl_api == "gles":
|
||||||
|
attribs.extend([glxext_arb.GLX_CONTEXT_PROFILE_MASK_ARB, glxext_arb.GLX_CONTEXT_ES2_PROFILE_BIT_EXT])
|
||||||
|
|
||||||
|
flags = 0
|
||||||
|
if self.config.forward_compatible:
|
||||||
|
flags |= glxext_arb.GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
|
||||||
|
if self.config.debug:
|
||||||
|
flags |= glxext_arb.GLX_CONTEXT_DEBUG_BIT_ARB
|
||||||
|
|
||||||
|
if flags:
|
||||||
|
attribs.extend([glxext_arb.GLX_CONTEXT_FLAGS_ARB, flags])
|
||||||
|
attribs.append(0)
|
||||||
|
attribs = (c_int * len(attribs))(*attribs)
|
||||||
|
|
||||||
|
return glxext_arb.glXCreateContextAttribsARB(self.config.canvas.display._display,
|
||||||
|
self.config.fbconfig, share_context, True, attribs)
|
||||||
|
|
||||||
|
def attach(self, canvas):
|
||||||
|
if canvas is self.canvas:
|
||||||
|
return
|
||||||
|
|
||||||
|
super().attach(canvas)
|
||||||
|
|
||||||
|
self.glx_window = glx.glXCreateWindow(self.x_display, self.config.fbconfig, canvas.x_window, None)
|
||||||
|
self.set_current()
|
||||||
|
|
||||||
|
def set_current(self):
|
||||||
|
glx.glXMakeContextCurrent(self.x_display, self.glx_window, self.glx_window, self.glx_context)
|
||||||
|
super().set_current()
|
||||||
|
|
||||||
|
def detach(self):
|
||||||
|
if not self.canvas:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.set_current()
|
||||||
|
gl.glFlush()
|
||||||
|
|
||||||
|
super().detach()
|
||||||
|
|
||||||
|
glx.glXMakeContextCurrent(self.x_display, 0, 0, None)
|
||||||
|
if self.glx_window:
|
||||||
|
glx.glXDestroyWindow(self.x_display, self.glx_window)
|
||||||
|
self.glx_window = None
|
||||||
|
|
||||||
|
def destroy(self):
|
||||||
|
super().destroy()
|
||||||
|
if self.glx_window:
|
||||||
|
glx.glXDestroyWindow(self.config.display._display, self.glx_window)
|
||||||
|
self.glx_window = None
|
||||||
|
if self.glx_context:
|
||||||
|
glx.glXDestroyContext(self.x_display, self.glx_context)
|
||||||
|
self.glx_context = None
|
||||||
|
|
||||||
def set_vsync(self, vsync=True):
|
def set_vsync(self, vsync=True):
|
||||||
self._vsync = vsync
|
self._vsync = vsync
|
||||||
interval = vsync and 1 or 0
|
interval = vsync and 1 or 0
|
||||||
@ -258,157 +271,11 @@ class BaseXlibContext(Context):
|
|||||||
glxext_arb.glXGetVideoSyncSGI(byref(count))
|
glxext_arb.glXGetVideoSyncSGI(byref(count))
|
||||||
glxext_arb.glXWaitVideoSyncSGI(2, (count.value + 1) % 2, byref(count))
|
glxext_arb.glXWaitVideoSyncSGI(2, (count.value + 1) % 2, byref(count))
|
||||||
|
|
||||||
|
|
||||||
class XlibContext10(BaseXlibContext):
|
|
||||||
def __init__(self, config, share):
|
|
||||||
super(XlibContext10, self).__init__(config, share)
|
|
||||||
|
|
||||||
def _create_glx_context(self, share):
|
|
||||||
if self.config.requires_gl_3():
|
|
||||||
raise gl.ContextException(
|
|
||||||
'Require GLX_ARB_create_context extension to create OpenGL 3 contexts.')
|
|
||||||
|
|
||||||
if share:
|
|
||||||
share_context = share.glx_context
|
|
||||||
else:
|
|
||||||
share_context = None
|
|
||||||
|
|
||||||
return glx.glXCreateContext(self.config.canvas.display._display,
|
|
||||||
self.config._visual_info, share_context, True)
|
|
||||||
|
|
||||||
def attach(self, canvas):
|
|
||||||
super(XlibContext10, self).attach(canvas)
|
|
||||||
|
|
||||||
self.set_current()
|
|
||||||
|
|
||||||
def set_current(self):
|
|
||||||
glx.glXMakeCurrent(self.x_display, self.canvas.x_window, self.glx_context)
|
|
||||||
super(XlibContext10, self).set_current()
|
|
||||||
|
|
||||||
def detach(self):
|
|
||||||
if not self.canvas:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.set_current()
|
|
||||||
gl.glFlush()
|
|
||||||
glx.glXMakeCurrent(self.x_display, 0, None)
|
|
||||||
super(XlibContext10, self).detach()
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
super(XlibContext10, self).destroy()
|
|
||||||
|
|
||||||
glx.glXDestroyContext(self.x_display, self.glx_context)
|
|
||||||
self.glx_context = None
|
|
||||||
|
|
||||||
def flip(self):
|
|
||||||
if not self.canvas:
|
|
||||||
return
|
|
||||||
|
|
||||||
if self._vsync:
|
|
||||||
self._wait_vsync()
|
|
||||||
glx.glXSwapBuffers(self.x_display, self.canvas.x_window)
|
|
||||||
|
|
||||||
|
|
||||||
class XlibContext13(BaseXlibContext):
|
|
||||||
def __init__(self, config, share):
|
|
||||||
super(XlibContext13, self).__init__(config, share)
|
|
||||||
self.glx_window = None
|
|
||||||
|
|
||||||
def _create_glx_context(self, share):
|
|
||||||
if self.config.requires_gl_3():
|
|
||||||
raise gl.ContextException(
|
|
||||||
'Require GLX_ARB_create_context extension to create ' +
|
|
||||||
'OpenGL 3 contexts.')
|
|
||||||
|
|
||||||
if share:
|
|
||||||
share_context = share.glx_context
|
|
||||||
else:
|
|
||||||
share_context = None
|
|
||||||
|
|
||||||
return glx.glXCreateNewContext(self.config.canvas.display._display,
|
|
||||||
self.config._fbconfig, glx.GLX_RGBA_TYPE, share_context,
|
|
||||||
True)
|
|
||||||
|
|
||||||
def attach(self, canvas):
|
|
||||||
if canvas is self.canvas:
|
|
||||||
return
|
|
||||||
|
|
||||||
super(XlibContext13, self).attach(canvas)
|
|
||||||
|
|
||||||
self.glx_window = glx.glXCreateWindow(
|
|
||||||
self.x_display, self.config._fbconfig, canvas.x_window, None)
|
|
||||||
self.set_current()
|
|
||||||
|
|
||||||
def set_current(self):
|
|
||||||
glx.glXMakeContextCurrent(
|
|
||||||
self.x_display, self.glx_window, self.glx_window, self.glx_context)
|
|
||||||
super(XlibContext13, self).set_current()
|
|
||||||
|
|
||||||
def detach(self):
|
|
||||||
if not self.canvas:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.set_current()
|
|
||||||
gl.glFlush() # needs to be in try/except?
|
|
||||||
|
|
||||||
super(XlibContext13, self).detach()
|
|
||||||
|
|
||||||
glx.glXMakeContextCurrent(self.x_display, 0, 0, None)
|
|
||||||
if self.glx_window:
|
|
||||||
glx.glXDestroyWindow(self.x_display, self.glx_window)
|
|
||||||
self.glx_window = None
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
super(XlibContext13, self).destroy()
|
|
||||||
if self.glx_window:
|
|
||||||
glx.glXDestroyWindow(self.config.display._display, self.glx_window)
|
|
||||||
self.glx_window = None
|
|
||||||
if self.glx_context:
|
|
||||||
glx.glXDestroyContext(self.x_display, self.glx_context)
|
|
||||||
self.glx_context = None
|
|
||||||
|
|
||||||
def flip(self):
|
def flip(self):
|
||||||
if not self.glx_window:
|
if not self.glx_window:
|
||||||
return
|
return
|
||||||
|
|
||||||
if self._vsync:
|
if self._vsync:
|
||||||
self._wait_vsync()
|
self._wait_vsync()
|
||||||
|
|
||||||
glx.glXSwapBuffers(self.x_display, self.glx_window)
|
glx.glXSwapBuffers(self.x_display, self.glx_window)
|
||||||
|
|
||||||
|
|
||||||
class XlibContextARB(XlibContext13):
|
|
||||||
def _create_glx_context(self, share):
|
|
||||||
if share:
|
|
||||||
share_context = share.glx_context
|
|
||||||
else:
|
|
||||||
share_context = None
|
|
||||||
|
|
||||||
attribs = []
|
|
||||||
if self.config.major_version is not None:
|
|
||||||
attribs.extend([glxext_arb.GLX_CONTEXT_MAJOR_VERSION_ARB,
|
|
||||||
self.config.major_version])
|
|
||||||
if self.config.minor_version is not None:
|
|
||||||
attribs.extend([glxext_arb.GLX_CONTEXT_MINOR_VERSION_ARB,
|
|
||||||
self.config.minor_version])
|
|
||||||
|
|
||||||
if self.config.opengl_api == "gl":
|
|
||||||
attribs.extend([glxext_arb.GLX_CONTEXT_PROFILE_MASK_ARB, glxext_arb.GLX_CONTEXT_CORE_PROFILE_BIT_ARB])
|
|
||||||
elif self.config.opengl_api == "gles":
|
|
||||||
attribs.extend([glxext_arb.GLX_CONTEXT_PROFILE_MASK_ARB, glxext_arb.GLX_CONTEXT_ES2_PROFILE_BIT_EXT])
|
|
||||||
else:
|
|
||||||
raise ValueError(f"Unknown OpenGL API: {self.opengl_api}")
|
|
||||||
|
|
||||||
flags = 0
|
|
||||||
if self.config.forward_compatible:
|
|
||||||
flags |= glxext_arb.GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB
|
|
||||||
if self.config.debug:
|
|
||||||
flags |= glxext_arb.GLX_CONTEXT_DEBUG_BIT_ARB
|
|
||||||
|
|
||||||
if flags:
|
|
||||||
attribs.extend([glxext_arb.GLX_CONTEXT_FLAGS_ARB, flags])
|
|
||||||
attribs.append(0)
|
|
||||||
attribs = (c_int * len(attribs))(*attribs)
|
|
||||||
|
|
||||||
return glxext_arb.glXCreateContextAttribsARB(
|
|
||||||
self.config.canvas.display._display,
|
|
||||||
self.config._fbconfig, share_context, True, attribs)
|
|
||||||
|
@ -687,7 +687,7 @@ class ShaderProgram:
|
|||||||
raise ShaderException(f"\nThe attribute `{name}` doesn't exist. Valid names: \n{list(attributes)}")
|
raise ShaderException(f"\nThe attribute `{name}` doesn't exist. Valid names: \n{list(attributes)}")
|
||||||
|
|
||||||
batch = batch or pyglet.graphics.get_default_batch()
|
batch = batch or pyglet.graphics.get_default_batch()
|
||||||
domain = batch.get_domain(False, mode, group, self._id, attributes)
|
domain = batch.get_domain(False, mode, group, self, attributes)
|
||||||
|
|
||||||
# Create vertex list and initialize
|
# Create vertex list and initialize
|
||||||
vlist = domain.create(count)
|
vlist = domain.create(count)
|
||||||
@ -731,7 +731,7 @@ class ShaderProgram:
|
|||||||
raise ShaderException(f"\nThe attribute `{name}` doesn't exist. Valid names: \n{list(attributes)}")
|
raise ShaderException(f"\nThe attribute `{name}` doesn't exist. Valid names: \n{list(attributes)}")
|
||||||
|
|
||||||
batch = batch or pyglet.graphics.get_default_batch()
|
batch = batch or pyglet.graphics.get_default_batch()
|
||||||
domain = batch.get_domain(True, mode, group, self._id, attributes)
|
domain = batch.get_domain(True, mode, group, self, attributes)
|
||||||
|
|
||||||
# Create vertex list and initialize
|
# Create vertex list and initialize
|
||||||
vlist = domain.create(count, len(indices))
|
vlist = domain.create(count, len(indices))
|
||||||
|
@ -33,12 +33,13 @@
|
|||||||
# POSSIBILITY OF SUCH DAMAGE.
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
import sys
|
|
||||||
import ctypes
|
import ctypes
|
||||||
from . import com
|
|
||||||
from ctypes import *
|
from ctypes import *
|
||||||
from ctypes.wintypes import *
|
from ctypes.wintypes import *
|
||||||
|
|
||||||
|
from . import com
|
||||||
|
|
||||||
|
|
||||||
_int_types = (c_int16, c_int32)
|
_int_types = (c_int16, c_int32)
|
||||||
if hasattr(ctypes, 'c_int64'):
|
if hasattr(ctypes, 'c_int64'):
|
||||||
@ -53,11 +54,6 @@ del t
|
|||||||
del _int_types
|
del _int_types
|
||||||
|
|
||||||
|
|
||||||
# PUINT is defined only from >= python 3.2
|
|
||||||
if sys.version_info < (3, 2)[:2]:
|
|
||||||
PUINT = POINTER(UINT)
|
|
||||||
|
|
||||||
|
|
||||||
class c_void(Structure):
|
class c_void(Structure):
|
||||||
# c_void_p is a buggy return type, converting to int, so
|
# c_void_p is a buggy return type, converting to int, so
|
||||||
# POINTER(None) == c_void_p is actually written as
|
# POINTER(None) == c_void_p is actually written as
|
||||||
@ -76,6 +72,7 @@ def POINTER_(obj):
|
|||||||
return cls()
|
return cls()
|
||||||
else:
|
else:
|
||||||
return x
|
return x
|
||||||
|
|
||||||
p.from_param = classmethod(from_param)
|
p.from_param = classmethod(from_param)
|
||||||
|
|
||||||
return p
|
return p
|
||||||
@ -367,6 +364,7 @@ class _DUMMYSTRUCTNAME(Structure):
|
|||||||
('dmPrintQuality', c_short),
|
('dmPrintQuality', c_short),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class _DUMMYSTRUCTNAME2(Structure):
|
class _DUMMYSTRUCTNAME2(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
('dmPosition', POINTL),
|
('dmPosition', POINTL),
|
||||||
@ -374,6 +372,7 @@ class _DUMMYSTRUCTNAME2(Structure):
|
|||||||
('dmDisplayFixedOutput', DWORD)
|
('dmDisplayFixedOutput', DWORD)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class _DUMMYDEVUNION(Union):
|
class _DUMMYDEVUNION(Union):
|
||||||
_anonymous_ = ('_dummystruct1', '_dummystruct2')
|
_anonymous_ = ('_dummystruct1', '_dummystruct2')
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@ -382,6 +381,7 @@ class _DUMMYDEVUNION(Union):
|
|||||||
('_dummystruct2', _DUMMYSTRUCTNAME2),
|
('_dummystruct2', _DUMMYSTRUCTNAME2),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class DEVMODE(Structure):
|
class DEVMODE(Structure):
|
||||||
_anonymous_ = ('_dummyUnion',)
|
_anonymous_ = ('_dummyUnion',)
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@ -391,7 +391,7 @@ class DEVMODE(Structure):
|
|||||||
('dmSize', WORD),
|
('dmSize', WORD),
|
||||||
('dmDriverExtra', WORD),
|
('dmDriverExtra', WORD),
|
||||||
('dmFields', DWORD),
|
('dmFields', DWORD),
|
||||||
# Just using largest union member here
|
# Just using the largest union member here
|
||||||
('_dummyUnion', _DUMMYDEVUNION),
|
('_dummyUnion', _DUMMYDEVUNION),
|
||||||
# End union
|
# End union
|
||||||
('dmColor', c_short),
|
('dmColor', c_short),
|
||||||
@ -404,7 +404,7 @@ class DEVMODE(Structure):
|
|||||||
('dmBitsPerPel', DWORD),
|
('dmBitsPerPel', DWORD),
|
||||||
('dmPelsWidth', DWORD),
|
('dmPelsWidth', DWORD),
|
||||||
('dmPelsHeight', DWORD),
|
('dmPelsHeight', DWORD),
|
||||||
('dmDisplayFlags', DWORD), # union with dmNup
|
('dmDisplayFlags', DWORD), # union with dmNup
|
||||||
('dmDisplayFrequency', DWORD),
|
('dmDisplayFrequency', DWORD),
|
||||||
('dmICMMethod', DWORD),
|
('dmICMMethod', DWORD),
|
||||||
('dmICMIntent', DWORD),
|
('dmICMIntent', DWORD),
|
||||||
@ -511,7 +511,7 @@ class RAWINPUT(Structure):
|
|||||||
|
|
||||||
|
|
||||||
# PROPVARIANT wrapper, doesn't require InitPropVariantFromInt64 this way.
|
# PROPVARIANT wrapper, doesn't require InitPropVariantFromInt64 this way.
|
||||||
class _VarTable(ctypes.Union):
|
class _VarTable(Union):
|
||||||
"""Must be in an anonymous union or values will not work across various VT's."""
|
"""Must be in an anonymous union or values will not work across various VT's."""
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
('llVal', ctypes.c_longlong),
|
('llVal', ctypes.c_longlong),
|
||||||
@ -519,7 +519,7 @@ class _VarTable(ctypes.Union):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class PROPVARIANT(ctypes.Structure):
|
class PROPVARIANT(Structure):
|
||||||
_anonymous_ = ['union']
|
_anonymous_ = ['union']
|
||||||
|
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@ -530,14 +530,15 @@ class PROPVARIANT(ctypes.Structure):
|
|||||||
('union', _VarTable)
|
('union', _VarTable)
|
||||||
]
|
]
|
||||||
|
|
||||||
class _VarTableVariant(ctypes.Union):
|
|
||||||
|
class _VarTableVariant(Union):
|
||||||
"""Must be in an anonymous union or values will not work across various VT's."""
|
"""Must be in an anonymous union or values will not work across various VT's."""
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
('bstrVal', LPCWSTR)
|
('bstrVal', LPCWSTR)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class VARIANT(ctypes.Structure):
|
class VARIANT(Structure):
|
||||||
_anonymous_ = ['union']
|
_anonymous_ = ['union']
|
||||||
|
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@ -548,7 +549,8 @@ class VARIANT(ctypes.Structure):
|
|||||||
('union', _VarTableVariant)
|
('union', _VarTableVariant)
|
||||||
]
|
]
|
||||||
|
|
||||||
class DWM_BLURBEHIND(ctypes.Structure):
|
|
||||||
|
class DWM_BLURBEHIND(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
("dwFlags", DWORD),
|
("dwFlags", DWORD),
|
||||||
("fEnable", BOOL),
|
("fEnable", BOOL),
|
||||||
@ -557,7 +559,7 @@ class DWM_BLURBEHIND(ctypes.Structure):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class STATSTG(ctypes.Structure):
|
class STATSTG(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
('pwcsName', LPOLESTR),
|
('pwcsName', LPOLESTR),
|
||||||
('type', DWORD),
|
('type', DWORD),
|
||||||
@ -572,6 +574,12 @@ class STATSTG(ctypes.Structure):
|
|||||||
('reserved', DWORD),
|
('reserved', DWORD),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class TIMECAPS(Structure):
|
||||||
|
_fields_ = (('wPeriodMin', UINT),
|
||||||
|
('wPeriodMax', UINT))
|
||||||
|
|
||||||
|
|
||||||
class IStream(com.pIUnknown):
|
class IStream(com.pIUnknown):
|
||||||
_methods_ = [
|
_methods_ = [
|
||||||
('Read',
|
('Read',
|
||||||
|
@ -87,7 +87,7 @@ import pyglet
|
|||||||
from pyglet.gl import GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
|
from pyglet.gl import GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
|
||||||
from pyglet.gl import GL_TRIANGLES, GL_LINES, GL_BLEND
|
from pyglet.gl import GL_TRIANGLES, GL_LINES, GL_BLEND
|
||||||
from pyglet.gl import glBlendFunc, glEnable, glDisable
|
from pyglet.gl import glBlendFunc, glEnable, glDisable
|
||||||
from pyglet.graphics import shader, Batch, Group
|
from pyglet.graphics import Batch, Group
|
||||||
|
|
||||||
|
|
||||||
vertex_source = """#version 150 core
|
vertex_source = """#version 150 core
|
||||||
|
Loading…
Reference in New Issue
Block a user