[cairo] Cairo 1.14.2 problems with Solaris 10, libXrender

Andreas F. Borchert andreas.borchert at uni-ulm.de
Tue Aug 4 07:29:29 PDT 2015


Hi folks,

the following problem is not the fault of the Cairo library in the first
place but of Solaris. However, the current release makes it pretty hard
to track down this problem and I am posting this here as other developers
might run into the same problem.

I build open source packages by myself for Solaris 10. To get GTK+ up and
running, I compiled and packaged the whole suite along with the Cairo
library. Everything could be compiled, at times with some minor fixes,
but the end result was unfortunately not usable as

   * Gtk2 failed to render text and
   * Gtk3 failed to render anything.

It took me a while to track this down to the Cairo library in
conjunction with the Xrender library. Newer updates of Solaris 10
provide libXrender.so.1 and Xrender.h. Unfortunately the versions of
both files do not match, i.e. libXrender.so.1 supports 0.10 along with
CreateLinearGradient etc [1] but Xrender.h appears to support 0.9 only
and does not provide the declarations of 0.10. This is known to Oracle
since November 2010 (bug id 15683111) but was unfortunately never fixed
since then despite numerous X11 updates (including patch 119060-69 which
was released in July 2015).

configure checks if the functions XRenderCreateSolidFill,
XRenderCreateLinearGradient, XRenderCreateRadialGradient, and
XRenderCreateConicalGradient are provided by -lXrender. As they
are defined, configure sets HAVE_XRENDERCREATECONICALGRADIENT etc to 1
in config.h. Subsequent compilations, however, fail as the associated
prototypes are not to be found in Xrender.h. Seeing these error messages,
I thought that these extensions do not appear to be supported and decided
quickly to set all these macros to 0. This compiled and lead to the
result above.

What is the problem? In cairo-xlib-xrender-private.h we find multiple
tests of these config.h macros. Here is the first one:

   #if !HAVE_XRENDERCREATESOLIDFILL
   #define XRenderCreateSolidFill                          _int_consume
   #endif

This means that calls of XRenderCreateSolidFill are replaced
by calls of _int_consume which is effectively a no-op. In
cairo-xlib-source.c, however, the config.h macros are ignored.
Instead macros like CAIRO_RENDER_HAS_GRADIENTS are used that
check the actual version of the RENDER extension in the X server
at runtime. Example from the color_source function:

   if (CAIRO_RENDER_HAS_GRADIENTS(dst->display)) {
      picture = XRenderCreateSolidFill (dpy, &xcolor);
   } else {
      // ...
   }

In consequence, if this code is compiled with
HAVE_XRENDERCREATECONICALGRADIENT switched off and run
with a RENDER extension of version 0.10 or better, we
invoke a no-op instead of rendering this. This explains why
Gtk rendering failed that badly.

The major problem was, of course, that Solaris 10 shipped a header file
and a library that were not in sync. However, you might run into this
problem as well if you compile cairo with a consistent Xrender library
of version 0.9 which happens to encounter during runtime an extension of
version 0.10. Your code assumes wrongly that the Xrender release of the
library matches that of the actual X server. I would suggest to fix this.

After patching Xrender.h on Solaris 10, Cairo compiled with
these options switched on and Gtk renders as expected.

Regards, Andreas.

[1] http://www.x.org/releases/X11R7.7/doc/renderproto/renderproto.txt

-- 
Dr. Andreas F. Borchert, Institut für Numerische Mathematik,
Universität Ulm, Helmholtzstraße 20, Zimmer 1.22, 89081 Ulm


More information about the cairo mailing list