Last active
August 29, 2015 14:05
-
-
Save almarklein/4b483f919f9ba698f839 to your computer and use it in GitHub Desktop.
angle backend that I wrote about half a year ago and is tight to Qt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
# Copyright (c) 2014, Vispy Development Team. | |
# Distributed under the (new) BSD License. See LICENSE.txt for more info. | |
""" | |
vispy backend for Qt (PySide and PyQt4). | |
""" | |
from __future__ import division | |
from ... import config | |
from ..base import BaseApplicationBackend, BaseCanvasBackend, BaseTimerBackend | |
from ...util import keys | |
from . import ATTEMPTED_BACKENDS | |
from ...util.six import text_type | |
from . import _libegl as egl | |
# Get what qt lib to try | |
if len(ATTEMPTED_BACKENDS): | |
qt_lib = ATTEMPTED_BACKENDS[-1].lower() | |
if qt_lib.lower() == 'qt': | |
qt_lib = config['qt_lib'].lower() | |
# in case the last app we ran was something else (e.g., Pyglet) | |
if qt_lib not in ['pyqt', 'pyqt4', 'pyside', 'qt']: | |
qt_lib = 'any' | |
else: | |
qt_lib = 'any' | |
# Import PySide or PyQt4 | |
if qt_lib in ('any', 'qt'): | |
try: | |
from PyQt4 import QtGui, QtCore | |
except ImportError: | |
from PySide import QtGui, QtCore | |
elif qt_lib in ('pyqt', 'pyqt4'): | |
from PyQt4 import QtGui, QtCore | |
elif qt_lib == 'pyside': | |
from PySide import QtGui, QtCore | |
else: | |
raise Exception("Do not recognize Qt library '%s'. Options are " | |
"'pyqt4', 'pyside', or 'qt'])." % str(qt_lib)) | |
# todo: add support for distinguishing left and right shift/ctrl/alt keys. | |
# Linux scan codes: (left, right) | |
# Shift 50, 62 | |
# Ctrl 37, 105 | |
# Alt 64, 108 | |
KEYMAP = { | |
QtCore.Qt.Key_Shift: keys.SHIFT, | |
QtCore.Qt.Key_Control: keys.CONTROL, | |
QtCore.Qt.Key_Alt: keys.ALT, | |
QtCore.Qt.Key_AltGr: keys.ALT, | |
QtCore.Qt.Key_Meta: keys.META, | |
QtCore.Qt.Key_Left: keys.LEFT, | |
QtCore.Qt.Key_Up: keys.UP, | |
QtCore.Qt.Key_Right: keys.RIGHT, | |
QtCore.Qt.Key_Down: keys.DOWN, | |
QtCore.Qt.Key_PageUp: keys.PAGEUP, | |
QtCore.Qt.Key_PageDown: keys.PAGEDOWN, | |
QtCore.Qt.Key_Insert: keys.INSERT, | |
QtCore.Qt.Key_Delete: keys.DELETE, | |
QtCore.Qt.Key_Home: keys.HOME, | |
QtCore.Qt.Key_End: keys.END, | |
QtCore.Qt.Key_Escape: keys.ESCAPE, | |
QtCore.Qt.Key_Backspace: keys.BACKSPACE, | |
QtCore.Qt.Key_F1: keys.F1, | |
QtCore.Qt.Key_F2: keys.F2, | |
QtCore.Qt.Key_F3: keys.F3, | |
QtCore.Qt.Key_F4: keys.F4, | |
QtCore.Qt.Key_F5: keys.F5, | |
QtCore.Qt.Key_F6: keys.F6, | |
QtCore.Qt.Key_F7: keys.F7, | |
QtCore.Qt.Key_F8: keys.F8, | |
QtCore.Qt.Key_F9: keys.F9, | |
QtCore.Qt.Key_F10: keys.F10, | |
QtCore.Qt.Key_F11: keys.F11, | |
QtCore.Qt.Key_F12: keys.F12, | |
QtCore.Qt.Key_Space: keys.SPACE, | |
QtCore.Qt.Key_Enter: keys.ENTER, | |
QtCore.Qt.Key_Return: keys.ENTER, | |
QtCore.Qt.Key_Tab: keys.TAB, | |
} | |
BUTTONMAP = {0: 0, 1: 1, 2: 2, 4: 3, 8: 4, 16: 5} | |
class ApplicationBackend(BaseApplicationBackend): | |
def __init__(self): | |
BaseApplicationBackend.__init__(self) | |
def _vispy_get_backend_name(self): | |
if 'pyside' in QtCore.__name__.lower(): | |
return 'PySide (qt)' | |
else: | |
return 'PyQt4 (qt)' | |
def _vispy_process_events(self): | |
app = self._vispy_get_native_app() | |
app.flush() | |
app.processEvents() | |
def _vispy_run(self): | |
app = self._vispy_get_native_app() | |
if hasattr(app, '_in_event_loop') and app._in_event_loop: | |
pass # Already in event loop | |
else: | |
return app.exec_() | |
def _vispy_quit(self): | |
return self._vispy_get_native_app().quit() | |
def _vispy_get_native_app(self): | |
# Get native app in save way. Taken from guisupport.py | |
app = QtGui.QApplication.instance() | |
if app is None: | |
app = QtGui.QApplication(['']) | |
# Store so it won't be deleted, but not on a visvis object, | |
# or an application may produce error when closed | |
QtGui._qApp = app | |
# Return | |
return app | |
class CanvasBackend(QtGui.QWidget, BaseCanvasBackend): | |
"""Qt backend for Canvas abstract class.""" | |
def __init__(self, *args, **kwargs): | |
BaseCanvasBackend.__init__(self) | |
QtGui.QWidget.__init__(self, *args, **kwargs) | |
self.setAttribute(QtCore.Qt.WA_PaintOnScreen, True) | |
self.setMouseTracking(True) | |
self.setAutoFillBackground(False) | |
# flags | |
self._is_initialized = False | |
# Get window id | |
w = egl.get_window_id(self) | |
# Setup egl to use this widget | |
self._egl_display = d = egl.eglGetDisplay() | |
self._egl_version = egl.eglInitialize(d) | |
self._egl_config = c = egl.eglChooseConfig(d)[0] # pick first | |
self._egl_surface = egl.eglCreateWindowSurface(d, c, w) | |
self._egl_context = egl.eglCreateContext(d, c) | |
# todo: maybe we should also clean up when window closes ... | |
def _vispy_set_current(self): | |
# Make this the current context | |
egl.eglMakeCurrent(self._egl_display, self._egl_surface, | |
self._egl_surface, self._egl_context) | |
def _vispy_swap_buffers(self): | |
# Swap front and back buffer | |
egl.eglSwapBuffers(self._egl_display, self._egl_surface) | |
def _vispy_set_title(self, title): | |
# Set the window title. Has no effect for widgets | |
self.setWindowTitle(title) | |
def _vispy_set_size(self, w, h): | |
# Set size of the widget or window | |
self.resize(w, h) | |
def _vispy_set_position(self, x, y): | |
# Set location of the widget or window. May have no effect for widgets | |
self.move(x, y) | |
def _vispy_set_visible(self, visible): | |
# Show or hide the window or widget | |
if visible: | |
self.show() | |
else: | |
self.hide() | |
def _vispy_update(self): | |
# Invoke a redraw | |
self.update() | |
def _vispy_close(self): | |
# Force the window or widget to shut down | |
self.close() | |
def _vispy_get_position(self): | |
g = self.geometry() | |
return g.x(), g.y() | |
def _vispy_get_size(self): | |
g = self.geometry() | |
return g.width(), g.height() | |
def initializeGL(self): | |
if self._vispy_canvas is None: | |
return | |
self._vispy_set_current() | |
self._vispy_canvas.events.initialize() | |
def resizeEvent(self, event): | |
w, h = event.size().width(), event.size().height() | |
if self._vispy_canvas is None: | |
return | |
self._vispy_canvas.events.resize(size=(w, h)) | |
def paintEngine(self): | |
pass | |
def paintEvent(self, event): | |
if self._vispy_canvas is None: | |
return | |
if not self._is_initialized: | |
self._is_initialized = True | |
self.initializeGL() | |
# (0, 0, self.width(), self.height())) | |
self._vispy_canvas.events.paint(region=None) | |
def closeEvent(self, ev): | |
if self._vispy_canvas is None: | |
return | |
self._vispy_canvas.events.close() | |
def mousePressEvent(self, ev): | |
if self._vispy_canvas is None: | |
return | |
self._vispy_mouse_press( | |
native=ev, | |
pos=(ev.pos().x(), ev.pos().y()), | |
button=BUTTONMAP.get(ev.button(), 0), | |
modifiers = self._modifiers(ev), | |
) | |
def mouseReleaseEvent(self, ev): | |
if self._vispy_canvas is None: | |
return | |
self._vispy_mouse_release( | |
native=ev, | |
pos=(ev.pos().x(), ev.pos().y()), | |
button=BUTTONMAP[ev.button()], | |
modifiers = self._modifiers(ev), | |
) | |
def mouseMoveEvent(self, ev): | |
if self._vispy_canvas is None: | |
return | |
self._vispy_mouse_move( | |
native=ev, | |
pos=(ev.pos().x(), ev.pos().y()), | |
modifiers=self._modifiers(ev), | |
) | |
def wheelEvent(self, ev): | |
if self._vispy_canvas is None: | |
return | |
# Get scrolling | |
deltax, deltay = 0.0, 0.0 | |
if ev.orientation == QtCore.Qt.Horizontal: | |
deltax = ev.delta() / 120.0 | |
else: | |
deltay = ev.delta() / 120.0 | |
# Emit event | |
self._vispy_canvas.events.mouse_wheel( | |
native=ev, | |
delta=(deltax, deltay), | |
pos=(ev.pos().x(), ev.pos().y()), | |
modifiers=self._modifiers(ev), | |
) | |
def keyPressEvent(self, ev): | |
self._vispy_canvas.events.key_press( | |
native=ev, | |
key=self._processKey(ev), | |
text=text_type(ev.text()), | |
modifiers=self._modifiers(ev), | |
) | |
def keyReleaseEvent(self, ev): | |
# if ev.isAutoRepeat(): | |
# return # Skip release auto repeat events | |
self._vispy_canvas.events.key_release( | |
native=ev, | |
key=self._processKey(ev), | |
text=text_type(ev.text()), | |
modifiers=self._modifiers(ev), | |
) | |
def _processKey(self, event): | |
# evaluates the keycode of qt, and transform to vispy key. | |
key = int(event.key()) | |
if key in KEYMAP: | |
return KEYMAP[key] | |
elif key >= 32 and key <= 127: | |
return keys.Key(chr(key)) | |
else: | |
return None | |
def _modifiers(self, event): | |
# Convert the QT modifier state into a tuple of active modifier keys. | |
mod = () | |
qtmod = event.modifiers() | |
if QtCore.Qt.ShiftModifier & qtmod: | |
mod += keys.SHIFT, | |
if QtCore.Qt.ControlModifier & qtmod: | |
mod += keys.CONTROL, | |
if QtCore.Qt.AltModifier & qtmod: | |
mod += keys.ALT, | |
if QtCore.Qt.MetaModifier & qtmod: | |
mod += keys.META, | |
return mod | |
# class QtMouseEvent(MouseEvent): | |
# special subclass of MouseEvent for propagating acceptance info back to Qt. | |
# @MouseEvent.handled.setter | |
# def handled(self, val): | |
# self._handled = val | |
# if val: | |
# self.qt_event.accept() | |
# else: | |
# self.qt_event.ignore() | |
class TimerBackend(BaseTimerBackend, QtCore.QTimer): | |
def __init__(self, vispy_timer): | |
if QtGui.QApplication.instance() is None: | |
global QAPP | |
QAPP = QtGui.QApplication([]) | |
BaseTimerBackend.__init__(self, vispy_timer) | |
QtCore.QTimer.__init__(self) | |
self.timeout.connect(self._vispy_timeout) | |
def _vispy_start(self, interval): | |
self.start(interval * 1000.) | |
def _vispy_stop(self): | |
self.stop() | |
def _vispy_timeout(self): | |
self._vispy_timer._timeout() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ctypes | |
from ctypes import c_int as _c_int, POINTER as _POINTER | |
fname = r'C:\almar\projects\py\vispy\Qt5.2.1 64bit gl es2 libs\libEGL.dll' | |
_lib = ctypes.windll.LoadLibrary(fname) | |
## Constants | |
EGL_FALSE = 0 | |
EGL_TRUE = 1 | |
# Out-of-band handle values | |
EGL_DEFAULT_DISPLAY = 0 | |
EGL_NO_CONTEXT = 0 | |
EGL_NO_DISPLAY = 0 | |
EGL_NO_SURFACE = 0 | |
# Out-of-band attribute value | |
EGL_DONT_CARE = -1 | |
# Errors / GetError return values | |
EGL_SUCCESS = 0x3000 | |
EGL_NOT_INITIALIZED = 0x3001 | |
EGL_BAD_ACCESS = 0x3002 | |
EGL_BAD_ALLOC = 0x3003 | |
EGL_BAD_ATTRIBUTE = 0x3004 | |
EGL_BAD_CONFIG = 0x3005 | |
EGL_BAD_CONTEXT = 0x3006 | |
EGL_BAD_CURRENT_SURFACE = 0x3007 | |
EGL_BAD_DISPLAY = 0x3008 | |
EGL_BAD_MATCH = 0x3009 | |
EGL_BAD_NATIVE_PIXMAP = 0x300A | |
EGL_BAD_NATIVE_WINDOW = 0x300B | |
EGL_BAD_PARAMETER = 0x300C | |
EGL_BAD_SURFACE = 0x300D | |
EGL_CONTEXT_LOST = 0x300E # EGL 1.1 - IMG_power_management | |
# Reserved 0x300F-0x301F for additional errors | |
# Config attributes | |
EGL_BUFFER_SIZE = 0x3020 | |
EGL_ALPHA_SIZE = 0x3021 | |
EGL_BLUE_SIZE = 0x3022 | |
EGL_GREEN_SIZE = 0x3023 | |
EGL_RED_SIZE = 0x3024 | |
EGL_DEPTH_SIZE = 0x3025 | |
EGL_STENCIL_SIZE = 0x3026 | |
EGL_CONFIG_CAVEAT = 0x3027 | |
EGL_CONFIG_ID = 0x3028 | |
EGL_LEVEL = 0x3029 | |
EGL_MAX_PBUFFER_HEIGHT = 0x302A | |
EGL_MAX_PBUFFER_PIXELS = 0x302B | |
EGL_MAX_PBUFFER_WIDTH = 0x302C | |
EGL_NATIVE_RENDERABLE = 0x302D | |
EGL_NATIVE_VISUAL_ID = 0x302E | |
EGL_NATIVE_VISUAL_TYPE = 0x302F | |
EGL_SAMPLES = 0x3031 | |
EGL_SAMPLE_BUFFERS = 0x3032 | |
EGL_SURFACE_TYPE = 0x3033 | |
EGL_TRANSPARENT_TYPE = 0x3034 | |
EGL_TRANSPARENT_BLUE_VALUE = 0x3035 | |
EGL_TRANSPARENT_GREEN_VALUE = 0x3036 | |
EGL_TRANSPARENT_RED_VALUE = 0x3037 | |
EGL_NONE = 0x3038 # Attrib list terminator | |
EGL_BIND_TO_TEXTURE_RGB = 0x3039 | |
EGL_BIND_TO_TEXTURE_RGBA = 0x303A | |
EGL_MIN_SWAP_INTERVAL = 0x303B | |
EGL_MAX_SWAP_INTERVAL = 0x303C | |
EGL_LUMINANCE_SIZE = 0x303D | |
EGL_ALPHA_MASK_SIZE = 0x303E | |
EGL_COLOR_BUFFER_TYPE = 0x303F | |
EGL_RENDERABLE_TYPE = 0x3040 | |
EGL_MATCH_NATIVE_PIXMAP = 0x3041 # Pseudo-attribute (not queryable) | |
EGL_CONFORMANT = 0x3042 | |
# Reserved 0x3041-0x304F for additional config attributes | |
# Config attribute values | |
EGL_SLOW_CONFIG = 0x3050 # EGL_CONFIG_CAVEAT value | |
EGL_NON_CONFORMANT_CONFIG = 0x3051 # EGL_CONFIG_CAVEAT value | |
EGL_TRANSPARENT_RGB = 0x3052 # EGL_TRANSPARENT_TYPE value | |
EGL_RGB_BUFFER = 0x308E # EGL_COLOR_BUFFER_TYPE value | |
EGL_LUMINANCE_BUFFER = 0x308F # EGL_COLOR_BUFFER_TYPE value | |
# More config attribute values, for EGL_TEXTURE_FORMAT | |
EGL_NO_TEXTURE = 0x305C | |
EGL_TEXTURE_RGB = 0x305D | |
EGL_TEXTURE_RGBA = 0x305E | |
EGL_TEXTURE_2D = 0x305F | |
# Config attribute mask bits | |
EGL_PBUFFER_BIT = 0x0001 # EGL_SURFACE_TYPE mask bits | |
EGL_PIXMAP_BIT = 0x0002 # EGL_SURFACE_TYPE mask bits | |
EGL_WINDOW_BIT = 0x0004 # EGL_SURFACE_TYPE mask bits | |
EGL_VG_COLORSPACE_LINEAR_BIT = 0x0020 # EGL_SURFACE_TYPE mask bits | |
EGL_VG_ALPHA_FORMAT_PRE_BIT = 0x0040 # EGL_SURFACE_TYPE mask bits | |
EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200 # EGL_SURFACE_TYPE mask bits | |
EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400 # EGL_SURFACE_TYPE mask bits | |
EGL_OPENGL_ES_BIT = 0x0001 # EGL_RENDERABLE_TYPE mask bits | |
EGL_OPENVG_BIT = 0x0002 # EGL_RENDERABLE_TYPE mask bits | |
EGL_OPENGL_ES2_BIT = 0x0004 # EGL_RENDERABLE_TYPE mask bits | |
EGL_OPENGL_BIT = 0x0008 # EGL_RENDERABLE_TYPE mask bits | |
# QueryString targets | |
EGL_VENDOR = 0x3053 | |
EGL_VERSION = 0x3054 | |
EGL_EXTENSIONS = 0x3055 | |
EGL_CLIENT_APIS = 0x308D | |
# QuerySurface / SurfaceAttrib / CreatePbufferSurface targets | |
EGL_HEIGHT = 0x3056 | |
EGL_WIDTH = 0x3057 | |
EGL_LARGEST_PBUFFER = 0x3058 | |
EGL_TEXTURE_FORMAT = 0x3080 | |
EGL_TEXTURE_TARGET = 0x3081 | |
EGL_MIPMAP_TEXTURE = 0x3082 | |
EGL_MIPMAP_LEVEL = 0x3083 | |
EGL_RENDER_BUFFER = 0x3086 | |
EGL_VG_COLORSPACE = 0x3087 | |
EGL_VG_ALPHA_FORMAT = 0x3088 | |
EGL_HORIZONTAL_RESOLUTION = 0x3090 | |
EGL_VERTICAL_RESOLUTION = 0x3091 | |
EGL_PIXEL_ASPECT_RATIO = 0x3092 | |
EGL_SWAP_BEHAVIOR = 0x3093 | |
EGL_MULTISAMPLE_RESOLVE = 0x3099 | |
# EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets | |
EGL_BACK_BUFFER = 0x3084 | |
EGL_SINGLE_BUFFER = 0x3085 | |
# OpenVG color spaces | |
EGL_VG_COLORSPACE_sRGB = 0x3089 # EGL_VG_COLORSPACE value | |
EGL_VG_COLORSPACE_LINEAR = 0x308A # EGL_VG_COLORSPACE value | |
# OpenVG alpha formats | |
EGL_VG_ALPHA_FORMAT_NONPRE = 0x308B # EGL_ALPHA_FORMAT value | |
EGL_VG_ALPHA_FORMAT_PRE = 0x308C # EGL_ALPHA_FORMAT value | |
# Constant scale factor by which fractional display resolutions & | |
# * aspect ratio are scaled when queried as integer values. | |
EGL_DISPLAY_SCALING = 10000 | |
# Unknown display resolution/aspect ratio | |
EGL_UNKNOWN = -1 | |
# Back buffer swap behaviors | |
EGL_BUFFER_PRESERVED = 0x3094 # EGL_SWAP_BEHAVIOR value | |
EGL_BUFFER_DESTROYED = 0x3095 # EGL_SWAP_BEHAVIOR value | |
# CreatePbufferFromClientBuffer buffer types | |
EGL_OPENVG_IMAGE = 0x3096 | |
# QueryContext targets | |
EGL_CONTEXT_CLIENT_TYPE = 0x3097 | |
# CreateContext attributes | |
EGL_CONTEXT_CLIENT_VERSION = 0x3098 | |
# Multisample resolution behaviors | |
EGL_MULTISAMPLE_RESOLVE_DEFAULT = 0x309A # EGL_MULTISAMPLE_RESOLVE value | |
EGL_MULTISAMPLE_RESOLVE_BOX = 0x309B # EGL_MULTISAMPLE_RESOLVE value | |
# BindAPI/QueryAPI targets | |
EGL_OPENGL_ES_API = 0x30A0 | |
EGL_OPENVG_API = 0x30A1 | |
EGL_OPENGL_API = 0x30A2 | |
# GetCurrentSurface targets | |
EGL_DRAW = 0x3059 | |
EGL_READ = 0x305A | |
# WaitNative engines | |
EGL_CORE_NATIVE_ENGINE = 0x305B | |
# EGL 1.2 tokens renamed for consistency in EGL 1.3 | |
EGL_COLORSPACE = EGL_VG_COLORSPACE | |
EGL_ALPHA_FORMAT = EGL_VG_ALPHA_FORMAT | |
EGL_COLORSPACE_sRGB = EGL_VG_COLORSPACE_sRGB | |
EGL_COLORSPACE_LINEAR = EGL_VG_COLORSPACE_LINEAR | |
EGL_ALPHA_FORMAT_NONPRE = EGL_VG_ALPHA_FORMAT_NONPRE | |
EGL_ALPHA_FORMAT_PRE = EGL_VG_ALPHA_FORMAT_PRE | |
## The functions | |
def eglGetError(): | |
""" Check for errors, returns an enum (int). | |
""" | |
return _lib.eglGetError() | |
_lib.eglGetDisplay.argtypes = _c_int, | |
# | |
def eglGetDisplay(display=EGL_DEFAULT_DISPLAY): | |
""" Connect to the EGL display server. | |
""" | |
res = _lib.eglGetDisplay(display) | |
if not res: | |
raise RuntimeError('Could not create display') | |
return res | |
_lib.eglInitialize.argtypes = _c_int, _POINTER(_c_int), _POINTER(_c_int), | |
# | |
def eglInitialize(display): | |
""" Initialize EGL and return EGL version tuple. | |
""" | |
majorVersion = (_c_int*1)() | |
minorVersion = (_c_int*1)() | |
res = _lib.eglInitialize(display, majorVersion, minorVersion) | |
if res == EGL_FALSE: | |
raise RuntimeError('Could not initialize') | |
return majorVersion[0], minorVersion[0] | |
DEFAULT_ATTRIB_LIST = [EGL_BUFFER_SIZE, 32, | |
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, | |
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | |
] | |
# | |
_lib.eglChooseConfig.argtypes = (_c_int, _POINTER(_c_int), | |
_POINTER(_c_int), _c_int, _POINTER(_c_int)) | |
# | |
def eglChooseConfig(display, attribList=None, maxConfigs=None): | |
# Deal with attrib list | |
attribList = attribList or DEFAULT_ATTRIB_LIST | |
attribList = [a for a in attribList] + [EGL_NONE] | |
attribList = (_c_int*len(attribList))(*attribList) | |
# | |
maxConfigs = maxConfigs or 32 | |
config = (_c_int*maxConfigs)() | |
numConfigs = (_c_int*1)() | |
_lib.eglChooseConfig(display, attribList, config, maxConfigs, numConfigs) | |
n = numConfigs[0] | |
if not n: | |
raise RuntimeError('Could not find any suitable config.') | |
return config[:n] | |
_lib.eglCreateWindowSurface.argtypes = _c_int, _c_int, _c_int, _POINTER(_c_int) | |
# | |
def eglCreateWindowSurface(display, config, window, attribList=None): | |
# Deal with attrib list | |
attribList = attribList or [] | |
attribList = [a for a in attribList] + [EGL_NONE] | |
attribList = (_c_int*len(attribList))(*attribList) | |
# | |
res = _lib.eglCreateWindowSurface(display, config, window, attribList) | |
if res == EGL_NO_SURFACE: | |
e = eglGetError() | |
if e == EGL_BAD_MATCH: | |
raise ValueError('Cannot create surface: attributes do not match or given config cannot render in window.') | |
elif e == EGL_BAD_CONFIG: | |
raise ValueError('Cannot create surface: given config is not supported by this system.') | |
elif e == EGL_BAD_NATIVE_WINDOW: | |
raise ValueError('Cannot create surface: the given native window handle is invalid.') | |
elif e == EGL_BAD_ALLOC: | |
raise RuntimeError('Could not allocate surface: not enough resources or native window already associated with another config.') | |
else: | |
raise RuntimeError('Could not create window surface due to unknown error: %i' % e) | |
return res | |
_lib.eglCreateContext.argtypes = _c_int, _c_int, _c_int, _POINTER(_c_int) | |
# | |
def eglCreateContext(display, config, shareContext=EGL_NO_CONTEXT, attribList=None): | |
# Deal with attrib list | |
attribList = attribList or [EGL_CONTEXT_CLIENT_VERSION, 2] | |
attribList = [a for a in attribList] + [EGL_NONE] | |
attribList = (_c_int*len(attribList))(*attribList) | |
# | |
res = _lib.eglCreateContext(display, config, shareContext, attribList) | |
if res == EGL_NO_CONTEXT: | |
if e == EGL_BAD_CONFIG: | |
raise ValueError('Could not create context: given config is not supported by this system.') | |
else: | |
raise RuntimeError('Could not create context due to unknown error: %i' % e) | |
return res | |
_lib.eglMakeCurrent.argtypes = _c_int, _c_int, _c_int, _c_int | |
# | |
def eglMakeCurrent(display, draw, read, context): | |
res = _lib.eglMakeCurrent(display, draw, read, context) | |
if res == EGL_FALSE: | |
raise RuntimeError('Could not make the context current.') | |
_lib.eglSwapBuffers.argtypes = _c_int, _c_int | |
# | |
def eglSwapBuffers(display, surface): | |
res = _lib.eglSwapBuffers(display, surface) | |
if res == EGL_FALSE: | |
raise RuntimeError('Could not swap buffers.') | |
## | |
# from PySide import QtGui, QtCore | |
# | |
# class DxWidget(QtGui.QWidget): | |
# def __init__(self, parent=None): | |
# QtGui.QWidget.__init__(self, parent) | |
# self.setAttribute(QtCore.Qt.WA_PaintOnScreen, True) | |
# def onPaint(self): | |
# pass | |
# | |
# w = DxWidget() | |
# w.show() | |
def get_window_id(widget): | |
""" Get the window id of a PySide Widget). Might also work for PyQt4. | |
""" | |
# Get window id from stupid capsule thingy | |
# http://translate.google.com/translate?hl=en&sl=zh-CN&u=http://www.cnblogs.com/Shiren-Y/archive/2011/04/06/2007288.html&prev=/search%3Fq%3Dpyside%2Bdirectx%26client%3Dfirefox-a%26hs%3DIsJ%26rls%3Dorg.mozilla:nl:official%26channel%3Dfflb%26biw%3D1366%26bih%3D614 | |
# Prepare | |
ctypes.pythonapi.PyCapsule_GetName.restype = ctypes.c_char_p | |
ctypes.pythonapi.PyCapsule_GetName.argtypes = [ctypes.py_object] | |
ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p | |
ctypes.pythonapi.PyCapsule_GetPointer.argtypes = [ctypes.py_object, ctypes.c_char_p] | |
# Extract handle from capsule thingy | |
capsule = widget.winId() | |
name = ctypes.pythonapi.PyCapsule_GetName(capsule) | |
handle = ctypes.pythonapi.PyCapsule_GetPointer(capsule, name) | |
return handle |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment