多年来一直在研究这个,我终于可以选择一个帧缓冲区、视觉和 pict 格式并设置一个 glx 上下文并绘制一个三角形。
我仍然无法弄清楚的唯一一件事是为什么背景是黑色而不是透明的。
谁能发现错误或建议我如何调试它?
我已经查看了 C 中的许多示例,据我所知,我已经完成了所有步骤,但我可能遗漏了一些简单的东西。
import sys
import xcb
import xcb.glx
import xcb.composite
import xcb.xproto as xproto
import struct
import Xlib
from Xlib.display import Display
from ctypes import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL import GLX
try:
from OpenGL.GLX import struct__XDisplay
except ImportError as err:
from OpenGL.raw._GLX import struct__XDisplay
class window_example:
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 = []
def __init__(self):
self.xserver = xcb.connect()
self.xclient = self.xserver.core
self.setup = self.xserver.get_setup()
self.canvas = self.setup.roots[0]
self.root_window = self.canvas.root
self.depth = self.setup.roots[0].root_depth
self.visual = self.setup.roots[0].root_visual
composite_ext = self.load_extension('Composite', xcb.composite.key)
render_ext = self.load_extension('RENDER', xcb.render.key)
glx_ext = self.load_extension('GLX', xcb.glx.key)
""" lets setup are opengl settings and create the context for our window """
self.add_attribute(GLX.GLX_RENDER_TYPE, GLX.GLX_RGBA_BIT)
self.add_attribute(GLX.GLX_DRAWABLE_TYPE, GLX.GLX_WINDOW_BIT)
self.add_attribute(GLX.GLX_X_RENDERABLE, True)
self.add_attribute(GLX.GLX_RED_SIZE, 8)
self.add_attribute(GLX.GLX_GREEN_SIZE, 8)
self.add_attribute(GLX.GLX_BLUE_SIZE, 8)
self.add_attribute(GLX.GLX_ALPHA_SIZE, 8)
self.add_attribute(GLX.GLX_DEPTH_SIZE, 32)
self.add_attribute(GLX.GLX_DOUBLEBUFFER, True)
config_count = c_int()
configs = GLX.glXChooseFBConfig(self.xdisplay, self.display.get_default_screen(), None, byref(config_count))
if config_count.value is 0 or configs.__class__ is "<class 'OpenGL.raw._GLX.LP_struct_anon_103'>":
sys.exit('no matching configs found')
#http://lists.freedesktop.org/archives/xcb/2004-December/000237.html
picture_formats = render_ext.QueryPictFormats().reply()
count = 0
for i in range(0, config_count.value):
config = configs[i]
count += 1
visual = GLX.glXGetVisualFromFBConfig(self.xdisplay, config)
try:
visual.contents
except ValueError:
continue
picture_format = self.match_pict_format_with__visual(picture_formats, visual)
if not picture_format:
print 'Unable to match a picture format with a visual format :('
if visual.contents.visualid == self.visual:
print 'matched visual'
self.fbconfig = config
break
self.fbconfig = config
self.visual=visual
try:
self.visual.contents
except ValueError:
sys.exit('Could not find visual')
self.context = GLX.glXCreateContext(self.xdisplay, self.visual, None, True)
self.glx_colourmap = self.xserver.generate_id()
cookie = self.xclient.CreateColormapChecked(xproto.ColormapAlloc._None, self.glx_colourmap, self.root_window, self.visual.contents.visualid)
try:
print cookie.check()
#~ print cookie.reply()
except xproto.BadMatch, e:
print e.message
print e.args[0]
print e.args[0].bad_value
self.get_fbconfig_attributes(self.fbconfig)
self.glx_visual_info(self.visual.contents)
self.create_window()
def get_fbconfig_attributes(self, config):
print "***** Frame Buffer Config *****"
print "\tGLX Render Type = %d" % self.get_fbconfig_attribute(config, GLX.GLX_RGBA_BIT)
print "\tGLX Drawable Type = %d" % self.get_fbconfig_attribute(config, GLX.GLX_DRAWABLE_TYPE)
print "\tX Renderable = %d" % self.get_fbconfig_attribute(config, GLX.GLX_X_RENDERABLE)
print "\tRED Size = %d" % self.get_fbconfig_attribute(config, GLX.GLX_RED_SIZE)
print "\tGREEN Size = %d" % self.get_fbconfig_attribute(config, GLX.GLX_GREEN_SIZE)
print "\tBLUE Size = %d" % self.get_fbconfig_attribute(config, GLX.GLX_BLUE_SIZE)
print "\tALPHA Size = %d" % self.get_fbconfig_attribute(config, GLX.GLX_ALPHA_SIZE)
print "\tDepth Size = %d" % self.get_fbconfig_attribute(config, GLX.GLX_DEPTH_SIZE)
print "\tDouble Buffer = %d" % self.get_fbconfig_attribute(config, GLX.GLX_DOUBLEBUFFER)
def get_fbconfig_attribute(self, config, attrib):
value = c_int()
GLX.glXGetFBConfigAttrib(self.xdisplay, config, attrib, byref(value))
return value.value
def get_visual_attribute(self):
value = c_int()
GLX.glXGetFBConfigAttrib(self.xdisplay, configs[0], GLX.GLX_RED_SIZE, byref(value))
return value.value
def match_pict_format_with__visual(self, formats, visual):
for screen in formats.screens:
for depth in screen.depths:
for pict_visual in depth.visuals:
if pict_visual.visual == visual.contents.visualid:
print 'depth %s' % str(depth.depth)
#~ self.glx_visual_info(visual.contents)
return visual
def glx_visual_info(self, visual):
print('***** GLX Visual Info *****')
print("\trgb depth = %s" % visual.depth)
print("\tred mask = %s" % visual.red_mask)
print("\tgreen mask = %s" % visual.green_mask)
print("\tblue mask = %s" % visual.blue_mask)
print("\tcolour map = %s" % visual.colormap_size)
print("\tscreen id = %s" % visual.screen)
print("\tbits per rgb = %s" % visual.bits_per_rgb)
print("\tvisual = %s" % visual.visual)
print("\tvisual id = %s" % visual.visualid)
def add_attribute(self, setting, value=None):
"""just to nicely add opengl parameters"""
self.attrs.append(setting)
if value:
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 load_extension(self, name, xcb_key):
# test extension is present
extension = self.xclient.QueryExtension(len(name), name).reply()
if extension.present != 1:
print("%s not available" % name)
return
print('Using %s extension' % name)
return self.xserver(xcb_key)
def create_window(self):
# create a new resource id for the window
self.window = self.xserver.generate_id()
result = self.xclient.CreateWindowChecked(self.depth, self.window, self.root_window,
0, 0, 300, 300, 0,
xproto.WindowClass.InputOutput,
self.visual.contents.visualid,
xproto.CW.EventMask | xproto.CW.Colormap,
[xproto.EventMask.Button1Motion | xproto.EventMask.Exposure | xproto.EventMask.SubstructureNotify, self.glx_colourmap])
try:
result.check()
except xproto.BadMatch, e:
print e.message
print e.args[0]
print e.args[0].bad_value
GLX.glXCreateWindow(self.xdisplay, self.fbconfig, self.window, byref(c_int()))
#~ // create OpenGL context
render_context = GLX.glXCreateNewContext(self.xdisplay, self.fbconfig, GLX.GLX_RGBA_TYPE, None, True)
#~ GLX.glXCreateContext(self.xdisplay, self.visual, render_context, True)
if GLX.glXIsDirect(self.xdisplay, render_context) is 1:
print 'Using Direct Rendering'
else:
print 'Using Indirect Rendering'
#~ GLX.glXMakeContextCurrent(self.xdisplay, self.window, self.window, render_context)
print GLX.glXMakeCurrent(self.xdisplay, self.window, render_context)
#lets set a property on the window, this property gives us a window title
name = 'X Window Example'
self.xclient.ChangeProperty(xproto.PropMode.Replace, self.window, xproto.Atom.WM_NAME, xproto.Atom.STRING, 8, len(name), name)
_NET_WM_WINDOW_OPACITY = 528
buf = struct.pack('I', _NET_WM_WINDOW_OPACITY)
_NET_WM_WINDOW_OPACITY = self.xclient.InternAtom(True, len('_NET_WM_WINDOW_OPACITY'), '_NET_WM_WINDOW_OPACITY').reply()
self.xclient.ChangeProperty(xproto.PropMode.Replace, self.window, _NET_WM_WINDOW_OPACITY.atom, xproto.Atom.STRING, 0.5, 1, buf)
self.xclient.MapWindow(self.window)
self.xserver.flush()
def draw(self):
if(not GLX.glXMakeCurrent(self.xdisplay, self.window, self.context)):
print ('configure failed running glXMakeCurrent')
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0, 0.0, 0.0, 0.0)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_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()
glFlush();
GLX.glXSwapBuffers(self.xdisplay, self.window)
def loop(self):
self.draw()
while True:
event = self.xserver.wait_for_event()
self.draw()
self.xserver.flush()
if __name__ == "__main__":
window_example().loop()