feat: pyglet update

This commit is contained in:
shenjack 2022-12-09 21:05:32 +08:00
parent fc74a41d70
commit 8be2d655ca
11 changed files with 168 additions and 293 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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))

View File

@ -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',

View File

@ -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