0

多年来一直在研究这个,我终于可以选择一个帧缓冲区、视觉和 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()
4

0 回答 0