xpra icon
Bug tracker and wiki

Ticket #1569: gtkglx.patch

File gtkglx.patch, 6.8 KB (added by Antoine Martin, 3 years ago)

poc using GLX to wrap the X11 window

  • xpra/client/gl/gtk3/gl_client_window.py

     
    88log = Logger("opengl", "window")
    99
    1010from xpra.client.gtk3.client_window import ClientWindow
    11 from xpra.client.gl.gtk3.gl_window_backing import GLPixmapBacking
     11from xpra.client.gl.gtk3.gl_drawing_area import GLDrawingArea
    1212
    1313
    1414class GLClientWindow(ClientWindow):
    1515
    16     def __init__(self, *args):
    17         log("GLClientWindow(..)")
    18         ClientWindow.__init__(self, *args)
    1916
    20 
    2117    def get_backing_class(self):
    22         return GLPixmapBacking
     18        return GLDrawingArea
    2319
    2420
    2521    def __str__(self):
  • xpra/client/gl/gtk3/gl_drawing_area.py

     
     1# This file is part of Xpra.
     2# Copyright (C) 2017 Antoine Martin <antoine@devloop.org.uk>
     3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
     4# later version. See the file COPYING for details.
     5
     6from xpra.log import Logger
     7log = Logger("opengl", "paint")
     8
     9from xpra.client.gl.gl_window_backing_base import GLWindowBackingBase
     10from xpra.gtk_common.gobject_compat import import_glib, import_gtk, get_xid
     11from xpra.gtk_common.gtk_util import POINTER_MOTION_MASK, POINTER_MOTION_HINT_MASK, display_get_default
     12from xpra.x11.bindings.display_source import get_display_ptr        #@UnresolvedImport
     13glib = import_glib()
     14gtk = import_gtk()
     15
     16DOUBLE_BUFFERED = True
     17
     18#Hardcoded for GLX:
     19from OpenGL import GLX
     20
     21def c_attrs(props):
     22    attrs = []
     23    for k,v in props.items():
     24        attrs += [k, v]
     25    attrs += [0, 0]
     26    from ctypes import c_int
     27    return (c_int * len(attrs))(*attrs)
     28
     29def get_xdisplay():
     30    ptr = get_display_ptr()
     31    from OpenGL.raw.GLX._types import struct__XDisplay
     32    from ctypes import cast, POINTER
     33    return cast(ptr, POINTER(struct__XDisplay))
     34   
     35
     36class GLXWindowContext(object):
     37
     38    def __init__(self, glx_context, xid):
     39        self.context = glx_context
     40        self.xid = xid
     41        self.xdisplay = get_xdisplay()
     42        self.valid = False
     43
     44    def __enter__(self):
     45        if not GLX.glXMakeCurrent(self.xdisplay, self.xid, self.context):
     46            raise Exception("glXMakeCurrent failed")
     47        self.valid = True
     48
     49    def __exit__(self, *_args):
     50        self.valid = False
     51        #TODO: xsync!
     52
     53    def swap_buffers(self):
     54        assert self.valid
     55        GLX.glXSwapBuffers(self.xdisplay, self.xid)
     56
     57    def __repr__(self):
     58        return "gtk3.GLXWindowContext(%#x)" % self.xid
     59
     60class GLXContext(object):
     61
     62    def __init__(self):
     63        display = display_get_default()
     64        screen = display.get_default_screen()
     65        attrs = c_attrs({
     66            GLX.GLX_RGBA            : True,
     67            GLX.GLX_RED_SIZE        : 8,
     68            GLX.GLX_GREEN_SIZE      : 8,
     69            GLX.GLX_BLUE_SIZE       : 8,
     70            GLX.GLX_DOUBLEBUFFER    : 0,
     71            })
     72        self.xdisplay = get_xdisplay()
     73        xvinfo = GLX.glXChooseVisual(self.xdisplay, screen.get_number(), attrs)
     74        self.context = GLX.glXCreateContext(self.xdisplay, xvinfo, None, True)
     75
     76    def get_paint_context(self, gdk_window):
     77        assert self.context and gdk_window
     78        return GLXWindowContext(self.context, get_xid(gdk_window))
     79
     80    def destroy(self):
     81        c = self.context
     82        if c:
     83            self.context = None
     84            GLX.glXDestroyContext(self.xdisplay, c)
     85
     86    def __repr__(self):
     87        return "gtk3.GLXContext"
     88
     89
     90class GLDrawingArea(GLWindowBackingBase):
     91
     92    def __repr__(self):
     93        return "gtk3.GLDrawingArea(%s, %s, %s)" % (self.wid, self.size, self.pixel_format)
     94
     95    def idle_add(self, *args, **kwargs):
     96        glib.idle_add(*args, **kwargs)
     97
     98    def init_gl_config(self, _window_alpha):
     99        self.context = GLXContext()
     100        self.window_context = None
     101
     102    def is_double_buffered(self):
     103        return DOUBLE_BUFFERED
     104
     105    def init_backing(self):
     106        da = gtk.DrawingArea()
     107        #da.connect('configure_event', self.on_configure_event)
     108        #da.connect('draw', self.on_draw)
     109        da.set_double_buffered(DOUBLE_BUFFERED)
     110        da.set_size_request(*self.size)
     111        da.set_events(da.get_events() | POINTER_MOTION_MASK | POINTER_MOTION_HINT_MASK)
     112        da.show()
     113        self._backing = da
     114
     115    #def get_bit_depth(self, pixel_depth=0):
     116    #    TODO!
     117
     118    def gl_context(self):
     119        gdk_window = self._backing.get_window()
     120        assert gdk_window
     121        self.window_context = self.context.get_paint_context(gdk_window)
     122        return self.window_context
     123
     124    def do_gl_show(self, _rect_count):
     125        if self.is_double_buffered():
     126            # Show the backbuffer on screen
     127            log("%s.gl_show() swapping buffers now", self)
     128            self.window_context.swap_buffers()
     129        else:
     130            #glFlush was enough
     131            pass
     132
     133    def close(self):
     134        GLWindowBackingBase.close(self)
     135        c = self.context
     136        if c:
     137            self.context = None
     138            c.destroy()
     139
     140    def cairo_draw(self, _context):
     141        w, h = self.size
     142        with self.gl_context():
     143            self.present_fbo(0, 0, w, h)
  • xpra/client/gtk_base/gtk_client_base.py

     
    739739        try:
    740740            opengllog("init_opengl: going to import xpra.client.gl")
    741741            __import__("xpra.client.gl", {}, {}, [])
    742             __import__("xpra.client.gl.gtk_base.gtk_compat", {}, {}, [])
    743             gl_check = __import__("xpra.client.gl.gtk_base.gtkgl_check", {}, {}, ["check_support"])
    744             opengllog("init_opengl: gl_check=%s", gl_check)
    745             self.opengl_props = gl_check.check_support(force_enable=(enable_opengl is True))
     742            if False:
     743                __import__("xpra.client.gl.gtk_base.gtk_compat", {}, {}, [])
     744                gl_check = __import__("xpra.client.gl.gtk_base.gtkgl_check", {}, {}, ["check_support"])
     745                opengllog("init_opengl: gl_check=%s", gl_check)
     746                self.opengl_props = gl_check.check_support(force_enable=(enable_opengl is True))
     747            else:
     748                self.opengl_props = {}
    746749            opengllog("init_opengl: found props %s", self.opengl_props)
    747750            GTK_GL_CLIENT_WINDOW_MODULE = "xpra.client.gl.gtk%s.gl_client_window" % (2+int(is_gtk3()))
    748751            opengllog("init_opengl: trying to load GL client window module '%s'", GTK_GL_CLIENT_WINDOW_MODULE)