(remaining) tasks:
do_expose_event
isn't called automatically - fix it
Changes required from commit r922:
SystemExit
python -c "from OpenGL.GL import glGetString, GL_VERSION; glGetString(GL_VERSION)"
GLWindowBacking
is not used??
vtxarrays
- not used?)
use_openGL_CSC
is hardcoded, make it a switch? Needs testing too.
self.current_mode
and self.textures
, need documenting more clearly, and initializing in constructor?
decompress_image_to_rgb
: csc_image_yuv2rgb
does not need the gil
Contingency plan: we can disable the opengl code if this proves unstable or problematic.
Note:
gl_window_backing.py
should be used or removed altogether
USE_OPENGL=False
in client.py
gl-colorspace-conversions
MIT licensed code in its own file
SystemExit
As for the win32 build, here are some pointers:
r926 fixes vpx for non-gl case
Sorry for not taking care of the cleanup myself, it was on my plans but you beat me to it. As for the python crash, your piece of code doesn't crash in my case - however it's not going to work because you can't issue OpenGL commands outside of a GL context. This means that you can check the GL version before actually having created a GL-enabled widget, which is why I didn't do the check in the constructor.
gl_begin
/gl_end
around it to avoid crashes, see r929. We also check for FragmentProgramARB
use_openGL_CSC
is now toggled depending on the availability of FragmentProgramARB
, in r930 - this will need more thorough testing (toggling it by hand to test these codepaths)
Which leaves (recap):
GLWindowBacking
to GLBacking
)
self.current_mode
and self.textures
, need documenting more clearly (and constifying?), and initializing in constructor?
fixing vpx to allow it to work with yuv/opengl codepath (work in progress patch)
More:
Cython
version requirements bumped to 0.16 in r935
current_mode
in r938
New recap:
--no-opengl
" switch
use_openGL_CSC = False
: test it thoroughly
compare cpu usage with opengl and gtk
comparing pixels decoded per second with opengl and gtk
comparing FPS with opengl and gtk
comparing average client UI thread latency with opengl and gtk
As can be seen here (user cpu + sys cpu): The CPU usage is noticeably lower with the opengl backend, which is impressive seeing that it is also pushing more frames: (some pathological tests samples were removed)
We decode + paint much faster (pixels per second):
Which in turn reduces the average UI thread latency:
r2008 updates the gl code so it compiles/runs again
r2009 fixes the calls from UI thread so rendering actually works
r2010 fixes support for all csc modes with x264 decoding
better gl patch
Mostly working as of r2018: we now handle lossless updates too.
New recap of pending items:
XPRA_OPENGL
env var to control (and make GL the default if possible/stable enough)
glGenPrograms
we call in the YUV420 setup, so we need to do cleanup otherwise next time we call it we're leaking the first"
Unfortunately, gtkgl is no-go on osx because it relies on the x11 bindings:
In file included from gdkglquery-x11.c:27: gdkglx.h:22:22: error: gdk/gdkx.h: No such file or directory gdkglquery-x11.c: In function 'gdk_gl_query_extension': gdkglquery-x11.c:51: warning: implicit declaration of function 'gdk_x11_get_default_xdisplay' (...)
The sad thing is that PyOpenGL
and PyOpenGL_accelerate
do build ok, so all we really need is the glue... one solution would be to bypass gtkgl completely.
On win32, although there are some really old binaries of gtkglext
version 1.0.6 on sourceforge, the latest binary python bindings available are for python 2.3!
So it looks like we will just have to build from source... (which is generally a major PITA on win32)
this all-in-one installer does have gtkglext, but it is way too old (based on gtk 2.17, etc)
Now, trying with MinGW using these home made instructions:
cd gtkglext-1.2.0/ export PATH=/c/Python27/Lib/site-packages/gtk-2.0/runtime/bin/:$PATH export PKG_CONFIG_PATH=/c/Python27/Lib/site-packages/gtk-2.0/runtime/lib/pkgconfig/ export PATH=/c/MinGW/bin:$PATH env CC='gcc' \ AR=/c/cygwin/bin/ar.exe \ ./configure --prefix=/c/gtkglext --build=i386-pc-mingw32 --disable-static
fails with:
gtkglwidget.c: In function 'gtk_gl_widget_size_allocate': gtkglwidget.c:130:3: warning: implicit declaration of function 'GTK_WIDGET_REALIZED' gtkglwidget.c: In function 'gtk_gl_widget_parent_set': gtkglwidget.c:177:3: warning: implicit declaration of function 'GTK_WIDGET_TOPLEVEL' gtkglwidget.c: In function 'gtk_widget_set_gl_capability': gtkglwidget.c:253:3: warning: implicit declaration of function 'GTK_WIDGET_NO_WINDOW' /bin/sh ../libtool --mode=link gcc -march=pentium -g -O2 -Wall -mms-bitfields \ -o libgtkglext-win32-1.0.la -version-info 0:0:0 -export-dynamic -rpath /c/gtkglext/lib \ -no-undefined -export-symbols gtkglext.def gtkglversion.lo gtkglinit.lo gtkglwidget.lo \ ../gdk/libgdkglext-win32-1.0.la -lglu32 -lopengl32 -lgdi32 -luser32 -lkernel32 \ -Lc:/Python27/Lib/site-packages/gtk-2.0/runtime/lib -lgtk-win32-2.0 -lgdk-win32-2.0 \ -latk-1.0 -lgio-2.0 -lpangowin32-1.0 -lgdi32 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lpango-1.0 \ -lcairo -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 -lintl if test "x`/bin/sed 1q gtkglext.def`" = xEXPORTS; then cp gtkglext.def .libs/libgtkglext-win32-1.0-0.dll.def; else echo EXPORTS > .libs/libgtkglext-win32-1.0-0.dll.def; cat gtkglext.def >> .libs/libgtkglext-win32-1.0-0.dll.def; fi gcc -march=pentium -shared .libs/libgtkglext-win32-1.0-0.dll.def .libs/gtkglversion.o \ .libs/gtkglinit.o .libs/gtkglwidget.o -Lc:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../..//.libs \ ../gdk/.libs/libgdkglext-win32-1.0.dll.a -Lc:/Python27/Lib/site-packages/gtk-2.0/runtime/lib \ -L/mingw/lib -lglu32 -lopengl32 -luser32 -lkernel32 -lgtk-win32-2.0 -lgdk-win32-2.0 \ -latk-1.0 -lgio-2.0 -lpangowin32-1.0 -lgdi32 -lpangocairo-1.0 -lgdk_pixbuf-2.0 -lpango-1.0 \ -lcairo -lgobject-2.0 -lgmodule-2.0 -lgthread-2.0 -lglib-2.0 \ c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../..//libintl.dll.a -march=pentium -mms-bitfields \ -o .libs/libgtkglext-win32-1.0-0.dll -Wl,--enable-auto-image-base -Xlinker --out-implib \ -Xlinker .libs/libgtkglext-win32-1.0.dll.a Creating library file: \ .libs/libgtkglext-win32-1.0.dll.a.libs/gtkglwidget.o: In function `gtk_gl_widget_size_allocate': e:\gtkglext-1.2.0\gtk/gtkglwidget.c:130: undefined reference to `GTK_WIDGET_REALIZED' .libs/gtkglwidget.o: In function `gtk_gl_widget_unrealize': (...)
This was solved by replacing:
GTK_WIDGET_REALIZED
with
gtk_widget_get_realized
Makes me think that maybe we ought to try with the latest unreleased source which has those changes already...
Now onto pygtkglext:
export PATH=/c/Python27/Lib/site-packages/gtk-2.0/runtime/bin:$PATH export PKG_CONFIG_PATH=/c/Python27/Lib/pkgconfig/ export PATH=/c/MinGW/:$PATH
(why the pkgconfig for pygtk and some other bits is one place and gtk in another... beats me) Then you have to comment out the line:
from override import Overrides
And you still get a build error... :
/c/Python/python.exe ./setup.py build running build running build_py running build_ext building 'gtk.gdkgl._gdkgl' extension C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- \ /DNDEBUG \ -DPYGTKGLEXT_MAJOR_VERSION=1 -DPYGTKGLEXT_MINOR_VERSION=1 -DPYGTKGLEXT_MICRO_VERSION=0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gtkglext-1.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/gtkglext-1.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gtk-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/gtk-2.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/pango-1.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gdk-pixbuf-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/glib-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/glib-2.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/cairo \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/freetype2 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/libpng14 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/atk-1.0 \ -I. -Igtk/gdkgl -Igtk/gtkgl -Ic:/Python27/include/pygtk-2.0 \ -Ic:/Python27/include/pygtk-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/glib-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/glib-2.0/include \ -Ic:\Python27\include -Ic:\Python27\PC \ /Tcgtk/gdkgl/gdkglmodule.c /Fobuild\temp.win32-2.7\Release\gtk/gdkgl/gdkglmodule.obj gdkglmodule.c C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe /c /nologo /Ox /MD /W3 /GS- \ /DNDEBUG \ -DPYGTKGLEXT_MAJOR_VERSION=1 -DPYGTKGLEXT_MINOR_VERSION=1 -DPYGTKGLEXT_MICRO_VERSION=0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gtkglext-1.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/gtkglext-1.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gtk-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/gtk-2.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/pango-1.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/gdk-pixbuf-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/glib-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/glib-2.0/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/cairo \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/freetype2 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/libpng14 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/atk-1.0 \ -I. -Igtk/gdkgl -Igtk/gtkgl \ -Ic:/Python27/include/pygtk-2.0 \ -Ic:/Python27/include/pygtk-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/include/glib-2.0 \ -Ic:/Python27/lib/site-packages/gtk-2.0/runtime/lib/glib-2.0/include \ -Ic:\Python27\include \ -Ic:\Python27\PC \ /Tcgtk/gdkgl/gdkglext.c /Fobuild\temp.win32-2.7\Release\gtk/gdkgl/gdkglext.obj gdkglext.c C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\link.exe /DLL /nologo /INCREMENTAL:NO \ /LIBPATH:c:/Python27/lib/site-packages/gtk-2.0/runtime/lib \ /LIBPATH:c:/Python27/lib/site-packages/gtk-2.0/runtime/lib \ /LIBPATH:c:\Python27\libs \ /LIBPATH:c:\Python27\PCbuild \ gtkglext-win32-1.0.lib gdkglext-win32-1.0.lib glu32.lib opengl32.lib user32.lib kernel32.lib \ gtk-win32-2.0.lib gdk-win32-2.0.lib atk-1.0.lib gio-2.0.lib pangowin32-1.0.lib gdi32.lib \ pangocairo-1.0.lib gdk_pixbuf-2.0.lib pango-1.0.lib cairo.lib gobject-2.0.lib gmodule-2.0.lib \ gthread-2.0.lib glib-2.0.lib intl.lib gobject-2.0.lib gthread-2.0.lib glib-2.0.lib intl.lib \ /EXPORT:init_gdkgl \ build\temp.win32-2.7\Release\gtk/gdkgl/gdkglmodule.obj \ build\temp.win32-2.7\Release\gtk/gdkgl/gdkglext.obj\ /OUT:build\lib.win32-2.7\gtk\gdkgl\_gdkgl.pyd \ /IMPLIB:build\temp.win32-2.7\Release\gtk/gdkgl\_gdkgl.lib \ /MANIFESTFILE:build\temp.win32-2.7\Release\gtk/gdkgl\_gdkgl.pyd.manifest LINK : fatal error LNK1181: cannot open input file 'gtkglext-win32-1.0.lib'
Next, we try to go back to gtkglext and add --enable-debug
, --enable-shared
and --enable-static
, which then causes more problems (..) so we have to modify gtkglwidget.c
:
GTK_WIDGET_TOPLEVEL
by gtk_widget_is_toplevel
GTK_GL_NOTE ...
lines in gtk_gl_widget_style_set
GTK_WIDGET_NO_WINDOW
by gtk_widget_get_has_window
FWIW: I'm not sure if the instructions above make any difference, but this is how I got it to build.
And then, we remember to actually follow some of the instructions (doh) and add --compiler="mingw32"
to the setup.py command... And then it builds OK.
But that is not the end of our troubles, it doesn't install:
running install running build running build_py running build_ext running install_lib Traceback (most recent call last): File "./setup.py", line 159, in <module> 'build_ext': BuildExt }) File "c:\Python27\lib\distutils\core.py", line 152, in setup dist.run_commands() File "c:\Python27\lib\distutils\dist.py", line 953, in run_commands self.run_command(cmd) File "c:\Python27\lib\distutils\dist.py", line 972, in run_command cmd_obj.run() File "c:\Python27\lib\distutils\command\install.py", line 575, in run self.run_command(cmd_name) File "c:\Python27\lib\distutils\cmd.py", line 326, in run_command self.distribution.run_command(command) File "c:\Python27\lib\distutils\dist.py", line 972, in run_command cmd_obj.run() File "./setup.py", line 61, in run self.add_template_option('VERSION', VERSION) File "c:\Python27\lib\distutils\cmd.py", line 105, in __getattr__ raise AttributeError, attr AttributeError: add_template_option
And judging by postings on the subject, there is no easy way to fix that. So we don't bother and just install manually by copying:
pygtkglext-1.1.0\build\lib.win32-2.7\gtk\*
to
Python27\Lib\site-packages\gtk-2.0\gtk\
We now have gtkgl/gdkgl installed! (albeit without the pkgconfig file, etc)
Next, we have a packaging problem with py2exe not including all the bits we need for PyOpenGL
, fortunately the solution is documented here.
Unfortunately, those don't work properly, and one can find a multitude of different ways of solving this problem... (5) with various levels of non-success: I'm not the only one running around in circles :(
We also have to go through the egg unpacking dance for OpenGL_accelerate
..
And then I find that some osx support code has been added to gtkglext trunk after the last release... so maybe we can have opengl rendering on osx after all..
Note: the problems above with py2exe may or may not be real. What is real though is the fact that I cannot use pixmaps with pygtkglext.. (so packaging is a moot point) - even just running the examples I get:
(python.exe:2224): GdkGLExt-WARNING **: cannot select DIB (python.exe:2224): GdkGLExt-WARNING **: cannot create GdkGLPixmap
I've tried building from trunk ('https://github.com/tdz/gtkglext.git) - natively with mingw and cross compiling from Linux. Both fail, the instructions are just rubbish, not up to date, and refer to non-existent files (autogen.sh etc).
I also found a more recent binary version of gtkglext here - but unfortunately this does not help and GL pixmaps still fail.
I also found these instructions - not tried them yet.
I am not the first one to hit this issue:
Maybe the VirtualBox
GL driver is causing problems?
Will try with VMWare
or a real windows PC, unless someone beats me to it.
Here's how (assuming a dev environment with pygtk and mingw installed and working):
PyOpenGL
: "C:\Python27\scripts\easy-install.exe PyOpenGL
"
C:\GtkGLExt
) to pygtk's runtime directory (by default: C:\Python27\Lib\site-packages\gtk-2.0\runtime
)
/c/Python/python.exe ./setup.py build --compiler="mingw32"
('see comment:20 for the overrides error fix') and copy the resulting pygtkglext-1.1.0\build\lib.win32-2.7\gtk\*
to Python27\Lib\site-packages\gtk-2.0\gtk\
/c/Python27/python.exe pixmap.py
- does it work or not? warnings shown?
if we do manage to get opengl working on win32, this deals with opengl libraries located in the frozen path
Finally working very well on *nix:
--without-opengl
Only win32 left...
closing, see #226 for osx and #227 for win32
re-opening:
pixel_format
to rgb and the render_image
shortcuts out (works on radeon for some strange reason)
work in progress to make it work with nvidia driver.. not too far
changesets r2342, r2343, r2344, r2345, r2346, r2347, r2350, r2353, r2354, r2355, r2356, r2357 fix a number of bugs listed above and improve error/corner cases. It now works on:
Radeon HD 5450
)
Radeon HD 5450
)
GM965
/GL960
Integrated Graphics Controller)
GeForce GTS 450
) - but with a bug: expose does not work
GeForce GTS 450
) - but with a bug: expose does not work
Summary of remaining issues:
glEnable
, glDisable
it when needed by paint_rgb24
(see example code attached which almost works)
destroy_program_variants_cb
warning (see r2327) - maybe we do need to call remove_shader
on the cleanup path
version which creates the fragment program only once and uses glEnable / glDisable
Got a GL crash with nvidia on Linux:
(gdb) py-bt #14 Frame 0x2637170, for file /usr/lib/python2.7/site-packages/OpenGL/wrapper.py, line 784, in wrapperCall (args=(<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\...(truncated) result = self.wrappedOperation( *cArguments ) #19 Frame 0x2636500, for file /usr/lib/python2.7/site-packages/OpenGL/latebind.py, line 41, in __call__ (self=<glTexSubImage2D(pyConverterNames=['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type', 'pixels'], pyConverters=[None, None, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, None, None, <ImageInputConverter(typeName='type', pixelsIndex=8, pixelsName='pixels', typeIndex=7, rank=3) at remote 0x1a4ee90>], _finalCall=<function at remote 0x2294938>) at remote 0x1a59440>, args=(<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x...(truncated) return self._finalCall( *args, **named ) #29 (frame information optimized out) #32 Frame 0x7f1f30004e60, for file /usr/lib64/python2.7/site-packages/xpra/gl/gl_window_backing.py, line 193, in do_gl_paint (self=<GLPixmapBacking(textures=<numpy.ndarray at remote 0x24bfeb0>, _last_pixmap_data=(639, 102, 5230, '\x00\n\x10\x00\n\x10\x00\n\x10\x00\n\x10\x00\n\x10\x00\n\x10\x00\n\x10\x00\n\x10\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x0e\x00\x08\x10\x00\x08\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x01\t\x12\x01\t\x12\x01\t\x12\x00\x07\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x00\x07\x10\x01\t\x12\x00\x07\x10\x00\x08\x0e\x00\x08\x0e\x00\x07\x0e\x00\x07\x0e\x00\x07\x0e\x00\x07\x0e\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x06\r\x00\x05\x0c\x00\x05\x0e\x00\x05\x0e\x00\x05\x0e\x00\x05\x0e\x00\x05\x0e\x00\x06\x0f\x00\x06\x0f\x00\x06\x0f\x00\x06\x0f\x00\x06\x0f\x00\x06\x0f\x00\x06\x0f\x00\x07\x0f\x00\x07\x0f\x00\x05\x11\x00\x05\x11\x00\x05\x11\x00\x06\x12\x00\x06\x12\x00\x06\x12...(truncated) self.update_texture_yuv(img_data, x, y, w, h, rowstrides, pixel_format) #46 (frame information optimized out) #49 Frame 0x9a3b50, for file /usr/lib64/python2.7/site-packages/xpra/scripts/main.py, line 769, in run_client (parser=<OptionParser(process_default_values=True, allow_interspersed_args=True, _long_opt={'--delay-tray': <Option(_long_opts=['--delay-tray'], help='Waits for the first events before showing the system tray', callback_args=None, callback=None, default=False, nargs=None, choices=None, dest='delay_tray', container=<OptionGroup(_long_opt={...}, title='Client Features Options', parser=<...>, _short_opt={'-d': <Option(_long_opts=['--debug'], help='List of categories to enable debugging for (or "all")', callback_args=None, callback=None, default=None, nargs=1, choices=None, dest='debug', container=<OptionGroup(_long_opt={...}, title='Advanced Options', parser=<...>, _short_opt={...}, option_list=[<Option(_long_opts=['--password-file'], help='The file containing the password required to connect (useful to secure TCP mode)', callback_args=None, callback=None, default=None, nargs=1, choices=None, dest='password_...(truncated) return app.run() #53 Frame 0x818c50, for file /usr/lib64/python2.7/site-packages/xpra/scripts/main.py, line 501, in main (script_file='/usr/bin/xpra', cmdline=['/usr/bin/xpra', 'attach', ':10', '--no-mmap', '--encoding=x264'], bool_default=<function at remote 0x7f1f46dca848>, int_default=<function at remote 0x7f1f46dca938>, float_default=<function at remote 0x7f1f46dca9b0>, string_list=<function at remote 0x7f1f46dcaa28>, supports_server=True, wait_for_x_server=<built-in function wait_for_x_server>, start_str='\t%prog start DISPLAY\n', list_str='\t%prog list\n', upgrade_str='\t%prog upgrade DISPLAY', shadow_str='\t%prog upgrade DISPLAY', note_str='', stop_str='\t%prog stop [DISPLAY]\n', parser=<OptionParser(process_default_values=True, allow_interspersed_args=True, _long_opt={'--delay-tray': <Option(_long_opts=['--delay-tray'], help='Waits for the first events before showing the system tray', callback_args=None, callback=None, default=False, nargs=None, choices=None, dest='delay_tray', container=<OptionGroup(_long_opt={...}, titl...(truncated) return run_client(parser, options, args, mode) #57 Frame 0x818770, for file /usr/bin/xpra, line 6, in <module> () sys.exit(xpra.scripts.main.main(__file__, sys.argv))
Full backtrace:
Program received signal SIGSEGV, Segmentation fault. 0x000000319d7e3e78 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 (gdb) bt #0 0x000000319d7e3e78 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #1 0x000000319d492456 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #2 0x000000319d49c59a in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #3 0x000000319d5913ee in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #4 0x000000319d586737 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #5 0x000000319d589b98 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #6 0x000000319d58a107 in ?? () from /usr/lib64/nvidia/libnvidia-glcore.so.304.64 #7 0x0000003564a05ed8 in ffi_call_unix64 () at ../src/x86/unix64.S:75 #8 0x0000003564a058e0 in ffi_call (cif=cif@entry=0x7fff2060e040, fn=fn@entry=0x319baf9120 <glTexSubImage2D>, rvalue=rvalue@entry=0x7fff2060de90, avalue=avalue@entry=0x7fff2060de30) at ../src/x86/ffi64.c:486 #9 0x00007f1f48197bf0 in _call_function_pointer (argcount=9, resmem=0x7fff2060de90, restype=<optimized out>, atypes=<optimized out>, avalues=0x7fff2060de30, pProc= 0x319baf9120 <glTexSubImage2D>, flags=4353) at /usr/src/debug/Python-2.7.3/Modules/_ctypes/callproc.c:827 #10 _ctypes_callproc (pProc=pProc@entry=0x319baf9120 <glTexSubImage2D>, argtuple=argtuple@entry= (<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x...(truncated), flags=4353, argtypes=argtypes@entry= (<built-in method from_param of _ctypes.PyCSimpleType object at remote 0x9503c0>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x94f110>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x94f110>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x94f110>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x94f110>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x94f110>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x9503c0>, <built-in method from_param of _ctypes.PyCSimpleType object at remote 0x9503c0>, <instancemethod at remote 0x193aaa0>), restype=None, checker=0x0) at /usr/src/debug/Python-2.7.3/Modules/_ctypes/callproc.c:1174 #11 0x00007f1f481913fd in PyCFuncPtr_call (self=<optimized out>, inargs=<optimized out>, kwds=0x0) at /usr/src/debug/Python-2.7.3/Modules/_ctypes/_ctypes.c:3913 #12 0x0000003561e49c0e in PyObject_Call (func=func@entry= <CFunctionType(extension=None, deprecated=False, argNames=['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type', 'pixels'], DLL=<CDLL(_FuncPtr=<_ctypes.PyCFuncPtrType at remote 0x125cad0>, glGetString=<_FuncPtr(__name__='glGetString', __doc__='glGetString( constant ) -> Current string value') at remote 0x1949a10>, glXGetCurrentContext=<_FuncPtr(__name__='glXGetCurrentContext') at remote 0xdb0ef0>, _handle=10160672, _name='libGL.so.1', glXGetProcAddressARB=<_FuncPtr(__name__='glXGetProcAddressARB') at remote 0xdb0d50>, glGetError=<_FuncPtr(__name__='glGetError') at remote 0x1286050>) at remote 0x123ac50>, __name__='glTexSubImage2D', __doc__='glTexSubImage2D( GLenum(target), GLint(level), GLint(xoffset), GLint(yoffset), GLsizei(width), GLsizei(height), GLenum(format), GLenum(type), POINTER(GLvoid)(pixels) ) -> None') at remote 0x19481f0>, arg=<optimized out>, kw=kw@entry=0x0) at /usr/src/debug/Python-2.7.3/Objects/abstract.c:2529 #13 0x0000003561eda08b in ext_do_call (nk=0, na=<optimized out>, flags=<optimized out>, pp_stack=0x7fff2060e358, func= <CFunctionType(extension=None, deprecated=False, argNames=['target', 'level', 'xoffset', 'yoffset', 'width', 'height', 'format', 'type', 'pixels'], DLL=<CDLL(_FuncPtr=<_ctypes.PyCFuncPtrType at remote 0x125cad0>, glGetString=<_FuncPtr(__name__='glGetString', __doc__='glGetString( constant ) -> Current string value') at remote 0x1949a10>, glXGetCurrentContext=<_FuncPtr(__name__='glXGetCurrentContext') at remote 0xdb0ef0>, _handle=10160672, _name='libGL.so.1', glXGetProcAddressARB=<_FuncPtr(__name__='glXGetProcAddressARB') at remote 0xdb0d50>, glGetError=<_FuncPtr(__name__='glGetError') at remote 0x1286050>) at remote 0x123ac50>, __name__='glTexSubImage2D', __doc__='glTexSubImage2D( GLenum(target), GLint(level), GLint(xoffset), GLint(yoffset), GLsizei(width), GLsizei(height), GLenum(format), GLenum(type), POINTER(GLvoid)(pixels) ) -> None') at remote 0x19481f0>) at /usr/src/debug/Python-2.7.3/Python/ceval.c:4411 #14 PyEval_EvalFrameEx (f=f@entry= Frame 0x2637170, for file /usr/lib/python2.7/site-packages/OpenGL/wrapper.py, line 784, in wrapperCall (args=(<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\...(truncated), throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.3/Python/ceval.c:2779 #15 0x0000003561eddcbf in PyEval_EvalCodeEx (co=<optimized out>, globals=<optimized out>, locals=locals@entry=0x0, args=args@entry=0x27580f0, argcount=9, kws=kws@entry=0x7f1f5135d068, kwcount=kwcount@entry=0, defs=defs@entry=0x0, defcount=defcount@entry=0, closure=(<cell at remote 0x22956e0>, <cell at remote 0x22957f8>)) at /usr/src/debug/Python-2.7.3/Python/ceval.c:3330 #16 0x0000003561e6da37 in function_call (func=<function at remote 0x2294938>, arg= (<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x...(truncated), kw={}) at /usr/src/debug/Python-2.7.3/Objects/funcobject.c:526 #17 0x0000003561e49c0e in PyObject_Call (func=func@entry=<function at remote 0x2294938>, arg=<optimized out>, kw=kw@entry={}) at /usr/src/debug/Python-2.7.3/Objects/abstract.c:2529 #18 0x0000003561eda08b in ext_do_call (nk=0, na=<optimized out>, flags=<optimized out>, pp_stack=0x7fff2060e6d8, func=<function at remote 0x2294938>) at /usr/src/debug/Python-2.7.3/Python/ceval.c:4411 #19 PyEval_EvalFrameEx (f=f@entry= Frame 0x2636500, for file /usr/lib/python2.7/site-packages/OpenGL/latebind.py, line 41, in __call__ (self=<glTexSubImage2D(pyConverterNames=['target', 'level', 'xoffset', 'yoffset', ---Type <return> to continue, or q <return> to quit--- 'width', 'height', 'format', 'type', 'pixels'], pyConverters=[None, None, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, <function at remote 0x1a58aa0>, None, None, <ImageInputConverter(typeName='type', pixelsIndex=8, pixelsName='pixels', typeIndex=7, rank=3) at remote 0x1a4ee90>], _finalCall=<function at remote 0x2294938>) at remote 0x1a59440>, args=(<IntConstant at remote 0x1c80320>, 0, 0, 0, 958, 526, <IntConstant at remote 0x188fb40>, <IntConstant at remote 0x1284d20>, '\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x...(truncated), throwflag=throwflag@entry=0) at /usr/src/debug/Python-2.7.3/Python/ceval.c:2779
We still need to pass small region updates as YUV data instead of RGB...
After our private discussions - I believe we should be able to draw to the Pixmap using the "normal" draw commands.
Something like the patch below is the general idea - but it doesn't work.
--- a/src/xpra/gl/gl_window_backing.py +++ b/src/xpra/gl/gl_window_backing.py @@ -133,6 +133,10 @@ class GLPixmapBacking(PixmapBacking): self.gl_end(drawable) def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): + gc = self._backing.new_gc() + self._backing.draw_rgb_image(gc, x, y, w, h, gdk.RGB_DITHER_NONE, img_data, rowstride) + fire_paint_callbacks(callbacks, True) + return log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x+w>ww or y+h>wh:
EDIT: actually, the following patch seems to do what we expect :
--- a/src/xpra/gl/gl_window_backing.py +++ b/src/xpra/gl/gl_window_backing.py @@ -133,6 +133,9 @@ class GLPixmapBacking(PixmapBacking): self.gl_end(drawable) def _do_paint_rgb24(self, img_data, x, y, w, h, rowstride, options, callbacks): + gc = self.glarea.window.new_gc() + self.glarea.window.draw_rgb_image(gc, x, y, w, h, gdk.RGB_DITHER_NONE, img_data, rowstride) + return log("do_paint_rgb24(%s bytes, %s, %s, %s, %s, %s, %s, %s)", len(img_data), x, y, w, h, rowstride, options, callbacks) ww, wh = self.size if x+w>ww or y+h>wh:
Will you please test, confirm, and cleanup?
Thanks!
applied in r2793 - Linux rendering works well enough and may be enabled by default (again!) in 0.9 release, win32 will need (a lot) more testing
Does not work with more than one window because we re-use the same textures/shader. :(
Testing with nouveau and the following patch:
--- src/xpra/gl/gl_window_backing.py (revision 2793) +++ src/xpra/gl/gl_window_backing.py (working copy) @@ -85,6 +86,7 @@ glDisable(GL_FRAGMENT_PROGRAM_ARB) if self.textures is None: self.textures = glGenTextures(3) + log.info("textures for wid=%s of size %s : %s", self.wid, self.size, self.textures) self.gl_setup = True return drawable
Then starting two windows, I see with the nouveau driver:
textures for wid=4 of size (529, 303) : [1 2 3] textures for wid=9 of size (499, 316) : [1 2 3]
So it looks like the texture IDs returned by glGenTextures
are the same...
It is expected that the textures IDs will be the same, since we're running in different contexts.
Now it's possible that either Gtk or the driver itself (but my money is against Gtk) is mixing up the contexts somehow, and effectively not giving us different textures for different windows. So what we have to do is the following: call glGenTextures once, at startup, for say 1000 textures, and store the resulting array somewhere. The array *will* be 1 2 3 4 5 ... 1000, so we can also forget about glGenTextures completely. Then, we need an internal texture broker, that we ask for a free texture ID. That way we'll be using different texture IDs, which may work around the problem.
As long as we're using the same shader - and we are - all the time, I think the texture IDs are the only problem.
With r2941, it looks pretty good with fglrx, except for this when we close a window (we probably should check the window isn't gone already before or at the very least after):
Traceback (most recent call last): File "xpra/gl/gl_window_backing.py", line 169, in do_gl_paint self.render_image(x, y, x+w, y+h) File "xpra/gl/gl_window_backing.py", line 256, in render_image glEnd() File "OpenGL/latebind.py", line 61, in __call__ return self.wrapperFunction( self.baseFunction, *args, **named ) File "OpenGL/GL/exceptional.py", line 57, in glEnd return baseFunction( ) File "OpenGL/error.py", line 208, in glCheckError baseOperation = baseOperation, GLError: GLError( err = 1282, description = 'invalid operation', baseOperation = glEnd, cArguments = () )
r2947 fixes GL_INVALID_OPERATION after closing a window - we were deleting the shader in the wrong GL context. r2948 sets FRAGMENT_PROGRAM_ARB to enabled by default as we always use a shader now (since RGB rendering is done via straight gtk) r2949 fixes strange colorplanes behavior or downright crashes due to incorrect CSC 422 texture sizes
closing, follow up in #229
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/147