Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
708 changes: 0 additions & 708 deletions pyopengltk.py

This file was deleted.

37 changes: 37 additions & 0 deletions pyopengltk/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# An opengl frame for pyopengl-tkinter based on ctypes (no togl compilation)
#
# Collected together by Jon Wright, Jan 2018.
#
# Based on the work of others:
#
# C + Tcl/Tk
# http://github.com/codeplea/opengl-tcltk/
# (zlib license)
# Article at:
# https://codeplea.com/opengl-with-c-and-tcl-tk
#
# Python + Tkinter (no pyopengl)
# http://github.com/arcanosam/pytkogl/
# (The Code Project Open License)
# Article at
# http://www.codeproject.com/Articles/1073475/OpenGL-in-Python-with-TKinter
#
# Large parts copied from pyopengl/Tk/__init__.py
import sys

# Platform specific frames
if sys.platform.startswith('linux'):
from pyopengltk.linux import OpenGLFrame

if sys.platform.startswith('win32'):
from pyopengltk.win32 import OpenGLFrame

# if sys.platform.startswith('darwin'):
# from pyopengltk.darwin import OpenGLFrame

# opengl
from pyopengltk.opengl import RawOpengl
from pyopengltk.opengl import Opengl
from pyopengltk.opengl import glTranslateScene
from pyopengltk.opengl import glRotateScene
from pyopengltk.opengl import v3distsq
108 changes: 108 additions & 0 deletions pyopengltk/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import sys
from OpenGL import GL

if sys.version_info[0] < 3:
import Tkinter as tk
import Dialog as dialog
else:
import tkinter as tk
from tkinter import dialog as dialog


class BaseOpenGLFrame(tk.Frame):
""" Common code for windows/x11 """
def __init__(self, *args, **kw):
# Set background to empty string to avoid
# flickering overdraw by Tk
kw['bg'] = ""
tk.Frame.__init__(self, *args, **kw)
self.bind('<Map>', self.tkMap)
self.bind('<Configure>', self.tkResize)
self.bind('<Expose>', self.tkExpose)
self.animate = 0
self.cb = None

def tkMap(self, evt):
"""" Called when frame goes onto the screen """
self._wid = self.winfo_id()
self.tkCreateContext()
self.initgl()

def printContext(self, extns=False):
""" For debugging """
exts = GL.glGetString(GL.GL_EXTENSIONS)
if extns:
print("Extension list:")
for e in sorted(exts.split()):
print("\t", e)
else:
print("Number of extensions:", len(exts.split()))

print("GL_VENDOR :", GL.glGetString(GL.GL_VENDOR))
print("GL_RENDERER:", GL.glGetString(GL.GL_RENDERER))
print("GL_VERSION :", GL.glGetString(GL.GL_VERSION))
try:
print(" GL_MAJOR_VERSION:", GL.glGetIntegerv(GL.GL_MAJOR_VERSION))
print(" GL_MINOR_VERSION:", GL.glGetIntegerv(GL.GL_MINOR_VERSION))
print(" GL_SHADING_LANGUAGE_VERSION :",
GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION))
msk = GL.glGetIntegerv(GL.GL_CONTEXT_PROFILE_MASK)
print(" GL_CONTEXT_CORE_PROFILE_BIT :",
bool(msk & GL.GL_CONTEXT_CORE_PROFILE_BIT))
print(" GL_CONTEXT_COMPATIBILITY_PROFILE_BIT :",
bool(msk & GL.GL_CONTEXT_COMPATIBILITY_PROFILE_BIT))
except:
print("Old context errors arose")
# raise

def tkCreateContext(self):
# Platform dependent part
raise NotImplementedError

def tkMakeCurrent(self):
# Platform dependent part
raise NotImplementedError

def tkSwapBuffers(self):
# Platform dependent part
raise NotImplementedError

def tkExpose(self, evt):
if self.cb:
self.after_cancel(self.cb)
self._display()

def tkResize(self, evt):
"""
Things to do on window resize:
Adjust viewport:
glViewPort(0,0, width, height)
Adjust projection matrix:
glFrustum(left * ratio, right * ratio, bottom, top, nearClip,farClip)
or
glOrtho(left * ratio, right * ratio, bottom, top, nearClip,farClip)
or
gluOrtho2D(left * ratio, right * ratio, bottom, top)
(assuming that left, right, bottom and top are all equal and
ratio=width/height)
"""
self.width, self.height = evt.width, evt.height
if self.winfo_ismapped():
GL.glViewport(0, 0, self.width, self.height)
self.initgl()

def _display(self):
self.update_idletasks()
self.tkMakeCurrent()
self.redraw()
self.tkSwapBuffers()
if self.animate > 0:
self.cb = self.after(self.animate, self._display)

def initgl(self):
# For the user code
raise NotImplementedError

def redraw(self):
# For the user code
raise NotImplementedError
1 change: 1 addition & 0 deletions pyopengltk/darwin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Currently not implemented"""
160 changes: 160 additions & 0 deletions pyopengltk/linux.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""
Linux implementation of the opengl frame
"""
from __future__ import print_function
import logging
from ctypes import c_int, c_char_p, c_void_p, cdll, POINTER, util, \
pointer, CFUNCTYPE, c_bool
from OpenGL import GL, GLX
from pyopengltk.base import BaseOpenGLFrame

try:
from OpenGL.raw._GLX import Display
except:
from OpenGL.raw.GLX._types import Display

_log = logging.getLogger(__name__)


_x11lib = cdll.LoadLibrary(util.find_library("X11"))
XOpenDisplay = _x11lib.XOpenDisplay
XOpenDisplay.argtypes = [c_char_p]
XOpenDisplay.restype = POINTER(Display)

Colormap = c_void_p
# Attributes for old style creation
att = [
GLX.GLX_RGBA, GLX.GLX_DOUBLEBUFFER,
GLX.GLX_RED_SIZE, 4,
GLX.GLX_GREEN_SIZE, 4,
GLX.GLX_BLUE_SIZE, 4,
GLX.GLX_DEPTH_SIZE, 16,
0,
]
# Attributes for newer style creations
fbatt = [
GLX.GLX_X_RENDERABLE, 1,
GLX.GLX_DRAWABLE_TYPE, GLX.GLX_WINDOW_BIT,
GLX.GLX_RENDER_TYPE, GLX.GLX_RGBA_BIT,
GLX.GLX_RED_SIZE, 1,
GLX.GLX_GREEN_SIZE, 1,
GLX.GLX_BLUE_SIZE, 1,
GLX.GLX_DOUBLEBUFFER, 1,
0,
]


# Inherits the base and fills in the 3 platform dependent functions
class OpenGLFrame(BaseOpenGLFrame):

def tkCreateContext(self):
self.__window = XOpenDisplay(self.winfo_screen().encode('utf-8'))
# Check glx version:
major = c_int(0)
minor = c_int(0)
GLX.glXQueryVersion(self.__window, major, minor)
print("GLX version: %d.%d" % (major.value, minor.value))
if major.value == 1 and minor.value < 3: # e.g. 1.2 and down
visual = GLX.glXChooseVisual(self.__window, 0, (GL.GLint * len(att))(* att))
if not visual:
_log.error("glXChooseVisual call failed")
self.__context = GLX.glXCreateContext(self.__window,
visual,
None,
GL.GL_TRUE)
GLX.glXMakeCurrent(self.__window, self._wid, self.__context)
return # OUT HERE FOR 1.2 and less
else:
# 1.3 or higher
# which screen - should it be winfo_screen instead ??
XDefaultScreen = _x11lib.XDefaultScreen
XDefaultScreen.argtypes = [POINTER(Display)]
XDefaultScreen.restype = c_int
screen = XDefaultScreen(self.__window)
print("Screen is ", screen)
# Look at framebuffer configs
ncfg = GL.GLint(0)
cfgs = GLX.glXChooseFBConfig(
self.__window,
screen,
(GL.GLint * len(fbatt))(* fbatt),
ncfg,
)
print("Number of FBconfigs", ncfg.value)
#
# Try to match to the current window
# ... might also be possible to set this for the frame
# ... but for now we just take what Tk gave us
ideal = int(self.winfo_visualid(), 16) # convert from hex
best = -1
for i in range(ncfg.value):
vis = GLX.glXGetVisualFromFBConfig(self.__window, cfgs[i])
if ideal == vis.contents.visualid:
best = i
print("Got a matching visual: index %d %d xid %s" % (
best, vis.contents.visualid, hex(ideal)))
if best < 0:
print("oh dear - visual does not match")
# Take the first in the list (should be another I guess)
best = 0
# Here we insist on RGBA - but didn't check earlier
self.__context = GLX.glXCreateNewContext(
self.__window,
cfgs[best],
GLX.GLX_RGBA_TYPE,
None, # share list
GL.GL_TRUE, # direct
)
print("Is Direct?: ", GLX.glXIsDirect(self.__window, self.__context))
# Not creating another window ... some tutorials do
# print("wid: ", self._wid)
# self._wid = GLX.glXCreateWindow(self.__window, cfgs[best], self._wid, None)
# print("wid: ", self._wid)
GLX.glXMakeContextCurrent(self.__window, self._wid, self._wid, self.__context)
print("Done making a first context")
extensions = GLX.glXQueryExtensionsString(self.__window, screen)
# Here we quit - getting a modern context needs further work below
return
if "GLX_ARB_create_context" in extensions:
# We can try to upgrade it ??
print("Trying to upgrade context")
s = "glXCreateContextAttribsARB"
p = GLX.glXGetProcAddress(c_char_p(s))

print(p)
if not p:
p = GLX.glXGetProcAddressARB((GL.GLubyte * len(s)).from_buffer_copy(s))
print(p)
if p:
print(" p is true")
p.restype = GLX.GLXContext
p.argtypes = [
POINTER(Display),
GLX.GLXFBConfig,
GLX.GLXContext,
c_bool,
POINTER(c_int),
]
arb_attrs = fbatt[:-1] + []

# GLX.GLX_CONTEXT_MAJOR_VERSION_ARB , 3
# GLX.GLX_CONTEXT_MINOR_VERSION_ARB , 1,
# 0 ]
#
# GLX.GLX_CONTEXT_FLAGS_ARB
# GLX.GLX_CONTEXT_PROFILE_MASK_ARB
# ]
# import pdb
# pdb.set_trace()
self.__context = p(
self.__window, cfgs[best], None, GL.GL_TRUE,
(GL.GLint * len(arb_attrs))(* arb_attrs),
)

def tkMakeCurrent(self):
if self.winfo_ismapped():
GLX.glXMakeCurrent(self.__window, self._wid, self.__context)

def tkSwapBuffers(self):
if self.winfo_ismapped():
GLX.glXSwapBuffers(self.__window, self._wid)
Loading