134 lines
4.4 KiB
Python
Executable File
134 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# [SNIPPET_NAME: gtk3 opengl example]
|
|
# [SNIPPET_CATEGORIES: opengl]
|
|
# [SNIPPET_TAGS: opengl, gtk3]
|
|
# [SNIPPET_DESCRIPTION: using gtk3 library lets draw using opengl]
|
|
# [SNIPPET_AUTHOR: Oliver Marks ]
|
|
# [SNIPPET_LICENSE: GPL]
|
|
|
|
import sys
|
|
from OpenGL.GL import *
|
|
from OpenGL.GLU import *
|
|
from OpenGL import GLX
|
|
from OpenGL.raw._GLX import struct__XDisplay
|
|
from OpenGL import GL
|
|
from ctypes import *
|
|
|
|
import Xlib
|
|
from Xlib.display import Display
|
|
from gi.repository import Gtk, GdkX11, Gdk
|
|
|
|
|
|
class gtkgl:
|
|
""" these method do not seem to exist in python x11 library lets exploit the c methods """
|
|
xlib = cdll.LoadLibrary('libX11.so')
|
|
xlib.XOpenDisplay.argtypes = [c_char_p]
|
|
xlib.XOpenDisplay.restype = POINTER(struct__XDisplay)
|
|
xdisplay = xlib.XOpenDisplay(None)
|
|
display = Xlib.display.Display()
|
|
attrs = []
|
|
|
|
xwindow_id = None
|
|
width = height = 200
|
|
|
|
def __init__(self):
|
|
""" lets setup are opengl settings and create the context for our window """
|
|
self.add_attribute(GLX.GLX_RGBA, True)
|
|
self.add_attribute(GLX.GLX_RED_SIZE, 1)
|
|
self.add_attribute(GLX.GLX_GREEN_SIZE, 1)
|
|
self.add_attribute(GLX.GLX_BLUE_SIZE, 1)
|
|
self.add_attribute(GLX.GLX_DOUBLEBUFFER, 0)
|
|
|
|
xvinfo = GLX.glXChooseVisual(self.xdisplay, self.display.get_default_screen(), self.get_attributes())
|
|
configs = GLX.glXChooseFBConfig(self.xdisplay, 0, None, byref(c_int()))
|
|
self.context = GLX.glXCreateContext(self.xdisplay, xvinfo, None, True)
|
|
|
|
def add_attribute(self, setting, value):
|
|
"""just to nicely add opengl parameters"""
|
|
self.attrs.append(setting)
|
|
self.attrs.append(value)
|
|
|
|
def get_attributes(self):
|
|
""" return our parameters in the expected structure"""
|
|
attrs = self.attrs + [0, 0]
|
|
return (c_int * len(attrs))(*attrs)
|
|
|
|
def configure(self, wid):
|
|
""" """
|
|
self.xwindow_id = GdkX11.X11Window.get_xid(wid)
|
|
if(not GLX.glXMakeCurrent(self.xdisplay, self.xwindow_id, self.context)):
|
|
print ('failed configuring context')
|
|
glViewport(0, 0, self.width, self.height)
|
|
|
|
def draw_start(self):
|
|
"""make cairo context current for drawing"""
|
|
if(not GLX.glXMakeCurrent(self.xdisplay, self.xwindow_id, self.context)):
|
|
print ("failed to get the context for drawing")
|
|
|
|
def draw_finish(self):
|
|
"""swap buffer when we have finished drawing"""
|
|
GLX.glXSwapBuffers(self.xdisplay, self.xwindow_id)
|
|
|
|
def test(self):
|
|
"""Test method to draw something so we can make sure opengl is working and we can see something"""
|
|
self.draw_start()
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0)
|
|
glClear(GL_COLOR_BUFFER_BIT)
|
|
glBegin(GL_TRIANGLES)
|
|
glIndexi(0)
|
|
glColor3f(1.0, 0.0, 0.0)
|
|
glVertex2i(0, 1)
|
|
glIndexi(0)
|
|
glColor3f(0.0, 1.0, 0.0)
|
|
glVertex2i(-1, -1)
|
|
glIndexi(0)
|
|
glColor3f(0.0, 0.0, 1.0)
|
|
glVertex2i(1, -1)
|
|
glEnd()
|
|
|
|
self.draw_finish()
|
|
|
|
|
|
class gui():
|
|
glwrap = gtkgl()
|
|
|
|
def __init__(self):
|
|
""" create a gtk window, attach a drawing area and connect the relevant events"""
|
|
|
|
self.window = Gtk.Window()
|
|
self.window.realize()
|
|
self.window.resize(self.glwrap.width, self.glwrap.height)
|
|
self.window.set_resizable(True)
|
|
self.window.set_reallocate_redraws(True)
|
|
self.window.set_title("GTK3 with opengl")
|
|
self.window.connect('delete_event', Gtk.main_quit)
|
|
self.window.connect('destroy', lambda quit: Gtk.main_quit())
|
|
|
|
self.drawing_area = Gtk.DrawingArea()
|
|
self.drawing_area.connect('configure_event', self.on_configure_event)
|
|
self.drawing_area.connect('draw', self.on_draw)
|
|
self.drawing_area.set_double_buffered(False)
|
|
self.drawing_area.set_size_request(self.glwrap.width, self.glwrap.height)
|
|
|
|
self.window.add(self.drawing_area)
|
|
self.window.show_all()
|
|
|
|
def on_configure_event(self, widget, event):
|
|
"""if we recieve a configure event for example a resize, then grab the context settings and resize our scene """
|
|
self.glwrap.configure(widget.get_window())
|
|
self.glwrap.test()
|
|
return True
|
|
|
|
def on_draw(self, widget, context):
|
|
"""if we recieve a draw event redraw our test triangle"""
|
|
self.glwrap.test()
|
|
|
|
|
|
def main():
|
|
g = gui()
|
|
Gtk.main()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|