Xpra: Ticket #147: GL acceleration for client rendering

(remaining) tasks:

Changes required from commit r922:

Contingency plan: we can disable the opengl code if this proves unstable or problematic.

Note:



Sat, 16 Jun 2012 07:17:29 GMT - Antoine Martin: status, description changed


Sat, 16 Jun 2012 07:31:08 GMT - Antoine Martin: description changed

r924 and r925 deal with:


Sat, 16 Jun 2012 07:40:54 GMT - Antoine Martin: description changed

As for the win32 build, here are some pointers:


Sat, 16 Jun 2012 08:20:29 GMT - Antoine Martin: description changed


Sat, 16 Jun 2012 08:36:35 GMT - Antoine Martin:

r926 fixes vpx for non-gl case


Sat, 16 Jun 2012 13:19:38 GMT - ahuillet:

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.


Sun, 17 Jun 2012 13:59:16 GMT - Antoine Martin:


Which leaves (recap):


Sun, 17 Jun 2012 14:01:20 GMT - Antoine Martin: attachment set

fixing vpx to allow it to work with yuv/opengl codepath (work in progress patch)


Mon, 18 Jun 2012 08:58:58 GMT - ahuillet:


Tue, 19 Jun 2012 03:59:34 GMT - Antoine Martin:

More:


Fri, 22 Jun 2012 11:15:47 GMT - Antoine Martin:

New recap:


Mon, 25 Jun 2012 11:14:02 GMT - Antoine Martin: attachment set

compare cpu usage with opengl and gtk


Mon, 25 Jun 2012 11:17:11 GMT - Antoine Martin: attachment set

comparing pixels decoded per second with opengl and gtk


Mon, 25 Jun 2012 11:23:15 GMT - Antoine Martin: attachment set

comparing FPS with opengl and gtk


Mon, 25 Jun 2012 11:26:56 GMT - Antoine Martin: attachment set

comparing average client UI thread latency with opengl and gtk


Mon, 25 Jun 2012 11:29:28 GMT - Antoine Martin:

As can be seen here (user cpu + sys cpu): https://www.xpra.org/trac/raw-attachment/ticket/147/opengl-vs-gtk-clientcpu.svg The CPU usage is noticeably lower with the opengl backend, which is impressive seeing that it is also pushing more frames: https://www.xpra.org/trac/raw-attachment/ticket/147/opengl-vs-gtk-fps.svg (some pathological tests samples were removed)

We decode + paint much faster (pixels per second): https://www.xpra.org/trac/raw-attachment/ticket/147/opengl-vs-gtk-pixelsdecodedpersecond.svg

Which in turn reduces the average UI thread latency: https://www.xpra.org/trac/raw-attachment/ticket/147/opengl-vs-gtk-avgclientlatency.svg


Thu, 27 Sep 2012 15:22:16 GMT - Antoine Martin: milestone changed


Wed, 31 Oct 2012 07:02:40 GMT - Antoine Martin:

r2008 updates the gl code so it compiles/runs again


Wed, 31 Oct 2012 07:12:54 GMT - Antoine Martin:

r2009 fixes the calls from UI thread so rendering actually works


Wed, 31 Oct 2012 08:39:59 GMT - Antoine Martin:

r2010 fixes support for all csc modes with x264 decoding


Wed, 31 Oct 2012 11:42:11 GMT - Antoine Martin: attachment set

better gl patch


Wed, 31 Oct 2012 15:26:13 GMT - Antoine Martin:

Mostly working as of r2018: we now handle lossless updates too.

New recap of pending items:


Thu, 01 Nov 2012 08:40:25 GMT - Antoine Martin:

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.


Thu, 01 Nov 2012 09:03:44 GMT - Antoine Martin:

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)


Thu, 01 Nov 2012 11:33:56 GMT - Antoine Martin:

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':
(...)

Thu, 01 Nov 2012 14:03:24 GMT - Antoine Martin:

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'

Thu, 01 Nov 2012 16:49:39 GMT - Antoine Martin:

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:

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..


Fri, 02 Nov 2012 10:22:41 GMT - Antoine Martin:

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):


Sat, 03 Nov 2012 09:49:44 GMT - Antoine Martin: attachment set

if we do manage to get opengl working on win32, this deals with opengl libraries located in the frozen path


Fri, 21 Dec 2012 14:48:36 GMT - Antoine Martin:

Finally working very well on *nix:

Only win32 left...


Sat, 22 Dec 2012 10:34:28 GMT - Antoine Martin: status changed; resolution set

closing, see #226 for osx and #227 for win32


Mon, 24 Dec 2012 16:39:49 GMT - Antoine Martin: status changed; resolution deleted

re-opening:


Mon, 24 Dec 2012 16:40:39 GMT - Antoine Martin: attachment set

work in progress to make it work with nvidia driver.. not too far


Tue, 25 Dec 2012 11:45:15 GMT - Antoine Martin:

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:


Summary of remaining issues:


Thu, 27 Dec 2012 07:46:48 GMT - Antoine Martin: attachment set

version which creates the fragment program only once and uses glEnable / glDisable


Wed, 02 Jan 2013 11:07:00 GMT - Antoine Martin:

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

Mon, 11 Feb 2013 16:30:27 GMT - Antoine Martin: milestone changed

We still need to pass small region updates as YUV data instead of RGB...


Tue, 19 Feb 2013 17:52:46 GMT - ahuillet:

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!


Mon, 25 Feb 2013 16:25:57 GMT - Antoine Martin:

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


Tue, 26 Feb 2013 09:59:57 GMT - Antoine Martin:

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...


Tue, 12 Mar 2013 14:40:51 GMT - ahuillet:

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.


Tue, 12 Mar 2013 15:22:49 GMT - Antoine Martin:

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 = ()
)

Wed, 13 Mar 2013 07:51:54 GMT - ahuillet:

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


Sat, 16 Mar 2013 12:03:45 GMT - Antoine Martin: status changed; resolution set

closing, follow up in #229


Sat, 23 Jan 2021 04:46:49 GMT - migration script:

this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/147