xpra icon
Bug tracker and wiki

Opened 7 years ago

Closed 6 years ago

#147 closed task (fixed)

GL acceleration for client rendering

Reported by: Antoine Martin Owned by: Antoine Martin
Priority: major Milestone: 0.9
Component: client Version:
Keywords: GL Cc:

Description (last modified by Antoine Martin)

(remaining) tasks:

  • provide a GL client window alternative to the standard gtk window, so OpenGL can take care of colourspace conversion, done in r922
  • urgent: fix vpx (ahuillet)
  • support all encodings (ie: mmap, jpeg and png)
  • do_expose_event isn't called automatically - fix it
  • fallback to non-GL rendering when PyOpenGL is not installed, or when the GL driver is blacklisted (or not whitelisted)
  • win32 build: we need to document how to build everything from scratch

Changes required from commit r922:

  • whitespace cleanup
  • remove wildcard imports
  • remove unused variables
  • constify GL command string
  • do not use SystemExit
  • why does this crash python??:
    python -c "from OpenGL.GL import glGetString, GL_VERSION; glGetString(GL_VERSION)"
    
  • remove duplicated window backing code: separate GL (backing) from window code - and re-use backing (super)class if needed. GLWindowBacking is not used??
  • use booleans and not integers (ie: 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?
  • restore nogil for decompress_image_to_rgb: csc_image_yuv2rgb does not need the gil
  • run automated tests to compare with more scenarios

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

Note:

  • with local connections, it might even be possible for the server to render directly to the client window? (even faster than mmap)

Attachments (10)

xpra-vpx-gl.patch (8.5 KB) - added by Antoine Martin 7 years ago.
fixing vpx to allow it to work with yuv/opengl codepath (work in progress patch)
opengl-vs-gtk-clientcpu.svg (48.9 KB) - added by Antoine Martin 6 years ago.
compare cpu usage with opengl and gtk
opengl-vs-gtk-pixelsdecodedpersecond.svg (49.5 KB) - added by Antoine Martin 6 years ago.
comparing pixels decoded per second with opengl and gtk
opengl-vs-gtk-fps.svg (36.5 KB) - added by Antoine Martin 6 years ago.
comparing FPS with opengl and gtk
opengl-vs-gtk-avgclientlatency.svg (35.8 KB) - added by Antoine Martin 6 years ago.
comparing average client UI thread latency with opengl and gtk
gl-rgb24.patch (8.9 KB) - added by Antoine Martin 6 years ago.
better gl patch
gl-frozen-path.patch (2.7 KB) - added by Antoine Martin 6 years ago.
if we do manage to get opengl working on win32, this deals with opengl libraries located in the frozen path
gl_window_backing.py (10.5 KB) - added by Antoine Martin 6 years ago.
work in progress to make it work with nvidia driver.. not too far
gl_window_backing.2.py (11.6 KB) - added by Antoine Martin 6 years ago.
version which creates the fragment program only once and uses glEnable / glDisable
gtk-2.0.zip (3.7 MB) - added by Antoine Martin 6 years ago.
gtkglxext and pygtkglext bits from my working installation - unzip in python's site-packages

Change History (45)

comment:1 Changed 7 years ago by Antoine Martin

Description: modified (diff)
Status: newaccepted

comment:2 Changed 7 years ago by Antoine Martin

Description: modified (diff)

r924 and r925 deal with:

  • splitting the GL code into separate files: gl_window_backing.py should be used or removed altogether
  • disable loading of GL code by default as this causes crashes, see USE_OPENGL=False in client.py
  • constifying gl-colorspace-conversions MIT licensed code in its own file
  • fix whitespace
  • remove wildcard imports
  • remove unused variables
  • remove use of SystemExit
Last edited 7 years ago by Antoine Martin (previous) (diff)

comment:3 Changed 7 years ago by Antoine Martin

Description: modified (diff)

As for the win32 build, here are some pointers:

comment:4 Changed 7 years ago by Antoine Martin

Description: modified (diff)

comment:5 Changed 7 years ago by Antoine Martin

r926 fixes vpx for non-gl case

comment:6 Changed 7 years ago by 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.

comment:7 Changed 7 years ago by Antoine Martin

  • non-gl fix for vpx, see r926
  • we no longer hold the gil when not needed, see r927
  • version check removed in r928, then re-enabled during early module load but with proper 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):

  • fix vpx (partial patch available)
  • blacklisting or whitelisting of opengl backends
  • win32 build: we need to document how to build everything from scratch
  • separate GL (backing) from GL window code (as per regular non-gl classes) - and re-use backing (super)class. (probably rename GLWindowBacking to GLBacking)
  • "No GL output for mmap", jpeg, png... (should be made easier by item just above)
  • padding issues in #146
  • self.current_mode and self.textures, need documenting more clearly (and constifying?), and initializing in constructor?
  • "FIXME: We use single buffer because double doesn't work, figure out why"
  • run automated tests to compare with more scenarios
  • crash in #150
  • do_expose_event isn't called automatically - fix it
Last edited 6 years ago by Antoine Martin (previous) (diff)

Changed 7 years ago by Antoine Martin

Attachment: xpra-vpx-gl.patch added

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

comment:8 Changed 7 years ago by ahuillet

  • Vpx fixed in r931
  • double buffer isn't actually needed so we can drop this issue
  • current_mode is meant to be initialized to 0 (you don't know if it's YUV or RGB mode at start). textures can't be initialized because you need a GL context to call glGenTextures
Last edited 7 years ago by ahuillet (previous) (diff)

comment:9 Changed 7 years ago by Antoine Martin

More:

  • x264 fix in r932
  • some docstrings in r933
  • win32 build fix in r934
  • debian/ebuild/setup.py Cython version requirements bumped to 0.16 in r935
  • patches updated to the new offsets in r936
  • packages should now pull opengl bits (if available for this platform), done in r937 (avoid stacktrace by pulling dep we don't need in r940 ...)
  • fixed initialization of current_mode in r938
  • tidy up in r943 and constification in r944
Last edited 6 years ago by Antoine Martin (previous) (diff)

comment:10 Changed 6 years ago by Antoine Martin

New recap:

  • blacklisting or whitelisting of opengl backends - not needed?
  • provide a "--no-opengl" switch
  • win32 build: we need to document how to build everything from scratch
  • separate GL (backing) from GL window code
  • "No GL output for mmap", jpeg, png...
  • padding issues in #146
  • crash in #150
  • do_expose_event isn't called automatically
  • use_openGL_CSC = False : test it thoroughly
Last edited 6 years ago by Antoine Martin (previous) (diff)

Changed 6 years ago by Antoine Martin

Attachment: opengl-vs-gtk-clientcpu.svg added

compare cpu usage with opengl and gtk

Changed 6 years ago by Antoine Martin

comparing pixels decoded per second with opengl and gtk

Changed 6 years ago by Antoine Martin

Attachment: opengl-vs-gtk-fps.svg added

comparing FPS with opengl and gtk

Changed 6 years ago by Antoine Martin

comparing average client UI thread latency with opengl and gtk

comment:11 Changed 6 years ago by 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

comment:12 Changed 6 years ago by Antoine Martin

Milestone: 0.40.8

comment:13 Changed 6 years ago by Antoine Martin

r2008 updates the gl code so it compiles/runs again

comment:14 Changed 6 years ago by Antoine Martin

r2009 fixes the calls from UI thread so rendering actually works

comment:15 Changed 6 years ago by Antoine Martin

r2010 fixes support for all csc modes with x264 decoding

Changed 6 years ago by Antoine Martin

Attachment: gl-rgb24.patch added

better gl patch

comment:16 Changed 6 years ago by Antoine Martin

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

New recap of pending items:

  • provide a "--no-opengl" switch: no, will use XPRA_OPENGL env var to control (and make GL the default if possible/stable enough)
  • win32 build: we need to document how to build everything from scratch
  • when we process a lossless update, we lose the ability to process expose events until the next lossless update..
  • somewhere in gtkgl prints out empty log lines - try to get rid of it or get it fixed
  • do we leak memory? "glGenPrograms we call in the YUV420 setup, so we need to do cleanup otherwise next time we call it we're leaking the first"
Last edited 6 years ago by Antoine Martin (previous) (diff)

comment:17 Changed 6 years ago by 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.

comment:18 Changed 6 years ago by 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)

comment:19 Changed 6 years ago by 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':
(...)
Last edited 6 years ago by Antoine Martin (previous) (diff)

comment:20 Changed 6 years ago by 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'

comment:21 Changed 6 years ago by 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:

  • replace GTK_WIDGET_TOPLEVEL by gtk_widget_is_toplevel
  • just comment out the GTK_GL_NOTE ... lines in gtk_gl_widget_style_set
  • replace 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... (1(*), 2, 3, 4, 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..

comment:22 Changed 6 years ago by 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 ('git://git.gnome.org/gtkglext') and from another tree I found (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):

  • install PyOpenGL: "C:\Python27\scripts\easy-install.exe PyOpenGL"
  • use this gtkglext installer (or see comment:20 to build from source) and copy the installation dir this creates (by default: C:\GtkGLExt) to pygtk's runtime directory (by default: C:\Python27\Lib\site-packages\gtk-2.0\runtime)
  • build pygtkglext-1.1.0.tar.gz with /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\
  • run the pixbuf examples: /c/Python27/python.exe pixmap.py - does it work or not? warnings shown?
Last edited 6 years ago by Antoine Martin (previous) (diff)

Changed 6 years ago by Antoine Martin

Attachment: gl-frozen-path.patch added

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

comment:23 Changed 6 years ago by Antoine Martin

Finally working very well on *nix:

  • see fixes in #150
  • r2332 fixes the last blocker
  • r2333 enables OpenGL by default when available
  • r2331 avoids warnings if we have installed --without-opengl

Only win32 left...

comment:24 Changed 6 years ago by Antoine Martin

Resolution: fixed
Status: acceptedclosed

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

comment:25 Changed 6 years ago by Antoine Martin

Resolution: fixed
Status: closedreopened

re-opening:

  • r2332 breaks radeon and does not work reliably with nouveau driver: nouveau does not support multiple gl contexts at the moment
  • r2336 partially fixes radeon, but we still get screen corruption in video/yuv mode (also true with nvidia)
  • current trunk does not work with nvidia driver at all (rgb broken, yuv buggy/stops)
  • need to test intel, etc and whitelist/blacklist those that do work
  • when we resize the window up, the expose event seems to paint random chunks of memory into the missing space... clip it
  • expose events do not work with nvidia after an rgb update: we set pixel_format to rgb and the render_image shortcuts out (works on radeon for some strange reason)
  • figure out why opengl logs empty lines to the logfile and make it stfu
Last edited 6 years ago by Antoine Martin (previous) (diff)

Changed 6 years ago by Antoine Martin

Attachment: gl_window_backing.py added

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

comment:26 Changed 6 years ago by 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:

  • radeon (Radeon HD 5450)
  • fglrx (Radeon HD 5450)
  • intel (GM965/GL960 Integrated Graphics Controller)
  • nvidia (GeForce GTS 450) - but with a bug: expose does not work
  • nouveau (GeForce GTS 450) - but with a bug: expose does not work

Summary of remaining issues:

  • occasional weird frame with no apparent cause (looks sort of black&white - seen mostly on intel with glxgears)
  • nvidia/nouveau expose events do not work - it is quite strange that it works for all the others...
  • re-doing the whole fragment program init everytime is wasteful, we should be able to load it up once and glEnable, glDisable it when needed by paint_rgb24 (see example code attached which almost works)
  • occasional destroy_program_variants_cb warning (see r2327) - maybe we do need to call remove_shader on the cleanup path
  • win32 crash: #229
Last edited 6 years ago by Antoine Martin (previous) (diff)

Changed 6 years ago by Antoine Martin

Attachment: gl_window_backing.2.py added

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

comment:27 Changed 6 years ago by 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

comment:28 Changed 6 years ago by Antoine Martin

Milestone: 0.80.9

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

comment:29 Changed 6 years ago by 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!

Last edited 6 years ago by ahuillet (previous) (diff)

comment:30 Changed 6 years ago by 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

comment:31 Changed 6 years ago by 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...

comment:32 Changed 6 years ago by 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.

comment:33 Changed 6 years ago by 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 = ()
)

comment:34 Changed 6 years ago by 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

comment:35 Changed 6 years ago by Antoine Martin

Resolution: fixed
Status: reopenedclosed

closing, follow up in #229

Changed 6 years ago by Antoine Martin

Attachment: gtk-2.0.zip added

gtkglxext and pygtkglext bits from my working installation - unzip in python's site-packages

Note: See TracTickets for help on using tickets.