From 8994df8c7dde792c7c018e3ad678aa3c03114f5b Mon Sep 17 00:00:00 2001 From: "vladimir%pobox.com" Date: Thu, 6 Oct 2005 04:02:10 +0000 Subject: [PATCH] Merge from org.mozilla.cvs.cairo branch. - Cairo 1.1.1 - Updated thebes, gfx/src/thebes - Fixes to plugins with thebes gfx under linux - Native theme fixes with thebes rendering (NOTE: widget changes only enabled when building with thebes, otherwise all old code) --- configure | 296 +-- configure.in | 1 + gfx/cairo/README | 29 +- gfx/cairo/cairo/src/Makefile.in | 5 +- gfx/cairo/cairo/src/cairo-arc.c | 20 +- gfx/cairo/cairo/src/cairo-atsui-font.c | 748 ++++--- gfx/cairo/cairo/src/cairo-atsui.h | 55 - gfx/cairo/cairo/src/cairo-cache-private.h | 125 ++ gfx/cairo/cairo/src/cairo-cache.c | 707 +++---- gfx/cairo/cairo/src/cairo-debug.c | 1 - gfx/cairo/cairo/src/cairo-features.h.in | 8 +- gfx/cairo/cairo/src/cairo-fixed.c | 4 +- gfx/cairo/cairo/src/cairo-font.c | 840 +------- gfx/cairo/cairo/src/cairo-ft-font.c | 1199 +++++------ gfx/cairo/cairo/src/cairo-ft.h | 10 +- gfx/cairo/cairo/src/cairo-glitz-surface.c | 939 +++++---- gfx/cairo/cairo/src/cairo-glitz.h | 2 +- gfx/cairo/cairo/src/cairo-gstate-private.h | 4 +- gfx/cairo/cairo/src/cairo-gstate.c | 375 +++- gfx/cairo/cairo/src/cairo-hull.c | 16 +- gfx/cairo/cairo/src/cairo-image-surface.c | 22 +- gfx/cairo/cairo/src/cairo-matrix.c | 183 +- gfx/cairo/cairo/src/cairo-meta-surface.c | 17 + gfx/cairo/cairo/src/cairo-path-data.c | 4 +- gfx/cairo/cairo/src/cairo-path-stroke.c | 178 +- gfx/cairo/cairo/src/cairo-path.c | 18 + gfx/cairo/cairo/src/cairo-pattern.c | 230 +-- gfx/cairo/cairo/src/cairo-pdf-surface.c | 18 + gfx/cairo/cairo/src/cairo-pdf.h | 6 +- gfx/cairo/cairo/src/cairo-pen.c | 152 +- gfx/cairo/cairo/src/cairo-platform.h | 84 + gfx/cairo/cairo/src/cairo-png.c | 28 +- gfx/cairo/cairo/src/cairo-ps-surface.c | 169 +- gfx/cairo/cairo/src/cairo-ps.h | 6 +- gfx/cairo/cairo/src/cairo-quartz-surface.c | 4 +- gfx/cairo/cairo/src/cairo-quartz.h | 2 +- gfx/cairo/cairo/src/cairo-scaled-font.c | 1193 +++++++++++ gfx/cairo/cairo/src/cairo-surface.c | 77 +- gfx/cairo/cairo/src/cairo-traps.c | 16 +- gfx/cairo/cairo/src/cairo-win32-font.c | 433 ++-- gfx/cairo/cairo/src/cairo-win32-private.h | 6 - gfx/cairo/cairo/src/cairo-win32-surface.c | 163 +- gfx/cairo/cairo/src/cairo-win32.h | 10 +- gfx/cairo/cairo/src/cairo-xcb-xrender.h | 2 +- gfx/cairo/cairo/src/cairo-xcb.h | 6 +- gfx/cairo/cairo/src/cairo-xlib-screen.c | 3 + gfx/cairo/cairo/src/cairo-xlib-surface.c | 1151 +++++------ gfx/cairo/cairo/src/cairo-xlib-xrender.h | 2 +- gfx/cairo/cairo/src/cairo-xlib.h | 8 +- gfx/cairo/cairo/src/cairo.c | 677 ++++--- gfx/cairo/cairo/src/cairo.h | 451 ++-- gfx/cairo/cairo/src/cairoint.h | 457 ++--- gfx/cairo/glitz/src/Makefile.in | 2 + gfx/cairo/glitz/src/agl/glitz-agl.h | 26 +- gfx/cairo/glitz/src/agl/glitz_agl_context.c | 672 +++--- gfx/cairo/glitz/src/agl/glitz_agl_drawable.c | 311 +-- gfx/cairo/glitz/src/agl/glitz_agl_extension.c | 98 +- gfx/cairo/glitz/src/agl/glitz_agl_format.c | 468 ++--- gfx/cairo/glitz/src/agl/glitz_agl_info.c | 324 +-- gfx/cairo/glitz/src/agl/glitz_agl_pbuffer.c | 38 +- gfx/cairo/glitz/src/agl/glitz_aglint.h | 91 +- gfx/cairo/glitz/src/egl/glitz-egl.h | 46 +- gfx/cairo/glitz/src/egl/glitz_egl_config.c | 326 +-- gfx/cairo/glitz/src/egl/glitz_egl_context.c | 505 ++--- gfx/cairo/glitz/src/egl/glitz_egl_info.c | 585 +++--- gfx/cairo/glitz/src/egl/glitz_egl_pbuffer.c | 56 +- gfx/cairo/glitz/src/egl/glitz_egl_surface.c | 292 +-- gfx/cairo/glitz/src/egl/glitz_eglext.h | 0 gfx/cairo/glitz/src/egl/glitz_eglint.h | 130 +- gfx/cairo/glitz/src/glitz.c | 959 ++++----- gfx/cairo/glitz/src/glitz.h | 459 +++-- gfx/cairo/glitz/src/glitz_buffer.c | 483 ++--- gfx/cairo/glitz/src/glitz_compose.c | 963 ++++----- gfx/cairo/glitz/src/glitz_context.c | 104 +- gfx/cairo/glitz/src/glitz_drawable.c | 295 ++- gfx/cairo/glitz/src/glitz_filter.c | 680 ++++--- gfx/cairo/glitz/src/glitz_format.c | 527 +++-- gfx/cairo/glitz/src/glitz_framebuffer.c | 405 +++- gfx/cairo/glitz/src/glitz_geometry.c | 873 ++++---- gfx/cairo/glitz/src/glitz_gl.h | 46 +- gfx/cairo/glitz/src/glitz_operator.c | 112 +- gfx/cairo/glitz/src/glitz_pixel.c | 1805 +++++++++-------- gfx/cairo/glitz/src/glitz_program.c | 854 ++++---- gfx/cairo/glitz/src/glitz_rect.c | 419 ++-- gfx/cairo/glitz/src/glitz_region.c | 243 +-- gfx/cairo/glitz/src/glitz_status.c | 84 +- gfx/cairo/glitz/src/glitz_surface.c | 1306 ++++++------ gfx/cairo/glitz/src/glitz_texture.c | 603 +++--- gfx/cairo/glitz/src/glitz_trap.c | 454 ++--- gfx/cairo/glitz/src/glitz_trapimp.h | 1030 +++++----- gfx/cairo/glitz/src/glitz_util.c | 576 +++--- gfx/cairo/glitz/src/glitzint.h | 357 ++-- gfx/cairo/glitz/src/glx/Makefile.in | 2 + gfx/cairo/glitz/src/glx/glitz-glx.h | 53 +- gfx/cairo/glitz/src/glx/glitz_glx_context.c | 622 +++--- gfx/cairo/glitz/src/glx/glitz_glx_drawable.c | 290 +-- gfx/cairo/glitz/src/glx/glitz_glx_extension.c | 65 +- gfx/cairo/glitz/src/glx/glitz_glx_format.c | 693 ++++--- gfx/cairo/glitz/src/glx/glitz_glx_info.c | 774 +++---- gfx/cairo/glitz/src/glx/glitz_glx_pbuffer.c | 54 +- gfx/cairo/glitz/src/glx/glitz_glxext.h | 26 +- gfx/cairo/glitz/src/glx/glitz_glxint.h | 163 +- gfx/cairo/libpixman/src/Makefile.in | 6 +- gfx/cairo/libpixman/src/fbcompose.c | 297 ++- gfx/cairo/libpixman/src/fbmmx.c | 211 +- gfx/cairo/libpixman/src/fbmmx.h | 12 + gfx/cairo/libpixman/src/fbpict.c | 179 +- gfx/cairo/libpixman/src/fbpict.h | 12 +- gfx/cairo/libpixman/src/ic.c | 0 gfx/cairo/libpixman/src/icbltone.c | 6 +- gfx/cairo/libpixman/src/icimage.c | 10 +- gfx/cairo/libpixman/src/icrect.c | 5 +- gfx/cairo/libpixman/src/ictrap.c | 6 +- gfx/cairo/libpixman/src/mozstdint.h | 0 gfx/cairo/libpixman/src/pixman-remap.h | 276 +-- gfx/cairo/libpixman/src/pixman.h | 21 +- gfx/cairo/libpixman/src/pixregion.c | 10 +- gfx/src/thebes/Makefile.in | 10 +- gfx/src/thebes/nsThebesDeviceContext.cpp | 9 +- gfx/src/thebes/nsThebesDrawingSurface.cpp | 58 +- gfx/src/thebes/nsThebesImage.cpp | 36 +- gfx/src/thebes/nsThebesRenderingContext.cpp | 198 +- gfx/src/thebes/nsThebesRenderingContext.h | 16 +- gfx/src/windows/nsRenderingContextWin.h | 1 - gfx/thebes/public/Makefile.in | 19 +- gfx/thebes/public/gfxASurface.h | 11 +- gfx/thebes/public/gfxColor.h | 2 +- gfx/thebes/public/gfxContext.h | 18 +- gfx/thebes/public/gfxFilter.h | 2 +- gfx/thebes/public/gfxGlitzSurface.h | 2 +- gfx/thebes/public/gfxImageSurface.h | 2 +- gfx/thebes/public/gfxMatrix.h | 17 +- gfx/thebes/public/gfxPattern.h | 2 +- gfx/thebes/public/gfxPoint.h | 4 +- gfx/thebes/public/gfxRect.h | 2 +- gfx/thebes/public/gfxRegion.h | 2 +- gfx/thebes/public/gfxTextRun.h | 72 - gfx/thebes/public/gfxWindowsSurface.h | 2 +- gfx/thebes/public/gfxXlibSurface.h | 11 +- gfx/thebes/src/Makefile.in | 30 +- gfx/thebes/src/gfxContext.cpp | 6 + gfx/thebes/src/gfxWindowsSurface.cpp | 14 +- gfx/thebes/src/gfxXlibSurface.cpp | 55 +- widget/src/build/Makefile.in | 4 + widget/src/gtk2/Makefile.in | 7 +- widget/src/gtk2/nsNativeThemeGTK.cpp | 152 ++ widget/src/gtkxtbin/gtk2xtbin.c | 7 + widget/src/windows/Makefile.in | 9 +- widget/src/windows/nsNativeThemeWin.cpp | 79 +- widget/src/windows/nsWindow.cpp | 4 +- 150 files changed, 17894 insertions(+), 15529 deletions(-) create mode 100644 gfx/cairo/cairo/src/cairo-cache-private.h create mode 100644 gfx/cairo/cairo/src/cairo-platform.h create mode 100644 gfx/cairo/cairo/src/cairo-scaled-font.c delete mode 100644 gfx/cairo/glitz/src/egl/glitz_eglext.h delete mode 100644 gfx/cairo/libpixman/src/ic.c delete mode 100644 gfx/cairo/libpixman/src/mozstdint.h diff --git a/configure b/configure index 449c1742997..7c2485f5667 100755 --- a/configure +++ b/configure @@ -12465,6 +12465,10 @@ if test "$MOZ_ENABLE_CAIRO_GFX" then cat >> confdefs.h <<\EOF #define MOZ_THEBES 1 +EOF + + cat >> confdefs.h <<\EOF +#define MOZ_CAIRO_GFX 1 EOF fi @@ -12939,7 +12943,7 @@ EOF # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:12943: checking for $ac_word" >&5 +echo "configure:12947: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -12983,19 +12987,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for xft""... $ac_c" 1>&6 -echo "configure:12987: checking for xft" >&5 +echo "configure:12991: checking for xft" >&5 if $PKG_CONFIG --exists "xft" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_XFT_CFLAGS""... $ac_c" 1>&6 -echo "configure:12994: checking MOZ_XFT_CFLAGS" >&5 +echo "configure:12998: checking MOZ_XFT_CFLAGS" >&5 MOZ_XFT_CFLAGS=`$PKG_CONFIG --cflags "xft"` echo "$ac_t""$MOZ_XFT_CFLAGS" 1>&6 echo $ac_n "checking MOZ_XFT_LIBS""... $ac_c" 1>&6 -echo "configure:12999: checking MOZ_XFT_LIBS" >&5 +echo "configure:13003: checking MOZ_XFT_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_XFT_LIBS="`$PKG_CONFIG --libs \"xft\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_XFT_LIBS" 1>&6 @@ -13028,7 +13032,7 @@ echo "configure:12999: checking MOZ_XFT_LIBS" >&5 # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13032: checking for $ac_word" >&5 +echo "configure:13036: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13072,19 +13076,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for pango >= 1.1.0""... $ac_c" 1>&6 -echo "configure:13076: checking for pango >= 1.1.0" >&5 +echo "configure:13080: checking for pango >= 1.1.0" >&5 if $PKG_CONFIG --exists "pango >= 1.1.0" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking _PANGOCHK_CFLAGS""... $ac_c" 1>&6 -echo "configure:13083: checking _PANGOCHK_CFLAGS" >&5 +echo "configure:13087: checking _PANGOCHK_CFLAGS" >&5 _PANGOCHK_CFLAGS=`$PKG_CONFIG --cflags "pango >= 1.1.0"` echo "$ac_t""$_PANGOCHK_CFLAGS" 1>&6 echo $ac_n "checking _PANGOCHK_LIBS""... $ac_c" 1>&6 -echo "configure:13088: checking _PANGOCHK_LIBS" >&5 +echo "configure:13092: checking _PANGOCHK_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic _PANGOCHK_LIBS="`$PKG_CONFIG --libs \"pango >= 1.1.0\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$_PANGOCHK_LIBS" 1>&6 @@ -13142,7 +13146,7 @@ EOF # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13146: checking for $ac_word" >&5 +echo "configure:13150: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13186,19 +13190,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for pango >= 1.6.0 pangoft2 >= 1.6.0""... $ac_c" 1>&6 -echo "configure:13190: checking for pango >= 1.6.0 pangoft2 >= 1.6.0" >&5 +echo "configure:13194: checking for pango >= 1.6.0 pangoft2 >= 1.6.0" >&5 if $PKG_CONFIG --exists "pango >= 1.6.0 pangoft2 >= 1.6.0" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_PANGO_CFLAGS""... $ac_c" 1>&6 -echo "configure:13197: checking MOZ_PANGO_CFLAGS" >&5 +echo "configure:13201: checking MOZ_PANGO_CFLAGS" >&5 MOZ_PANGO_CFLAGS=`$PKG_CONFIG --cflags "pango >= 1.6.0 pangoft2 >= 1.6.0"` echo "$ac_t""$MOZ_PANGO_CFLAGS" 1>&6 echo $ac_n "checking MOZ_PANGO_LIBS""... $ac_c" 1>&6 -echo "configure:13202: checking MOZ_PANGO_LIBS" >&5 +echo "configure:13206: checking MOZ_PANGO_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_PANGO_LIBS="`$PKG_CONFIG --libs \"pango >= 1.6.0 pangoft2 >= 1.6.0\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_PANGO_LIBS" 1>&6 @@ -13265,7 +13269,7 @@ then _SAVE_LDFLAGS="$LDFLAGS" LDFLAGS="$XLDFLAGS $LDFLAGS" echo $ac_n "checking for XpGetPrinterList in -lXp""... $ac_c" 1>&6 -echo "configure:13269: checking for XpGetPrinterList in -lXp" >&5 +echo "configure:13273: checking for XpGetPrinterList in -lXp" >&5 ac_lib_var=`echo Xp'_'XpGetPrinterList | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -13273,7 +13277,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lXp $XEXT_LIBS $XLIBS $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:13292: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -13356,7 +13360,7 @@ fi # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13360: checking for $ac_word" >&5 +echo "configure:13364: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13400,19 +13404,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION""... $ac_c" 1>&6 -echo "configure:13404: checking for gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION" >&5 +echo "configure:13408: checking for gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION" >&5 if $PKG_CONFIG --exists "gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_GNOMEVFS_CFLAGS""... $ac_c" 1>&6 -echo "configure:13411: checking MOZ_GNOMEVFS_CFLAGS" >&5 +echo "configure:13415: checking MOZ_GNOMEVFS_CFLAGS" >&5 MOZ_GNOMEVFS_CFLAGS=`$PKG_CONFIG --cflags "gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION"` echo "$ac_t""$MOZ_GNOMEVFS_CFLAGS" 1>&6 echo $ac_n "checking MOZ_GNOMEVFS_LIBS""... $ac_c" 1>&6 -echo "configure:13416: checking MOZ_GNOMEVFS_LIBS" >&5 +echo "configure:13420: checking MOZ_GNOMEVFS_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_GNOMEVFS_LIBS="`$PKG_CONFIG --libs \"gnome-vfs-2.0 >= $GNOMEVFS_VERSION gnome-vfs-module-2.0 >= $GNOMEVFS_VERSION\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_GNOMEVFS_LIBS" 1>&6 @@ -13460,7 +13464,7 @@ echo "configure:13416: checking MOZ_GNOMEVFS_LIBS" >&5 # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13464: checking for $ac_word" >&5 +echo "configure:13468: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13504,19 +13508,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for gconf-2.0 >= $GCONF_VERSION""... $ac_c" 1>&6 -echo "configure:13508: checking for gconf-2.0 >= $GCONF_VERSION" >&5 +echo "configure:13512: checking for gconf-2.0 >= $GCONF_VERSION" >&5 if $PKG_CONFIG --exists "gconf-2.0 >= $GCONF_VERSION" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_GCONF_CFLAGS""... $ac_c" 1>&6 -echo "configure:13515: checking MOZ_GCONF_CFLAGS" >&5 +echo "configure:13519: checking MOZ_GCONF_CFLAGS" >&5 MOZ_GCONF_CFLAGS=`$PKG_CONFIG --cflags "gconf-2.0 >= $GCONF_VERSION"` echo "$ac_t""$MOZ_GCONF_CFLAGS" 1>&6 echo $ac_n "checking MOZ_GCONF_LIBS""... $ac_c" 1>&6 -echo "configure:13520: checking MOZ_GCONF_LIBS" >&5 +echo "configure:13524: checking MOZ_GCONF_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_GCONF_LIBS="`$PKG_CONFIG --libs \"gconf-2.0 >= $GCONF_VERSION\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_GCONF_LIBS" 1>&6 @@ -13560,7 +13564,7 @@ echo "configure:13520: checking MOZ_GCONF_LIBS" >&5 # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13564: checking for $ac_word" >&5 +echo "configure:13568: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13604,19 +13608,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for libgnome-2.0 >= $LIBGNOME_VERSION""... $ac_c" 1>&6 -echo "configure:13608: checking for libgnome-2.0 >= $LIBGNOME_VERSION" >&5 +echo "configure:13612: checking for libgnome-2.0 >= $LIBGNOME_VERSION" >&5 if $PKG_CONFIG --exists "libgnome-2.0 >= $LIBGNOME_VERSION" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_LIBGNOME_CFLAGS""... $ac_c" 1>&6 -echo "configure:13615: checking MOZ_LIBGNOME_CFLAGS" >&5 +echo "configure:13619: checking MOZ_LIBGNOME_CFLAGS" >&5 MOZ_LIBGNOME_CFLAGS=`$PKG_CONFIG --cflags "libgnome-2.0 >= $LIBGNOME_VERSION"` echo "$ac_t""$MOZ_LIBGNOME_CFLAGS" 1>&6 echo $ac_n "checking MOZ_LIBGNOME_LIBS""... $ac_c" 1>&6 -echo "configure:13620: checking MOZ_LIBGNOME_LIBS" >&5 +echo "configure:13624: checking MOZ_LIBGNOME_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_LIBGNOME_LIBS="`$PKG_CONFIG --libs \"libgnome-2.0 >= $LIBGNOME_VERSION\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_LIBGNOME_LIBS" 1>&6 @@ -13691,7 +13695,7 @@ fi # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:13695: checking for $ac_word" >&5 +echo "configure:13699: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -13735,19 +13739,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for libgnomeui-2.0 >= $GNOMEUI_VERSION""... $ac_c" 1>&6 -echo "configure:13739: checking for libgnomeui-2.0 >= $GNOMEUI_VERSION" >&5 +echo "configure:13743: checking for libgnomeui-2.0 >= $GNOMEUI_VERSION" >&5 if $PKG_CONFIG --exists "libgnomeui-2.0 >= $GNOMEUI_VERSION" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking MOZ_GNOMEUI_CFLAGS""... $ac_c" 1>&6 -echo "configure:13746: checking MOZ_GNOMEUI_CFLAGS" >&5 +echo "configure:13750: checking MOZ_GNOMEUI_CFLAGS" >&5 MOZ_GNOMEUI_CFLAGS=`$PKG_CONFIG --cflags "libgnomeui-2.0 >= $GNOMEUI_VERSION"` echo "$ac_t""$MOZ_GNOMEUI_CFLAGS" 1>&6 echo $ac_n "checking MOZ_GNOMEUI_LIBS""... $ac_c" 1>&6 -echo "configure:13751: checking MOZ_GNOMEUI_LIBS" >&5 +echo "configure:13755: checking MOZ_GNOMEUI_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic MOZ_GNOMEUI_LIBS="`$PKG_CONFIG --libs \"libgnomeui-2.0 >= $GNOMEUI_VERSION\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$MOZ_GNOMEUI_LIBS" 1>&6 @@ -14250,7 +14254,7 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c java` -ne 0; then # Extract the first word of "javac", so it can be a program name with args. set dummy javac; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:14254: checking for $ac_word" >&5 +echo "configure:14258: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_JAVAC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -14286,7 +14290,7 @@ fi # Extract the first word of "jar", so it can be a program name with args. set dummy jar; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:14290: checking for $ac_word" >&5 +echo "configure:14294: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_JAR'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -14465,7 +14469,7 @@ fi gdiplus) MOZ_SVG_RENDERER_GDIPLUS=1 echo $ac_n "checking for Gdiplus.h""... $ac_c" 1>&6 -echo "configure:14469: checking for Gdiplus.h" >&5 +echo "configure:14473: checking for Gdiplus.h" >&5 ac_ext=C # CXXFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -14475,7 +14479,7 @@ ac_link='${CXX-g++} -o conftest${ac_exeext} $CXXFLAGS $CPPFLAGS $LDFLAGS conftes cross_compiling=$ac_cv_prog_cxx_cross cat > conftest.$ac_ext < #include @@ -14484,7 +14488,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:14488: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14492: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else @@ -14581,13 +14585,13 @@ case "$target_os" in msvc*|mks*|cygwin*|mingw*|wince*) if test -n "$MOZ_UPDATER"; then echo $ac_n "checking for iconv""... $ac_c" 1>&6 -echo "configure:14585: checking for iconv" >&5 +echo "configure:14589: checking for iconv" >&5 for ac_prog in $HOST_ICONV "iconv" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:14591: checking for $ac_word" >&5 +echo "configure:14595: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_HOST_ICONV'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -14853,18 +14857,18 @@ MOZ_DEBUG_DISABLE_DEFS="-DNDEBUG -DTRIMMED" if test -n "$MOZ_DEBUG"; then echo $ac_n "checking for valid debug flags""... $ac_c" 1>&6 -echo "configure:14857: checking for valid debug flags" >&5 +echo "configure:14861: checking for valid debug flags" >&5 _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $MOZ_DEBUG_FLAGS" cat > conftest.$ac_ext < int main() { printf("Hello World\n"); ; return 0; } EOF -if { (eval echo configure:14868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14872: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* _results=yes else @@ -14905,18 +14909,18 @@ fi if test "$COMPILE_ENVIRONMENT"; then if test -n "$MOZ_OPTIMIZE"; then echo $ac_n "checking for valid optimization flags""... $ac_c" 1>&6 -echo "configure:14909: checking for valid optimization flags" >&5 +echo "configure:14913: checking for valid optimization flags" >&5 _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $MOZ_OPTIMIZE_FLAGS" cat > conftest.$ac_ext < int main() { printf("Hello World\n"); ; return 0; } EOF -if { (eval echo configure:14920: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:14924: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* _results=yes else @@ -15133,7 +15137,7 @@ fi if test -n "$_ENABLE_EFENCE"; then echo $ac_n "checking for malloc in -lefence""... $ac_c" 1>&6 -echo "configure:15137: checking for malloc in -lefence" >&5 +echo "configure:15141: checking for malloc in -lefence" >&5 ac_lib_var=`echo efence'_'malloc | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -15141,7 +15145,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lefence $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15160: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -15253,12 +15257,12 @@ cross_compiling=$ac_cv_prog_cxx_cross for ac_func in __builtin_vec_new __builtin_vec_delete __builtin_new __builtin_delete __pure_virtual do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:15257: checking for $ac_func" >&5 +echo "configure:15261: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15292: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -15527,12 +15531,12 @@ cross_compiling=$ac_cv_prog_cxx_cross for ac_func in __cxa_demangle do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:15531: checking for $ac_func" >&5 +echo "configure:15535: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:15566: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -15696,7 +15700,7 @@ if test -z "$SKIP_COMPILER_CHECKS"; then # Compiler Options echo $ac_n "checking for gcc -pipe support""... $ac_c" 1>&6 -echo "configure:15700: checking for gcc -pipe support" >&5 +echo "configure:15704: checking for gcc -pipe support" >&5 if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then echo '#include ' > dummy-hello.c echo 'int main() { printf("Hello World\n"); exit(0); }' >> dummy-hello.c @@ -15711,14 +15715,14 @@ if test -n "$GNU_CC" && test -n "$GNU_CXX" && test -n "$GNU_AS"; then _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -pipe" cat > conftest.$ac_ext < int main() { printf("Hello World\n"); ; return 0; } EOF -if { (eval echo configure:15722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15726: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* _res_gcc_pipe="yes" else @@ -15760,16 +15764,16 @@ if test "$_IGNORE_LONG_LONG_WARNINGS"; then _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS ${_COMPILER_PREFIX}-Wno-long-long" echo $ac_n "checking whether compiler supports -Wno-long-long""... $ac_c" 1>&6 -echo "configure:15764: checking whether compiler supports -Wno-long-long" >&5 +echo "configure:15768: checking whether compiler supports -Wno-long-long" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* _WARNINGS_CFLAGS="${_WARNINGS_CFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-Wno-long-long" @@ -15790,16 +15794,16 @@ _SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -fprofile-generate" echo $ac_n "checking whether C compiler supports -fprofile-generate""... $ac_c" 1>&6 -echo "configure:15794: checking whether C compiler supports -fprofile-generate" >&5 +echo "configure:15798: checking whether C compiler supports -fprofile-generate" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15807: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* PROFILE_GEN_CFLAGS="-fprofile-generate" result="yes" @@ -15817,16 +15821,16 @@ if test $result = "yes"; then else CFLAGS="$_SAVE_CFLAGS -fprofile-arcs" echo $ac_n "checking whether C compiler supports -fprofile-arcs""... $ac_c" 1>&6 -echo "configure:15821: checking whether C compiler supports -fprofile-arcs" >&5 +echo "configure:15825: checking whether C compiler supports -fprofile-arcs" >&5 cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:15834: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* PROFILE_GEN_CFLAGS="-fprofile-arcs" result="yes" @@ -15872,18 +15876,18 @@ if test "$_PEDANTIC"; then _SAVE_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS} ${_COMPILER_PREFIX}-pedantic" echo $ac_n "checking whether C++ compiler has -pedantic long long bug""... $ac_c" 1>&6 -echo "configure:15876: checking whether C++ compiler has -pedantic long long bug" >&5 +echo "configure:15880: checking whether C++ compiler has -pedantic long long bug" >&5 if test "$cross_compiling" = yes; then result="maybe" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:15891: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then result="no" else @@ -15913,12 +15917,12 @@ fi fi echo $ac_n "checking for correct temporary object destruction order""... $ac_c" 1>&6 -echo "configure:15917: checking for correct temporary object destruction order" >&5 +echo "configure:15921: checking for correct temporary object destruction order" >&5 if test "$cross_compiling" = yes; then result="maybe" else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:15946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then result="yes" else @@ -15959,12 +15963,12 @@ fi _SAVE_CXXFLAGS=$CXXFLAGS CXXFLAGS="$CXXFLAGS ${_WARNINGS_CXXFLAGS}" echo $ac_n "checking for correct overload resolution with const and templates""... $ac_c" 1>&6 -echo "configure:15963: checking for correct overload resolution with const and templates" >&5 +echo "configure:15967: checking for correct overload resolution with const and templates" >&5 if eval "test \"`echo '$''{'ac_nscap_nonconst_opeq_bug'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -15994,7 +15998,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:15998: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:16002: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_nscap_nonconst_opeq_bug="no" else @@ -16256,7 +16260,7 @@ then # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:16260: checking for $ac_word" >&5 +echo "configure:16264: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -16300,19 +16304,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for libIDL-2.0 >= 0.8.0""... $ac_c" 1>&6 -echo "configure:16304: checking for libIDL-2.0 >= 0.8.0" >&5 +echo "configure:16308: checking for libIDL-2.0 >= 0.8.0" >&5 if $PKG_CONFIG --exists "libIDL-2.0 >= 0.8.0" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking LIBIDL_CFLAGS""... $ac_c" 1>&6 -echo "configure:16311: checking LIBIDL_CFLAGS" >&5 +echo "configure:16315: checking LIBIDL_CFLAGS" >&5 LIBIDL_CFLAGS=`$PKG_CONFIG --cflags "libIDL-2.0 >= 0.8.0"` echo "$ac_t""$LIBIDL_CFLAGS" 1>&6 echo $ac_n "checking LIBIDL_LIBS""... $ac_c" 1>&6 -echo "configure:16316: checking LIBIDL_LIBS" >&5 +echo "configure:16320: checking LIBIDL_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic LIBIDL_LIBS="`$PKG_CONFIG --libs \"libIDL-2.0 >= 0.8.0\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$LIBIDL_LIBS" 1>&6 @@ -16434,7 +16438,7 @@ fi # Extract the first word of "glib-config", so it can be a program name with args. set dummy glib-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:16438: checking for $ac_word" >&5 +echo "configure:16442: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GLIB_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -16469,7 +16473,7 @@ fi min_glib_version=1.2.0 echo $ac_n "checking for GLIB - version >= $min_glib_version""... $ac_c" 1>&6 -echo "configure:16473: checking for GLIB - version >= $min_glib_version" >&5 +echo "configure:16477: checking for GLIB - version >= $min_glib_version" >&5 no_glib="" if test "$GLIB_CONFIG" = "no" ; then no_glib=yes @@ -16492,7 +16496,7 @@ echo "configure:16473: checking for GLIB - version >= $min_glib_version" >&5 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < @@ -16568,7 +16572,7 @@ main () } EOF -if { (eval echo configure:16572: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:16576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -16602,7 +16606,7 @@ fi CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" cat > conftest.$ac_ext < @@ -16612,7 +16616,7 @@ int main() { return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ; return 0; } EOF -if { (eval echo configure:16616: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding GLIB or finding the wrong" @@ -16656,7 +16660,7 @@ rm -f conftest* # Extract the first word of "libIDL-config", so it can be a program name with args. set dummy libIDL-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:16660: checking for $ac_word" >&5 +echo "configure:16664: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LIBIDL_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -16691,7 +16695,7 @@ fi min_libIDL_version=$LIBIDL_VERSION echo $ac_n "checking for libIDL - version >= $min_libIDL_version""... $ac_c" 1>&6 -echo "configure:16695: checking for libIDL - version >= $min_libIDL_version" >&5 +echo "configure:16699: checking for libIDL - version >= $min_libIDL_version" >&5 no_libIDL="" if test "$LIBIDL_CONFIG" = "no" ; then no_libIDL=yes @@ -16718,7 +16722,7 @@ echo "configure:16695: checking for libIDL - version >= $min_libIDL_version" >&5 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < @@ -16804,7 +16808,7 @@ main () } EOF -if { (eval echo configure:16808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:16812: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -16838,7 +16842,7 @@ fi CFLAGS="$CFLAGS $LIBIDL_CFLAGS" LIBS="$LIBS $LIBIDL_LIBS" cat > conftest.$ac_ext < @@ -16849,7 +16853,7 @@ int main() { return IDL_get_libver_string ? 1 : 0; ; return 0; } EOF -if { (eval echo configure:16853: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:16857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding libIDL or finding the wrong" @@ -16977,7 +16981,7 @@ fi # Extract the first word of "glib-config", so it can be a program name with args. set dummy glib-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:16981: checking for $ac_word" >&5 +echo "configure:16985: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GLIB_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17012,7 +17016,7 @@ fi min_glib_version=1.2.0 echo $ac_n "checking for GLIB - version >= $min_glib_version""... $ac_c" 1>&6 -echo "configure:17016: checking for GLIB - version >= $min_glib_version" >&5 +echo "configure:17020: checking for GLIB - version >= $min_glib_version" >&5 no_glib="" if test "$GLIB_CONFIG" = "no" ; then no_glib=yes @@ -17035,7 +17039,7 @@ echo "configure:17016: checking for GLIB - version >= $min_glib_version" >&5 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < @@ -17111,7 +17115,7 @@ main () } EOF -if { (eval echo configure:17115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:17119: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -17145,7 +17149,7 @@ fi CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" cat > conftest.$ac_ext < @@ -17155,7 +17159,7 @@ int main() { return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ; return 0; } EOF -if { (eval echo configure:17159: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:17163: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding GLIB or finding the wrong" @@ -17199,7 +17203,7 @@ rm -f conftest* # Extract the first word of "libIDL-config", so it can be a program name with args. set dummy libIDL-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:17203: checking for $ac_word" >&5 +echo "configure:17207: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_LIBIDL_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17234,7 +17238,7 @@ fi min_libIDL_version=$LIBIDL_VERSION echo $ac_n "checking for libIDL - version >= $min_libIDL_version""... $ac_c" 1>&6 -echo "configure:17238: checking for libIDL - version >= $min_libIDL_version" >&5 +echo "configure:17242: checking for libIDL - version >= $min_libIDL_version" >&5 no_libIDL="" if test "$LIBIDL_CONFIG" = "no" ; then no_libIDL=yes @@ -17261,7 +17265,7 @@ echo "configure:17238: checking for libIDL - version >= $min_libIDL_version" >&5 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < @@ -17347,7 +17351,7 @@ main () } EOF -if { (eval echo configure:17351: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:17355: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -17381,7 +17385,7 @@ fi CFLAGS="$CFLAGS $LIBIDL_CFLAGS" LIBS="$LIBS $LIBIDL_LIBS" cat > conftest.$ac_ext < @@ -17392,7 +17396,7 @@ int main() { return IDL_get_libver_string ? 1 : 0; ; return 0; } EOF -if { (eval echo configure:17396: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:17400: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding libIDL or finding the wrong" @@ -17432,7 +17436,7 @@ rm -f conftest* # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:17436: checking for $ac_word" >&5 +echo "configure:17440: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17476,19 +17480,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for libIDL-2.0 >= 0.8.0""... $ac_c" 1>&6 -echo "configure:17480: checking for libIDL-2.0 >= 0.8.0" >&5 +echo "configure:17484: checking for libIDL-2.0 >= 0.8.0" >&5 if $PKG_CONFIG --exists "libIDL-2.0 >= 0.8.0" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking LIBIDL_CFLAGS""... $ac_c" 1>&6 -echo "configure:17487: checking LIBIDL_CFLAGS" >&5 +echo "configure:17491: checking LIBIDL_CFLAGS" >&5 LIBIDL_CFLAGS=`$PKG_CONFIG --cflags "libIDL-2.0 >= 0.8.0"` echo "$ac_t""$LIBIDL_CFLAGS" 1>&6 echo $ac_n "checking LIBIDL_LIBS""... $ac_c" 1>&6 -echo "configure:17492: checking LIBIDL_LIBS" >&5 +echo "configure:17496: checking LIBIDL_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic LIBIDL_LIBS="`$PKG_CONFIG --libs \"libIDL-2.0 >= 0.8.0\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$LIBIDL_LIBS" 1>&6 @@ -17523,7 +17527,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:17527: checking for $ac_word" >&5 +echo "configure:17531: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_ORBIT_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17560,7 +17564,7 @@ done if test -n "$ORBIT_CONFIG"; then echo $ac_n "checking for ORBit libIDL usability""... $ac_c" 1>&6 -echo "configure:17564: checking for ORBit libIDL usability" >&5 +echo "configure:17568: checking for ORBit libIDL usability" >&5 _ORBIT_CFLAGS=`${ORBIT_CONFIG} client --cflags` _ORBIT_LIBS=`${ORBIT_CONFIG} client --libs` _ORBIT_INC_PATH=`${PERL} -e '{ for $f (@ARGV) { print "$f " if ($f =~ m/^-I/); } }' -- ${_ORBIT_CFLAGS}` @@ -17577,7 +17581,7 @@ echo "configure:17564: checking for ORBit libIDL usability" >&5 result="maybe" else cat > conftest.$ac_ext < @@ -17592,7 +17596,7 @@ int main() { } EOF -if { (eval echo configure:17596: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:17600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then _LIBIDL_FOUND=1 result="yes" @@ -17645,7 +17649,7 @@ if test -z "${GLIB_CFLAGS}" || test -z "${GLIB_LIBS}" ; then # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:17649: checking for $ac_word" >&5 +echo "configure:17653: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17689,19 +17693,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for glib-2.0 >= 1.3.7""... $ac_c" 1>&6 -echo "configure:17693: checking for glib-2.0 >= 1.3.7" >&5 +echo "configure:17697: checking for glib-2.0 >= 1.3.7" >&5 if $PKG_CONFIG --exists "glib-2.0 >= 1.3.7" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking GLIB_CFLAGS""... $ac_c" 1>&6 -echo "configure:17700: checking GLIB_CFLAGS" >&5 +echo "configure:17704: checking GLIB_CFLAGS" >&5 GLIB_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 1.3.7"` echo "$ac_t""$GLIB_CFLAGS" 1>&6 echo $ac_n "checking GLIB_LIBS""... $ac_c" 1>&6 -echo "configure:17705: checking GLIB_LIBS" >&5 +echo "configure:17709: checking GLIB_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic GLIB_LIBS="`$PKG_CONFIG --libs \"glib-2.0 >= 1.3.7\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$GLIB_LIBS" 1>&6 @@ -17784,7 +17788,7 @@ fi # Extract the first word of "glib-config", so it can be a program name with args. set dummy glib-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:17788: checking for $ac_word" >&5 +echo "configure:17792: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GLIB_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -17819,7 +17823,7 @@ fi min_glib_version=${GLIB_VERSION} echo $ac_n "checking for GLIB - version >= $min_glib_version""... $ac_c" 1>&6 -echo "configure:17823: checking for GLIB - version >= $min_glib_version" >&5 +echo "configure:17827: checking for GLIB - version >= $min_glib_version" >&5 no_glib="" if test "$GLIB_CONFIG" = "no" ; then no_glib=yes @@ -17842,7 +17846,7 @@ echo "configure:17823: checking for GLIB - version >= $min_glib_version" >&5 echo $ac_n "cross compiling; assumed OK... $ac_c" else cat > conftest.$ac_ext < @@ -17918,7 +17922,7 @@ main () } EOF -if { (eval echo configure:17922: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:17926: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -17952,7 +17956,7 @@ fi CFLAGS="$CFLAGS $GLIB_CFLAGS" LIBS="$LIBS $GLIB_LIBS" cat > conftest.$ac_ext < @@ -17962,7 +17966,7 @@ int main() { return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ; return 0; } EOF -if { (eval echo configure:17966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:17970: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "*** The test program compiled, but did not run. This usually means" echo "*** that the run-time linker is not finding GLIB or finding the wrong" @@ -18041,19 +18045,19 @@ mk_add_options MOZ_CO_MODULE=mozilla/other-licenses/libart_lgpl" 1>&2; exit 1; } # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6 -echo "configure:18045: checking for working alloca.h" >&5 +echo "configure:18049: checking for working alloca.h" >&5 if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { char *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:18057: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:18061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_header_alloca_h=yes else @@ -18074,12 +18078,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:18078: checking for alloca" >&5 +echo "configure:18082: checking for alloca" >&5 if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:18115: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_alloca_works=yes else @@ -18139,12 +18143,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:18143: checking whether alloca needs Cray hooks" >&5 +echo "configure:18147: checking whether alloca needs Cray hooks" >&5 if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&6 if test $ac_cv_os_cray = yes; then for ac_func in _getb67 GETB67 getb67; do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:18173: checking for $ac_func" >&5 +echo "configure:18177: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:18205: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -18224,7 +18228,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:18228: checking stack direction for C alloca" >&5 +echo "configure:18232: checking stack direction for C alloca" >&5 if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -18232,7 +18236,7 @@ else ac_cv_c_stack_direction=0 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:18259: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_stack_direction=1 else @@ -18300,17 +18304,17 @@ fi do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:18304: checking for $ac_hdr" >&5 +echo "configure:18308: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:18314: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:18318: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -18414,7 +18418,7 @@ EOF # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:18418: checking for $ac_word" >&5 +echo "configure:18422: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -18458,19 +18462,19 @@ fi PKG_CONFIG_MIN_VERSION=0.9.0 if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then echo $ac_n "checking for cairo >= $CAIRO_VERSION""... $ac_c" 1>&6 -echo "configure:18462: checking for cairo >= $CAIRO_VERSION" >&5 +echo "configure:18466: checking for cairo >= $CAIRO_VERSION" >&5 if $PKG_CONFIG --exists "cairo >= $CAIRO_VERSION" ; then echo "$ac_t""yes" 1>&6 succeeded=yes echo $ac_n "checking CAIRO_CFLAGS""... $ac_c" 1>&6 -echo "configure:18469: checking CAIRO_CFLAGS" >&5 +echo "configure:18473: checking CAIRO_CFLAGS" >&5 CAIRO_CFLAGS=`$PKG_CONFIG --cflags "cairo >= $CAIRO_VERSION"` echo "$ac_t""$CAIRO_CFLAGS" 1>&6 echo $ac_n "checking CAIRO_LIBS""... $ac_c" 1>&6 -echo "configure:18474: checking CAIRO_LIBS" >&5 +echo "configure:18478: checking CAIRO_LIBS" >&5 ## Remove evil flags like -Wl,--export-dynamic CAIRO_LIBS="`$PKG_CONFIG --libs \"cairo >= $CAIRO_VERSION\" |sed s/-Wl,--export-dynamic//g`" echo "$ac_t""$CAIRO_LIBS" 1>&6 @@ -18534,7 +18538,7 @@ if test `echo "$MOZ_EXTENSIONS" | grep -c python/xpcom` -ne 0; then # Extract the first word of "python", so it can be a program name with args. set dummy python; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:18538: checking for $ac_word" >&5 +echo "configure:18542: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PYTHON'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -18794,14 +18798,14 @@ ac_link='${CC-cc} -o conftest${ac_exeext} $CFLAGS $CPPFLAGS $LDFLAGS conftest.$a cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext < int main() { int x = 1; x++; ; return 0; } EOF -if { (eval echo configure:18805: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:18809: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then : else echo "configure: failed program was:" >&5 @@ -19096,7 +19100,7 @@ if test "$MOZ_X11"; then _SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $XCFLAGS" cat > conftest.$ac_ext < @@ -19112,7 +19116,7 @@ int main() { ; return 0; } EOF -if { (eval echo configure:19116: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:19120: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then : else echo "configure: failed program was:" >&5 diff --git a/configure.in b/configure.in index db2de3f38fd..38953c9af20 100644 --- a/configure.in +++ b/configure.in @@ -3932,6 +3932,7 @@ AC_SUBST(MOC) if test "$MOZ_ENABLE_CAIRO_GFX" then AC_DEFINE(MOZ_THEBES) + AC_DEFINE(MOZ_CAIRO_GFX) fi if test "$MOZ_ENABLE_GTK" \ diff --git a/gfx/cairo/README b/gfx/cairo/README index a790f7f34c2..4468a56d043 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -1,4 +1,4 @@ -Snapshots of cairo, libpixman, and glitz for mozilla usage. Where possible, +Snapshots of cairo and glitz for mozilla usage. Where possible, these should be official releases from the cairo project as-is. If changes are necessary, they should be documented below and the patch file included in this directory. @@ -10,29 +10,10 @@ http://www.cairographics.org/. VERSIONS: - cairo 0.9.1 - libpixman 0.1.5 - glitz 0.4.0 + cairo 1.1.1 (cvs) + glitz 0.5.0 ***** NOTE FOR VISUAL C++ 6.0 ***** -VC6 cannot build pixman correctly for various reasons. There is a static -win32 pixman library provided in libpixman/src/pixman-vc71.lib that will -be used instead of building on all Win32/Visual C++ builds. Building with -VC7.1, gcc/mingw, or anything else other than VC6 is fine. - -PATCHES: - - stdint.h - select between inttypes.h, stdint.h, and mozstdint.h. - - dash-dos.diff - prevent DOS attack with dasharray. - - alphablend.diff - check for AlphaBlend usability at runtime (win32) - - feature-tests.diff - change #if to #ifdef, and change - cairo-features.h.in to #define things based on mozilla configure - tests - - allow-null-surface.diff - allow creating a cairo_t with a NULL - target surface - atsui-empty.diff - prevent OS-X crash with empty string +VC6 cannot build pixman from cairo. Therefore, VC6 builds are not supported +if cairo is enabled. Please upgrade to VC7.1/8. diff --git a/gfx/cairo/cairo/src/Makefile.in b/gfx/cairo/cairo/src/Makefile.in index 2a30b29e3e2..6f1e2b956d9 100644 --- a/gfx/cairo/cairo/src/Makefile.in +++ b/gfx/cairo/cairo/src/Makefile.in @@ -43,6 +43,8 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk +VISIBILITY_FLAGS = + MODULE = cairo LIBRARY_NAME = mozcairo LIBXUL_LIBRARY = 1 @@ -79,6 +81,7 @@ CSRCS = \ cairo-pen.c \ cairo-polygon.c \ cairo-region.c \ + cairo-scaled-font.c \ cairo-slope.c \ cairo-spline.c \ cairo-surface.c \ @@ -87,7 +90,7 @@ CSRCS = \ cairo-wideint.c \ $(NULL) -EXPORTS = cairo.h cairo-features.h +EXPORTS = cairo.h cairo-features.h cairo-platform.h ifeq ($(MOZ_GFX_TOOLKIT),windows) diff --git a/gfx/cairo/cairo/src/cairo-arc.c b/gfx/cairo/cairo/src/cairo-arc.c index e9f35993e45..4b767f17657 100644 --- a/gfx/cairo/cairo/src/cairo-arc.c +++ b/gfx/cairo/cairo/src/cairo-arc.c @@ -100,27 +100,19 @@ _arc_max_angle_for_tolerance_normalized (double tolerance) return angle; } -/* XXX: The computation here if bogus. Correct math (with proof!) is - * available in _cairo_pen_vertices_needed. */ static int _arc_segments_needed (double angle, double radius, cairo_matrix_t *ctm, double tolerance) { - double l1, l2, lmax; - double max_angle; + double major_axis, max_angle; - _cairo_matrix_compute_eigen_values (ctm, &l1, &l2); - - l1 = fabs (l1); - l2 = fabs (l2); - if (l1 > l2) - lmax = l1; - else - lmax = l2; - - max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / (radius * lmax)); + /* the error is amplified by at most the length of the + * major axis of the circle; see cairo-pen.c for a more detailed analysis + * of this. */ + major_axis = _cairo_matrix_transformed_circle_major_axis (ctm, radius); + max_angle = _arc_max_angle_for_tolerance_normalized (tolerance / major_axis); return (int) ceil (angle / max_angle); } diff --git a/gfx/cairo/cairo/src/cairo-atsui-font.c b/gfx/cairo/cairo/src/cairo-atsui-font.c index 84b7ea19ab6..4c42ed67bee 100644 --- a/gfx/cairo/cairo/src/cairo-atsui-font.c +++ b/gfx/cairo/cairo/src/cairo-atsui-font.c @@ -38,35 +38,85 @@ #include "cairo-atsui.h" #include "cairoint.h" #include "cairo.h" -#if 0 -#include -#endif -/* - * FixedToFloat/FloatToFixed are 10.3+ SDK items - include definitions - * here so we can use older SDKs. - */ -#ifndef FixedToFloat -#define fixed1 ((Fixed) 0x00010000L) -#define FixedToFloat(a) ((float)(a) / fixed1) -#define FloatToFixed(a) ((Fixed)((float)(a) * fixed1)) -#endif +typedef struct _cairo_atsui_font_face cairo_atsui_font_face_t; +typedef struct _cairo_atsui_font cairo_atsui_font_t; -typedef struct { +static cairo_status_t _cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, + ATSUFontID font_id, + ATSUStyle style, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **font_out); + +struct _cairo_atsui_font { cairo_scaled_font_t base; cairo_matrix_t scale; ATSUStyle style; ATSUStyle unscaled_style; ATSUFontID fontID; -} cairo_atsui_font_t; +}; + + +struct _cairo_atsui_font_face { + cairo_font_face_t base; + ATSUFontID font_id; +}; + +static void +_cairo_atsui_font_face_destroy (void *abstract_face) +{ +} + +static cairo_status_t +_cairo_atsui_font_face_scaled_font_create (void *abstract_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **font) +{ + cairo_atsui_font_face_t *font_face = abstract_face; + OSStatus err; + ATSUAttributeTag styleTags[] = { kATSUFontTag }; + ATSUAttributeValuePtr styleValues[] = { &font_face->font_id }; + ByteCount styleSizes[] = { sizeof(ATSUFontID) }; + ATSUStyle style; + + err = ATSUCreateStyle (&style); + err = ATSUSetAttributes(style, + sizeof(styleTags) / sizeof(styleTags[0]), + styleTags, styleSizes, styleValues); + + return _cairo_atsui_font_create_scaled (&font_face->base, font_face->font_id, style, + font_matrix, ctm, options, font); +} + +static const cairo_font_face_backend_t _cairo_atsui_font_face_backend = { + _cairo_atsui_font_face_destroy, + _cairo_atsui_font_face_scaled_font_create +}; + +cairo_public cairo_font_face_t * +cairo_atsui_font_face_create_for_atsu_font_id (ATSUFontID font_id) +{ + cairo_atsui_font_face_t *font_face; + + font_face = malloc (sizeof (cairo_atsui_font_face_t)); + if (!font_face) { + _cairo_error (CAIRO_STATUS_NO_MEMORY); + return (cairo_font_face_t *)&_cairo_font_face_nil; + } + + font_face->font_id = font_id; + + _cairo_font_face_init (&font_face->base, &_cairo_atsui_font_face_backend); + + return &font_face->base; +} -typedef struct cairo_ATSUI_glyph_path_callback_info_t { - cairo_path_fixed_t *path; - cairo_matrix_t scale; -} cairo_ATSUI_glyph_path_callback_info_t; -const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend; static CGAffineTransform CGAffineTransformMakeWithCairoFontScale(cairo_matrix_t *scale) @@ -82,7 +132,6 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale) ATSUStyle style; OSStatus err; - // Set the style's size CGAffineTransform theTransform = CGAffineTransformMakeWithCairoFontScale(scale); @@ -103,6 +152,86 @@ CreateSizedCopyOfStyle(ATSUStyle inStyle, cairo_matrix_t *scale) return style; } +static cairo_status_t +_cairo_atsui_font_set_metrics (cairo_atsui_font_t *font) +{ + ATSFontRef atsFont; + ATSFontMetrics metrics; + OSStatus err; + + atsFont = FMGetATSFontRefFromFont(font->fontID); + + if (atsFont) { + err = + ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault, + &metrics); + + if (err == noErr) { + cairo_font_extents_t extents; + + extents.ascent = metrics.ascent; + extents.descent = metrics.descent; + extents.height = metrics.capHeight; + extents.max_x_advance = metrics.maxAdvanceWidth; + + // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. + extents.max_y_advance = 0.0; + + _cairo_scaled_font_set_metrics (&font->base, &extents); + + return CAIRO_STATUS_SUCCESS; + } + } + + return CAIRO_STATUS_NULL_POINTER; +} + +static cairo_status_t +_cairo_atsui_font_create_scaled (cairo_font_face_t *font_face, + ATSUFontID font_id, + ATSUStyle style, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + cairo_scaled_font_t **font_out) +{ + cairo_atsui_font_t *font = NULL; + cairo_matrix_t scale; + OSStatus err; + cairo_status_t status; + + font = malloc(sizeof(cairo_atsui_font_t)); + + _cairo_scaled_font_init(&font->base, font_face, font_matrix, ctm, options, + &cairo_atsui_scaled_font_backend); + + cairo_matrix_multiply(&scale, font_matrix, ctm); + font->style = CreateSizedCopyOfStyle(style, &scale); + + Fixed theSize = FloatToFixed(1.0); + const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; + const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; + ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; + err = ATSUSetAttributes(style, + sizeof(theFontStyleTags) / + sizeof(ATSUAttributeTag), theFontStyleTags, + theFontStyleSizes, theFontStyleValues); + + font->unscaled_style = style; + + font->fontID = font_id; + font->scale = scale; + + *font_out = &font->base; + + status = _cairo_atsui_font_set_metrics (font); + if (status) { + cairo_scaled_font_destroy (&font->base); + return status; + } + + return CAIRO_STATUS_SUCCESS; +} static cairo_status_t _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, @@ -111,12 +240,10 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, const cairo_font_options_t *options, cairo_scaled_font_t **font_out) { - cairo_atsui_font_t *font = NULL; ATSUStyle style; ATSUFontID fontID; OSStatus err; Boolean isItalic, isBold; - cairo_matrix_t scale; const char *family = toy_face->family; err = ATSUCreateStyle(&style); @@ -173,43 +300,19 @@ _cairo_atsui_font_create_toy(cairo_toy_font_face_t *toy_face, kFontNoLanguageCode, &fontID); } - ATSUAttributeTag styleTags[] = { kATSUQDItalicTag, kATSUQDBoldfaceTag, kATSUFontTag }; ATSUAttributeValuePtr styleValues[] = { &isItalic, &isBold, &fontID }; ByteCount styleSizes[] = { sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID) }; - err = ATSUSetAttributes(style, sizeof(styleTags) / sizeof(styleTags[0]), styleTags, styleSizes, styleValues); - font = malloc(sizeof(cairo_atsui_font_t)); - _cairo_scaled_font_init(&font->base, toy_face, font_matrix, ctm, options, - &cairo_atsui_scaled_font_backend); - - cairo_matrix_multiply(&scale, font_matrix, ctm); - font->style = CreateSizedCopyOfStyle(style, &scale); - - Fixed theSize = FloatToFixed(1.0); - const ATSUAttributeTag theFontStyleTags[] = { kATSUSizeTag }; - const ByteCount theFontStyleSizes[] = { sizeof(Fixed) }; - ATSUAttributeValuePtr theFontStyleValues[] = { &theSize }; - err = ATSUSetAttributes(style, - sizeof(theFontStyleTags) / - sizeof(ATSUAttributeTag), theFontStyleTags, - theFontStyleSizes, theFontStyleValues); - - font->unscaled_style = style; - - font->fontID = fontID; - font->scale = scale; - - *font_out = &font->base; - - return CAIRO_STATUS_SUCCESS; + return _cairo_atsui_font_create_scaled (&toy_face->base, fontID, style, + font_matrix, ctm, options, font_out); } static void @@ -226,235 +329,230 @@ _cairo_atsui_font_fini(void *abstract_font) ATSUDisposeStyle(font->unscaled_style); } - -static void -_cairo_atsui_font_get_glyph_cache_key(void *abstract_font, - cairo_glyph_cache_key_t *key) +static cairo_status_t +_cairo_atsui_font_init_glyph_metrics (cairo_atsui_font_t *font, + cairo_scaled_glyph_t *scaled_glyph) { + cairo_text_extents_t extents; + OSStatus err; + GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph); + ATSGlyphIdealMetrics metricsH, metricsV; + ATSUStyle style; + ATSUVerticalCharacterType verticalType = kATSUStronglyVertical; + const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag }; + const ByteCount theSizes[] = { sizeof(verticalType) }; + ATSUAttributeValuePtr theValues[] = { &verticalType }; + + ATSUCreateAndCopyStyle(font->unscaled_style, &style); + + err = ATSUGlyphGetIdealMetrics(style, + 1, &theGlyph, 0, &metricsH); + err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues); + err = ATSUGlyphGetIdealMetrics(style, + 1, &theGlyph, 0, &metricsV); + + extents.x_bearing = metricsH.sideBearing.x; + extents.y_bearing = metricsV.advance.y; + extents.width = + metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x; + extents.height = + -metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y; + extents.x_advance = metricsH.advance.x; + extents.y_advance = 0; + + _cairo_scaled_glyph_set_metrics (scaled_glyph, + &font->base, + &extents); + + return CAIRO_STATUS_SUCCESS; } +static OSStatus +_move_to (const Float32Point *point, + void *callback_data) +{ + cairo_path_fixed_t *path = callback_data; + + _cairo_path_fixed_close_path (path); + _cairo_path_fixed_move_to (path, + _cairo_fixed_from_double(point->x), + _cairo_fixed_from_double(point->y)); + + return noErr; +} + +static OSStatus +_line_to (const Float32Point *point, + void *callback_data) +{ + cairo_path_fixed_t *path = callback_data; + + _cairo_path_fixed_line_to (path, + _cairo_fixed_from_double(point->x), + _cairo_fixed_from_double(point->y)); + + return noErr; +} + +static OSStatus +_curve_to (const Float32Point *point1, + const Float32Point *point2, + const Float32Point *point3, + void *callback_data) +{ + cairo_path_fixed_t *path = callback_data; + + _cairo_path_fixed_curve_to (path, + _cairo_fixed_from_double(point1->x), + _cairo_fixed_from_double(point1->y), + _cairo_fixed_from_double(point2->x), + _cairo_fixed_from_double(point2->y), + _cairo_fixed_from_double(point3->x), + _cairo_fixed_from_double(point3->y)); + + return noErr; +} + +static OSStatus +_close_path (void *callback_data) + +{ + cairo_path_fixed_t *path = callback_data; + + _cairo_path_fixed_close_path (path); + + return noErr; +} + +static cairo_status_t +_cairo_atsui_scaled_font_init_glyph_path (cairo_atsui_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) +{ + static ATSCubicMoveToUPP moveProc = NULL; + static ATSCubicLineToUPP lineProc = NULL; + static ATSCubicCurveToUPP curveProc = NULL; + static ATSCubicClosePathUPP closePathProc = NULL; + OSStatus err; + cairo_path_fixed_t *path; + + path = _cairo_path_fixed_create (); + if (!path) + return CAIRO_STATUS_NO_MEMORY; + + if (moveProc == NULL) { + moveProc = NewATSCubicMoveToUPP(_move_to); + lineProc = NewATSCubicLineToUPP(_line_to); + curveProc = NewATSCubicCurveToUPP(_curve_to); + closePathProc = NewATSCubicClosePathUPP(_close_path); + } + + err = ATSUGlyphGetCubicPaths(scaled_font->style, + _cairo_scaled_glyph_index (scaled_glyph), + moveProc, + lineProc, + curveProc, + closePathProc, (void *)path, &err); + + _cairo_scaled_glyph_set_path (scaled_glyph, &scaled_font->base, path); + + return CAIRO_STATUS_SUCCESS; +} static cairo_status_t -_cairo_atsui_font_text_to_glyphs(void *abstract_font, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) +_cairo_atsui_font_scaled_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info) { - cairo_atsui_font_t *font = abstract_font; - size_t i; + cairo_atsui_font_t *scaled_font = abstract_font; + cairo_status_t status; + + if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { + status = _cairo_atsui_font_init_glyph_metrics (scaled_font, scaled_glyph); + if (status) + return status; + } + + if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { + status = _cairo_atsui_scaled_font_init_glyph_path (scaled_font, scaled_glyph); + if (status) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t +_cairo_atsui_font_text_to_glyphs (void *abstract_font, + double x, + double y, + const char *utf8, + cairo_glyph_t **glyphs, + int *num_glyphs) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + uint16_t *utf16; + int n16; OSStatus err; ATSUTextLayout textLayout; ATSLayoutRecord *layoutRecords; - ItemCount glyphCount, charCount; - UniChar *theText; + cairo_atsui_font_t *font = abstract_font; + ItemCount glyphCount; + int i; - // liberal estimate of size - charCount = strlen(utf8); - - if (charCount == 0) { - *glyphs = NULL; - *num_glyphs = 0; - return CAIRO_STATUS_SUCCESS; - } - - // Set the text in the text layout object, so we can measure it - theText = (UniChar *) malloc(charCount * sizeof(UniChar)); - -#if 1 - for (i = 0; i < charCount; i++) { - theText[i] = utf8[i]; - } -#endif - -#if 0 - size_t inBytes = charCount, outBytes = charCount; - iconv_t converter = iconv_open("UTF-8", "UTF-16"); - charCount = iconv(converter, utf8, &inBytes, theText, &outBytes); -#endif + status = _cairo_utf8_to_utf16 ((unsigned char *)utf8, -1, &utf16, &n16); + if (status) + return status; err = ATSUCreateTextLayout(&textLayout); - err = ATSUSetTextPointerLocation(textLayout, - theText, 0, charCount, charCount); - + err = ATSUSetTextPointerLocation(textLayout, utf16, 0, n16, n16); // Set the style for all of the text err = ATSUSetRunStyle(textLayout, - font->unscaled_style, kATSUFromTextBeginning, kATSUToTextEnd); + font->style, kATSUFromTextBeginning, kATSUToTextEnd); - // Get the glyphs from the text layout object err = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, - 0, - kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - (void *) - &layoutRecords, - &glyphCount); + 0, + kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, + (void *)&layoutRecords, + &glyphCount); *num_glyphs = glyphCount - 1; - - - *glyphs = - (cairo_glyph_t *) malloc(*num_glyphs * (sizeof(cairo_glyph_t))); + *glyphs = + (cairo_glyph_t *) malloc(*num_glyphs * (sizeof (cairo_glyph_t))); if (*glyphs == NULL) { - return CAIRO_STATUS_NO_MEMORY; + return CAIRO_STATUS_NO_MEMORY; } for (i = 0; i < *num_glyphs; i++) { - (*glyphs)[i].index = layoutRecords[i].glyphID; - (*glyphs)[i].x = FixedToFloat(layoutRecords[i].realPos); - (*glyphs)[i].y = 0; + (*glyphs)[i].index = layoutRecords[i].glyphID; + (*glyphs)[i].x = x + FixedToFloat(layoutRecords[i].realPos); + (*glyphs)[i].y = y; } + free (utf16); - free(theText); - - ATSUDirectReleaseLayoutDataArrayPtr(NULL, - kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - (void *) &layoutRecords); - + ATSUDirectReleaseLayoutDataArrayPtr(NULL, + kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, + (void *) &layoutRecords); ATSUDisposeTextLayout(textLayout); - - return CAIRO_STATUS_SUCCESS; -} - - -static cairo_status_t -_cairo_atsui_font_font_extents(void *abstract_font, - cairo_font_extents_t * extents) -{ - cairo_atsui_font_t *font = abstract_font; - ATSFontRef atsFont; - ATSFontMetrics metrics; - OSStatus err; - - // TODO - test this - - atsFont = FMGetATSFontRefFromFont(font->fontID); - - if (atsFont) { - err = - ATSFontGetHorizontalMetrics(atsFont, kATSOptionFlagsDefault, - &metrics); - - if (err == noErr) { - extents->ascent = metrics.ascent; - extents->descent = metrics.descent; - extents->height = metrics.capHeight; - extents->max_x_advance = metrics.maxAdvanceWidth; - - // The FT backend doesn't handle max_y_advance either, so we'll ignore it for now. - extents->max_y_advance = 0.0; - - return CAIRO_STATUS_SUCCESS; - } - } - - - return CAIRO_STATUS_NULL_POINTER; -} - - -static cairo_status_t -_cairo_atsui_font_glyph_extents(void *abstract_font, - cairo_glyph_t * glyphs, - int num_glyphs, - cairo_text_extents_t * extents) -{ - cairo_atsui_font_t *font = abstract_font; - OSStatus err; - - assert(num_glyphs == 1); - - GlyphID theGlyph = glyphs[0].index; - - ATSGlyphIdealMetrics metricsH, metricsV; - ATSUStyle style; - - ATSUCreateAndCopyStyle(font->unscaled_style, &style); - - err = ATSUGlyphGetIdealMetrics(style, - 1, &theGlyph, 0, &metricsH); - - ATSUVerticalCharacterType verticalType = kATSUStronglyVertical; - const ATSUAttributeTag theTag[] = { kATSUVerticalCharacterTag }; - const ByteCount theSizes[] = { sizeof(verticalType) }; - ATSUAttributeValuePtr theValues[] = { &verticalType }; - err = ATSUSetAttributes(style, 1, theTag, theSizes, theValues); - - err = ATSUGlyphGetIdealMetrics(style, - 1, &theGlyph, 0, &metricsV); - - extents->x_bearing = metricsH.sideBearing.x; - extents->y_bearing = metricsV.advance.y; - extents->width = - metricsH.advance.x - metricsH.sideBearing.x - metricsH.otherSideBearing.x; - extents->height = - -metricsV.advance.y - metricsV.sideBearing.y - metricsV.otherSideBearing.y; - extents->x_advance = metricsH.advance.x; - extents->y_advance = 0; - - ATSUDisposeStyle(style); - return CAIRO_STATUS_SUCCESS; } - -static cairo_status_t -_cairo_atsui_font_glyph_bbox(void *abstract_font, - const cairo_glyph_t *glyphs, - int num_glyphs, cairo_box_t *bbox) -{ - cairo_atsui_font_t *font = abstract_font; - cairo_fixed_t x1, y1, x2, y2; - int i; - - bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16; - bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16; - - - for (i = 0; i < num_glyphs; i++) { - GlyphID theGlyph = glyphs[i].index; - - ATSGlyphScreenMetrics metrics; - ATSUGlyphGetScreenMetrics(font->style, - 1, &theGlyph, 0, true, true, &metrics); - - x1 = _cairo_fixed_from_double(glyphs[i].x + metrics.topLeft.x); - y1 = _cairo_fixed_from_double(glyphs[i].y - metrics.topLeft.y); - x2 = x1 + _cairo_fixed_from_double(metrics.height); - y2 = y1 + _cairo_fixed_from_double(metrics.width); - - if (x1 < bbox->p1.x) - bbox->p1.x = x1; - - if (y1 < bbox->p1.y) - bbox->p1.y = y1; - - if (x2 > bbox->p2.x) - bbox->p2.x = x2; - - if (y2 > bbox->p2.y) - bbox->p2.y = y2; - } - - return CAIRO_STATUS_SUCCESS; -} - - -static cairo_status_t -_cairo_atsui_font_show_glyphs(void *abstract_font, - cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *generic_surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - const cairo_glyph_t *glyphs, - int num_glyphs) +static cairo_int_status_t +_cairo_atsui_font_show_glyphs (void *abstract_font, + cairo_operator_t operator, + cairo_pattern_t *pattern, + cairo_surface_t *generic_surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + const cairo_glyph_t *glyphs, + int num_glyphs) { cairo_atsui_font_t *font = abstract_font; CGContextRef myBitmapContext; @@ -517,7 +615,7 @@ _cairo_atsui_font_show_glyphs(void *abstract_font, for (i = 0; i < num_glyphs; i++) { CGGlyph theGlyph = glyphs[i].index; - + CGContextShowGlyphsAtPoint(myBitmapContext, glyphs[i].x, glyphs[i].y, @@ -537,166 +635,12 @@ _cairo_atsui_font_show_glyphs(void *abstract_font, return CAIRO_STATUS_SUCCESS; } - -static OSStatus MyATSCubicMoveToCallback(const Float32Point * pt, - void *callBackDataPtr) -{ - cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr; - double scaledPt[2]; - cairo_fixed_t x, y; - - scaledPt[0] = pt->x; - scaledPt[1] = pt->y; - - cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]); - - x = _cairo_fixed_from_double(scaledPt[0]); - y = _cairo_fixed_from_double(scaledPt[1]); - - _cairo_path_fixed_close_path(info->path); - _cairo_path_fixed_move_to(info->path, x, y); - - return noErr; -} - - -static OSStatus MyATSCubicLineToCallback(const Float32Point * pt, - void *callBackDataPtr) -{ - cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr; - double scaledPt[2]; - cairo_fixed_t x, y; - - scaledPt[0] = pt->x; - scaledPt[1] = pt->y; - - cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]); - - x = _cairo_fixed_from_double(scaledPt[0]); - y = _cairo_fixed_from_double(scaledPt[1]); - - _cairo_path_fixed_line_to(info->path, x, y); - - - return noErr; -} - - -static OSStatus MyATSCubicCurveToCallback(const Float32Point * pt1, - const Float32Point * pt2, - const Float32Point * pt3, - void *callBackDataPtr) -{ - cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr; - double scaledPt[2]; - cairo_fixed_t x0, y0; - cairo_fixed_t x1, y1; - cairo_fixed_t x2, y2; - - - scaledPt[0] = pt1->x; - scaledPt[1] = pt1->y; - - cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]); - - x0 = _cairo_fixed_from_double(scaledPt[0]); - y0 = _cairo_fixed_from_double(scaledPt[1]); - - - scaledPt[0] = pt2->x; - scaledPt[1] = pt2->y; - - cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]); - - x1 = _cairo_fixed_from_double(scaledPt[0]); - y1 = _cairo_fixed_from_double(scaledPt[1]); - - - scaledPt[0] = pt3->x; - scaledPt[1] = pt3->y; - - cairo_matrix_transform_point(&info->scale, &scaledPt[0], &scaledPt[1]); - - x2 = _cairo_fixed_from_double(scaledPt[0]); - y2 = _cairo_fixed_from_double(scaledPt[1]); - - - _cairo_path_fixed_curve_to(info->path, x0, y0, x1, y1, x2, y2); - - - return noErr; -} - - -static OSStatus MyCubicClosePathProc(void *callBackDataPtr) -{ - cairo_ATSUI_glyph_path_callback_info_t *info = callBackDataPtr; - - - _cairo_path_fixed_close_path(info->path); - - - return noErr; -} - - -static cairo_status_t -_cairo_atsui_font_glyph_path(void *abstract_font, - cairo_glyph_t *glyphs, int num_glyphs, - cairo_path_fixed_t *path) -{ - int i; - cairo_atsui_font_t *font = abstract_font; - OSStatus err; - cairo_ATSUI_glyph_path_callback_info_t info; - - - static ATSCubicMoveToUPP moveProc = NULL; - static ATSCubicLineToUPP lineProc = NULL; - static ATSCubicCurveToUPP curveProc = NULL; - static ATSCubicClosePathUPP closePathProc = NULL; - - - if (moveProc == NULL) { - moveProc = NewATSCubicMoveToUPP(MyATSCubicMoveToCallback); - lineProc = NewATSCubicLineToUPP(MyATSCubicLineToCallback); - curveProc = NewATSCubicCurveToUPP(MyATSCubicCurveToCallback); - closePathProc = NewATSCubicClosePathUPP(MyCubicClosePathProc); - } - - - info.path = path; - - - for (i = 0; i < num_glyphs; i++) { - GlyphID theGlyph = glyphs[i].index; - - - cairo_matrix_init(&info.scale, - 1.0, 0.0, - 0.0, 1.0, glyphs[i].x, glyphs[i].y); - - - err = ATSUGlyphGetCubicPaths(font->style, - theGlyph, - moveProc, - lineProc, - curveProc, - closePathProc, (void *) &info, &err); - } - - return CAIRO_STATUS_SUCCESS; -} - const cairo_scaled_font_backend_t cairo_atsui_scaled_font_backend = { _cairo_atsui_font_create_toy, _cairo_atsui_font_fini, - _cairo_atsui_font_font_extents, + _cairo_atsui_font_scaled_glyph_init, _cairo_atsui_font_text_to_glyphs, - _cairo_atsui_font_glyph_extents, - _cairo_atsui_font_glyph_bbox, + NULL, /* ucs4_to_index */ _cairo_atsui_font_show_glyphs, - _cairo_atsui_font_glyph_path, - _cairo_atsui_font_get_glyph_cache_key, }; diff --git a/gfx/cairo/cairo/src/cairo-atsui.h b/gfx/cairo/cairo/src/cairo-atsui.h index 72e2d6d15e1..e69de29bb2d 100644 --- a/gfx/cairo/cairo/src/cairo-atsui.h +++ b/gfx/cairo/cairo/src/cairo-atsui.h @@ -1,55 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2004 Calum Robinson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Calum Robinson - * - * Contributor(s): - * Calum Robinson - */ - -#ifndef CAIRO_ATSUI_H -#define CAIRO_ATSUI_H - -#include - -#if CAIRO_HAS_ATSUI_FONT - -/* ATSUI platform-specific font interface */ - -#include - -CAIRO_BEGIN_DECLS - -CAIRO_END_DECLS - -#else /* CAIRO_HAS_ATSUI_FONT */ -# error Cairo was not compiled with support for the atsui font backend -#endif /* CAIRO_HAS_ATSUI_FONT */ - -#endif /* CAIRO_ATSUI_H */ diff --git a/gfx/cairo/cairo/src/cairo-cache-private.h b/gfx/cairo/cairo/src/cairo-cache-private.h new file mode 100644 index 00000000000..a75e8c0be24 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-cache-private.h @@ -0,0 +1,125 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2004 Red Hat, Inc. + * Copyright © 2005 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Keith Packard + * Graydon Hoare + * Carl Worth + */ + +#ifndef CAIRO_CACHE_PRIVATE_H +#define CAIRO_CACHE_PRIVATE_H + +typedef struct _cairo_cache cairo_cache_t; + +/** + * cairo_cache_entry_t: + * + * A #cairo_cache_entry_t contains both a key and a value for + * cairo_cache_t. User-derived types for cairo_cache_entry_t must + * have a cairo_cache_entry_t as their first field. For example: + * + * typedef _my_entry { + * cairo_cache_entry_t base; + * ... Remainder of key and value fields here .. + * } my_entry_t; + * + * which then allows a pointer to my_entry_t to be passed to any of + * the cairo_cache functions as follows without requiring a cast: + * + * _cairo_cache_insert (cache, &my_entry->base, size); + * + * IMPORTANT: The caller is responsible for initializing + * my_entry->base.hash with a hash code derived from the key. The + * essential property of the hash code is that keys_equal must never + * return %TRUE for two keys that have different hashes. The best hash + * code will reduce the frequency of two keys with the same code for + * which keys_equal returns %FALSE. + * + * The user must also initialize my_entry->base.size to indicate + * the size of the current entry. What units to use for size is + * entirely up to the caller, (though the same units must be used for + * the max_size parameter passed to _cairo_cache_create()). If all + * entries are close to the same size, the simplest thing to do is to + * just use units of "entries", (eg. set size==1 in all entries and + * set max_size to the number of entries which you want to be saved + * in the cache). + * + * Which parts of the entry make up the "key" and which part make up + * the value are entirely up to the caller, (as determined by the + * computation going into base.hash as well as the keys_equal + * function). A few of the cairo_cache functions accept an entry which + * will be used exclusively as a "key", (indicated by a parameter name + * of key). In these cases, the value-related fields of the entry need + * not be initialized if so desired. + **/ +typedef struct _cairo_cache_entry { + unsigned long hash; + unsigned long size; +} cairo_cache_entry_t; + +typedef cairo_bool_t +(*cairo_cache_keys_equal_func_t) (void *key_a, void *key_b); + +typedef void +(*cairo_cache_callback_func_t) (void *entry, + void *closure); + +cairo_private cairo_cache_t * +_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, + cairo_destroy_func_t entry_destroy, + unsigned long max_size); + +cairo_private void +_cairo_cache_destroy (cairo_cache_t *cache); + +cairo_private void +_cairo_cache_freeze (cairo_cache_t *cache); + +cairo_private void +_cairo_cache_thaw (cairo_cache_t *cache); + +cairo_private cairo_bool_t +_cairo_cache_lookup (cairo_cache_t *cache, + cairo_cache_entry_t *key, + cairo_cache_entry_t **entry_return); + +cairo_private cairo_status_t +_cairo_cache_insert (cairo_cache_t *cache, + cairo_cache_entry_t *entry); + +cairo_private void +_cairo_cache_foreach (cairo_cache_t *cache, + cairo_cache_callback_func_t cache_callback, + void *closure); + +#endif diff --git a/gfx/cairo/cairo/src/cairo-cache.c b/gfx/cairo/cairo/src/cairo-cache.c index b43bccabfff..1bd850fd1f0 100644 --- a/gfx/cairo/cairo/src/cairo-cache.c +++ b/gfx/cairo/cairo/src/cairo-cache.c @@ -1,6 +1,7 @@ /* cairo - a vector graphics library with display and print output * - * This file is Copyright © 2004 Red Hat, Inc. + * Copyright © 2004 Red Hat, Inc. + * Copyright © 2005 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -30,481 +31,343 @@ * The Initial Developer of the Original Code is Red Hat, Inc. * * Contributor(s): - * Keith Packard + * Keith Packard * Graydon Hoare + * Carl Worth */ #include "cairoint.h" -/* - * This structure, and accompanying table, is borrowed/modified from the - * file xserver/render/glyph.c in the freedesktop.org x server, with - * permission (and suggested modification of doubling sizes) by Keith - * Packard. - */ +struct _cairo_cache { + cairo_hash_table_t *hash_table; -static const cairo_cache_arrangement_t cache_arrangements [] = { - { 16, 43, 41 }, - { 32, 73, 71 }, - { 64, 151, 149 }, - { 128, 283, 281 }, - { 256, 571, 569 }, - { 512, 1153, 1151 }, - { 1024, 2269, 2267 }, - { 2048, 4519, 4517 }, - { 4096, 9013, 9011 }, - { 8192, 18043, 18041 }, - { 16384, 36109, 36107 }, - { 32768, 72091, 72089 }, - { 65536, 144409, 144407 }, - { 131072, 288361, 288359 }, - { 262144, 576883, 576881 }, - { 524288, 1153459, 1153457 }, - { 1048576, 2307163, 2307161 }, - { 2097152, 4613893, 4613891 }, - { 4194304, 9227641, 9227639 }, - { 8388608, 18455029, 18455027 }, - { 16777216, 36911011, 36911009 }, - { 33554432, 73819861, 73819859 }, - { 67108864, 147639589, 147639587 }, - { 134217728, 295279081, 295279079 }, - { 268435456, 590559793, 590559791 } + cairo_destroy_func_t entry_destroy; + + unsigned long max_size; + unsigned long size; + + int freeze_count; }; -#define N_CACHE_SIZES (sizeof(cache_arrangements)/sizeof(cache_arrangements[0])) - -/* - * Entries 'e' are poiners, in one of 3 states: - * - * e == NULL: The entry has never had anything put in it - * e != DEAD_ENTRY: The entry has an active value in it currently - * e == DEAD_ENTRY: The entry *had* a value in it at some point, but the - * entry has been killed. Lookups requesting free space can - * reuse these entries; lookups requesting a precise match - * should neither return these entries nor stop searching when - * seeing these entries. - * - * We expect keys will not be destroyed frequently, so our table does not - * contain any explicit shrinking code nor any chain-coalescing code for - * entries randomly deleted by memory pressure (except during rehashing, of - * course). These assumptions are potentially bad, but they make the - * implementation straightforward. - * - * Revisit later if evidence appears that we're using excessive memory from - * a mostly-dead table. - * - * Generally you do not need to worry about freeing cache entries; the - * cache will expire entries randomly as it experiences memory pressure. - * If max_memory is set, entries are not expired, and must be explicitely - * removed. - * - * This table is open-addressed with double hashing. Each table size is a - * prime chosen to be a little more than double the high water mark for a - * given arrangement, so the tables should remain < 50% full. The table - * size makes for the "first" hash modulus; a second prime (2 less than the - * first prime) serves as the "second" hash modulus, which is co-prime and - * thus guarantees a complete permutation of table indices. - * - */ - -#define DEAD_ENTRY ((cairo_cache_entry_base_t *) 1) -#define NULL_ENTRY_P(cache, i) ((cache)->entries[i] == NULL) -#define DEAD_ENTRY_P(cache, i) ((cache)->entries[i] == DEAD_ENTRY) -#define LIVE_ENTRY_P(cache, i) \ - (!((NULL_ENTRY_P((cache),(i))) || (DEAD_ENTRY_P((cache),(i))))) - -#ifdef NDEBUG -#define _cache_sane_state(c) -#else -static void -_cache_sane_state (cairo_cache_t *cache) -{ - assert (cache != NULL); - assert (cache->entries != NULL); - assert (cache->backend != NULL); - assert (cache->arrangement != NULL); - /* Cannot check this, a single object may larger */ - /* assert (cache->used_memory <= cache->max_memory); */ - assert (cache->live_entries <= cache->arrangement->size); -} -#endif +static void +_cairo_cache_remove (cairo_cache_t *cache, + cairo_cache_entry_t *entry); static void -_entry_destroy (cairo_cache_t *cache, unsigned long i) -{ - _cache_sane_state (cache); +_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache, + unsigned long additional); - if (LIVE_ENTRY_P(cache, i)) - { - cairo_cache_entry_base_t *entry = cache->entries[i]; - assert(cache->live_entries > 0); - assert(cache->used_memory >= entry->memory); - - cache->live_entries--; - cache->used_memory -= entry->memory; - cache->backend->destroy_entry (cache, entry); - cache->entries[i] = DEAD_ENTRY; - } -} - -static cairo_cache_entry_base_t ** -_cache_lookup (cairo_cache_t *cache, - void *key, - int (*predicate)(void*,void*,void*)) -{ - - cairo_cache_entry_base_t **probe; - unsigned long hash; - unsigned long table_size, i, idx, step; - - _cache_sane_state (cache); - assert (key != NULL); - - table_size = cache->arrangement->size; - hash = cache->backend->hash (cache, key); - idx = hash % table_size; - step = 0; - - for (i = 0; i < table_size; ++i) - { -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - cache->probes++; -#endif - assert(idx < table_size); - probe = cache->entries + idx; - - /* - * There are two lookup modes: searching for a free slot and searching - * for an exact entry. - */ - - if (predicate != NULL) - { - /* We are looking up an exact entry. */ - if (*probe == NULL) - { - /* Found an empty spot, there can't be a match */ - break; - } - else if (*probe != DEAD_ENTRY - && (*probe)->hashcode == hash - && predicate (cache, key, *probe)) - { - return probe; - } - } - else - { - /* We are just looking for a free slot. */ - if (*probe == NULL - || *probe == DEAD_ENTRY) - { - return probe; - } - } - - if (step == 0) { - step = hash % cache->arrangement->rehash; - if (step == 0) - step = 1; - } - - idx += step; - if (idx >= table_size) - idx -= table_size; - } - - /* - * The table should not have permitted you to get here if you were just - * looking for a free slot: there should have been room. - */ - assert(predicate != NULL); - return NULL; -} - -static cairo_cache_entry_base_t ** -_find_available_entry_for (cairo_cache_t *cache, - void *key) -{ - return _cache_lookup (cache, key, NULL); -} - -static cairo_cache_entry_base_t ** -_find_exact_live_entry_for (cairo_cache_t *cache, - void *key) -{ - return _cache_lookup (cache, key, cache->backend->keys_equal); -} - -static const cairo_cache_arrangement_t * -_find_cache_arrangement (unsigned long proposed_size) -{ - unsigned long idx; - - for (idx = 0; idx < N_CACHE_SIZES; ++idx) - if (cache_arrangements[idx].high_water_mark >= proposed_size) - return &cache_arrangements[idx]; - return NULL; -} static cairo_status_t -_resize_cache (cairo_cache_t *cache, unsigned long proposed_size) +_cairo_cache_init (cairo_cache_t *cache, + cairo_cache_keys_equal_func_t keys_equal, + cairo_destroy_func_t entry_destroy, + unsigned long max_size) { - cairo_cache_t tmp; - cairo_cache_entry_base_t **e; - unsigned long new_size, i; - - tmp = *cache; - tmp.arrangement = _find_cache_arrangement (proposed_size); - assert(tmp.arrangement != NULL); - if (tmp.arrangement == cache->arrangement) - return CAIRO_STATUS_SUCCESS; - - new_size = tmp.arrangement->size; - tmp.entries = calloc (new_size, sizeof (cairo_cache_entry_base_t *)); - if (tmp.entries == NULL) + cache->hash_table = _cairo_hash_table_create (keys_equal); + if (cache->hash_table == NULL) return CAIRO_STATUS_NO_MEMORY; - - for (i = 0; i < cache->arrangement->size; ++i) { - if (LIVE_ENTRY_P(cache, i)) { - e = _find_available_entry_for (&tmp, cache->entries[i]); - assert (e != NULL); - *e = cache->entries[i]; - } - } - free (cache->entries); - cache->entries = tmp.entries; - cache->arrangement = tmp.arrangement; + + cache->entry_destroy = entry_destroy; + + cache->max_size = max_size; + cache->size = 0; + + cache->freeze_count = 0; + return CAIRO_STATUS_SUCCESS; } - -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE -static double -_load_factor (cairo_cache_t *cache) +static void +_cairo_cache_fini (cairo_cache_t *cache) { - return ((double) cache->live_entries) - / ((double) cache->arrangement->size); -} -#endif + cairo_cache_entry_t *entry; -/* Find a random in the cache matching the given predicate. We use the - * same algorithm as the probing algorithm to walk over the entries in - * the hash table in a pseudo-random order. Walking linearly would - * favor entries following gaps in the hash table. We could also - * call rand() repeatedly, which works well for almost-full tables, - * but degrades when the table is almost empty, or predicate - * returns false for most entries. - */ -static cairo_cache_entry_base_t ** -_random_entry (cairo_cache_t *cache, - int (*predicate)(void*)) -{ - cairo_cache_entry_base_t **probe; - unsigned long hash; - unsigned long table_size, i, idx, step; - - _cache_sane_state (cache); + /* We have to manually remove all entries from the cache ourselves + * rather than relying on _cairo_hash_table_destroy() to do that + * since otherwise the cache->entry_destroy callback would not get + * called on each entry. */ - table_size = cache->arrangement->size; - hash = rand (); - idx = hash % table_size; - step = 0; - - for (i = 0; i < table_size; ++i) - { - assert(idx < table_size); - probe = cache->entries + idx; - - if (LIVE_ENTRY_P(cache, idx) - && (!predicate || predicate (*probe))) - return probe; - - if (step == 0) { - step = hash % cache->arrangement->rehash; - if (step == 0) - step = 1; - } - - idx += step; - if (idx >= table_size) - idx -= table_size; + while (1) { + entry = _cairo_hash_table_random_entry (cache->hash_table, NULL); + if (entry == NULL) + break; + _cairo_cache_remove (cache, entry); } - return NULL; + _cairo_hash_table_destroy (cache->hash_table); + cache->size = 0; } -/* public API follows */ +/** + * _cairo_cache_create: + * @keys_equal: a function to return %TRUE if two keys are equal + * @entry_destroy: destroy notifier for cache entries + * @max_size: the maximum size for this cache + * + * Creates a new cache using the keys_equal() function to determine + * the equality of entries. + * + * Data is provided to the cache in the form of user-derived version + * of cairo_cache_entry_t. A cache entry must be able to hold hash + * code, a size, and the key/value pair being stored in the + * cache. Sometimes only the key will be necessary, (as in + * _cairo_cache_lookup()), and in these cases the value portion of the + * entry need not be initialized. + * + * The units for max_size can be chosen by the caller, but should be + * consistent with the units of the size field of cache entries. When + * adding an entry with _cairo_cache_insert() if the total size of + * entries in the cache would exceed max_size then entries will be + * removed at random until the new entry would fit or the cache is + * empty. Then the new entry is inserted. + * + * There are cases in which the automatic removal of entries is + * undesired. If the cache entries have reference counts, then it is a + * simple matter to use the reference counts to ensure that entries + * continue to live even after being ejected from the cache. However, + * in some cases the memory overhead of adding a reference count to + * the entry would be objectionable. In such cases, the + * _cairo_cache_freeze() and _cairo_cache_thaw() calls can be + * used to establish a window during which no automatic removal of + * entries will occur. + * + * Return value: + **/ +cairo_cache_t * +_cairo_cache_create (cairo_cache_keys_equal_func_t keys_equal, + cairo_destroy_func_t entry_destroy, + unsigned long max_size) +{ + cairo_status_t status; + cairo_cache_t *cache; -cairo_status_t -_cairo_cache_init (cairo_cache_t *cache, - const cairo_cache_backend_t *backend, - unsigned long max_memory) -{ - assert (backend != NULL); + cache = malloc (sizeof (cairo_cache_t)); + if (cache == NULL) + return NULL; - if (cache != NULL){ - cache->arrangement = &cache_arrangements[0]; - cache->max_memory = max_memory; - cache->used_memory = 0; - cache->live_entries = 0; + status = _cairo_cache_init (cache, keys_equal, entry_destroy, max_size); + if (status) { + free (cache); + return NULL; + } -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - cache->hits = 0; - cache->misses = 0; - cache->probes = 0; -#endif - - cache->backend = backend; - cache->entries = calloc (cache->arrangement->size, - sizeof(cairo_cache_entry_base_t *)); - - if (cache->entries == NULL) - return CAIRO_STATUS_NO_MEMORY; - } - _cache_sane_state (cache); - return CAIRO_STATUS_SUCCESS; + return cache; } +/** + * _cairo_cache_destroy: + * @cache: a cache to destroy + * + * Immediately destroys the given cache, freeing all resources + * associated with it. As part of this process, the entry_destroy() + * function, (as passed to _cairo_cache_create()), will be called for + * each entry in the cache. + **/ void _cairo_cache_destroy (cairo_cache_t *cache) { - unsigned long i; - if (cache == NULL) - return; - - _cache_sane_state (cache); + _cairo_cache_fini (cache); - for (i = 0; i < cache->arrangement->size; ++i) - _entry_destroy (cache, i); - - free (cache->entries); - cache->entries = NULL; - cache->backend->destroy_cache (cache); + free (cache); } +/** + * _cairo_cache_freeze: + * @cache: a cache with some precious entries in it (or about to be + * added) + * + * Disable the automatic ejection of entries from the cache. For as + * long as the cache is "frozen", calls to _cairo_cache_insert() will + * add new entries to the cache regardless of how large the cache + * grows. See _cairo_cache_thaw(). + * + * NOTE: Multiple calls to _cairo_cache_freeze() will stack, in that + * the cache will remain "frozen" until a corresponding number of + * calls are made to _cairo_cache_thaw(). + **/ void -_cairo_cache_shrink_to (cairo_cache_t *cache, - unsigned long max_memory) +_cairo_cache_freeze (cairo_cache_t *cache) { - unsigned long idx; - /* Make some entries die if we're under memory pressure. */ - while (cache->live_entries > 0 && cache->used_memory > max_memory) { - idx = _random_entry (cache, NULL) - cache->entries; - assert (idx < cache->arrangement->size); - _entry_destroy (cache, idx); - } + assert (cache->freeze_count >= 0); + + cache->freeze_count++; } -cairo_status_t -_cairo_cache_lookup (cairo_cache_t *cache, - void *key, - void **entry_return, - int *created_entry) +/** + * _cairo_cache_thaw: + * @cache: a cache, just after the entries in it have become less + * precious + * + * Cancels the effects of _cairo_cache_freeze(). + * + * When a number of calls to _cairo_cache_thaw() is made corresponding + * to the number of calls to _cairo_cache_freeze() the cache will no + * longer be "frozen". If the cache had grown larger than max_size + * while frozen, entries will immediately be ejected (by random) from + * the cache until the cache is smaller than max_size. Also, the + * automatic ejection of entries on _cairo_cache_insert() will resume. + **/ +void +_cairo_cache_thaw (cairo_cache_t *cache) { + assert (cache->freeze_count > 0); - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_cache_entry_base_t **slot = NULL, *new_entry; + cache->freeze_count--; - _cache_sane_state (cache); - -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - if ((cache->hits + cache->misses) % 0xffff == 0) - printf("cache %p stats: size %ld, live %ld, load %.2f\n" - " mem %ld/%ld, hit %ld, miss %ld\n" - " probe %ld, %.2f probe/access\n", - cache, - cache->arrangement->size, - cache->live_entries, - _load_factor (cache), - cache->used_memory, - cache->max_memory, - cache->hits, - cache->misses, - cache->probes, - ((double) cache->probes) - / ((double) (cache->hits + - cache->misses + 1))); -#endif - - /* See if we have an entry in the table already. */ - slot = _find_exact_live_entry_for (cache, key); - if (slot != NULL) { -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - cache->hits++; -#endif - *entry_return = *slot; - if (created_entry) - *created_entry = 0; - return status; - } - -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - cache->misses++; -#endif - - /* Build the new entry. */ - status = cache->backend->create_entry (cache, key, - (void **)&new_entry); - if (status != CAIRO_STATUS_SUCCESS) - return status; - - /* Store the hash value in case the backend forgot. */ - new_entry->hashcode = cache->backend->hash (cache, key); - - if (cache->live_entries && cache->max_memory) - _cairo_cache_shrink_to (cache, cache->max_memory); - - /* Can't assert this; new_entry->memory may be larger than max_memory */ - /* assert(cache->max_memory >= (cache->used_memory + new_entry->memory)); */ - - /* Make room in the table for a new slot. */ - status = _resize_cache (cache, cache->live_entries + 1); - if (status != CAIRO_STATUS_SUCCESS) { - cache->backend->destroy_entry (cache, new_entry); - return status; - } - - slot = _find_available_entry_for (cache, key); - assert(slot != NULL); - - /* Store entry in slot and increment statistics. */ - *slot = new_entry; - cache->live_entries++; - cache->used_memory += new_entry->memory; - - _cache_sane_state (cache); - - *entry_return = new_entry; - if (created_entry) - *created_entry = 1; - - return status; + if (cache->freeze_count == 0) + _cairo_cache_shrink_to_accomodate (cache, 0); } -cairo_status_t -_cairo_cache_remove (cairo_cache_t *cache, - void *key) +/** + * _cairo_cache_lookup: + * @cache: a cache + * @key: the key of interest + * @entry_return: pointer for return value + * + * Performs a lookup in @cache looking for an entry which has a key + * that matches @key, (as determined by the keys_equal() function + * passed to _cairo_cache_create()). + * + * Return value: %TRUE if there is an entry in the cache that matches + * @key, (which will now be in *entry_return). %FALSE otherwise, (in + * which case *entry_return will be %NULL). + **/ +cairo_bool_t +_cairo_cache_lookup (cairo_cache_t *cache, + cairo_cache_entry_t *key, + cairo_cache_entry_t **entry_return) { - cairo_cache_entry_base_t **slot; + return _cairo_hash_table_lookup (cache->hash_table, + (cairo_hash_entry_t *) key, + (cairo_hash_entry_t **) entry_return); +} - _cache_sane_state (cache); +/** + * _cairo_cache_remove_random: + * @cache: a cache + * + * Remove a random entry from the cache. + * + * Return value: CAIRO_STATUS_SUCCESS if an entry was successfully + * removed. CAIRO_INT_STATUS_CACHE_EMPTY if there are no entries that + * can be removed. + **/ +static cairo_int_status_t +_cairo_cache_remove_random (cairo_cache_t *cache) +{ + cairo_cache_entry_t *entry; - /* See if we have an entry in the table already. */ - slot = _find_exact_live_entry_for (cache, key); - if (slot != NULL) - _entry_destroy (cache, slot - cache->entries); + entry = _cairo_hash_table_random_entry (cache->hash_table, NULL); + if (entry == NULL) + return CAIRO_INT_STATUS_CACHE_EMPTY; + + _cairo_cache_remove (cache, entry); return CAIRO_STATUS_SUCCESS; } -void * -_cairo_cache_random_entry (cairo_cache_t *cache, - int (*predicate)(void*)) +/** + * _cairo_cache_shrink_to_accomodate: + * @cache: a cache + * @additional: additional size requested in bytes + * + * If cache is not frozen, eject entries randomly until the size of + * the cache is at least @additional bytes less than + * cache->max_size. That is, make enough room to accomodate a new + * entry of size @additional. + **/ +static void +_cairo_cache_shrink_to_accomodate (cairo_cache_t *cache, + unsigned long additional) { - cairo_cache_entry_base_t **slot = _random_entry (cache, predicate); + cairo_int_status_t status; - return slot ? *slot : NULL; + if (cache->freeze_count) + return; + + while (cache->size + additional > cache->max_size) { + status = _cairo_cache_remove_random (cache); + if (status) { + if (status == CAIRO_INT_STATUS_CACHE_EMPTY) + return; + ASSERT_NOT_REACHED; + } + } +} + +/** + * _cairo_cache_insert: + * @cache: a cache + * @entry: an entry to be inserted + * + * Insert @entry into the cache. If an entry exists in the cache with + * a matching key, then the old entry will be removed first, (and the + * entry_destroy() callback will be called on it). + * + * Return value: CAIRO_STATUS_SUCCESS if successful or + * CAIRO_STATUS_NO_MEMORY if insufficient memory is available. + **/ +cairo_status_t +_cairo_cache_insert (cairo_cache_t *cache, + cairo_cache_entry_t *entry) +{ + cairo_status_t status; + + _cairo_cache_shrink_to_accomodate (cache, entry->size); + + status = _cairo_hash_table_insert (cache->hash_table, + (cairo_hash_entry_t *) entry); + if (status) + return status; + + cache->size += entry->size; + + return CAIRO_STATUS_SUCCESS; +} + +/** + * _cairo_cache_remove: + * @cache: a cache + * @entry: an entry that exists in the cache + * + * Remove an existing entry from the cache. + * + * (NOTE: If any caller wanted access to a non-static version of this + * function, an improved version would require only a key rather than + * an entry. Fixing that would require fixing _cairo_hash_table_remove + * to return (a copy of?) the entry being removed.) + **/ +static void +_cairo_cache_remove (cairo_cache_t *cache, + cairo_cache_entry_t *entry) +{ + cache->size -= entry->size; + + _cairo_hash_table_remove (cache->hash_table, + (cairo_hash_entry_t *) entry); + + if (cache->entry_destroy) + cache->entry_destroy (entry); +} + +/** + * _cairo_cache_foreach: + * @cache: a cache + * @cache_callback: function to be called for each entry + * @closure: additional argument to be passed to @cache_callback + * + * Call @cache_callback for each entry in the cache, in a + * non-specified order. + **/ +void +_cairo_cache_foreach (cairo_cache_t *cache, + cairo_cache_callback_func_t cache_callback, + void *closure) +{ + _cairo_hash_table_foreach (cache->hash_table, + cache_callback, + closure); } unsigned long diff --git a/gfx/cairo/cairo/src/cairo-debug.c b/gfx/cairo/cairo/src/cairo-debug.c index 31eefc5ae5c..6d32b418bfa 100644 --- a/gfx/cairo/cairo/src/cairo-debug.c +++ b/gfx/cairo/cairo/src/cairo-debug.c @@ -60,7 +60,6 @@ void cairo_debug_reset_static_data (void) { #if CAIRO_HAS_XLIB_SURFACE - _cairo_xlib_surface_reset_static_data (); _cairo_xlib_screen_reset_static_data (); #endif diff --git a/gfx/cairo/cairo/src/cairo-features.h.in b/gfx/cairo/cairo/src/cairo-features.h.in index aa64e8dc9ff..81878843ae7 100644 --- a/gfx/cairo/cairo/src/cairo-features.h.in +++ b/gfx/cairo/cairo/src/cairo-features.h.in @@ -37,6 +37,8 @@ #ifndef CAIRO_FEATURES_H #define CAIRO_FEATURES_H +#include "cairo-platform.h" + #ifdef __cplusplus # define CAIRO_BEGIN_DECLS extern "C" { # define CAIRO_END_DECLS } @@ -45,11 +47,11 @@ # define CAIRO_END_DECLS #endif -#define CAIRO_VERSION_MAJOR 0 -#define CAIRO_VERSION_MINOR 9 +#define CAIRO_VERSION_MAJOR 1 +#define CAIRO_VERSION_MINOR 1 #define CAIRO_VERSION_MICRO 1 -#define CAIRO_VERSION_STRING "0.9.1" +#define CAIRO_VERSION_STRING "1.1.1" @PS_SURFACE_FEATURE@ diff --git a/gfx/cairo/cairo/src/cairo-fixed.c b/gfx/cairo/cairo/src/cairo-fixed.c index a4faa1708d6..604c9e729da 100644 --- a/gfx/cairo/cairo/src/cairo-fixed.c +++ b/gfx/cairo/cairo/src/cairo-fixed.c @@ -45,7 +45,7 @@ _cairo_fixed_from_int (int i) cairo_fixed_t _cairo_fixed_from_double (double d) { - return (cairo_fixed_t) (d * 65536); + return (cairo_fixed_t) floor (d * 65536 + 0.5); } cairo_fixed_t @@ -84,7 +84,7 @@ _cairo_fixed_integer_floor (cairo_fixed_t f) int _cairo_fixed_integer_ceil (cairo_fixed_t f) { - if (f >= 0) + if (f > 0) return ((f - 1)>>16) + 1; else return - (-f >> 16); diff --git a/gfx/cairo/cairo/src/cairo-font.c b/gfx/cairo/cairo/src/cairo-font.c index 913eb95dec4..b0fab1b4a0c 100644 --- a/gfx/cairo/cairo/src/cairo-font.c +++ b/gfx/cairo/cairo/src/cairo-font.c @@ -85,6 +85,10 @@ cairo_font_face_reference (cairo_font_face_t *font_face) if (font_face->ref_count == (unsigned int)-1) return font_face; + /* We would normally assert (font_face->ref_count >0) here but we + * can't get away with that due to the zombie case as documented + * in _cairo_ft_font_face_destroy. */ + font_face->ref_count++; return font_face; @@ -107,6 +111,8 @@ cairo_font_face_destroy (cairo_font_face_t *font_face) if (font_face->ref_count == (unsigned int)-1) return; + assert (font_face->ref_count > 0); + if (--(font_face->ref_count) > 0) return; @@ -407,544 +413,6 @@ static const cairo_font_face_backend_t _cairo_toy_font_face_backend = { _cairo_toy_font_face_scaled_font_create }; -/* cairo_scaled_font_t */ - -static const cairo_scaled_font_t _cairo_scaled_font_nil = { - { 0 }, /* hash_entry */ - CAIRO_STATUS_NO_MEMORY, /* status */ - -1, /* ref_count */ - NULL, /* font_face */ - { 1., 0., 0., 1., 0, 0}, /* font_matrix */ - { 1., 0., 0., 1., 0, 0}, /* ctm */ - { 1., 0., 0., 1., 0, 0}, /* scale */ - { CAIRO_ANTIALIAS_DEFAULT, /* options */ - CAIRO_SUBPIXEL_ORDER_DEFAULT, - CAIRO_HINT_STYLE_DEFAULT, - CAIRO_HINT_METRICS_DEFAULT} , - CAIRO_SCALED_FONT_BACKEND_DEFAULT, -}; - -/** - * _cairo_scaled_font_set_error: - * @scaled_font: a scaled_font - * @status: a status value indicating an error, (eg. not - * CAIRO_STATUS_SUCCESS) - * - * Sets scaled_font->status to @status and calls _cairo_error; - * - * All assignments of an error status to scaled_font->status should happen - * through _cairo_scaled_font_set_error() or else _cairo_error() should be - * called immediately after the assignment. - * - * The purpose of this function is to allow the user to set a - * breakpoint in _cairo_error() to generate a stack trace for when the - * user causes cairo to detect an error. - **/ -void -_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, - cairo_status_t status) -{ - scaled_font->status = status; - - _cairo_error (status); -} - -/** - * cairo_scaled_font_status: - * @scaled_font: a #cairo_scaled_font_t - * - * Checks whether an error has previously occurred for this - * scaled_font. - * - * Return value: %CAIRO_STATUS_SUCCESS or another error such as - * %CAIRO_STATUS_NO_MEMORY. - **/ -cairo_status_t -cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->status; -} - -/* Here we keep a unique mapping from - * cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t. - * - * Here are the things that we want to map: - * - * a) All otherwise referenced cairo_scaled_font_t's - * b) Some number of not otherwise referenced cairo_scaled_font_t's - * - * The implementation uses a hash table which covers (a) - * completely. Then, for (b) we have an array of otherwise - * unreferenced fonts (holdovers) which are expired in - * least-recently-used order. - * - * The cairo_scaled_font_create code gets to treat this like a regular - * hash table. All of the magic for the little holdover cache is in - * cairo_scaled_font_reference and cairo_scaled_font_destroy. - */ - -/* This defines the size of the holdover array ... that is, the number - * of scaled fonts we keep around even when not otherwise referenced - */ -#define CAIRO_SCALED_FONT_MAX_HOLDOVERS 24 - -typedef struct _cairo_scaled_font_map { - cairo_hash_table_t *hash_table; - cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS]; - int num_holdovers; -} cairo_scaled_font_map_t; - -static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL; - -CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex); - -static int -_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b); - -static cairo_scaled_font_map_t * -_cairo_scaled_font_map_lock (void) -{ - CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); - - if (cairo_scaled_font_map == NULL) - { - cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); - if (cairo_scaled_font_map == NULL) - goto CLEANUP_MUTEX_LOCK; - - cairo_scaled_font_map->hash_table = - _cairo_hash_table_create (_cairo_scaled_font_keys_equal); - - if (cairo_scaled_font_map->hash_table == NULL) - goto CLEANUP_SCALED_FONT_MAP; - - cairo_scaled_font_map->num_holdovers = 0; - } - - return cairo_scaled_font_map; - - CLEANUP_SCALED_FONT_MAP: - free (cairo_scaled_font_map); - CLEANUP_MUTEX_LOCK: - CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); - return NULL; -} - -static void -_cairo_scaled_font_map_unlock (void) -{ - CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); -} - -static void -_cairo_scaled_font_map_destroy (void) -{ - int i; - cairo_scaled_font_map_t *font_map = cairo_scaled_font_map; - cairo_scaled_font_t *scaled_font; - - if (font_map == NULL) - return; - - CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); - - for (i = 0; i < font_map->num_holdovers; i++) { - scaled_font = font_map->holdovers[i]; - /* We should only get here through the reset_static_data path - * and there had better not be any active references at that - * point. */ - assert (scaled_font->ref_count == 0); - _cairo_hash_table_remove (font_map->hash_table, - &scaled_font->hash_entry); - _cairo_scaled_font_fini (scaled_font); - free (scaled_font); - } - - _cairo_hash_table_destroy (font_map->hash_table); - - free (cairo_scaled_font_map); - cairo_scaled_font_map = NULL; -} - -/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) - * - * Not necessarily better than a lot of other hashes, but should be OK, and - * well tested with binary data. - */ - -#define FNV_32_PRIME ((uint32_t)0x01000193) -#define FNV1_32_INIT ((uint32_t)0x811c9dc5) - -static uint32_t -_hash_bytes_fnv (unsigned char *buffer, - int len, - uint32_t hval) -{ - while (len--) { - hval *= FNV_32_PRIME; - hval ^= *buffer++; - } - - return hval; -} - -static void -_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options) -{ - uint32_t hash = FNV1_32_INIT; - - scaled_font->status = CAIRO_STATUS_SUCCESS; - scaled_font->font_face = font_face; - scaled_font->font_matrix = *font_matrix; - scaled_font->ctm = *ctm; - scaled_font->options = *options; - - /* We do a bytewise hash on the font matrices, ignoring the - * translation values. */ - hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx), - sizeof(double) * 4, - hash); - hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx), - sizeof(double) * 4, - hash); - - hash ^= (unsigned long) scaled_font->font_face; - - hash ^= cairo_font_options_hash (&scaled_font->options); - - scaled_font->hash_entry.hash = hash; -} - -static cairo_bool_t -_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b) -{ - cairo_scaled_font_t *key_a = abstract_key_a; - cairo_scaled_font_t *key_b = abstract_key_b; - - return (key_a->font_face == key_b->font_face && - memcmp ((unsigned char *)(&key_a->font_matrix.xx), - (unsigned char *)(&key_b->font_matrix.xx), - sizeof(double) * 4) == 0 && - memcmp ((unsigned char *)(&key_a->ctm.xx), - (unsigned char *)(&key_b->ctm.xx), - sizeof(double) * 4) == 0 && - cairo_font_options_equal (&key_a->options, &key_b->options)); -} - -void -_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - const cairo_scaled_font_backend_t *backend) -{ - scaled_font->ref_count = 1; - - _cairo_scaled_font_init_key (scaled_font, font_face, - font_matrix, ctm, options); - - cairo_font_face_reference (font_face); - - cairo_matrix_multiply (&scaled_font->scale, - &scaled_font->font_matrix, - &scaled_font->ctm); - - scaled_font->backend = backend; -} - -void -_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font->font_face) - cairo_font_face_destroy (scaled_font->font_face); - - scaled_font->backend->fini (scaled_font); -} - -/** - * cairo_scaled_font_create: - * @font_face: a #cairo_font_face_t - * @font_matrix: font space to user space transformation matrix for the - * font. In the simplest case of a N point font, this matrix is - * just a scale by N, but it can also be used to shear the font - * or stretch it unequally along the two axes. See - * cairo_set_font_matrix(). - * @ctm: user to device transformation matrix with which the font will - * be used. - * @options: options to use when getting metrics for the font and - * rendering with it. - * - * Creates a #cairo_scaled_font_t object from a font face and matrices that - * describe the size of the font and the environment in which it will - * be used. - * - * Return value: a newly created #cairo_scaled_font_t. Destroy with - * cairo_scaled_font_destroy() - **/ -cairo_scaled_font_t * -cairo_scaled_font_create (cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options) -{ - cairo_status_t status; - cairo_scaled_font_map_t *font_map; - cairo_scaled_font_t key, *scaled_font = NULL; - - font_map = _cairo_scaled_font_map_lock (); - if (font_map == NULL) - goto UNWIND; - - _cairo_scaled_font_init_key (&key, font_face, - font_matrix, ctm, options); - - /* Return existing scaled_font if it exists in the hash table. */ - if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry, - (cairo_hash_entry_t**) &scaled_font)) - { - _cairo_scaled_font_map_unlock (); - return cairo_scaled_font_reference (scaled_font); - } - - /* Otherwise create it and insert it into the hash table. */ - status = font_face->backend->scaled_font_create (font_face, font_matrix, - ctm, options, &scaled_font); - if (status) - goto UNWIND_FONT_MAP_LOCK; - - status = _cairo_hash_table_insert (font_map->hash_table, - &scaled_font->hash_entry); - if (status) - goto UNWIND_SCALED_FONT_CREATE; - - _cairo_scaled_font_map_unlock (); - - return scaled_font; - -UNWIND_SCALED_FONT_CREATE: - /* We can't call _cairo_scaled_font_destroy here since it expects - * that the font has already been successfully inserted into the - * hash table. */ - _cairo_scaled_font_fini (scaled_font); - free (scaled_font); -UNWIND_FONT_MAP_LOCK: - _cairo_scaled_font_map_unlock (); -UNWIND: - return NULL; -} - -/** - * cairo_scaled_font_reference: - * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case - * this function does nothing) - * - * Increases the reference count on @scaled_font by one. This prevents - * @scaled_font from being destroyed until a matching call to - * cairo_scaled_font_destroy() is made. - **/ -cairo_scaled_font_t * -cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) -{ - if (scaled_font == NULL) - return NULL; - - if (scaled_font->ref_count == (unsigned int)-1) - return scaled_font; - - /* If the original reference count is 0, then this font must have - * been found in font_map->holdovers, (which means this caching is - * actually working). So now we remove it from the holdovers - * array. */ - if (scaled_font->ref_count == 0) { - cairo_scaled_font_map_t *font_map; - int i; - - font_map = _cairo_scaled_font_map_lock (); - { - for (i = 0; i < font_map->num_holdovers; i++) - if (font_map->holdovers[i] == scaled_font) - break; - assert (i < font_map->num_holdovers); - - font_map->num_holdovers--; - memmove (&font_map->holdovers[i], - &font_map->holdovers[i+1], - (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*)); - } - _cairo_scaled_font_map_unlock (); - } - - scaled_font->ref_count++; - - return scaled_font; -} - -/** - * cairo_scaled_font_destroy: - * @scaled_font: a #cairo_scaled_font_t - * - * Decreases the reference count on @font by one. If the result - * is zero, then @font and all associated resources are freed. - * See cairo_scaled_font_reference(). - **/ -void -cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) -{ - cairo_scaled_font_map_t *font_map; - - if (scaled_font == NULL) - return; - - if (scaled_font->ref_count == (unsigned int)-1) - return; - - if (--(scaled_font->ref_count) > 0) - return; - - font_map = _cairo_scaled_font_map_lock (); - assert (font_map != NULL); - { - /* Rather than immediately destroying this object, we put it into - * the font_map->holdovers array in case it will get used again - * soon. To make room for it, we do actually destroy the - * least-recently-used holdover. - */ - if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) { - cairo_scaled_font_t *lru; - - lru = font_map->holdovers[0]; - assert (lru->ref_count == 0); - - _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry); - - _cairo_scaled_font_fini (lru); - free (lru); - - font_map->num_holdovers--; - memmove (&font_map->holdovers[0], - &font_map->holdovers[1], - font_map->num_holdovers * sizeof (cairo_scaled_font_t*)); - } - - font_map->holdovers[font_map->num_holdovers] = scaled_font; - font_map->num_holdovers++; - } - _cairo_scaled_font_map_unlock (); -} - -cairo_status_t -_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - if (scaled_font->status) - return scaled_font->status; - - return scaled_font->backend->text_to_glyphs (scaled_font, utf8, glyphs, num_glyphs); -} - -cairo_status_t -_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - if (scaled_font->status) - return scaled_font->status; - - return scaled_font->backend->glyph_extents (scaled_font, glyphs, num_glyphs, extents); -} - - -cairo_status_t -_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox) -{ - if (scaled_font->status) - return scaled_font->status; - - return scaled_font->backend->glyph_bbox (scaled_font, glyphs, num_glyphs, bbox); -} - -cairo_status_t -_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_status_t status; - - if (scaled_font->status) - return scaled_font->status; - - status = _cairo_surface_show_glyphs (scaled_font, operator, pattern, - surface, - source_x, source_y, - dest_x, dest_y, - width, height, - glyphs, num_glyphs); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - - /* Surface display routine either does not exist or failed. */ - return scaled_font->backend->show_glyphs (scaled_font, operator, pattern, - surface, - source_x, source_y, - dest_x, dest_y, - width, height, - glyphs, num_glyphs); -} - -cairo_status_t -_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path) -{ - if (scaled_font->status) - return scaled_font->status; - - return scaled_font->backend->glyph_path (scaled_font, glyphs, num_glyphs, path); -} - -cairo_status_t -_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font, - cairo_glyph_cache_key_t *key) -{ - if (scaled_font->status) - return scaled_font->status; - - scaled_font->backend->get_glyph_cache_key (scaled_font, key); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents) -{ - if (scaled_font->status) - return scaled_font->status; - - return scaled_font->backend->font_extents (scaled_font, extents); -} - void _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font, const cairo_unscaled_font_backend_t *backend) @@ -978,307 +446,11 @@ _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font) free (unscaled_font); } -/* Public font API follows. */ - -/** - * cairo_scaled_font_extents: - * @scaled_font: a #cairo_scaled_font_t - * @extents: a #cairo_font_extents_t which to store the retrieved extents. - * - * Gets the metrics for a #cairo_scaled_font_t. - **/ -void -cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents) -{ - cairo_int_status_t status; - double font_scale_x, font_scale_y; - - if (scaled_font->status) { - _cairo_scaled_font_set_error (scaled_font, scaled_font->status); - return; - } - - status = _cairo_scaled_font_font_extents (scaled_font, extents); - if (status) { - _cairo_scaled_font_set_error (scaled_font, status); - return; - } - - _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix, - &font_scale_x, &font_scale_y, - /* XXX */ 1); - - /* - * The font responded in unscaled units, scale by the font - * matrix scale factors to get to user space - */ - - extents->ascent *= font_scale_y; - extents->descent *= font_scale_y; - extents->height *= font_scale_y; - extents->max_x_advance *= font_scale_x; - extents->max_y_advance *= font_scale_y; -} - -/** - * cairo_font_glyph_extents: - * @scaled_font: a #cairo_scaled_font_t - * @glyphs: an array of glyph IDs with X and Y offsets. - * @num_glyphs: the number of glyphs in the @glyphs array - * @extents: a #cairo_text_extents_t which to store the retrieved extents. - * - * cairo_font_glyph_extents() gets the overall metrics for a string of - * glyphs. The X and Y offsets in @glyphs are taken from an origin of 0,0. - **/ -void -cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_glyph_t origin_glyph; - cairo_text_extents_t origin_extents; - int i; - double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0; - double x_pos = 0.0, y_pos = 0.0; - int set = 0; - - if (scaled_font->status) { - _cairo_scaled_font_set_error (scaled_font, scaled_font->status); - return; - } - - if (!num_glyphs) - { - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; - - return; - } - - for (i = 0; i < num_glyphs; i++) - { - double x, y; - double wm, hm; - - origin_glyph = glyphs[i]; - origin_glyph.x = 0.0; - origin_glyph.y = 0.0; - status = _cairo_scaled_font_glyph_extents (scaled_font, - &origin_glyph, 1, - &origin_extents); - - /* - * Transform font space metrics into user space metrics - * by running the corners through the font matrix and - * expanding the bounding box as necessary - */ - x = origin_extents.x_bearing; - y = origin_extents.y_bearing; - cairo_matrix_transform_point (&scaled_font->font_matrix, - &x, &y); - - for (hm = 0.0; hm <= 1.0; hm += 1.0) - for (wm = 0.0; wm <= 1.0; wm += 1.0) - { - x = origin_extents.x_bearing + origin_extents.width * wm; - y = origin_extents.y_bearing + origin_extents.height * hm; - cairo_matrix_transform_point (&scaled_font->font_matrix, - &x, &y); - x += glyphs[i].x; - y += glyphs[i].y; - if (!set) - { - min_x = max_x = x; - min_y = max_y = y; - set = 1; - } - else - { - if (x < min_x) min_x = x; - if (x > max_x) max_x = x; - if (y < min_y) min_y = y; - if (y > max_y) max_y = y; - } - } - - x = origin_extents.x_advance; - y = origin_extents.y_advance; - cairo_matrix_transform_point (&scaled_font->font_matrix, - &x, &y); - x_pos = glyphs[i].x + x; - y_pos = glyphs[i].y + y; - } - - extents->x_bearing = min_x - glyphs[0].x; - extents->y_bearing = min_y - glyphs[0].y; - extents->width = max_x - min_x; - extents->height = max_y - min_y; - extents->x_advance = x_pos - glyphs[0].x; - extents->y_advance = y_pos - glyphs[0].y; -} - -/* Now we implement functions to access a default global image & metrics - * cache. - */ - -unsigned long -_cairo_glyph_cache_hash (void *cache, void *key) -{ - cairo_glyph_cache_key_t *in; - in = (cairo_glyph_cache_key_t *) key; - return - ((unsigned long) in->unscaled) - ^ ((unsigned long) in->scale.xx) - ^ ((unsigned long) in->scale.yx) - ^ ((unsigned long) in->scale.xy) - ^ ((unsigned long) in->scale.yy) - ^ (in->flags * 1451) /* 1451 is just an abitrary prime */ - ^ in->index; -} - -int -_cairo_glyph_cache_keys_equal (void *cache, - void *k1, - void *k2) -{ - cairo_glyph_cache_key_t *a, *b; - a = (cairo_glyph_cache_key_t *) k1; - b = (cairo_glyph_cache_key_t *) k2; - return (a->index == b->index) - && (a->unscaled == b->unscaled) - && (a->flags == b->flags) - && (a->scale.xx == b->scale.xx) - && (a->scale.yx == b->scale.yx) - && (a->scale.xy == b->scale.xy) - && (a->scale.yy == b->scale.yy); -} - - -static cairo_status_t -_image_glyph_cache_create_entry (void *cache, - void *key, - void **return_value) -{ - cairo_glyph_cache_key_t *k = (cairo_glyph_cache_key_t *) key; - cairo_image_glyph_cache_entry_t *im; - cairo_status_t status; - - im = calloc (1, sizeof (cairo_image_glyph_cache_entry_t)); - if (im == NULL) - return CAIRO_STATUS_NO_MEMORY; - - im->key = *k; - status = im->key.unscaled->backend->create_glyph (im->key.unscaled, - im); - - if (status != CAIRO_STATUS_SUCCESS) { - free (im); - return status; - } - - _cairo_unscaled_font_reference (im->key.unscaled); - - im->key.base.memory = - sizeof (cairo_image_glyph_cache_entry_t) - + (im->image ? - sizeof (cairo_image_surface_t) - + 28 * sizeof (int) /* rough guess at size of pixman image structure */ - + (im->image->height * im->image->stride) : 0); - - *return_value = im; - - return CAIRO_STATUS_SUCCESS; -} - - -static void -_image_glyph_cache_destroy_entry (void *cache, - void *value) -{ - cairo_image_glyph_cache_entry_t *im; - - im = (cairo_image_glyph_cache_entry_t *) value; - _cairo_unscaled_font_destroy (im->key.unscaled); - cairo_surface_destroy (&(im->image->base)); - free (im); -} - -static void -_image_glyph_cache_destroy_cache (void *cache) -{ - free (cache); -} - -static const cairo_cache_backend_t cairo_image_cache_backend = { - _cairo_glyph_cache_hash, - _cairo_glyph_cache_keys_equal, - _image_glyph_cache_create_entry, - _image_glyph_cache_destroy_entry, - _image_glyph_cache_destroy_cache -}; - -CAIRO_MUTEX_DECLARE(_global_image_glyph_cache_mutex); - -static cairo_cache_t * -_global_image_glyph_cache = NULL; - -void -_cairo_lock_global_image_glyph_cache() -{ - CAIRO_MUTEX_LOCK (_global_image_glyph_cache_mutex); -} - -void -_cairo_unlock_global_image_glyph_cache() -{ - if (_global_image_glyph_cache) { - _cairo_cache_shrink_to (_global_image_glyph_cache, - CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT); - } - CAIRO_MUTEX_UNLOCK (_global_image_glyph_cache_mutex); -} - -cairo_cache_t * -_cairo_get_global_image_glyph_cache () -{ - if (_global_image_glyph_cache == NULL) { - _global_image_glyph_cache = malloc (sizeof (cairo_cache_t)); - - if (_global_image_glyph_cache == NULL) - goto FAIL; - - if (_cairo_cache_init (_global_image_glyph_cache, - &cairo_image_cache_backend, - 0)) - goto FAIL; - } - - return _global_image_glyph_cache; - - FAIL: - if (_global_image_glyph_cache) - free (_global_image_glyph_cache); - _global_image_glyph_cache = NULL; - return NULL; -} - void _cairo_font_reset_static_data (void) { _cairo_scaled_font_map_destroy (); - _cairo_lock_global_image_glyph_cache(); - _cairo_cache_destroy (_global_image_glyph_cache); - _global_image_glyph_cache = NULL; - _cairo_unlock_global_image_glyph_cache(); - CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex); _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); cairo_toy_font_face_hash_table = NULL; diff --git a/gfx/cairo/cairo/src/cairo-ft-font.c b/gfx/cairo/cairo/src/cairo-ft-font.c index 15180c9879f..a150881f0ba 100644 --- a/gfx/cairo/cairo/src/cairo-ft-font.c +++ b/gfx/cairo/cairo/src/cairo-ft-font.c @@ -48,25 +48,15 @@ #include FT_FREETYPE_H #include FT_OUTLINE_H #include FT_IMAGE_H +#if HAVE_FT_GLYPHSLOT_EMBOLDEN +#include FT_SYNTHESIS_H +#endif #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0)) #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0) #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0)) #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0) -/* We pack some of our own information into the bits unused - * by FreeType's load flags. If FreeType ever uses up all - * the load flag bits, we'll have to do something else. - * (probably just store what we care about in load_flags - * then convert into FreeType terms. - */ -#define PRIVATE_FLAG_HINT_METRICS (0x01 << 24) -#define PRIVATE_FLAGS_MASK (0xff << 24) - - /* This is the max number of FT_face objects we keep open at once - */ - #define MAX_OPEN_FACES 10 - /* This is the max number of FT_face objects we keep open at once */ #define MAX_OPEN_FACES 10 @@ -119,14 +109,24 @@ _cairo_ft_unscaled_font_keys_equal (void *key_a, static void _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled); +typedef enum _cairo_ft_extra_flags { + CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0), + CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1) +} cairo_ft_extra_flags_t; + +typedef struct _cairo_ft_options { + int load_flags; /* flags for FT_Load_Glyph */ + cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */ +} cairo_ft_options_t; + struct _cairo_ft_font_face { cairo_font_face_t base; cairo_ft_unscaled_font_t *unscaled; - int load_flags; + cairo_ft_options_t ft_options; cairo_ft_font_face_t *next; }; -const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend; +static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend; /* * We maintain a hash table to map file/id => cairo_ft_unscaled_font_t. @@ -147,6 +147,19 @@ static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL; CAIRO_MUTEX_DECLARE(cairo_ft_unscaled_font_map_mutex); +static void +_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map, + cairo_ft_unscaled_font_t *unscaled) +{ + if (unscaled->face) { + FT_Done_Face (unscaled->face); + unscaled->face = NULL; + unscaled->have_scale = FALSE; + + font_map->num_open_faces--; + } +} + static void _cairo_ft_unscaled_font_map_create (void) { @@ -206,10 +219,14 @@ _cairo_ft_unscaled_font_map_destroy (void) break; _cairo_hash_table_remove (font_map->hash_table, &unscaled->base.hash_entry); + + _font_map_release_face_lock_held (font_map, unscaled); _cairo_ft_unscaled_font_fini (unscaled); free (unscaled); } + assert (font_map->num_open_faces == 0); + FT_Done_FreeType (font_map->ft_library); _cairo_hash_table_destroy (font_map->hash_table); @@ -311,7 +328,7 @@ _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled, _cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id); } - unscaled->have_scale = 0; + unscaled->have_scale = FALSE; unscaled->lock = 0; unscaled->faces = NULL; @@ -325,18 +342,26 @@ _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font) return unscaled_font->backend == &cairo_ft_unscaled_font_backend; } +/** + * _cairo_ft_unscaled_font_fini: + * + * Free all data associated with a cairo_ft_unscaled_font_t. + * + * CAUTION: The unscaled->face field must be NULL before calling this + * function. This is because the cairo_ft_unscaled_font_map keeps a + * count of these faces (font_map->num_open_faces) so it maintains the + * unscaled->face field while it has its lock held. See + * _font_map_release_face_lock_held(). + **/ static void _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled) { + assert (unscaled->face == NULL); + if (unscaled->filename) { free (unscaled->filename); unscaled->filename = NULL; } - - if (unscaled->face) { - FT_Done_Face (unscaled->face); - unscaled->face = NULL; - } } static int @@ -456,9 +481,10 @@ _cairo_ft_unscaled_font_destroy (void *abstract_font) _cairo_hash_table_remove (font_map->hash_table, &unscaled->base.hash_entry); - _cairo_ft_unscaled_font_map_unlock (); - + _font_map_release_face_lock_held (font_map, unscaled); _cairo_ft_unscaled_font_fini (unscaled); + + _cairo_ft_unscaled_font_map_unlock (); } } @@ -503,11 +529,7 @@ _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled) if (entry == NULL) break; - FT_Done_Face (entry->face); - entry->face = NULL; - entry->have_scale = 0; - - font_map->num_open_faces--; + _font_map_release_face_lock_held (font_map, entry); } if (FT_New_Face (font_map->ft_library, @@ -589,7 +611,7 @@ _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled, scale->yy == unscaled->current_scale.yy) return; - unscaled->have_scale = 1; + unscaled->have_scale = TRUE; unscaled->current_scale = *scale; _compute_transform (&sf, scale); @@ -680,10 +702,10 @@ _native_byte_order_lsb (void) /* Fills in val->image with an image surface created from @bitmap */ static cairo_status_t -_get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, - FT_Bitmap *bitmap, - cairo_bool_t own_buffer, - int rgba) +_get_bitmap_surface (FT_Bitmap *bitmap, + cairo_bool_t own_buffer, + cairo_font_options_t *font_options, + cairo_image_surface_t **surface) { int width, height, stride; unsigned char *data; @@ -697,7 +719,7 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, if (own_buffer && bitmap->buffer) free (bitmap->buffer); - val->image = NULL; + *surface = NULL; } else { switch (bitmap->pixel_mode) { case FT_PIXEL_MODE_MONO: @@ -745,10 +767,13 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, break; case FT_PIXEL_MODE_LCD: - case FT_PIXEL_MODE_LCD_V: + case FT_PIXEL_MODE_LCD_V: case FT_PIXEL_MODE_GRAY: - if (rgba == FC_RGBA_NONE || rgba == FC_RGBA_UNKNOWN) - { + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: + case CAIRO_ANTIALIAS_NONE: + default: stride = bitmap->pitch; if (own_buffer) { data = bitmap->buffer; @@ -759,7 +784,8 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, memcpy (data, bitmap->buffer, stride * height); } format = CAIRO_FORMAT_A8; - } else { + break; + case CAIRO_ANTIALIAS_SUBPIXEL: { int x, y; unsigned char *in_line, *out_line, *in; unsigned int *out; @@ -772,20 +798,20 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, int vmul = 1; int hmul = 1; - switch (rgba) { - case FC_RGBA_RGB: - case FC_RGBA_BGR: + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: + case CAIRO_SUBPIXEL_ORDER_BGR: default: width /= 3; hmul = 3; break; - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: + case CAIRO_SUBPIXEL_ORDER_VRGB: + case CAIRO_SUBPIXEL_ORDER_VBGR: vmul = 3; height /= 3; break; } - subpixel = TRUE; /* * Filter the glyph to soften the color fringes */ @@ -795,18 +821,19 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, data_rgba = calloc (1, stride_rgba * height); os = 1; - switch (rgba) { - case FC_RGBA_VRGB: + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_VRGB: os = stride; - case FC_RGBA_RGB: + case CAIRO_SUBPIXEL_ORDER_DEFAULT: + case CAIRO_SUBPIXEL_ORDER_RGB: default: rf = 0; gf = 1; bf = 2; break; - case FC_RGBA_VBGR: + case CAIRO_SUBPIXEL_ORDER_VBGR: os = stride; - case FC_RGBA_BGR: + case CAIRO_SUBPIXEL_ORDER_BGR: bf = 0; gf = 1; rf = 2; @@ -847,6 +874,9 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, data = data_rgba; stride = stride_rgba; format = CAIRO_FORMAT_ARGB32; + subpixel = TRUE; + break; + } } break; case FT_PIXEL_MODE_GRAY2: @@ -856,24 +886,21 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, return CAIRO_STATUS_NO_MEMORY; } - val->image = (cairo_image_surface_t *) + *surface = (cairo_image_surface_t *) cairo_image_surface_create_for_data (data, format, width, height, stride); - if (val->image->base.status) { + if ((*surface)->base.status) { free (data); return CAIRO_STATUS_NO_MEMORY; } if (subpixel) - pixman_image_set_component_alpha (val->image->pixman_image, TRUE); + pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE); - _cairo_image_surface_assume_ownership_of_data (val->image); + _cairo_image_surface_assume_ownership_of_data ((*surface)); } - val->size.width = width; - val->size.height = height; - return CAIRO_STATUS_SUCCESS; } @@ -893,10 +920,10 @@ _get_bitmap_surface (cairo_image_glyph_cache_entry_t *val, * this version of the code path entirely. */ static cairo_status_t -_render_glyph_outline (FT_Face face, - cairo_image_glyph_cache_entry_t *val) +_render_glyph_outline (FT_Face face, + cairo_font_options_t *font_options, + cairo_image_surface_t **surface) { - int rgba = FC_RGBA_UNKNOWN; FT_GlyphSlot glyphslot = face->glyph; FT_Outline *outline = &glyphslot->outline; FT_Bitmap bitmap; @@ -905,7 +932,6 @@ _render_glyph_outline (FT_Face face, int hmul = 1; int vmul = 1; unsigned int width, height, stride; - cairo_format_t format; cairo_bool_t subpixel = FALSE; cairo_status_t status; @@ -921,63 +947,66 @@ _render_glyph_outline (FT_Face face, stride = (width * hmul + 3) & ~3; if (width * height == 0) { + cairo_format_t format; /* Looks like fb handles zero-sized images just fine */ - if ((val->key.flags & FT_LOAD_MONOCHROME) != 0) - format = CAIRO_FORMAT_A8; - else if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD || - FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD_V) + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_NONE: + format = CAIRO_FORMAT_A1; + break; + case CAIRO_ANTIALIAS_SUBPIXEL: format= CAIRO_FORMAT_ARGB32; - else + break; + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: + default: format = CAIRO_FORMAT_A8; + break; + } - val->image = (cairo_image_surface_t *) + (*surface) = (cairo_image_surface_t *) cairo_image_surface_create_for_data (NULL, format, 0, 0, 0); - if (val->image->base.status) + if ((*surface)->base.status) return CAIRO_STATUS_NO_MEMORY; } else { matrix.xx = matrix.yy = 0x10000L; matrix.xy = matrix.yx = 0; - if ((val->key.flags & FT_LOAD_MONOCHROME) != 0) { + switch (font_options->antialias) { + case CAIRO_ANTIALIAS_NONE: bitmap.pixel_mode = FT_PIXEL_MODE_MONO; bitmap.num_grays = 1; stride = ((width + 31) & -32) >> 3; - } else { - /* XXX not a complete set of flags. This code - * will go away when cworth rewrites the glyph - * cache code */ - if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD) - rgba = FC_RGBA_RGB; - else if (FT_LOAD_TARGET_MODE (val->key.flags) == FT_RENDER_MODE_LCD_V) - rgba = FC_RGBA_VBGR; - - switch (rgba) { - case FC_RGBA_RGB: - case FC_RGBA_BGR: + break; + case CAIRO_ANTIALIAS_DEFAULT: + case CAIRO_ANTIALIAS_GRAY: + bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + bitmap.num_grays = 256; + stride = (width + 3) & -4; + break; + case CAIRO_ANTIALIAS_SUBPIXEL: + switch (font_options->subpixel_order) { + case CAIRO_SUBPIXEL_ORDER_RGB: + case CAIRO_SUBPIXEL_ORDER_BGR: + default: matrix.xx *= 3; hmul = 3; subpixel = TRUE; break; - case FC_RGBA_VRGB: - case FC_RGBA_VBGR: + case CAIRO_SUBPIXEL_ORDER_VRGB: + case CAIRO_SUBPIXEL_ORDER_VBGR: matrix.yy *= 3; vmul = 3; subpixel = TRUE; break; } - if (subpixel) - format = CAIRO_FORMAT_ARGB32; - else - format = CAIRO_FORMAT_A8; - - if (subpixel) - FT_Outline_Transform (outline, &matrix); + FT_Outline_Transform (outline, &matrix); bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; bitmap.num_grays = 256; stride = (width * hmul + 3) & -4; } + bitmap.pitch = stride; bitmap.width = width * hmul; bitmap.rows = height * vmul; @@ -994,7 +1023,7 @@ _render_glyph_outline (FT_Face face, return CAIRO_STATUS_NO_MEMORY; } - status = _get_bitmap_surface (val, &bitmap, TRUE, rgba); + status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface); if (status) return status; } @@ -1004,8 +1033,8 @@ _render_glyph_outline (FT_Face face, * Y coordinate of the control box needs to be negated. */ - val->size.x = (short) (cbox.xMin >> 6); - val->size.y = - (short) (cbox.yMax >> 6); + (*surface)->base.device_x_offset = floor ((double) cbox.xMin / 64.0); + (*surface)->base.device_y_offset = floor (-(double) cbox.yMax / 64.0); return CAIRO_STATUS_SUCCESS; } @@ -1026,8 +1055,9 @@ _render_glyph_outline (FT_Face face, * this version of the code path entirely. */ static cairo_status_t -_render_glyph_bitmap (FT_Face face, - cairo_image_glyph_cache_entry_t *val) +_render_glyph_bitmap (FT_Face face, + cairo_font_options_t *font_options, + cairo_image_surface_t **surface) { FT_GlyphSlot glyphslot = face->glyph; cairo_status_t status = CAIRO_STATUS_SUCCESS; @@ -1044,14 +1074,21 @@ _render_glyph_bitmap (FT_Face face, if (error) return CAIRO_STATUS_NO_MEMORY; - _get_bitmap_surface (val, &glyphslot->bitmap, FALSE, FC_RGBA_NONE); - - val->size.x = glyphslot->bitmap_left; - val->size.y = - glyphslot->bitmap_top; + _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface); + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinate of the control box needs to be negated. + */ + + (*surface)->base.device_x_offset = glyphslot->bitmap_left; + (*surface)->base.device_y_offset = -glyphslot->bitmap_top; + return status; } +#if 0 +/* XXX */ static cairo_status_t _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) { @@ -1133,14 +1170,14 @@ _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) /* Initialize it to empty */ - _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_SOURCE, + _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, 0, 0, width, height); /* Draw the original bitmap transformed into the new bitmap */ - _cairo_pattern_init_for_surface (&pattern, &val->image->base); + _cairo_pattern_init_for_surface (&pattern, &(*surface)->base); cairo_pattern_set_matrix (&pattern.base, &transformed_to_original); _cairo_surface_composite (CAIRO_OPERATOR_OVER, @@ -1159,8 +1196,8 @@ _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) cairo_matrix_transform_point (&original_to_transformed, &origin_x, &origin_y); - old_image = val->image; - val->image = (cairo_image_surface_t *)image; + old_image = (*surface); + (*surface) = (cairo_image_surface_t *)image; cairo_surface_destroy (&old_image->base); val->size.width = width; @@ -1170,112 +1207,13 @@ _transform_glyph_bitmap (cairo_image_glyph_cache_entry_t *val) return status; } +#endif -static cairo_status_t -_cairo_ft_unscaled_font_create_glyph (void *abstract_font, - cairo_image_glyph_cache_entry_t *val) -{ - cairo_ft_unscaled_font_t *unscaled = abstract_font; - FT_GlyphSlot glyphslot; - FT_Face face; - FT_Glyph_Metrics *metrics; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - double x_factor, y_factor; - - face = _cairo_ft_unscaled_font_lock_face (unscaled); - if (!face) - return CAIRO_STATUS_NO_MEMORY; - - glyphslot = face->glyph; - metrics = &glyphslot->metrics; - - _cairo_ft_unscaled_font_set_scale (unscaled, &val->key.scale); - - if (FT_Load_Glyph (face, val->key.index, val->key.flags & ~PRIVATE_FLAGS_MASK) != 0) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL; - } - - if (unscaled->x_scale == 0) - x_factor = 0; - else - x_factor = 1 / unscaled->x_scale; - - if (unscaled->y_scale == 0) - y_factor = 0; - else - y_factor = 1 / unscaled->y_scale; - - /* - * Note: the font's coordinate system is upside down from ours, so the - * Y coordinates of the bearing and advance need to be negated. - * - * Scale metrics back to glyph space from the scaled glyph space returned - * by FreeType - * - * If we want hinted metrics but aren't asking for hinted glyphs from - * FreeType, then we need to do the metric hinting ourselves. - */ - - if ((val->key.flags & PRIVATE_FLAG_HINT_METRICS) && - (val->key.flags & FT_LOAD_NO_HINTING)) { - FT_Pos x1, x2; - FT_Pos y1, y2; - FT_Pos advance; - - x1 = (metrics->horiBearingX) & -64; - x2 = (metrics->horiBearingX + metrics->width + 63) & -64; - y1 = (metrics->horiBearingY) & -64; - y2 = (metrics->horiBearingY + metrics->height + 63) & -64; - - advance = ((metrics->horiAdvance + 32) & -64); - - val->extents.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; - val->extents.y_bearing = -DOUBLE_FROM_26_6 (y1) * y_factor; - - val->extents.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; - val->extents.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; - - /* - * use untransformed advance values - * XXX uses horizontal advance only at present; should provide FT_LOAD_VERTICAL_LAYOUT - */ - val->extents.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; - val->extents.y_advance = 0; - } else { - val->extents.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; - val->extents.y_bearing = -DOUBLE_FROM_26_6 (metrics->horiBearingY) * y_factor; - - val->extents.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; - val->extents.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; - - val->extents.x_advance = DOUBLE_FROM_26_6 (face->glyph->metrics.horiAdvance) * x_factor; - val->extents.y_advance = 0 * y_factor; - } - - if (glyphslot->format == FT_GLYPH_FORMAT_OUTLINE) - status = _render_glyph_outline (face, val); - else - status = _render_glyph_bitmap (face, val); - - if (unscaled->have_shape && - (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) - status = _transform_glyph_bitmap (val); - - FAIL: - if (status && val->image) { - cairo_surface_destroy (&val->image->base); - val->image = NULL; - } - - _cairo_ft_unscaled_font_unlock_face (unscaled); - - return status; -} - -const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { +static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { _cairo_ft_unscaled_font_destroy, +#if 0 _cairo_ft_unscaled_font_create_glyph +#endif }; /* cairo_ft_scaled_font_t */ @@ -1283,7 +1221,7 @@ const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = { typedef struct _cairo_ft_scaled_font { cairo_scaled_font_t base; cairo_ft_unscaled_font_t *unscaled; - int load_flags; + cairo_ft_options_t ft_options; } cairo_ft_scaled_font_t; const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend; @@ -1291,26 +1229,29 @@ const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend; /* The load flags passed to FT_Load_Glyph control aspects like hinting and * antialiasing. Here we compute them from the fields of a FcPattern. */ -static int -_get_pattern_load_flags (FcPattern *pattern) +static cairo_ft_options_t +_get_pattern_ft_options (FcPattern *pattern) { FcBool antialias, vertical_layout, hinting, autohint; + cairo_ft_options_t ft_options; int rgba; #ifdef FC_HINT_STYLE int hintstyle; #endif - int load_flags = 0; int target_flags = 0; + ft_options.load_flags = 0; + ft_options.extra_flags = 0; + /* disable antialiasing if requested */ if (FcPatternGetBool (pattern, FC_ANTIALIAS, 0, &antialias) != FcResultMatch) antialias = FcTrue; if (antialias) - load_flags |= FT_LOAD_NO_BITMAP; + ft_options.load_flags |= FT_LOAD_NO_BITMAP; else - load_flags |= FT_LOAD_MONOCHROME; + ft_options.load_flags |= FT_LOAD_MONOCHROME; /* disable hinting if requested */ if (FcPatternGetBool (pattern, @@ -1322,7 +1263,7 @@ _get_pattern_load_flags (FcPattern *pattern) hintstyle = FC_HINT_FULL; if (!hinting || hintstyle == FC_HINT_NONE) - load_flags |= FT_LOAD_NO_HINTING; + ft_options.load_flags |= FT_LOAD_NO_HINTING; if (antialias) { switch (hintstyle) { @@ -1363,7 +1304,7 @@ _get_pattern_load_flags (FcPattern *pattern) break; } - load_flags |= target_flags; + ft_options.load_flags |= target_flags; /* force autohinting if requested */ if (FcPatternGetBool (pattern, @@ -1371,16 +1312,29 @@ _get_pattern_load_flags (FcPattern *pattern) autohint = FcFalse; if (autohint) - load_flags |= FT_LOAD_FORCE_AUTOHINT; + ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT; if (FcPatternGetBool (pattern, FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch) vertical_layout = FcFalse; if (vertical_layout) - load_flags |= FT_LOAD_VERTICAL_LAYOUT; + ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT; - return load_flags; +#ifdef FC_EMBOLDEN + { + FcBool embolden; + + if (FcPatternGetBool (pattern, + FC_EMBOLDEN, 0, &embolden) != FcResultMatch) + embolden = FcFalse; + + if (embolden) + ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN; + } +#endif + + return ft_options; } static int @@ -1439,26 +1393,76 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options, - int load_flags) + cairo_ft_options_t ft_options) { cairo_ft_scaled_font_t *scaled_font = NULL; + FT_Face face; + FT_Size_Metrics *metrics; + cairo_font_extents_t fs_metrics; - scaled_font = malloc (sizeof(cairo_ft_scaled_font_t)); - if (scaled_font == NULL) + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) return NULL; + + scaled_font = malloc (sizeof(cairo_ft_scaled_font_t)); + if (scaled_font == NULL) { + _cairo_ft_unscaled_font_unlock_face (unscaled); + return NULL; + } + + _cairo_unscaled_font_reference (&unscaled->base); + scaled_font->unscaled = unscaled; + + if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) + ft_options.extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS; + + scaled_font->ft_options = ft_options; _cairo_scaled_font_init (&scaled_font->base, font_face, font_matrix, ctm, options, &cairo_ft_scaled_font_backend); - _cairo_unscaled_font_reference (&unscaled->base); - scaled_font->unscaled = unscaled; + _cairo_ft_unscaled_font_set_scale (unscaled, + &scaled_font->base.scale); - if (options->hint_metrics != CAIRO_HINT_METRICS_OFF) - load_flags |= PRIVATE_FLAG_HINT_METRICS; + metrics = &face->size->metrics; - scaled_font->load_flags = load_flags; + /* + * Get to unscaled metrics so that the upper level can get back to + * user space + */ + if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { + double x_factor, y_factor; + + if (unscaled->x_scale == 0) + x_factor = 0; + else + x_factor = 1 / unscaled->x_scale; + + if (unscaled->y_scale == 0) + y_factor = 0; + else + y_factor = 1 / unscaled->y_scale; + + fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor; + fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor; + fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor; + fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor; + } else { + double scale = face->units_per_EM; + + fs_metrics.ascent = face->ascender / scale; + fs_metrics.descent = - face->descender / scale; + fs_metrics.height = face->height / scale; + fs_metrics.max_x_advance = face->max_advance_width / scale; + } + + + /* FIXME: this doesn't do vertical layout atm. */ + fs_metrics.max_y_advance = 0.0; + + _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics); return &scaled_font->base; } @@ -1473,7 +1477,7 @@ static cairo_status_t _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, - const cairo_font_options_t *options, + const cairo_font_options_t *font_options, cairo_scaled_font_t **font) { FcPattern *pattern, *resolved; @@ -1484,7 +1488,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, int fcweight; cairo_matrix_t scale; cairo_ft_font_transform_t sf; - int load_flags; + cairo_ft_options_t ft_options; unsigned char *family = (unsigned char*) toy_face->family; pattern = FcPatternCreate (); @@ -1529,7 +1533,7 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, FcPatternAddInteger (pattern, FC_PIXEL_SIZE, sf.y_scale); FcConfigSubstitute (NULL, pattern, FcMatchPattern); - cairo_ft_font_options_substitute (options, pattern); + cairo_ft_font_options_substitute (font_options, pattern); FcDefaultSubstitute (pattern); resolved = FcFontMatch (NULL, pattern, &result); @@ -1540,12 +1544,12 @@ _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, if (!unscaled) goto FREE_RESOLVED; - load_flags = _get_pattern_load_flags (pattern); + ft_options = _get_pattern_ft_options (resolved); new_font = _cairo_ft_scaled_font_create (unscaled, &toy_face->base, font_matrix, ctm, - options, load_flags); + font_options, ft_options); _cairo_unscaled_font_destroy (&unscaled->base); @@ -1574,450 +1578,6 @@ _cairo_ft_scaled_font_fini (void *abstract_font) _cairo_unscaled_font_destroy (&scaled_font->unscaled->base); } -static void -_cairo_ft_scaled_font_get_glyph_cache_key (void *abstract_font, - cairo_glyph_cache_key_t *key) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - - key->unscaled = &scaled_font->unscaled->base; - key->scale = scaled_font->base.scale; - key->flags = scaled_font->load_flags; -} - -static cairo_status_t -_cairo_ft_scaled_font_text_to_glyphs (void *abstract_font, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - double x = 0., y = 0.; - size_t i; - uint32_t *ucs4 = NULL; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - FT_Face face; - cairo_glyph_cache_key_t key; - cairo_image_glyph_cache_entry_t *val; - cairo_cache_t *cache = NULL; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key); - - status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs); - if (status) - return status; - - face = cairo_ft_scaled_font_lock_face (&scaled_font->base); - if (!face) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL1; - } - - _cairo_lock_global_image_glyph_cache (); - cache = _cairo_get_global_image_glyph_cache (); - if (cache == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL2; - } - - *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t))); - if (*glyphs == NULL) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL2; - } - - for (i = 0; i < *num_glyphs; i++) - { - (*glyphs)[i].index = FT_Get_Char_Index (face, ucs4[i]); - (*glyphs)[i].x = x; - (*glyphs)[i].y = y; - - val = NULL; - key.index = (*glyphs)[i].index; - - if (_cairo_cache_lookup (cache, &key, (void **) &val, NULL) - != CAIRO_STATUS_SUCCESS || val == NULL) - continue; - - x += val->extents.x_advance; - y += val->extents.y_advance; - } - - FAIL2: - if (cache) - _cairo_unlock_global_image_glyph_cache (); - - cairo_ft_scaled_font_unlock_face (&scaled_font->base); - - FAIL1: - free (ucs4); - - return status; -} - - -static cairo_status_t -_cairo_ft_scaled_font_font_extents (void *abstract_font, - cairo_font_extents_t *extents) -{ - cairo_ft_scaled_font_t *scaled_font = abstract_font; - FT_Face face; - FT_Size_Metrics *metrics; - - face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled); - if (!face) - return CAIRO_STATUS_NO_MEMORY; - - metrics = &face->size->metrics; - - _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, - &scaled_font->base.scale); - - /* - * Get to unscaled metrics so that the upper level can get back to - * user space - */ - if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { - double x_factor, y_factor; - - if (scaled_font->unscaled->x_scale == 0) - x_factor = 0; - else - x_factor = 1 / scaled_font->unscaled->x_scale; - - if (scaled_font->unscaled->y_scale == 0) - y_factor = 0; - else - y_factor = 1 / scaled_font->unscaled->y_scale; - - extents->ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor; - extents->descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor; - extents->height = DOUBLE_FROM_26_6(metrics->height) * y_factor; - extents->max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor; - } else { - double scale = face->units_per_EM; - - extents->ascent = face->ascender / scale; - extents->descent = - face->descender / scale; - extents->height = face->height / scale; - extents->max_x_advance = face->max_advance_width / scale; - } - - /* FIXME: this doesn't do vertical layout atm. */ - extents->max_y_advance = 0.0; - - _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_ft_scaled_font_glyph_extents (void *abstract_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) -{ - int i; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_point_double_t origin; - cairo_point_double_t glyph_min, glyph_max; - /* Initialize just to squelch anti-helpful compiler warning. */ - cairo_point_double_t total_min = { 0, 0}, total_max = {0,0}; - - cairo_image_glyph_cache_entry_t *img = NULL; - cairo_cache_t *cache; - cairo_glyph_cache_key_t key; - - if (num_glyphs == 0) - { - extents->x_bearing = 0.0; - extents->y_bearing = 0.0; - extents->width = 0.0; - extents->height = 0.0; - extents->x_advance = 0.0; - extents->y_advance = 0.0; - - return CAIRO_STATUS_SUCCESS; - } - - origin.x = glyphs[0].x; - origin.y = glyphs[0].y; - - _cairo_lock_global_image_glyph_cache (); - cache = _cairo_get_global_image_glyph_cache (); - if (cache == NULL) { - _cairo_unlock_global_image_glyph_cache (); - return CAIRO_STATUS_NO_MEMORY; - } - - _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key); - - for (i = 0; i < num_glyphs; i++) - { - img = NULL; - key.index = glyphs[i].index; - if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL) - != CAIRO_STATUS_SUCCESS || img == NULL) - continue; - - /* XXX: Need to add code here to check the font's FcPattern - for FC_VERTICAL_LAYOUT and if set get vertBearingX/Y - instead. This will require that - cairo_ft_font_face_create_for_ft_face accept an - FcPattern. */ - glyph_min.x = glyphs[i].x + img->extents.x_bearing; - glyph_min.y = glyphs[i].y + img->extents.y_bearing; - glyph_max.x = glyph_min.x + img->extents.width; - glyph_max.y = glyph_min.y + img->extents.height; - - if (i==0) { - total_min = glyph_min; - total_max = glyph_max; - } else { - if (glyph_min.x < total_min.x) - total_min.x = glyph_min.x; - if (glyph_min.y < total_min.y) - total_min.y = glyph_min.y; - - if (glyph_max.x > total_max.x) - total_max.x = glyph_max.x; - if (glyph_max.y > total_max.y) - total_max.y = glyph_max.y; - } - } - _cairo_unlock_global_image_glyph_cache (); - - extents->x_bearing = (total_min.x - origin.x); - extents->y_bearing = (total_min.y - origin.y); - extents->width = (total_max.x - total_min.x); - extents->height = (total_max.y - total_min.y); - extents->x_advance = glyphs[i-1].x + (img == NULL ? 0 : img->extents.x_advance) - origin.x; - extents->y_advance = glyphs[i-1].y + (img == NULL ? 0 : img->extents.y_advance) - origin.y; - - return CAIRO_STATUS_SUCCESS; -} - - -static cairo_status_t -_cairo_ft_scaled_font_glyph_bbox (void *abstract_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox) -{ - cairo_image_glyph_cache_entry_t *img; - cairo_cache_t *cache; - cairo_glyph_cache_key_t key; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - - cairo_fixed_t x1, y1, x2, y2; - int i; - - bbox->p1.x = bbox->p1.y = CAIRO_MAXSHORT << 16; - bbox->p2.x = bbox->p2.y = CAIRO_MINSHORT << 16; - - _cairo_lock_global_image_glyph_cache (); - cache = _cairo_get_global_image_glyph_cache(); - - if (cache == NULL - || scaled_font == NULL - || glyphs == NULL) { - _cairo_unlock_global_image_glyph_cache (); - return CAIRO_STATUS_NO_MEMORY; - } - - _cairo_ft_scaled_font_get_glyph_cache_key (scaled_font, &key); - - for (i = 0; i < num_glyphs; i++) - { - - img = NULL; - key.index = glyphs[i].index; - - if (_cairo_cache_lookup (cache, &key, (void **) &img, NULL) - != CAIRO_STATUS_SUCCESS || img == NULL) - continue; - - x1 = _cairo_fixed_from_double (glyphs[i].x + img->size.x); - y1 = _cairo_fixed_from_double (glyphs[i].y + img->size.y); - x2 = x1 + _cairo_fixed_from_double (img->size.width); - y2 = y1 + _cairo_fixed_from_double (img->size.height); - - if (x1 < bbox->p1.x) - bbox->p1.x = x1; - - if (y1 < bbox->p1.y) - bbox->p1.y = y1; - - if (x2 > bbox->p2.x) - bbox->p2.x = x2; - - if (y2 > bbox->p2.y) - bbox->p2.y = y2; - } - _cairo_unlock_global_image_glyph_cache (); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_format_t -_select_text_mask_format (cairo_bool_t have_a1_glyphs, - cairo_bool_t have_a8_glyphs, - cairo_bool_t have_argb32_glyphs) -{ - if (have_a8_glyphs) - return CAIRO_FORMAT_A8; - - if (have_a1_glyphs && have_argb32_glyphs) - return CAIRO_FORMAT_A8; - - if (have_a1_glyphs) - return CAIRO_FORMAT_A1; - - if (have_argb32_glyphs) - return CAIRO_FORMAT_ARGB32; - - /* when there are no glyphs to draw, just pick something */ - return CAIRO_FORMAT_A8; -} - -static cairo_status_t -_cairo_ft_scaled_font_show_glyphs (void *abstract_font, - cairo_operator_t operator, - cairo_pattern_t *pattern, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - const cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_image_glyph_cache_entry_t **entries; - cairo_cache_t *cache; - cairo_glyph_cache_key_t key; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - cairo_surface_pattern_t glyph_pattern; - cairo_surface_t *mask; - cairo_surface_pattern_t mask_pattern; - cairo_format_t mask_format = CAIRO_FORMAT_A1; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_bool_t have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs; - int x, y; - int i; - - _cairo_lock_global_image_glyph_cache (); - cache = _cairo_get_global_image_glyph_cache(); - - if (cache == NULL - || scaled_font == NULL - || pattern == NULL - || surface == NULL - || glyphs == NULL) { - _cairo_unlock_global_image_glyph_cache (); - return CAIRO_STATUS_NO_MEMORY; - } - - key.unscaled = &scaled_font->unscaled->base; - key.scale = scaled_font->base.scale; - key.flags = scaled_font->load_flags; - - entries = malloc (num_glyphs * sizeof (cairo_image_glyph_cache_entry_t)); - if (!entries) - goto CLEANUP_CACHE; - - have_a1_glyphs = FALSE; - have_a8_glyphs = FALSE; - have_argb32_glyphs = FALSE; - - for (i = 0; i < num_glyphs; i++) - { - entries[i] = NULL; - key.index = glyphs[i].index; - - if (_cairo_cache_lookup (cache, &key, (void **) &entries[i], NULL) != CAIRO_STATUS_SUCCESS) - continue; - - switch (entries[i]->image->format) { - case CAIRO_FORMAT_A1: - have_a1_glyphs = TRUE; - break; - case CAIRO_FORMAT_A8: - have_a8_glyphs = TRUE; - break; - case CAIRO_FORMAT_ARGB32: - have_argb32_glyphs = TRUE; - break; - default: - break; - } - } - - mask_format = _select_text_mask_format (have_a1_glyphs, have_a8_glyphs, have_argb32_glyphs); - - mask = cairo_image_surface_create (mask_format, width, height); - if (!mask) - goto CLEANUP_ENTRIES; - - status = _cairo_surface_fill_rectangle (mask, CAIRO_OPERATOR_SOURCE, - CAIRO_COLOR_TRANSPARENT, - 0, 0, width, height); - if (status) - goto CLEANUP_MASK; - - for (i = 0; i < num_glyphs; i++) - { - if (entries[i] == NULL - || entries[i]->image == NULL) - continue; - - x = (int) floor (glyphs[i].x + 0.5); - y = (int) floor (glyphs[i].y + 0.5); - - _cairo_pattern_init_for_surface (&glyph_pattern, &(entries[i]->image->base)); - - status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, pattern, - &glyph_pattern.base, - mask, - x + entries[i]->size.x, - y + entries[i]->size.y, - 0, 0, - x + entries[i]->size.x - dest_x, - y + entries[i]->size.y - dest_y, - entries[i]->size.width, - entries[i]->size.height); - - _cairo_pattern_fini (&glyph_pattern.base); - - if (status) - goto CLEANUP_MASK; - } - - _cairo_pattern_init_for_surface (&mask_pattern, mask); - - status = _cairo_surface_composite (operator, pattern, &mask_pattern.base, - surface, - source_x, source_y, - 0, 0, - dest_x, dest_y, - width, height); - - _cairo_pattern_fini (&mask_pattern.base); - - CLEANUP_MASK: - cairo_surface_destroy (mask); - - CLEANUP_ENTRIES: - free (entries); - - CLEANUP_CACHE: - _cairo_unlock_global_image_glyph_cache (); - - return status; -} - - static int _move_to (FT_Vector *to, void *closure) { @@ -2107,17 +1667,11 @@ _cubic_to (FT_Vector *control1, FT_Vector *control2, } static cairo_status_t -_cairo_ft_scaled_font_glyph_path (void *abstract_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path) +_decompose_glyph_outline (FT_Face face, + cairo_font_options_t *options, + cairo_path_fixed_t **pathp) { - int i; - cairo_ft_scaled_font_t *scaled_font = abstract_font; - FT_GlyphSlot glyph; - FT_Face face; - FT_Error error; - FT_Outline_Funcs outline_funcs = { + static const FT_Outline_Funcs outline_funcs = { _move_to, _line_to, _conic_to, @@ -2125,52 +1679,239 @@ _cairo_ft_scaled_font_glyph_path (void *abstract_font, 0, /* shift */ 0, /* delta */ }; + static const FT_Matrix invert_y = { + DOUBLE_TO_16_16 (1.0), 0, + 0, DOUBLE_TO_16_16 (-1.0), + }; - face = cairo_ft_scaled_font_lock_face (abstract_font); - if (!face) + FT_GlyphSlot glyph; + cairo_path_fixed_t *path; + + path = _cairo_path_fixed_create (); + if (!path) return CAIRO_STATUS_NO_MEMORY; glyph = face->glyph; - for (i = 0; i < num_glyphs; i++) - { - FT_Matrix invert_y = { - DOUBLE_TO_16_16 (1.0), 0, - 0, DOUBLE_TO_16_16 (-1.0), - }; - - error = FT_Load_Glyph (scaled_font->unscaled->face, glyphs[i].index, scaled_font->load_flags | FT_LOAD_NO_BITMAP); - /* XXX: What to do in this error case? */ - if (error) - continue; - /* XXX: Do we want to support bitmap fonts here? */ - if (glyph->format == ft_glyph_format_bitmap) - continue; - - /* Font glyphs have an inverted Y axis compared to cairo. */ - FT_Outline_Transform (&glyph->outline, &invert_y); - FT_Outline_Translate (&glyph->outline, - DOUBLE_TO_26_6(glyphs[i].x), - DOUBLE_TO_26_6(glyphs[i].y)); - FT_Outline_Decompose (&glyph->outline, &outline_funcs, path); - } + /* Font glyphs have an inverted Y axis compared to cairo. */ + FT_Outline_Transform (&glyph->outline, &invert_y); + FT_Outline_Decompose (&glyph->outline, &outline_funcs, path); + _cairo_path_fixed_close_path (path); + *pathp = path; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +_cairo_ft_scaled_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info) +{ + cairo_text_extents_t fs_metrics; + cairo_ft_scaled_font_t *scaled_font = abstract_font; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_GlyphSlot glyph; + FT_Face face; + FT_Error error; + int load_flags = scaled_font->ft_options.load_flags; + FT_Glyph_Metrics *metrics; + double x_factor, y_factor; + + face = cairo_ft_scaled_font_lock_face (abstract_font); + if (!face) + return CAIRO_STATUS_NO_MEMORY; + + if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && + (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0) + load_flags |= FT_LOAD_NO_BITMAP; + + error = FT_Load_Glyph (scaled_font->unscaled->face, + _cairo_scaled_glyph_index(scaled_glyph), + load_flags); + + if (error) { + cairo_ft_scaled_font_unlock_face (abstract_font); + return CAIRO_STATUS_NO_MEMORY; + } + + glyph = face->glyph; + +#if HAVE_FT_GLYPHSLOT_EMBOLDEN + /* + * embolden glyphs if requested + */ + if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN) + FT_GlyphSlot_Embolden (glyph); +#endif + + if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) { + /* + * Compute font-space metrics + */ + metrics = &glyph->metrics; + + if (unscaled->x_scale == 0) + x_factor = 0; + else + x_factor = 1 / unscaled->x_scale; + + if (unscaled->y_scale == 0) + y_factor = 0; + else + y_factor = 1 / unscaled->y_scale; + + /* + * Note: the font's coordinate system is upside down from ours, so the + * Y coordinates of the bearing and advance need to be negated. + * + * Scale metrics back to glyph space from the scaled glyph space returned + * by FreeType + * + * If we want hinted metrics but aren't asking for hinted glyphs from + * FreeType, then we need to do the metric hinting ourselves. + */ + + if ((scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) && + (load_flags & FT_LOAD_NO_HINTING)) + { + FT_Pos x1, x2; + FT_Pos y1, y2; + FT_Pos advance; + + x1 = (metrics->horiBearingX) & -64; + x2 = (metrics->horiBearingX + metrics->width + 63) & -64; + y1 = (-metrics->horiBearingY) & -64; + y2 = (-metrics->horiBearingY + metrics->height + 63) & -64; + + advance = ((metrics->horiAdvance + 32) & -64); + + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor; + + fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor; + fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor; + + /* + * use untransformed advance values + * XXX uses horizontal advance only at present; should provide FT_LOAD_VERTICAL_LAYOUT + */ + fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor; + fs_metrics.y_advance = 0; + } else { + fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor; + fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor; + + fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor; + fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor; + + fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor; + fs_metrics.y_advance = 0 * y_factor; + } + + _cairo_scaled_glyph_set_metrics (scaled_glyph, + &scaled_font->base, + &fs_metrics); + } + + if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { + cairo_image_surface_t *surface; + cairo_status_t status; + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) + status = _render_glyph_outline (face, &scaled_font->base.options, + &surface); + else + status = _render_glyph_bitmap (face, &scaled_font->base.options, + &surface); + if (status) { + cairo_ft_scaled_font_unlock_face (abstract_font); + return status; + } + _cairo_scaled_glyph_set_surface (scaled_glyph, + &scaled_font->base, + surface); + } + + if (info & CAIRO_SCALED_GLYPH_INFO_PATH) { + cairo_path_fixed_t *path; + cairo_status_t status; + + /* + * A kludge -- the above code will trash the outline, + * so reload it. This will probably never occur though + */ + if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { + error = FT_Load_Glyph (face, + _cairo_scaled_glyph_index(scaled_glyph), + load_flags | FT_LOAD_NO_BITMAP); + + if (error) { + cairo_ft_scaled_font_unlock_face (abstract_font); + return CAIRO_STATUS_NO_MEMORY; + } + } + if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) + status = _decompose_glyph_outline (face, &scaled_font->base.options, + &path); + else + status = CAIRO_STATUS_NO_MEMORY; + + if (status) { + cairo_ft_scaled_font_unlock_face (abstract_font); + return status; + } + _cairo_scaled_glyph_set_path (scaled_glyph, + &scaled_font->base, + path); + } + cairo_ft_scaled_font_unlock_face (abstract_font); return CAIRO_STATUS_SUCCESS; } +static unsigned long +_cairo_ft_ucs4_to_index (void *abstract_font, + uint32_t ucs4) +{ + cairo_ft_scaled_font_t *scaled_font = abstract_font; + cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled; + FT_Face face; + FT_UInt index; + + face = _cairo_ft_unscaled_font_lock_face (unscaled); + if (!face) + return 0; + index = FT_Get_Char_Index (face, ucs4); + _cairo_ft_unscaled_font_unlock_face (unscaled); + return index; +} + +static cairo_int_status_t +_cairo_ft_show_glyphs (void *abstract_font, + cairo_operator_t operator, + cairo_pattern_t *pattern, + cairo_surface_t *surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + const cairo_glyph_t *glyphs, + int num_glyphs) +{ + return CAIRO_INT_STATUS_UNSUPPORTED; +} + const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = { _cairo_ft_scaled_font_create_toy, _cairo_ft_scaled_font_fini, - _cairo_ft_scaled_font_font_extents, - _cairo_ft_scaled_font_text_to_glyphs, - _cairo_ft_scaled_font_glyph_extents, - _cairo_ft_scaled_font_glyph_bbox, - _cairo_ft_scaled_font_show_glyphs, - _cairo_ft_scaled_font_glyph_path, - _cairo_ft_scaled_font_get_glyph_cache_key + _cairo_ft_scaled_glyph_init, + NULL, /* text_to_glyphs */ + _cairo_ft_ucs4_to_index, + _cairo_ft_show_glyphs, }; /* cairo_ft_font_face_t */ @@ -2241,7 +1982,7 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face, cairo_scaled_font_t **scaled_font) { cairo_ft_font_face_t *font_face = abstract_face; - int load_flags; + cairo_ft_options_t ft_options; /* The handling of font options is different depending on how the * font face was created. When the user creates a font face with @@ -2252,15 +1993,15 @@ _cairo_ft_font_face_scaled_font_create (void *abstract_face, * cairo_ft_font_options_substitute(), so *just* use those load * flags and ignore the options. */ + + ft_options = font_face->ft_options; if (font_face->unscaled->from_face) - load_flags = _get_options_load_flags (options) | font_face->load_flags; - else - load_flags = font_face->load_flags; + ft_options.load_flags |= _get_options_load_flags (options); *scaled_font = _cairo_ft_scaled_font_create (font_face->unscaled, &font_face->base, font_matrix, ctm, - options, load_flags); + options, ft_options); if (*scaled_font) return CAIRO_STATUS_SUCCESS; else @@ -2274,7 +2015,7 @@ static const cairo_font_face_backend_t _cairo_ft_font_face_backend = { static cairo_font_face_t * _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, - int load_flags) + cairo_ft_options_t ft_options) { cairo_ft_font_face_t *font_face; @@ -2283,7 +2024,8 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, font_face; font_face = font_face->next) { - if (font_face->load_flags == load_flags) + if (font_face->ft_options.load_flags == ft_options.load_flags && + font_face->ft_options.extra_flags == ft_options.extra_flags) return cairo_font_face_reference (&font_face->base); } @@ -2295,7 +2037,7 @@ _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled, font_face->unscaled = unscaled; _cairo_unscaled_font_reference (&unscaled->base); - font_face->load_flags = load_flags; + font_face->ft_options = ft_options; font_face->next = unscaled->faces; unscaled->faces = font_face; @@ -2432,7 +2174,7 @@ cairo_ft_font_face_create_for_pattern (FcPattern *pattern) } font_face = _cairo_ft_font_face_create (unscaled, - _get_pattern_load_flags (pattern)); + _get_pattern_ft_options (pattern)); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) @@ -2474,6 +2216,7 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face, { cairo_ft_unscaled_font_t *unscaled; cairo_font_face_t *font_face; + cairo_ft_options_t ft_options; unscaled = _cairo_ft_unscaled_font_create_from_face (face); if (unscaled == NULL) { @@ -2481,7 +2224,10 @@ cairo_ft_font_face_create_for_ft_face (FT_Face face, return (cairo_font_face_t *)&_cairo_font_face_nil; } - font_face = _cairo_ft_font_face_create (unscaled, load_flags); + ft_options.load_flags = load_flags; + ft_options.extra_flags = 0; + + font_face = _cairo_ft_font_face_create (unscaled, ft_options); _cairo_unscaled_font_destroy (&unscaled->base); if (font_face) { @@ -2547,10 +2293,9 @@ cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font) * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an * object can be created by calling cairo_scaled_font_create() on a * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(), - * cairo_ft_font_face_create_for_face()). + * cairo_ft_font_face_create_for_ft_face()). * - * Releases a face obtained with cairo_ft_font_lock_face(). See the - * documentation for that function for full details. + * Releases a face obtained with cairo_ft_scaled_font_lock_face(). **/ void cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font) diff --git a/gfx/cairo/cairo/src/cairo-ft.h b/gfx/cairo/cairo/src/cairo-ft.h index 3bdbae1bdcc..b59435fe7c0 100644 --- a/gfx/cairo/cairo/src/cairo-ft.h +++ b/gfx/cairo/cairo/src/cairo-ft.h @@ -49,21 +49,21 @@ CAIRO_BEGIN_DECLS -cairo_font_face_t * +cairo_public cairo_font_face_t * cairo_ft_font_face_create_for_pattern (FcPattern *pattern); -void +cairo_public void cairo_ft_font_options_substitute (const cairo_font_options_t *options, FcPattern *pattern); -cairo_font_face_t * +cairo_public cairo_font_face_t * cairo_ft_font_face_create_for_ft_face (FT_Face face, int load_flags); -FT_Face +cairo_public FT_Face cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *scaled_font); -void +cairo_public void cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *scaled_font); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-glitz-surface.c b/gfx/cairo/cairo/src/cairo-glitz-surface.c index 2684f9f0020..f6e5c1abd1d 100644 --- a/gfx/cairo/cairo/src/cairo-glitz-surface.c +++ b/gfx/cairo/cairo/src/cairo-glitz-surface.c @@ -35,6 +35,9 @@ typedef struct _cairo_glitz_surface { pixman_region16_t *clip; } cairo_glitz_surface_t; +static const cairo_surface_backend_t * +_cairo_glitz_surface_get_backend (void); + static cairo_status_t _cairo_glitz_surface_finish (void *abstract_surface) { @@ -45,7 +48,7 @@ _cairo_glitz_surface_finish (void *abstract_surface) glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0); pixman_region_destroy (surface->clip); } - + glitz_surface_destroy (surface->surface); return CAIRO_STATUS_SUCCESS; @@ -80,14 +83,15 @@ _cairo_glitz_surface_create_similar (void *abstract_src, glitz_format_t *gformat; drawable = glitz_surface_get_drawable (src->surface); - - gformat = glitz_find_standard_format (drawable, - _glitz_format_from_content (content)); + + gformat = + glitz_find_standard_format (drawable, + _glitz_format_from_content (content)); if (!gformat) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } - + surface = glitz_surface_create (drawable, gformat, width, height, 0, NULL); if (surface == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); @@ -95,7 +99,7 @@ _cairo_glitz_surface_create_similar (void *abstract_src, } crsurface = cairo_glitz_surface_create (surface); - + glitz_surface_destroy (surface); return crsurface; @@ -148,16 +152,16 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface, rect_out->width = width; rect_out->height = height; } - + if (surface->format->type == GLITZ_FORMAT_TYPE_COLOR) { if (surface->format->color.red_size > 0) { format.bpp = 32; - + if (surface->format->color.alpha_size > 0) format.alpha_mask = 0xff000000; else format.alpha_mask = 0x0; - + format.red_mask = 0xff0000; format.green_mask = 0xff00; format.blue_mask = 0xff; @@ -196,7 +200,7 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface, free (pixels); return CAIRO_STATUS_NO_MEMORY; } - + glitz_get_pixels (surface->surface, x1, y1, width, height, @@ -204,9 +208,9 @@ _cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface, buffer); glitz_buffer_destroy (buffer); - + image = (cairo_image_surface_t *) - _cairo_image_surface_create_with_masks (pixels, + _cairo_image_surface_create_with_masks (pixels, &format, width, height, pf.bytes_per_line); @@ -235,7 +239,7 @@ _cairo_glitz_surface_set_image (void *abstract_surface, pixman_format_t *format; int am, rm, gm, bm; char *data; - + format = pixman_image_get_format (image->pixman_image); if (!format) return CAIRO_STATUS_NO_MEMORY; @@ -266,15 +270,15 @@ _cairo_glitz_surface_set_image (void *abstract_surface, buffer = glitz_buffer_create_for_data (data); if (!buffer) return CAIRO_STATUS_NO_MEMORY; - + glitz_set_pixels (surface->surface, x_dst, y_dst, image->width, image->height, &pf, buffer); - + glitz_buffer_destroy (buffer); - + return CAIRO_STATUS_SUCCESS; } @@ -286,7 +290,7 @@ _cairo_glitz_surface_acquire_source_image (void *abstract_surface, cairo_glitz_surface_t *surface = abstract_surface; *image_extra = NULL; - + return _cairo_glitz_surface_get_image (surface, NULL, image_out, NULL); } @@ -349,15 +353,17 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface, if (src->backend == surface->base.backend) { - *clone_out = cairo_surface_reference (src); - + *clone_out = cairo_surface_reference (src); + return CAIRO_STATUS_SUCCESS; } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *) src; - cairo_content_t content = _cairo_content_from_format (image_src->format); - + cairo_content_t content; + + content = _cairo_content_from_format (image_src->format); + clone = (cairo_glitz_surface_t *) _cairo_glitz_surface_create_similar (surface, content, image_src->width, @@ -366,12 +372,12 @@ _cairo_glitz_surface_clone_similar (void *abstract_surface, return CAIRO_STATUS_NO_MEMORY; _cairo_glitz_surface_set_image (clone, image_src, 0, 0); - + *clone_out = &clone->base; return CAIRO_STATUS_SUCCESS; } - + return CAIRO_INT_STATUS_UNSUPPORTED; } @@ -430,12 +436,14 @@ _glitz_operator (cairo_operator_t op) case CAIRO_OPERATOR_ADD: return GLITZ_OPERATOR_ADD; case CAIRO_OPERATOR_SATURATE: - /* XXX: OVER is definitely not the right thing here, (but it - * is what the original glitz backend code has always - * done). Cairo's SATURATE operator is the native GL - * compositing mode, (from my understanding). So why isn't - * there a GLITZ_OPERATOR_SATURATE for us to use here? */ - return GLITZ_OPERATOR_OVER; + /* XXX: This line should never be reached. Glitz backend should bail + out earlier if saturate operator is used. OpenGL can't do saturate + with pre-multiplied colors. Solid colors can still be done as we + can just un-pre-multiply them. However, support for that will have + to be added to glitz. */ + + /* fall-through */ + break; } ASSERT_NOT_REACHED; @@ -454,16 +462,59 @@ _glitz_operator (cairo_operator_t op) static glitz_status_t _glitz_ensure_target (glitz_surface_t *surface) { - if (glitz_surface_get_attached_drawable (surface) || - CAIRO_GLITZ_FEATURE_OK (surface, FRAMEBUFFER_OBJECT)) - return CAIRO_STATUS_SUCCESS; + if (!glitz_surface_get_attached_drawable (surface)) + { + glitz_drawable_format_t *target_format, templ; + glitz_format_t *format; + glitz_drawable_t *drawable, *target; + unsigned int width, height; + unsigned long mask; - return CAIRO_INT_STATUS_UNSUPPORTED; + drawable = glitz_surface_get_drawable (surface); + format = glitz_surface_get_format (surface); + width = glitz_surface_get_width (surface); + height = glitz_surface_get_height (surface); + + if (format->type != GLITZ_FORMAT_TYPE_COLOR) + return CAIRO_INT_STATUS_UNSUPPORTED; + + templ.color = format->color; + templ.depth_size = 0; + templ.stencil_size = 0; + templ.doublebuffer = 0; + templ.samples = 1; + + mask = + GLITZ_FORMAT_RED_SIZE_MASK | + GLITZ_FORMAT_GREEN_SIZE_MASK | + GLITZ_FORMAT_BLUE_SIZE_MASK | + GLITZ_FORMAT_ALPHA_SIZE_MASK | + GLITZ_FORMAT_DEPTH_SIZE_MASK | + GLITZ_FORMAT_STENCIL_SIZE_MASK | + GLITZ_FORMAT_DOUBLEBUFFER_MASK | + GLITZ_FORMAT_SAMPLES_MASK; + + target_format = glitz_find_drawable_format (drawable, mask, &templ, 0); + if (!target_format) + return CAIRO_INT_STATUS_UNSUPPORTED; + + target = glitz_create_drawable (drawable, target_format, + width, height); + if (!target) + return CAIRO_INT_STATUS_UNSUPPORTED; + + glitz_surface_attach (surface, target, + GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); + + glitz_drawable_destroy (target); + } + + return CAIRO_STATUS_SUCCESS; } typedef struct _cairo_glitz_surface_attributes { cairo_surface_attributes_t base; - + glitz_fill_t fill; glitz_filter_t filter; glitz_fixed16_16_t *params; @@ -498,17 +549,17 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, unsigned char alpha; glitz_buffer_t *buffer; static glitz_pixel_format_t format = { - { - 32, - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }; - + { + 32, + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }; + /* XXX: the current color gradient acceleration provided by glitz is * experimental, it's been proven inappropriate in a number of ways, * most importantly, it's currently implemented as filters and @@ -524,7 +575,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, if (pattern->type == CAIRO_PATTERN_RADIAL) { cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern; - + if (grad->center0.x != grad->center1.x || grad->center0.y != grad->center1.y) break; @@ -532,7 +583,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, if (!CAIRO_GLITZ_FEATURE_OK (dst->surface, FRAGMENT_PROGRAM)) break; - + if (pattern->filter != CAIRO_FILTER_BILINEAR && pattern->filter != CAIRO_FILTER_GOOD && pattern->filter != CAIRO_FILTER_BEST) @@ -542,7 +593,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, for (i = 1; i < gradient->n_stops; i++) { unsigned char a; - + a = gradient->stops[i].color.alpha * 0xff; if (a != alpha) break; @@ -585,11 +636,11 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, for (i = 0; i < gradient->n_stops; i++) { pixels[i] = - (((int) alpha) << 24) | - (((int) gradient->stops[i].color.red * alpha) << 16) | - (((int) gradient->stops[i].color.green * alpha) << 8) | - (((int) gradient->stops[i].color.blue * alpha)); - + (((int) alpha) << 24) | + (((int) gradient->stops[i].color.red * alpha) << 16) | + (((int) gradient->stops[i].color.green * alpha) << 8) | + (((int) gradient->stops[i].color.blue * alpha)); + params[4 + 3 * i] = gradient->stops[i].offset; params[5 + 3 * i] = i << 16; params[6 + 3 * i] = 0; @@ -603,7 +654,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, if (pattern->type == CAIRO_PATTERN_LINEAR) { cairo_linear_pattern_t *grad = (cairo_linear_pattern_t *) pattern; - + params[0] = _cairo_fixed_from_double (grad->point0.x); params[1] = _cairo_fixed_from_double (grad->point0.y); params[2] = _cairo_fixed_from_double (grad->point1.x); @@ -613,7 +664,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, else { cairo_radial_pattern_t *grad = (cairo_radial_pattern_t *) pattern; - + params[0] = _cairo_fixed_from_double (grad->center0.x); params[1] = _cairo_fixed_from_double (grad->center0.y); params[2] = _cairo_fixed_from_double (grad->radius0); @@ -653,7 +704,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, &attr->base); if (status) return status; - + if (src) { switch (attr->base.extend) { @@ -680,7 +731,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, attr->filter = GLITZ_FILTER_BILINEAR; break; } - + attr->params = NULL; attr->n_params = 0; attr->acquired = TRUE; @@ -688,7 +739,7 @@ _cairo_glitz_pattern_acquire_surface (cairo_pattern_t *pattern, } *surface_out = src; - + return CAIRO_STATUS_SUCCESS; } @@ -744,12 +795,12 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, } else { _cairo_pattern_init_copy (&tmp.base, src); } - + status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, src_x, src_y, width, height, src_out, sattr); - + _cairo_pattern_fini (&tmp.base); if (status) @@ -758,12 +809,12 @@ _cairo_glitz_pattern_acquire_surfaces (cairo_pattern_t *src, if (mask) { _cairo_pattern_init_copy (&tmp.base, mask); - + status = _cairo_glitz_pattern_acquire_surface (&tmp.base, dst, mask_x, mask_y, width, height, mask_out, mattr); - + if (status) _cairo_glitz_pattern_release_surface (&tmp.base, *src_out, sattr); @@ -839,14 +890,14 @@ _cairo_glitz_surface_composite (cairo_operator_t op, mask_y + mask_attr.base.y_offset, dst_x, dst_y, width, height); - + if (mask_attr.n_params) free (mask_attr.params); - + _cairo_glitz_pattern_release_surface (mask_pattern, mask, &mask_attr); } else - { + { glitz_composite (_glitz_operator (op), src->surface, NULL, @@ -865,7 +916,7 @@ _cairo_glitz_surface_composite (cairo_operator_t op, if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; - + return CAIRO_STATUS_SUCCESS; } @@ -893,7 +944,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst, else { cairo_glitz_surface_t *src; - + if (op == CAIRO_OPERATOR_SATURATE) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -909,7 +960,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst, return CAIRO_STATUS_NO_MEMORY; glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT); - + while (n_rects--) { glitz_composite (_glitz_operator (op), @@ -922,7 +973,7 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst, rects->width, rects->height); rects++; } - + cairo_surface_destroy (&src->base); } @@ -946,8 +997,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, cairo_trapezoid_t *traps, int n_traps) { - cairo_pattern_union_t tmp_src_pattern; - cairo_pattern_t *src_pattern; + cairo_pattern_union_t tmp_src_pattern; + cairo_pattern_t *src_pattern; cairo_glitz_surface_attributes_t attributes; cairo_glitz_surface_t *dst = abstract_dst; cairo_glitz_surface_t *src; @@ -969,8 +1020,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (pattern->type == CAIRO_PATTERN_SURFACE) { _cairo_pattern_init_copy (&tmp_src_pattern.base, pattern); - - status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, dst, + + status = _cairo_glitz_pattern_acquire_surface (&tmp_src_pattern.base, + dst, src_x, src_y, width, height, &src, &attributes); @@ -1029,9 +1081,9 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, glitz_surface_set_filter (mask->surface, GLITZ_FILTER_BILINEAR, NULL, 0); - + size *= format.vertex.bytes_per_vertex; - + while (n_traps) { if (data_size < size) @@ -1049,7 +1101,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (buffer) glitz_buffer_destroy (buffer); - + buffer = glitz_buffer_create_for_data (data); if (!buffer) { free (data); @@ -1060,19 +1112,19 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, return CAIRO_STATUS_NO_MEMORY; } } - + offset += glitz_add_trapezoids (buffer, offset, size - offset, format.vertex.type, mask->surface, (glitz_trapezoid_t *) traps, n_traps, &n_trap_added); - + n_traps -= n_trap_added; traps += n_trap_added; size *= 2; } - + glitz_set_geometry (dst->surface, GLITZ_GEOMETRY_TYPE_VERTEX, &format, buffer); @@ -1100,7 +1152,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, /* using negative stride */ ptr = (unsigned char *) data + stride * (height - 1); - + image = (cairo_image_surface_t *) cairo_image_surface_create_for_data (ptr, CAIRO_FORMAT_A8, @@ -1132,7 +1184,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, } _cairo_glitz_surface_set_attributes (src, &attributes); - + glitz_composite (_glitz_operator (op), src->surface, mask->surface, @@ -1152,7 +1204,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (buffer) glitz_buffer_destroy (buffer); - + free (data); _cairo_glitz_pattern_release_surface (src_pattern, src, &attributes); @@ -1164,7 +1216,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op, if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; - + return CAIRO_STATUS_SUCCESS; } @@ -1178,7 +1230,7 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface, { glitz_box_t *box; int n; - + if (!surface->clip) { surface->clip = pixman_region_create (); @@ -1194,13 +1246,13 @@ _cairo_glitz_surface_set_clip_region (void *abstract_surface, else { glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0); - + if (surface->clip) pixman_region_destroy (surface->clip); surface->clip = NULL; } - + return CAIRO_STATUS_SUCCESS; } @@ -1218,8 +1270,6 @@ _cairo_glitz_surface_get_extents (void *abstract_surface, return CAIRO_STATUS_SUCCESS; } -#define CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT 0x100000 - #define CAIRO_GLITZ_AREA_AVAILABLE 0 #define CAIRO_GLITZ_AREA_DIVIDED 1 #define CAIRO_GLITZ_AREA_OCCUPIED 2 @@ -1246,10 +1296,10 @@ static cairo_glitz_area_t _empty_area = { typedef struct _cairo_glitz_area_funcs { cairo_status_t (*move_in) (cairo_glitz_area_t *area, void *closure); - + void (*move_out) (cairo_glitz_area_t *area, void *closure); - + int (*compare_score) (cairo_glitz_area_t *area, void *closure1, void *closure2); @@ -1268,7 +1318,7 @@ _cairo_glitz_area_move_in (cairo_glitz_area_t *area, { area->closure = closure; area->state = CAIRO_GLITZ_AREA_OCCUPIED; - + return (*area->root->funcs->move_in) (area, area->closure); } @@ -1294,7 +1344,7 @@ _cairo_glitz_area_create (cairo_glitz_root_area_t *root, { cairo_glitz_area_t *area; int n = 4; - + area = malloc (sizeof (cairo_glitz_area_t)); if (!area) return NULL; @@ -1307,7 +1357,7 @@ _cairo_glitz_area_create (cairo_glitz_root_area_t *root, area->root = root; area->closure = NULL; area->state = CAIRO_GLITZ_AREA_AVAILABLE; - + while (n--) area->area[n] = NULL; @@ -1316,7 +1366,7 @@ _cairo_glitz_area_create (cairo_glitz_root_area_t *root, static void _cairo_glitz_area_destroy (cairo_glitz_area_t *area) -{ +{ if (area == NULL) return; @@ -1327,11 +1377,11 @@ _cairo_glitz_area_destroy (cairo_glitz_area_t *area) else { int n = 4; - + while (n--) _cairo_glitz_area_destroy (area->area[n]); } - + free (area); } @@ -1340,7 +1390,7 @@ _cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area) { if (!area) return NULL; - + switch (area->state) { case CAIRO_GLITZ_AREA_OCCUPIED: return area; @@ -1349,7 +1399,7 @@ _cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area) case CAIRO_GLITZ_AREA_DIVIDED: { cairo_glitz_area_t *tmp, *top = NULL; int i; - + for (i = 0; i < 4; i++) { tmp = _cairo_glitz_area_get_top_scored_sub_area (area->area[i]); @@ -1368,7 +1418,7 @@ _cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t *area) return top; } } - + return NULL; } @@ -1392,12 +1442,12 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, area->closure, closure) >= 0) return CAIRO_INT_STATUS_UNSUPPORTED; - + _cairo_glitz_area_move_out (area); } else { return CAIRO_INT_STATUS_UNSUPPORTED; } - + /* fall-through */ case CAIRO_GLITZ_AREA_AVAILABLE: { if (area->level == area->root->max_level || @@ -1408,15 +1458,15 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, else { int dx[4], dy[4], w[4], h[4], i; - + dx[0] = dx[2] = dy[0] = dy[1] = 0; - + w[0] = w[2] = dx[1] = dx[3] = width; h[0] = h[1] = dy[2] = dy[3] = height; w[1] = w[3] = area->width - width; h[2] = h[3] = area->height - height; - + for (i = 0; i < 2; i++) { if (w[i]) @@ -1440,12 +1490,12 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, } area->state = CAIRO_GLITZ_AREA_DIVIDED; - + status = _cairo_glitz_area_find (area->area[0], width, height, kick_out, closure); if (status == CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; } } break; case CAIRO_GLITZ_AREA_DIVIDED: { @@ -1464,7 +1514,7 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, kick_out, closure); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; - + rejected = TRUE; } } @@ -1492,7 +1542,7 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, _cairo_glitz_area_destroy (area->area[i]); area->area[i] = NULL; } - + area->closure = NULL; area->state = CAIRO_GLITZ_AREA_AVAILABLE; @@ -1500,7 +1550,7 @@ _cairo_glitz_area_find (cairo_glitz_area_t *area, TRUE, closure); if (status == CAIRO_STATUS_SUCCESS) return CAIRO_STATUS_SUCCESS; - + } break; } @@ -1520,7 +1570,7 @@ _cairo_glitz_root_area_init (cairo_glitz_root_area_t *root, root->area = _cairo_glitz_area_create (root, 0, 0, 0, width, height); if (!root->area) return CAIRO_STATUS_NO_MEMORY; - + return CAIRO_STATUS_SUCCESS; } @@ -1530,6 +1580,56 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root) _cairo_glitz_area_destroy (root->area); } +typedef struct _cairo_glitz_surface_font_private { + cairo_glitz_root_area_t root; + glitz_surface_t *surface; +} cairo_glitz_surface_font_private_t; + +typedef struct _cairo_glitz_surface_glyph_private { + cairo_glitz_area_t *area; + cairo_bool_t locked; + cairo_point_double_t p1, p2; +} cairo_glitz_surface_glyph_private_t; + +static cairo_status_t +_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area, + void *closure) +{ + cairo_glitz_surface_glyph_private_t *glyph_private = closure; + + glyph_private->area = area; + + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area, + void *closure) +{ + cairo_glitz_surface_glyph_private_t *glyph_private = closure; + + glyph_private->area = NULL; +} + +static int +_cairo_glitz_glyph_compare (cairo_glitz_area_t *area, + void *closure1, + void *closure2) +{ + cairo_glitz_surface_glyph_private_t *glyph_private = closure1; + + if (glyph_private->locked) + return 1; + + return -1; +} + +static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = { + _cairo_glitz_glyph_move_in, + _cairo_glitz_glyph_move_out, + _cairo_glitz_glyph_compare +}; + #define GLYPH_CACHE_TEXTURE_SIZE 512 #define GLYPH_CACHE_MAX_LEVEL 64 #define GLYPH_CACHE_MAX_HEIGHT 72 @@ -1549,266 +1649,170 @@ _cairo_glitz_root_area_fini (cairo_glitz_root_area_t *root) WRITE_VEC2 (ptr, _vx1, _vy2); \ WRITE_VEC2 (ptr, (p1)->x, (p1)->y) -typedef struct _cairo_glitz_glyph_cache { - cairo_cache_t base; - cairo_glitz_root_area_t root; - glitz_surface_t *surface; -} cairo_glitz_glyph_cache_t; - -typedef struct { - cairo_glyph_cache_key_t key; - int ref_count; - cairo_glyph_size_t size; - cairo_glitz_area_t *area; - cairo_bool_t locked; - cairo_point_double_t p1, p2; -} cairo_glitz_glyph_cache_entry_t; - static cairo_status_t -_cairo_glitz_glyph_move_in (cairo_glitz_area_t *area, - void *closure) +_cairo_glitz_surface_font_init (cairo_glitz_surface_t *surface, + cairo_scaled_font_t *scaled_font, + cairo_format_t format) { - cairo_glitz_glyph_cache_entry_t *entry = closure; - - entry->area = area; + cairo_glitz_surface_font_private_t *font_private; + glitz_drawable_t *drawable; + glitz_format_t *surface_format = NULL; + cairo_int_status_t status; + + drawable = glitz_surface_get_drawable (surface->surface); + + switch (format) { + case CAIRO_FORMAT_A8: + surface_format = + glitz_find_standard_format (drawable, GLITZ_STANDARD_A8); + break; + case CAIRO_FORMAT_ARGB32: + surface_format = + glitz_find_standard_format (drawable, GLITZ_STANDARD_ARGB32); + default: + break; + } + + if (!surface_format) + return CAIRO_INT_STATUS_UNSUPPORTED; + + font_private = malloc (sizeof (cairo_glitz_surface_font_private_t)); + if (!font_private) + return CAIRO_STATUS_NO_MEMORY; + + font_private->surface = glitz_surface_create (drawable, surface_format, + GLYPH_CACHE_TEXTURE_SIZE, + GLYPH_CACHE_TEXTURE_SIZE, + 0, NULL); + if (font_private->surface == NULL) + { + free (font_private); + + return CAIRO_INT_STATUS_UNSUPPORTED; + } + + if (format == CAIRO_FORMAT_ARGB32) + glitz_surface_set_component_alpha (font_private->surface, 1); + + status = _cairo_glitz_root_area_init (&font_private->root, + GLYPH_CACHE_MAX_LEVEL, + GLYPH_CACHE_TEXTURE_SIZE, + GLYPH_CACHE_TEXTURE_SIZE, + &_cairo_glitz_area_funcs); + if (status != CAIRO_STATUS_SUCCESS) + { + glitz_surface_destroy (font_private->surface); + free (font_private); + + return status; + } + + scaled_font->surface_private = font_private; + scaled_font->surface_backend = _cairo_glitz_surface_get_backend (); return CAIRO_STATUS_SUCCESS; } static void -_cairo_glitz_glyph_move_out (cairo_glitz_area_t *area, - void *closure) +_cairo_glitz_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) { - cairo_glitz_glyph_cache_entry_t *entry = closure; - - entry->area = NULL; -} + cairo_glitz_surface_font_private_t *font_private; -static int -_cairo_glitz_glyph_compare (cairo_glitz_area_t *area, - void *closure1, - void *closure2) -{ - cairo_glitz_glyph_cache_entry_t *entry = closure1; - - if (entry->locked) - return 1; - - return -1; -} - -static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs = { - _cairo_glitz_glyph_move_in, - _cairo_glitz_glyph_move_out, - _cairo_glitz_glyph_compare -}; - -static cairo_status_t -_cairo_glitz_glyph_cache_create_entry (void *abstract_cache, - void *abstract_key, - void **return_entry) -{ - cairo_glitz_glyph_cache_entry_t *entry; - cairo_glyph_cache_key_t *key = abstract_key; - - cairo_status_t status; - cairo_cache_t *im_cache; - cairo_image_glyph_cache_entry_t *im; - - unsigned long entry_memory = 0; - - entry = malloc (sizeof (cairo_glitz_glyph_cache_entry_t)); - if (!entry) - return CAIRO_STATUS_NO_MEMORY; - - _cairo_lock_global_image_glyph_cache (); - - im_cache = _cairo_get_global_image_glyph_cache (); - if (im_cache == NULL) { - _cairo_unlock_global_image_glyph_cache (); - free (entry); - return CAIRO_STATUS_NO_MEMORY; - } - - status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL); - if (status != CAIRO_STATUS_SUCCESS || im == NULL) { - _cairo_unlock_global_image_glyph_cache (); - free (entry); - return CAIRO_STATUS_NO_MEMORY; - } - - if (im->image) - entry_memory = im->image->width * im->image->stride; - - _cairo_unlock_global_image_glyph_cache (); - - entry->ref_count = 1; - entry->key = *key; - entry->key.base.memory = entry_memory; - entry->area = NULL; - entry->locked = FALSE; - - _cairo_unscaled_font_reference (entry->key.unscaled); - - *return_entry = entry; - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_glitz_glyph_cache_destroy_entry (void *abstract_cache, - void *abstract_entry) -{ - cairo_glitz_glyph_cache_entry_t *entry = abstract_entry; - - entry->ref_count--; - if (entry->ref_count) - return; - - if (entry->area) - _cairo_glitz_area_move_out (entry->area); - - _cairo_unscaled_font_destroy (entry->key.unscaled); - - free (entry); -} - -static void -_cairo_glitz_glyph_cache_entry_reference (void *abstract_entry) -{ - cairo_glitz_glyph_cache_entry_t *entry = abstract_entry; - - entry->ref_count++; -} - -static void -_cairo_glitz_glyph_cache_destroy_cache (void *abstract_cache) -{ - cairo_glitz_glyph_cache_t *cache = abstract_cache; - - _cairo_glitz_root_area_fini (&cache->root); - - glitz_surface_destroy (cache->surface); -} - -static const cairo_cache_backend_t _cairo_glitz_glyph_cache_backend = { - _cairo_glyph_cache_hash, - _cairo_glyph_cache_keys_equal, - _cairo_glitz_glyph_cache_create_entry, - _cairo_glitz_glyph_cache_destroy_entry, - _cairo_glitz_glyph_cache_destroy_cache -}; - -static cairo_glitz_glyph_cache_t *_cairo_glitz_glyph_caches = NULL; - -static cairo_glitz_glyph_cache_t * -_cairo_glitz_get_glyph_cache (cairo_glitz_surface_t *surface) -{ - cairo_glitz_glyph_cache_t *cache; - glitz_drawable_t *drawable; - glitz_format_t *format; - - /* - * FIXME: caches should be thread specific, display specific and screen - * specific. - */ - - if (_cairo_glitz_glyph_caches) - return _cairo_glitz_glyph_caches; - - drawable = glitz_surface_get_drawable (surface->surface); - - format = glitz_find_standard_format (drawable, GLITZ_STANDARD_A8); - if (!format) - return NULL; - - cache = malloc (sizeof (cairo_glitz_glyph_cache_t)); - if (!cache) - return NULL; - - cache->surface = - glitz_surface_create (drawable, format, - GLYPH_CACHE_TEXTURE_SIZE, - GLYPH_CACHE_TEXTURE_SIZE, - 0, NULL); - if (cache->surface == NULL) + font_private = scaled_font->surface_private; + if (font_private) { - free (cache); - return NULL; + _cairo_glitz_root_area_fini (&font_private->root); + glitz_surface_destroy (font_private->surface); + free (font_private); } +} - if (_cairo_glitz_root_area_init (&cache->root, - GLYPH_CACHE_MAX_LEVEL, - GLYPH_CACHE_TEXTURE_SIZE, - GLYPH_CACHE_TEXTURE_SIZE, - &_cairo_glitz_area_funcs)) - { - glitz_surface_destroy (cache->surface); - free (cache); - return NULL; - } +static void +_cairo_glitz_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font) +{ + cairo_glitz_surface_glyph_private_t *glyph_private; - if (_cairo_cache_init (&cache->base, - &_cairo_glitz_glyph_cache_backend, - CAIRO_GLITZ_GLYPH_CACHE_MEMORY_DEFAULT)) + glyph_private = scaled_glyph->surface_private; + if (glyph_private) { - _cairo_glitz_root_area_fini (&cache->root); - glitz_surface_destroy (cache->surface); - free (cache); - return NULL; + if (glyph_private->area) + _cairo_glitz_area_move_out (glyph_private->area); + + free (glyph_private); } - - _cairo_glitz_glyph_caches = cache; - - return cache; } #define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536) static cairo_status_t -_cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache, - cairo_glitz_glyph_cache_entry_t *entry, - cairo_image_glyph_cache_entry_t *image_entry) +_cairo_glitz_surface_add_glyph (cairo_glitz_surface_t *surface, + cairo_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) { - glitz_point_fixed_t p1, p2; - glitz_pixel_format_t pf; - glitz_buffer_t *buffer; - pixman_format_t *format; - int am, rm, gm, bm; + cairo_image_surface_t *glyph_surface = scaled_glyph->surface; + cairo_glitz_surface_font_private_t *font_private; + cairo_glitz_surface_glyph_private_t *glyph_private; + glitz_point_fixed_t p1, p2; + glitz_pixel_format_t pf; + glitz_buffer_t *buffer; + pixman_format_t *format; + int am, rm, gm, bm; + cairo_int_status_t status; - entry->size = image_entry->size; - - if (entry->size.width > GLYPH_CACHE_MAX_WIDTH || - entry->size.height > GLYPH_CACHE_MAX_HEIGHT) + glyph_private = scaled_glyph->surface_private; + if (glyph_private == NULL) + { + glyph_private = malloc (sizeof (cairo_glitz_surface_glyph_private_t)); + if (!glyph_private) + return CAIRO_STATUS_NO_MEMORY; + + glyph_private->area = NULL; + glyph_private->locked = FALSE; + + scaled_glyph->surface_private = (void *) glyph_private; + } + + if (glyph_surface->width > GLYPH_CACHE_MAX_WIDTH || + glyph_surface->height > GLYPH_CACHE_MAX_HEIGHT) return CAIRO_STATUS_SUCCESS; - if ((entry->size.width == 0 && entry->size.height == 0) || - !image_entry->image) + if (scaled_font->surface_private == NULL) { - entry->area = &_empty_area; + status = _cairo_glitz_surface_font_init (surface, scaled_font, + glyph_surface->format); + if (status) + return status; + } + + font_private = scaled_font->surface_private; + + if (glyph_surface->width == 0 || glyph_surface->height == 0) + { + glyph_private->area = &_empty_area; return CAIRO_STATUS_SUCCESS; } - - format = pixman_image_get_format (image_entry->image->pixman_image); + + format = pixman_image_get_format (glyph_surface->pixman_image); if (!format) return CAIRO_STATUS_NO_MEMORY; - - if (_cairo_glitz_area_find (cache->root.area, - entry->size.width, - entry->size.height, - FALSE, entry)) + + if (_cairo_glitz_area_find (font_private->root.area, + glyph_surface->width, + glyph_surface->height, + FALSE, glyph_private)) { - if (_cairo_glitz_area_find (cache->root.area, - entry->size.width, - entry->size.height, - TRUE, entry)) + if (_cairo_glitz_area_find (font_private->root.area, + glyph_surface->width, + glyph_surface->height, + TRUE, glyph_private)) return CAIRO_STATUS_SUCCESS; } - - buffer = glitz_buffer_create_for_data (image_entry->image->data); + + buffer = glitz_buffer_create_for_data (glyph_surface->data); if (!buffer) { - _cairo_glitz_area_move_out (entry->area); + _cairo_glitz_area_move_out (glyph_private->area); return CAIRO_STATUS_NO_MEMORY; } @@ -1818,34 +1822,34 @@ _cairo_glitz_cache_glyph (cairo_glitz_glyph_cache_t *cache, pf.masks.red_mask = rm; pf.masks.green_mask = gm; pf.masks.blue_mask = bm; - - pf.bytes_per_line = image_entry->image->stride; + + pf.bytes_per_line = glyph_surface->stride; pf.scanline_order = GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP; pf.xoffset = 0; pf.skip_lines = 0; - - glitz_set_pixels (cache->surface, - entry->area->x, - entry->area->y, - entry->size.width, - entry->size.height, + + glitz_set_pixels (font_private->surface, + glyph_private->area->x, + glyph_private->area->y, + glyph_surface->width, + glyph_surface->height, &pf, buffer); glitz_buffer_destroy (buffer); - - p1.x = entry->area->x << 16; - p1.y = entry->area->y << 16; - p2.x = (entry->area->x + entry->size.width) << 16; - p2.y = (entry->area->y + entry->size.height) << 16; - - glitz_surface_translate_point (cache->surface, &p1, &p1); - glitz_surface_translate_point (cache->surface, &p2, &p2); - - entry->p1.x = FIXED_TO_FLOAT (p1.x); - entry->p1.y = FIXED_TO_FLOAT (p1.y); - entry->p2.x = FIXED_TO_FLOAT (p2.x); - entry->p2.y = FIXED_TO_FLOAT (p2.y); - + + p1.x = glyph_private->area->x << 16; + p1.y = glyph_private->area->y << 16; + p2.x = (glyph_private->area->x + glyph_surface->width) << 16; + p2.y = (glyph_private->area->y + glyph_surface->height) << 16; + + glitz_surface_translate_point (font_private->surface, &p1, &p1); + glitz_surface_translate_point (font_private->surface, &p2, &p2); + + glyph_private->p1.x = FIXED_TO_FLOAT (p1.x); + glyph_private->p1.y = FIXED_TO_FLOAT (p1.y); + glyph_private->p2.x = FIXED_TO_FLOAT (p2.x); + glyph_private->p2.y = FIXED_TO_FLOAT (p2.y); + return CAIRO_STATUS_SUCCESS; } @@ -1865,21 +1869,21 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs) { - cairo_glitz_surface_attributes_t attributes; - cairo_glitz_surface_t *dst = abstract_surface; - cairo_glitz_surface_t *src; - cairo_glitz_glyph_cache_t *cache; - cairo_glitz_glyph_cache_entry_t *stack_entries[N_STACK_BUF]; - cairo_glitz_glyph_cache_entry_t **entries; - cairo_glyph_cache_key_t key; - glitz_float_t stack_vertices[N_STACK_BUF * 16]; - glitz_float_t *vertices; - glitz_buffer_t *buffer; - cairo_int_status_t status; - int i, cached_glyphs = 0; - int remaining_glyps = num_glyphs; - glitz_float_t x1, y1, x2, y2; - static glitz_vertex_format_t format = { + cairo_glitz_surface_attributes_t attributes; + cairo_glitz_surface_glyph_private_t *glyph_private; + cairo_glitz_surface_t *dst = abstract_surface; + cairo_glitz_surface_t *src; + cairo_scaled_glyph_t *stack_scaled_glyphs[N_STACK_BUF]; + cairo_scaled_glyph_t **scaled_glyphs; + glitz_float_t stack_vertices[N_STACK_BUF * 16]; + glitz_float_t *vertices; + glitz_buffer_t *buffer; + cairo_int_status_t status; + int x_offset, y_offset; + int i, cached_glyphs = 0; + int remaining_glyps = num_glyphs; + glitz_float_t x1, y1, x2, y2; + static glitz_vertex_format_t format = { GLITZ_PRIMITIVE_QUADS, GLITZ_DATA_TYPE_FLOAT, sizeof (glitz_float_t) * 4, @@ -1892,6 +1896,10 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, } }; + if (scaled_font->surface_backend != NULL && + scaled_font->surface_backend != _cairo_glitz_surface_get_backend ()) + return CAIRO_INT_STATUS_UNSUPPORTED; + if (op == CAIRO_OPERATOR_SATURATE) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1910,67 +1918,57 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (num_glyphs > N_STACK_BUF) { char *data; - + data = malloc (num_glyphs * sizeof (void *) + num_glyphs * sizeof (glitz_float_t) * 16); if (!data) goto FAIL1; - - entries = (cairo_glitz_glyph_cache_entry_t **) data; + + scaled_glyphs = (cairo_scaled_glyph_t **) data; vertices = (glitz_float_t *) (data + num_glyphs * sizeof (void *)); } else { - entries = stack_entries; + scaled_glyphs = stack_scaled_glyphs; vertices = stack_vertices; } buffer = glitz_buffer_create_for_data (vertices); if (!buffer) goto FAIL2; - - cache = _cairo_glitz_get_glyph_cache (dst); - if (!cache) - { - num_glyphs = 0; - goto UNLOCK; - } - - status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key); - if (status) - goto UNLOCK; for (i = 0; i < num_glyphs; i++) { - key.index = glyphs[i].index; - - status = _cairo_cache_lookup (&cache->base, - &key, - (void **) &entries[i], - NULL); - if (status) + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyphs[i]); + if (status != CAIRO_STATUS_SUCCESS) { num_glyphs = i; goto UNLOCK; } - _cairo_glitz_glyph_cache_entry_reference (entries[i]); - - if (entries[i]->area) + glyph_private = scaled_glyphs[i]->surface_private; + if (glyph_private && glyph_private->area) { remaining_glyps--; - if (entries[i]->area->width) + if (glyph_private->area->width) { - x1 = floor (glyphs[i].x + 0.5) + entries[i]->size.x; - y1 = floor (glyphs[i].y + 0.5) + entries[i]->size.y; - x2 = x1 + entries[i]->size.width; - y2 = y1 + entries[i]->size.height; - + x_offset = scaled_glyphs[i]->surface->base.device_x_offset; + y_offset = scaled_glyphs[i]->surface->base.device_y_offset; + + x1 = floor (glyphs[i].x + 0.5) + x_offset; + y1 = floor (glyphs[i].y + 0.5) + y_offset; + x2 = x1 + glyph_private->area->width; + y2 = y1 + glyph_private->area->height; + WRITE_BOX (vertices, x1, y1, x2, y2, - &entries[i]->p1, &entries[i]->p2); - - entries[i]->locked = TRUE; + &glyph_private->p1, &glyph_private->p2); + + glyph_private->locked = TRUE; + cached_glyphs++; } } @@ -1978,96 +1976,65 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (remaining_glyps) { - cairo_cache_t *image_cache; - cairo_image_glyph_cache_entry_t *image_entry; - cairo_surface_t *image; - cairo_glitz_surface_t *clone; - - _cairo_lock_global_image_glyph_cache (); + cairo_surface_t *image; + cairo_glitz_surface_t *clone; - image_cache = _cairo_get_global_image_glyph_cache (); - if (!image_cache) - { - _cairo_unlock_global_image_glyph_cache (); - status = CAIRO_STATUS_NO_MEMORY; - goto UNLOCK; - } - for (i = 0; i < num_glyphs; i++) { - if (!entries[i]->area) + glyph_private = scaled_glyphs[i]->surface_private; + if (!glyph_private || !glyph_private->area) { - key.index = glyphs[i].index; - - status = _cairo_cache_lookup (image_cache, - &key, - (void **) &image_entry, - NULL); + status = _cairo_glitz_surface_add_glyph (dst, + scaled_font, + scaled_glyphs[i]); if (status) - { - _cairo_unlock_global_image_glyph_cache (); goto UNLOCK; - } - status = _cairo_glitz_cache_glyph (cache, - entries[i], - image_entry); - if (status) - { - _cairo_unlock_global_image_glyph_cache (); - goto UNLOCK; - } + glyph_private = scaled_glyphs[i]->surface_private; } - - x1 = floor (glyphs[i].x + 0.5); - y1 = floor (glyphs[i].y + 0.5); - if (entries[i]->area) + x_offset = scaled_glyphs[i]->surface->base.device_x_offset; + y_offset = scaled_glyphs[i]->surface->base.device_y_offset; + + x1 = floor (glyphs[i].x + 0.5) + x_offset; + y1 = floor (glyphs[i].y + 0.5) + y_offset; + + if (glyph_private->area) { - if (entries[i]->area->width) + if (glyph_private->area->width) { - x1 += entries[i]->size.x; - y1 += entries[i]->size.y; - x2 = x1 + entries[i]->size.width; - y2 = y1 + entries[i]->size.height; - + x2 = x1 + glyph_private->area->width; + y2 = y1 + glyph_private->area->height; + WRITE_BOX (vertices, x1, y1, x2, y2, - &entries[i]->p1, &entries[i]->p2); - - entries[i]->locked = TRUE; + &glyph_private->p1, &glyph_private->p2); + + glyph_private->locked = TRUE; + cached_glyphs++; } } else { - x1 += image_entry->size.x; - y1 += image_entry->size.y; - - if (!image_entry->image) - continue; - - image = &image_entry->image->base; + image = &scaled_glyphs[i]->surface->base; status = _cairo_glitz_surface_clone_similar (abstract_surface, image, (cairo_surface_t **) &clone); if (status) - { - _cairo_unlock_global_image_glyph_cache (); goto UNLOCK; - } - glitz_composite (_glitz_operator (op), - src->surface, + glitz_composite (_glitz_operator (op), + src->surface, clone->surface, dst->surface, src_x + attributes.base.x_offset + x1, src_y + attributes.base.y_offset + y1, 0, 0, x1, y1, - image_entry->size.width, - image_entry->size.height); + scaled_glyphs[i]->surface->width, + scaled_glyphs[i]->surface->height); cairo_surface_destroy (&clone->base); @@ -2075,17 +2042,16 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, GLITZ_STATUS_NOT_SUPPORTED) { status = CAIRO_INT_STATUS_UNSUPPORTED; - _cairo_unlock_global_image_glyph_cache (); goto UNLOCK; } } } - - _cairo_unlock_global_image_glyph_cache (); } if (cached_glyphs) { + cairo_glitz_surface_font_private_t *font_private; + glitz_set_geometry (dst->surface, GLITZ_GEOMETRY_TYPE_VERTEX, (glitz_geometry_format_t *) &format, @@ -2093,9 +2059,11 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, glitz_set_array (dst->surface, 0, 4, cached_glyphs * 4, 0, 0); + font_private = scaled_font->surface_private; + glitz_composite (_glitz_operator (op), src->surface, - cache->surface, + font_private->surface, dst->surface, src_x + attributes.base.x_offset, src_y + attributes.base.y_offset, @@ -2107,22 +2075,23 @@ _cairo_glitz_surface_show_glyphs (cairo_scaled_font_t *scaled_font, GLITZ_GEOMETRY_TYPE_NONE, NULL, NULL); } - + UNLOCK: if (cached_glyphs) { for (i = 0; i < num_glyphs; i++) - entries[i]->locked = FALSE; + { + glyph_private = scaled_glyphs[i]->surface_private; + if (glyph_private) + glyph_private->locked = FALSE; + } } - - for (i = 0; i < num_glyphs; i++) - _cairo_glitz_glyph_cache_destroy_entry (cache, entries[i]); glitz_buffer_destroy (buffer); FAIL2: if (num_glyphs > N_STACK_BUF) - free (entries); + free (scaled_glyphs); FAIL1: if (attributes.n_params) @@ -2132,10 +2101,10 @@ UNLOCK: if (status) return status; - + if (glitz_surface_get_status (dst->surface) == GLITZ_STATUS_NOT_SUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; - + return CAIRO_STATUS_SUCCESS; } @@ -2159,9 +2128,17 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = { NULL, /* fill_path */ NULL, /* get_font_options */ NULL, /* flush */ - NULL /* mark_dirty_rectangle */ + NULL, /* mark_dirty_rectangle */ + _cairo_glitz_surface_scaled_font_fini, + _cairo_glitz_surface_scaled_glyph_fini }; +static const cairo_surface_backend_t * +_cairo_glitz_surface_get_backend (void) +{ + return &cairo_glitz_surface_backend; +} + cairo_surface_t * cairo_glitz_surface_create (glitz_surface_t *surface) { @@ -2179,10 +2156,10 @@ cairo_glitz_surface_create (glitz_surface_t *surface) _cairo_surface_init (&crsurface->base, &cairo_glitz_surface_backend); glitz_surface_reference (surface); - + crsurface->surface = surface; crsurface->format = glitz_surface_get_format (surface); crsurface->clip = NULL; - + return (cairo_surface_t *) crsurface; } diff --git a/gfx/cairo/cairo/src/cairo-glitz.h b/gfx/cairo/cairo/src/cairo-glitz.h index f5b4f281507..622fda2a34e 100644 --- a/gfx/cairo/cairo/src/cairo-glitz.h +++ b/gfx/cairo/cairo/src/cairo-glitz.h @@ -45,7 +45,7 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_glitz_surface_create (glitz_surface_t *surface); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-gstate-private.h b/gfx/cairo/cairo/src/cairo-gstate-private.h index 489afdba4c9..cf4a221568e 100644 --- a/gfx/cairo/cairo/src/cairo-gstate-private.h +++ b/gfx/cairo/cairo/src/cairo-gstate-private.h @@ -63,14 +63,14 @@ struct _cairo_gstate { cairo_clip_t clip; + cairo_surface_t *target; + cairo_matrix_t ctm; cairo_matrix_t ctm_inverse; cairo_matrix_t source_ctm_inverse; /* At the time ->source was set */ cairo_pen_t pen_regular; - cairo_surface_t *target; - cairo_pattern_t *source; struct _cairo_gstate *next; diff --git a/gfx/cairo/cairo/src/cairo-gstate.c b/gfx/cairo/cairo/src/cairo-gstate.c index 83b48d13301..c54ef7246fe 100644 --- a/gfx/cairo/cairo/src/cairo-gstate.c +++ b/gfx/cairo/cairo/src/cairo-gstate.c @@ -116,13 +116,13 @@ _cairo_gstate_init (cairo_gstate_t *gstate, _cairo_clip_init (&gstate->clip, target); + gstate->target = cairo_surface_reference (target); + _cairo_gstate_identity_matrix (gstate); - cairo_matrix_init_identity (&gstate->source_ctm_inverse); + gstate->source_ctm_inverse = gstate->ctm_inverse; _cairo_pen_init_empty (&gstate->pen_regular); - gstate->target = cairo_surface_reference (target); - gstate->source = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK); if (gstate->source->status) return CAIRO_STATUS_NO_MEMORY; @@ -179,7 +179,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other) return CAIRO_STATUS_NO_MEMORY; } -void +static void _cairo_gstate_fini (cairo_gstate_t *gstate) { if (gstate->font_face) @@ -231,6 +231,13 @@ _cairo_gstate_clone (cairo_gstate_t *gstate) return clone; } +void +_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target) +{ + cairo_surface_destroy (gstate->target); + gstate->target = cairo_surface_reference (target); +} + /* Push rendering off to an off-screen group. */ /* XXX: Rethinking this API cairo_status_t @@ -258,8 +265,8 @@ _cairo_gstate_begin_group (cairo_gstate_t *gstate) _cairo_surface_set_drawableWH (gstate->target, pix, width, height); status = _cairo_surface_fill_rectangle (gstate->target, - CAIRO_OPERATOR_SOURCE, - &CAIRO_COLOR_TRANSPARENT, + CAIRO_OPERATOR_CLEAR, + CAIRO_COLOR_TRANSPARENT, 0, 0, _cairo_surface_get_width (gstate->target), _cairo_surface_get_height (gstate->target)); @@ -430,21 +437,48 @@ _cairo_gstate_get_line_join (cairo_gstate_t *gstate) cairo_status_t _cairo_gstate_set_dash (cairo_gstate_t *gstate, double *dash, int num_dashes, double offset) { - if (gstate->dash) { + int i; + double dash_total; + + if (gstate->dash) free (gstate->dash); - gstate->dash = NULL; - } gstate->num_dashes = num_dashes; - if (gstate->num_dashes) { - gstate->dash = malloc (gstate->num_dashes * sizeof (double)); - if (gstate->dash == NULL) { - gstate->num_dashes = 0; - return CAIRO_STATUS_NO_MEMORY; - } + + if (gstate->num_dashes == 0) { + gstate->dash = NULL; + gstate->dash_offset = 0.0; + return CAIRO_STATUS_SUCCESS; + } + + gstate->dash = malloc (gstate->num_dashes * sizeof (double)); + if (gstate->dash == NULL) { + gstate->num_dashes = 0; + return CAIRO_STATUS_NO_MEMORY; } memcpy (gstate->dash, dash, gstate->num_dashes * sizeof (double)); + + dash_total = 0.0; + for (i = 0; i < gstate->num_dashes; i++) { + if (gstate->dash[i] < 0) + return CAIRO_STATUS_INVALID_DASH; + dash_total += gstate->dash[i]; + } + + if (dash_total == 0.0) + return CAIRO_STATUS_INVALID_DASH; + + /* A single dash value indicate symmetric repeating, so the total + * is twice as long. */ + if (gstate->num_dashes == 1) + dash_total *= 2; + + /* The dashing code doesn't like a negative offset, so we compute + * the equivalent positive offset. */ + if (offset < 0) + offset += ceil (-offset / dash_total + 0.5) * dash_total; + gstate->dash_offset = offset; return CAIRO_STATUS_SUCCESS; @@ -464,10 +498,37 @@ _cairo_gstate_get_miter_limit (cairo_gstate_t *gstate) return gstate->miter_limit; } +static void +_cairo_gstate_apply_device_transform (cairo_gstate_t *gstate, + cairo_matrix_t *matrix) +{ + if (gstate->target->device_x_scale != 1.0 || + gstate->target->device_y_scale != 1.0) + { + cairo_matrix_scale (matrix, + gstate->target->device_x_scale, + gstate->target->device_y_scale); + } +} + +static void +_cairo_gstate_apply_device_inverse_transform (cairo_gstate_t *gstate, + cairo_matrix_t *matrix) +{ + if (gstate->target->device_x_scale != 1.0 || + gstate->target->device_y_scale != 1.0) + { + cairo_matrix_scale (matrix, + 1/gstate->target->device_x_scale, + 1/gstate->target->device_y_scale); + } +} + void _cairo_gstate_get_matrix (cairo_gstate_t *gstate, cairo_matrix_t *matrix) { *matrix = gstate->ctm; + _cairo_gstate_apply_device_inverse_transform (gstate, matrix); } cairo_status_t @@ -553,6 +614,9 @@ _cairo_gstate_set_matrix (cairo_gstate_t *gstate, if (status) return status; + _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); + _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); + return CAIRO_STATUS_SUCCESS; } @@ -564,6 +628,9 @@ _cairo_gstate_identity_matrix (cairo_gstate_t *gstate) cairo_matrix_init_identity (&gstate->ctm); cairo_matrix_init_identity (&gstate->ctm_inverse); + _cairo_gstate_apply_device_transform (gstate, &gstate->ctm); + _cairo_gstate_apply_device_inverse_transform (gstate, &gstate->ctm_inverse); + return CAIRO_STATUS_SUCCESS; } @@ -605,19 +672,15 @@ void _cairo_gstate_user_to_backend (cairo_gstate_t *gstate, double *x, double *y) { cairo_matrix_transform_point (&gstate->ctm, x, y); - if (gstate->target) { - *x += gstate->target->device_x_offset; - *y += gstate->target->device_y_offset; - } + *x += gstate->target->device_x_offset; + *y += gstate->target->device_y_offset; } void _cairo_gstate_backend_to_user (cairo_gstate_t *gstate, double *x, double *y) { - if (gstate->target) { - *x -= gstate->target->device_x_offset; - *y -= gstate->target->device_y_offset; - } + *x -= gstate->target->device_x_offset; + *y -= gstate->target->device_y_offset; cairo_matrix_transform_point (&gstate->ctm_inverse, x, y); } @@ -723,6 +786,8 @@ cairo_bool_t _cairo_operator_bounded (cairo_operator_t operator) { switch (operator) { + case CAIRO_OPERATOR_CLEAR: + case CAIRO_OPERATOR_SOURCE: case CAIRO_OPERATOR_OVER: case CAIRO_OPERATOR_ATOP: case CAIRO_OPERATOR_DEST: @@ -732,8 +797,6 @@ _cairo_operator_bounded (cairo_operator_t operator) case CAIRO_OPERATOR_ADD: case CAIRO_OPERATOR_SATURATE: return TRUE; - case CAIRO_OPERATOR_CLEAR: - case CAIRO_OPERATOR_SOURCE: case CAIRO_OPERATOR_OUT: case CAIRO_OPERATOR_IN: case CAIRO_OPERATOR_DEST_IN: @@ -753,6 +816,47 @@ typedef cairo_status_t (*cairo_draw_func_t) (void *closure, int dst_y, const cairo_rectangle_t *extents); +static cairo_status_t +_create_composite_mask_pattern (cairo_surface_pattern_t *mask_pattern, + cairo_clip_t *clip, + cairo_draw_func_t draw_func, + void *draw_closure, + cairo_surface_t *dst, + const cairo_rectangle_t *extents) +{ + cairo_surface_t *mask; + cairo_status_t status; + + mask = cairo_surface_create_similar (dst, + CAIRO_CONTENT_ALPHA, + extents->width, + extents->height); + if (mask->status) + return CAIRO_STATUS_NO_MEMORY; + + status = (*draw_func) (draw_closure, CAIRO_OPERATOR_ADD, + NULL, mask, + extents->x, extents->y, + extents); + if (status) + goto CLEANUP_SURFACE; + + if (clip->surface) + status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN, + mask, + extents->x, extents->y, + extents); + if (status) + goto CLEANUP_SURFACE; + + _cairo_pattern_init_for_surface (mask_pattern, mask); + + CLEANUP_SURFACE: + cairo_surface_destroy (mask); + + return status; +} + /* Handles compositing with a clip surface when the operator allows * us to combine the clip with the mask */ @@ -765,50 +869,30 @@ _cairo_gstate_clip_and_composite_with_mask (cairo_clip_t *clip, cairo_surface_t *dst, const cairo_rectangle_t *extents) { - cairo_surface_t *intermediate; - cairo_surface_pattern_t intermediate_pattern; + cairo_surface_pattern_t mask_pattern; cairo_status_t status; - intermediate = cairo_surface_create_similar (clip->surface, - CAIRO_CONTENT_ALPHA, - extents->width, - extents->height); - if (intermediate->status) - return CAIRO_STATUS_NO_MEMORY; - - status = (*draw_func) (draw_closure, CAIRO_OPERATOR_SOURCE, - NULL, intermediate, - extents->x, extents->y, - extents); + status = _create_composite_mask_pattern (&mask_pattern, + clip, + draw_func, draw_closure, + dst, extents); if (status) - goto CLEANUP_SURFACE; - - status = _cairo_clip_combine_to_surface (clip, CAIRO_OPERATOR_IN, - intermediate, - extents->x, extents->y, - extents); - if (status) - goto CLEANUP_SURFACE; - - _cairo_pattern_init_for_surface (&intermediate_pattern, intermediate); - + return status; + status = _cairo_surface_composite (operator, - src, &intermediate_pattern.base, dst, + src, &mask_pattern.base, dst, extents->x, extents->y, 0, 0, extents->x, extents->y, extents->width, extents->height); - _cairo_pattern_fini (&intermediate_pattern.base); - - CLEANUP_SURFACE: - cairo_surface_destroy (intermediate); + _cairo_pattern_fini (&mask_pattern.base); return status; } -/* Handles compositing with a clip surface when the operator allows - * us to combine the clip with the mask +/* Handles compositing with a clip surface when we have to do the operation + * in two pieces and combine them together. */ static cairo_status_t _cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip, @@ -827,6 +911,7 @@ _cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip, /* We'd be better off here creating a surface identical in format * to dst, but we have no way of getting that information. * A CAIRO_CONTENT_CLONE or something might be useful. + * cairo_surface_create_similar() also unnecessarily clears the surface. */ intermediate = cairo_surface_create_similar (dst, CAIRO_CONTENT_COLOR_ALPHA, @@ -895,6 +980,55 @@ _cairo_gstate_clip_and_composite_combine (cairo_clip_t *clip, return status; } +/* Handles compositing for CAIRO_OPERATOR_SOURCE, which is special; it's + * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip)) + */ +static cairo_status_t +_cairo_gstate_clip_and_composite_source (cairo_clip_t *clip, + cairo_pattern_t *src, + cairo_draw_func_t draw_func, + void *draw_closure, + cairo_surface_t *dst, + const cairo_rectangle_t *extents) +{ + cairo_surface_pattern_t mask_pattern; + cairo_status_t status; + + /* Create a surface that is mask IN clip + */ + status = _create_composite_mask_pattern (&mask_pattern, + clip, + draw_func, draw_closure, + dst, extents); + if (status) + return status; + + /* Compute dest' = dest OUT (mask IN clip) + */ + status = _cairo_surface_composite (CAIRO_OPERATOR_DEST_OUT, + &mask_pattern.base, NULL, dst, + 0, 0, + 0, 0, + extents->x, extents->y, + extents->width, extents->height); + + if (status) + goto CLEANUP_MASK_PATTERN; + + /* Now compute (src IN (mask IN clip)) ADD dest' + */ + status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, + src, &mask_pattern.base, dst, + extents->x, extents->y, + 0, 0, + extents->x, extents->y, + extents->width, extents->height); + + CLEANUP_MASK_PATTERN: + _cairo_pattern_fini (&mask_pattern.base); + return status; +} + static int _cairo_rectangle_empty (const cairo_rectangle_t *rect) { @@ -931,30 +1065,49 @@ _cairo_gstate_clip_and_composite (cairo_clip_t *clip, cairo_surface_t *dst, const cairo_rectangle_t *extents) { + cairo_pattern_union_t solid_pattern; + cairo_status_t status; + if (_cairo_rectangle_empty (extents)) /* Nothing to do */ return CAIRO_STATUS_SUCCESS; - if (clip->surface) + if (operator == CAIRO_OPERATOR_CLEAR) { + _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE); + src = &solid_pattern.base; + operator = CAIRO_OPERATOR_DEST_OUT; + } + + if (clip->surface || operator == CAIRO_OPERATOR_SOURCE) { - if (_cairo_operator_bounded (operator)) - return _cairo_gstate_clip_and_composite_with_mask (clip, operator, + if (operator == CAIRO_OPERATOR_SOURCE) + status = _cairo_gstate_clip_and_composite_source (clip, + src, + draw_func, draw_closure, + dst, extents); + else if (_cairo_operator_bounded (operator)) + status = _cairo_gstate_clip_and_composite_with_mask (clip, operator, + src, + draw_func, draw_closure, + dst, extents); + else + status = _cairo_gstate_clip_and_composite_combine (clip, operator, src, draw_func, draw_closure, dst, extents); - else - return _cairo_gstate_clip_and_composite_combine (clip, operator, - src, - draw_func, draw_closure, - dst, extents); } else { - return (*draw_func) (draw_closure, operator, - src, dst, - 0, 0, - extents); + status = (*draw_func) (draw_closure, operator, + src, dst, + 0, 0, + extents); } + + if (src == &solid_pattern.base) + _cairo_pattern_fini (&solid_pattern.base); + + return status; } @@ -1158,10 +1311,17 @@ _composite_trap_region (cairo_clip_t *clip, cairo_rectangle_t *extents) { cairo_status_t status; + cairo_pattern_union_t solid_pattern; cairo_pattern_union_t mask; int num_rects = pixman_region_num_rects (trap_region); unsigned int clip_serial; + if (clip->surface && operator == CAIRO_OPERATOR_CLEAR) { + _cairo_pattern_init_solid (&solid_pattern.solid, CAIRO_COLOR_WHITE); + src = &solid_pattern.base; + operator = CAIRO_OPERATOR_DEST_OUT; + } + if (num_rects == 0) return CAIRO_STATUS_SUCCESS; @@ -1193,6 +1353,9 @@ _composite_trap_region (cairo_clip_t *clip, if (clip->surface) _cairo_pattern_fini (&mask.base); + if (src == &solid_pattern.base) + _cairo_pattern_fini (&solid_pattern.base); + return status; } @@ -1308,21 +1471,28 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src, if (trap_region) { - if (src->type == CAIRO_PATTERN_SOLID && !clip->surface) + if ((src->type == CAIRO_PATTERN_SOLID || operator == CAIRO_OPERATOR_CLEAR) && + !clip->surface) { + const cairo_color_t *color; + + if (operator == CAIRO_OPERATOR_CLEAR) + color = CAIRO_COLOR_TRANSPARENT; + else + color = &((cairo_solid_pattern_t *)src)->color; + /* Solid rectangles special case */ - status = _cairo_surface_fill_region (dst, operator, - &((cairo_solid_pattern_t *)src)->color, - trap_region); + status = _cairo_surface_fill_region (dst, operator, color, trap_region); if (!status && clear_region) - status = _cairo_surface_fill_region (dst, operator, + status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR, CAIRO_COLOR_TRANSPARENT, clear_region); goto out; } - if (_cairo_operator_bounded (operator) || !clip->surface) + if ((_cairo_operator_bounded (operator) && operator != CAIRO_OPERATOR_SOURCE) || + !clip->surface) { /* For a simple rectangle, we can just use composite(), for more * rectangles, we have to set a clip region. The cost of rasterizing @@ -1330,8 +1500,10 @@ _cairo_surface_clip_and_composite_trapezoids (cairo_pattern_t *src, * worthwhile even if a region is needed. * * If we have a clip surface, we set it as the mask; this only works - * for bounded operators; for unbounded operators, clip and mask - * cannot be interchanged. + * for bounded operators other than SOURCE; for unbounded operators, + * clip and mask cannot be interchanged. For SOURCE, the operator + * as implemented by the backends is different in it's handling + * of the mask then what we want. * * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has * more than rectangle and the destination doesn't support clip @@ -1785,30 +1957,17 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, int *num_glyphs) { cairo_status_t status; - int i; status = _cairo_gstate_ensure_scaled_font (gstate); if (status) return status; - status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, + status = _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, utf8, glyphs, num_glyphs); if (status || !glyphs || !num_glyphs || !(*glyphs) || !(num_glyphs)) return status; - /* The font responded in glyph space, starting from (0,0). Convert to - user space by applying the font transform, then add any current point - offset. */ - - for (i = 0; i < *num_glyphs; ++i) { - cairo_matrix_transform_point (&gstate->font_matrix, - &((*glyphs)[i].x), - &((*glyphs)[i].y)); - (*glyphs)[i].x += x; - (*glyphs)[i].y += y; - } - return CAIRO_STATUS_SUCCESS; } @@ -1885,6 +2044,17 @@ _cairo_gstate_show_glyphs_draw_func (void *closure, if (!src) src = &pattern.base; + status = _cairo_surface_show_glyphs (glyph_info->font, operator, src, + dst, + extents->x, extents->y, + extents->x - dst_x, extents->y - dst_y, + extents->width, extents->height, + glyph_info->glyphs, + glyph_info->num_glyphs); + + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + status = _cairo_scaled_font_show_glyphs (glyph_info->font, operator, src, dst, @@ -1909,7 +2079,6 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, int i; cairo_glyph_t *transformed_glyphs = NULL; cairo_pattern_union_t pattern; - cairo_box_t bbox; cairo_rectangle_t extents; cairo_show_glyphs_info_t glyph_info; @@ -1937,21 +2106,15 @@ _cairo_gstate_show_glyphs (cairo_gstate_t *gstate, } if (_cairo_operator_bounded (gstate->operator)) - { - status = _cairo_scaled_font_glyph_bbox (gstate->scaled_font, - transformed_glyphs, num_glyphs, - &bbox); - if (status) - goto CLEANUP_GLYPHS; - - _cairo_box_round_to_rectangle (&bbox, &extents); - } + status = _cairo_scaled_font_glyph_device_extents (gstate->scaled_font, + transformed_glyphs, + num_glyphs, + &extents); else - { status = _cairo_surface_get_extents (gstate->target, &extents); - if (status) - goto CLEANUP_GLYPHS; - } + + if (status) + goto CLEANUP_GLYPHS; status = _cairo_clip_intersect_to_rectangle (&gstate->clip, &extents); if (status) @@ -2011,7 +2174,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate, return status; } -cairo_private cairo_status_t +cairo_status_t _cairo_gstate_set_antialias (cairo_gstate_t *gstate, cairo_antialias_t antialias) { @@ -2020,7 +2183,7 @@ _cairo_gstate_set_antialias (cairo_gstate_t *gstate, return CAIRO_STATUS_SUCCESS; } -cairo_private cairo_antialias_t +cairo_antialias_t _cairo_gstate_get_antialias (cairo_gstate_t *gstate) { return gstate->antialias; diff --git a/gfx/cairo/cairo/src/cairo-hull.c b/gfx/cairo/cairo/src/cairo-hull.c index c93d7062538..7fff0a0c13c 100644 --- a/gfx/cairo/cairo/src/cairo-hull.c +++ b/gfx/cairo/cairo/src/cairo-hull.c @@ -41,6 +41,7 @@ typedef struct cairo_hull cairo_point_t point; cairo_slope_t slope; int discard; + int id; } cairo_hull_t; static cairo_hull_t * @@ -69,11 +70,15 @@ _cairo_hull_create (cairo_pen_vertex_t *vertices, int num_vertices) hull[i].point = vertices[i].point; _cairo_slope_init (&hull[i].slope, &hull[0].point, &hull[i].point); + /* give each point a unique id for later comparison */ + hull[i].id = i; + + /* Don't discard by default */ + hull[i].discard = 0; + /* Discard all points coincident with the extremal point */ if (i != 0 && hull[i].slope.dx == 0 && hull[i].slope.dy == 0) hull[i].discard = 1; - else - hull[i].discard = 0; } return hull; @@ -97,7 +102,12 @@ _cairo_hull_vertex_compare (const void *av, const void *bv) (cairo_fixed_48_16_t) a->slope.dy * a->slope.dy); b_dist = ((cairo_fixed_48_16_t) b->slope.dx * b->slope.dx + (cairo_fixed_48_16_t) b->slope.dy * b->slope.dy); - if (a_dist < b_dist) { + /* + * Use the point's ids to ensure a total ordering. + * a well-defined ordering, and avoid setting discard on + * both points. + */ + if (a_dist < b_dist || (a_dist == b_dist && a->id < b->id)) { a->discard = 1; ret = -1; } else { diff --git a/gfx/cairo/cairo/src/cairo-image-surface.c b/gfx/cairo/cairo/src/cairo-image-surface.c index 1de9402e534..cc675c06416 100644 --- a/gfx/cairo/cairo/src/cairo-image-surface.c +++ b/gfx/cairo/cairo/src/cairo-image-surface.c @@ -149,8 +149,13 @@ _create_pixman_format (cairo_format_t format) * must explicitely clear the buffer, using, for example, * cairo_rectangle() and cairo_fill() if you want it cleared. * - * Return value: the newly created surface, or %NULL if it couldn't - * be created because of lack of memory + * Return value: a pointer to the newly created surface. The caller + * owns the surface and should call cairo_surface_destroy when done + * with it. + * + * This function always returns a valid pointer, but it will return a + * pointer to a "nil" surface if an error such as out of memory + * occurs. You can use cairo_surface_status() to check for this. **/ cairo_surface_t * cairo_image_surface_create (cairo_format_t format, @@ -203,8 +208,13 @@ cairo_image_surface_create (cairo_format_t format, * must explicitely clear the buffer, using, for example, * cairo_rectangle() and cairo_fill() if you want it cleared. * - * Return value: the newly created surface, or %NULL if it couldn't - * be created because of lack of memory + * Return value: a pointer to the newly created surface. The caller + * owns the surface and should call cairo_surface_destroy when done + * with it. + * + * This function always returns a valid pointer, but it will return a + * pointer to a "nil" surface if an error such as out of memory + * occurs. You can use cairo_surface_status() to check for this. **/ cairo_surface_t * cairo_image_surface_create_for_data (unsigned char *data, @@ -616,7 +626,9 @@ _cairo_image_surface_composite (cairo_operator_t operator, width, height); } - if (!_cairo_operator_bounded (operator)) + if (!_cairo_operator_bounded (operator) || + operator == CAIRO_OPERATOR_SOURCE || + operator == CAIRO_OPERATOR_CLEAR) status = _cairo_surface_composite_fixup_unbounded (&dst->base, &src_attr, src->width, src->height, mask ? &mask_attr : NULL, diff --git a/gfx/cairo/cairo/src/cairo-matrix.c b/gfx/cairo/cairo/src/cairo-matrix.c index 7596b0843c6..d75fc21005d 100644 --- a/gfx/cairo/cairo/src/cairo-matrix.c +++ b/gfx/cairo/cairo/src/cairo-matrix.c @@ -82,6 +82,7 @@ slim_hidden_def(cairo_matrix_init_identity); void cairo_matrix_init (cairo_matrix_t *matrix, double xx, double yx, + double xy, double yy, double x0, double y0) { @@ -228,12 +229,10 @@ cairo_matrix_init_rotate (cairo_matrix_t *matrix, { double s; double c; -#if HAVE_SINCOS - sincos (radians, &s, &c); -#else + s = sin (radians); c = cos (radians); -#endif + cairo_matrix_init (matrix, c, s, -s, c, @@ -484,37 +483,6 @@ _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, *det = a*d - b*c; } -void -_cairo_matrix_compute_eigen_values (const cairo_matrix_t *matrix, - double *lambda1, double *lambda2) -{ - /* The eigenvalues of an NxN matrix M are found by solving the polynomial: - - det (M - lI) = 0 - - The zeros in our homogeneous 3x3 matrix make this equation equal - to that formed by the sub-matrix: - - M = a b - c d - - by which: - - l^2 - (a+d)l + (ad - bc) = 0 - - l = (a+d +/- sqrt (a^2 + 2ad + d^2 - 4 (ad-bc))) / 2; - */ - - double a, b, c, d, rad; - - a = matrix->xx; b = matrix->yx; - c = matrix->xy; d = matrix->yy; - - rad = sqrt (a*a + 2*a*d + d*d - 4*(a*d - b*c)); - *lambda1 = (a + d + rad) / 2.0; - *lambda2 = (a + d - rad) / 2.0; -} - /* Compute the amount that each basis vector is scaled by. */ cairo_status_t _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix, @@ -587,3 +555,148 @@ _cairo_matrix_is_integer_translation(const cairo_matrix_t *m, return TRUE; } + +/* + A circle in user space is transformed into an ellipse in device space. + + The following is a derivation of a formula to calculate the length of the + major axis for this ellipse; this is useful for error bounds calculations. + + Thanks to Walter Brisken for this derivation: + + 1. First some notation: + + All capital letters represent vectors in two dimensions. A prime ' + represents a transformed coordinate. Matrices are written in underlined + form, ie _R_. Lowercase letters represent scalar real values. + + 2. The question has been posed: What is the maximum expansion factor + achieved by the linear transformation + + X' = X _R_ + + where _R_ is a real-valued 2x2 matrix with entries: + + _R_ = [a b] + [c d] . + + In other words, what is the maximum radius, MAX[ |X'| ], reached for any + X on the unit circle ( |X| = 1 ) ? + + + 3. Some useful formulae + + (A) through (C) below are standard double-angle formulae. (D) is a lesser + known result and is derived below: + + (A) sin²(θ) = (1 - cos(2*θ))/2 + (B) cos²(θ) = (1 + cos(2*θ))/2 + (C) sin(θ)*cos(θ) = sin(2*θ)/2 + (D) MAX[a*cos(θ) + b*sin(θ)] = sqrt(a² + b²) + + Proof of (D): + + find the maximum of the function by setting the derivative to zero: + + -a*sin(θ)+b*cos(θ) = 0 + + From this it follows that + + tan(θ) = b/a + + and hence + + sin(θ) = b/sqrt(a² + b²) + + and + + cos(θ) = a/sqrt(a² + b²) + + Thus the maximum value is + + MAX[a*cos(θ) + b*sin(θ)] = (a² + b²)/sqrt(a² + b²) + = sqrt(a² + b²) + + + 4. Derivation of maximum expansion + + To find MAX[ |X'| ] we search brute force method using calculus. The unit + circle on which X is constrained is to be parameterized by t: + + X(θ) = (cos(θ), sin(θ)) + + Thus + + X'(θ) = X(θ) * _R_ = (cos(θ), sin(θ)) * [a b] + [c d] + = (a*cos(θ) + c*sin(θ), b*cos(θ) + d*sin(θ)). + + Define + + r(θ) = |X'(θ)| + + Thus + + r²(θ) = (a*cos(θ) + c*sin(θ))² + (b*cos(θ) + d*sin(θ))² + = (a² + b²)*cos²(θ) + (c² + d²)*sin²(θ) + + 2*(a*c + b*d)*cos(θ)*sin(θ) + + Now apply the double angle formulae (A) to (C) from above: + + r²(θ) = (a² + b² + c² + d²)/2 + + (a² + b² - c² - d²)*cos(2*θ)/2 + + (a*c + b*d)*sin(2*θ) + = f + g*cos(φ) + h*sin(φ) + + Where + + f = (a² + b² + c² + d²)/2 + g = (a² + b² - c² - d²)/2 + h = (a*c + d*d) + φ = 2*θ + + It is clear that MAX[ |X'| ] = sqrt(MAX[ r² ]). Here we determine MAX[ r² ] + using (D) from above: + + MAX[ r² ] = f + sqrt(g² + h²) + + And finally + + MAX[ |X'| ] = sqrt( f + sqrt(g² + h²) ) + + Which is the solution to this problem. + + + Walter Brisken + 2004/10/08 + + (Note that the minor axis length is at the minimum of the above solution, + which is just sqrt ( f - sqrt(g² + h²) ) given the symmetry of (D)). +*/ + +/* determine the length of the major axis of a circle of the given radius + after applying the transformation matrix. */ +double +_cairo_matrix_transformed_circle_major_axis (cairo_matrix_t *matrix, double radius) +{ + double a, b, c, d, f, g, h, i, j; + + _cairo_matrix_get_affine (matrix, + &a, &b, + &c, &d, + NULL, NULL); + + i = a*a + b*b; + j = c*c + d*d; + + f = 0.5 * (i + j); + g = 0.5 * (i - j); + h = a*c + b*d; + + return radius * sqrt (f + sqrt (g*g+h*h)); + + /* + * we don't need the minor axis length, which is + * double min = radius * sqrt (f - sqrt (g*g+h*h)); + */ +} diff --git a/gfx/cairo/cairo/src/cairo-meta-surface.c b/gfx/cairo/cairo/src/cairo-meta-surface.c index f218ae24046..2d3ae362988 100644 --- a/gfx/cairo/cairo/src/cairo-meta-surface.c +++ b/gfx/cairo/cairo/src/cairo-meta-surface.c @@ -541,6 +541,23 @@ _cairo_meta_surface_replay (cairo_surface_t *surface, command->show_glyphs.height, command->show_glyphs.glyphs, command->show_glyphs.num_glyphs); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + break; + + status = (*command->show_glyphs.scaled_font->backend-> + show_glyphs) (command->show_glyphs.scaled_font, + command->show_glyphs.operator, + &command->show_glyphs.pattern.base, + target, + command->show_glyphs.source_x, + command->show_glyphs.source_y, + command->show_glyphs.dest_x, + command->show_glyphs.dest_y, + command->show_glyphs.width, + command->show_glyphs.height, + command->show_glyphs.glyphs, + command->show_glyphs.num_glyphs); + break; case CAIRO_COMMAND_FILL_PATH: diff --git a/gfx/cairo/cairo/src/cairo-path-data.c b/gfx/cairo/cairo/src/cairo-path-data.c index e72e0738cbd..cbb23b90f80 100644 --- a/gfx/cairo/cairo/src/cairo-path-data.c +++ b/gfx/cairo/cairo/src/cairo-path-data.c @@ -367,8 +367,8 @@ _cairo_path_data_create_real (cairo_path_fixed_t *path_fixed, /** * cairo_path_destroy: - * @path: a path to destroy which was previously returned by either - * cairo_copy_path or cairo_copy_path_flat. + * @path: a path previously returned by either cairo_copy_path() or + * cairo_copy_path_flat(). * * Immediately releases all memory associated with @path. After a call * to cairo_path_destroy() the @path pointer is no longer valid and diff --git a/gfx/cairo/cairo/src/cairo-path-stroke.c b/gfx/cairo/cairo/src/cairo-path-stroke.c index b81d862b93f..78897310072 100644 --- a/gfx/cairo/cairo/src/cairo-path-stroke.c +++ b/gfx/cairo/cairo/src/cairo-path-stroke.c @@ -42,17 +42,17 @@ typedef struct cairo_stroker { cairo_gstate_t *gstate; cairo_traps_t *traps; - int has_current_point; + cairo_bool_t has_current_point; cairo_point_t current_point; cairo_point_t first_point; - int has_current_face; + cairo_bool_t has_current_face; cairo_stroke_face_t current_face; - int has_first_face; + cairo_bool_t has_first_face; cairo_stroke_face_t first_face; - int dashed; + cairo_bool_t dashed; int dash_index; int dash_on; double dash_remain; @@ -80,6 +80,12 @@ _cairo_stroker_curve_to (void *closure, cairo_point_t *c, cairo_point_t *d); +static cairo_status_t +_cairo_stroker_curve_to_dashed (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d); + static cairo_status_t _cairo_stroker_close_path (void *closure); @@ -107,7 +113,7 @@ _cairo_stroker_start_dash (cairo_stroker_t *stroker) if (++i == gstate->num_dashes) i = 0; } - stroker->dashed = 1; + stroker->dashed = TRUE; stroker->dash_index = i; stroker->dash_on = on; stroker->dash_remain = gstate->dash[i] - offset; @@ -133,14 +139,14 @@ _cairo_stroker_init (cairo_stroker_t *stroker, cairo_gstate_t *gstate, cairo_tra stroker->gstate = gstate; stroker->traps = traps; - stroker->has_current_point = 0; - stroker->has_current_face = 0; - stroker->has_first_face = 0; + stroker->has_current_point = FALSE; + stroker->has_current_face = FALSE; + stroker->has_first_face = FALSE; if (gstate->dash) _cairo_stroker_start_dash (stroker); else - stroker->dashed = 0; + stroker->dashed = FALSE; } static void @@ -335,7 +341,7 @@ _cairo_stroker_join (cairo_stroker_t *stroker, cairo_stroke_face_t *in, cairo_st } static cairo_status_t -_cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f) +_cairo_stroker_add_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f) { cairo_status_t status; cairo_gstate_t *gstate = stroker->gstate; @@ -405,6 +411,54 @@ _cairo_stroker_cap (cairo_stroker_t *stroker, cairo_stroke_face_t *f) } } +static cairo_status_t +_cairo_stroker_add_leading_cap (cairo_stroker_t *stroker, + cairo_stroke_face_t *face) +{ + cairo_stroke_face_t reversed; + cairo_point_t t; + + reversed = *face; + + /* The initial cap needs an outward facing vector. Reverse everything */ + reversed.usr_vector.x = -reversed.usr_vector.x; + reversed.usr_vector.y = -reversed.usr_vector.y; + reversed.dev_vector.dx = -reversed.dev_vector.dx; + reversed.dev_vector.dy = -reversed.dev_vector.dy; + t = reversed.cw; + reversed.cw = reversed.ccw; + reversed.ccw = t; + + return _cairo_stroker_add_cap (stroker, &reversed); +} + +static cairo_status_t +_cairo_stroker_add_trailing_cap (cairo_stroker_t *stroker, + cairo_stroke_face_t *face) +{ + return _cairo_stroker_add_cap (stroker, face); +} + +static cairo_status_t +_cairo_stroker_add_caps (cairo_stroker_t *stroker) +{ + cairo_status_t status; + + if (stroker->has_first_face) { + status = _cairo_stroker_add_leading_cap (stroker, &stroker->first_face); + if (status) + return status; + } + + if (stroker->has_current_face) { + status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); + if (status) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + static void _compute_face (cairo_point_t *point, cairo_slope_t *slope, cairo_gstate_t *gstate, cairo_stroke_face_t *face) { @@ -527,8 +581,13 @@ _cairo_stroker_add_sub_edge (cairo_stroker_t *stroker, cairo_point_t *p1, cairo_ static cairo_status_t _cairo_stroker_move_to (void *closure, cairo_point_t *point) { + cairo_status_t status; cairo_stroker_t *stroker = closure; + status = _cairo_stroker_add_caps (stroker); + if (status) + return status; + stroker->first_point = *point; stroker->current_point = *point; stroker->has_current_point = 1; @@ -633,7 +692,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) /* * Not first dash in this segment, cap start */ - status = _cairo_stroker_cap (stroker, &sub_start); + status = _cairo_stroker_add_leading_cap (stroker, &sub_start); if (status) return status; } else { @@ -651,7 +710,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) stroker->first_face = sub_start; stroker->has_first_face = 1; } else { - status = _cairo_stroker_cap (stroker, &sub_start); + status = _cairo_stroker_add_leading_cap (stroker, &sub_start); if (status) return status; } @@ -661,7 +720,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) /* * Cap if not at end of segment */ - status = _cairo_stroker_cap (stroker, &sub_end); + status = _cairo_stroker_add_trailing_cap (stroker, &sub_end); if (status) return status; } else { @@ -679,7 +738,7 @@ _cairo_stroker_line_to_dashed (void *closure, cairo_point_t *point) */ if (first) { if (stroker->has_current_face) { - status = _cairo_stroker_cap (stroker, &stroker->current_face); + status = _cairo_stroker_add_trailing_cap (stroker, &stroker->current_face); if (status) return status; } @@ -767,6 +826,74 @@ _cairo_stroker_curve_to (void *closure, return status; } +/* We're using two different algorithms here for dashed and un-dashed + * splines. The dashed alogorithm uses the existing line dashing + * code. It's linear in path length, but gets subtly wrong results for + * self-intersecting paths (an outstanding but for self-intersecting + * non-curved paths as well). The non-dashed algorithm tessellates a + * single polygon for the whole curve. It handles the + * self-intersecting problem, but it's (unsurprisingly) not O(n) and + * more significantly, it doesn't yet handle dashes. + * + * The only reason we're doing split algortihms here is to + * minimize the impact of fixing the splines-aren't-dashed bug for + * 1.0.2. Long-term the right answer is to rewrite the whole pile + * of stroking code so that the entire result is computed as a + * single polygon that is tessellated, (that is, stroking can be + * built on top of filling). That will solve the self-intersecting + * problem. It will also increase the importance of implementing + * an efficient and more robust tessellator. + */ +static cairo_status_t +_cairo_stroker_curve_to_dashed (void *closure, + cairo_point_t *b, + cairo_point_t *c, + cairo_point_t *d) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_stroker_t *stroker = closure; + cairo_gstate_t *gstate = stroker->gstate; + cairo_spline_t spline; + cairo_point_t *a = &stroker->current_point; + cairo_line_join_t line_join_save; + int i; + + status = _cairo_spline_init (&spline, a, b, c, d); + if (status == CAIRO_INT_STATUS_DEGENERATE) + return CAIRO_STATUS_SUCCESS; + + /* If the line width is so small that the pen is reduced to a + single point, then we have nothing to do. */ + if (gstate->pen_regular.num_vertices <= 1) + goto CLEANUP_SPLINE; + + /* Temporarily modify the gstate to use round joins to guarantee + * smooth stroked curves. */ + line_join_save = gstate->line_join; + gstate->line_join = CAIRO_LINE_JOIN_ROUND; + + status = _cairo_spline_decompose (&spline, gstate->tolerance); + if (status) + goto CLEANUP_GSTATE; + + for (i = 1; i < spline.num_points; i++) { + if (stroker->dashed) + status = _cairo_stroker_line_to_dashed (stroker, &spline.points[i]); + else + status = _cairo_stroker_line_to (stroker, &spline.points[i]); + if (status) + break; + } + + CLEANUP_GSTATE: + gstate->line_join = line_join_save; + + CLEANUP_SPLINE: + _cairo_spline_fini (&spline); + + return status; +} + static cairo_status_t _cairo_stroker_close_path (void *closure) { @@ -810,7 +937,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, CAIRO_DIRECTION_FORWARD, _cairo_stroker_move_to, _cairo_stroker_line_to_dashed, - _cairo_stroker_curve_to, + _cairo_stroker_curve_to_dashed, _cairo_stroker_close_path, &stroker); else @@ -824,26 +951,7 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, if (status) goto BAIL; - if (stroker.has_first_face) { - cairo_point_t t; - /* The initial cap needs an outward facing vector. Reverse everything */ - stroker.first_face.usr_vector.x = -stroker.first_face.usr_vector.x; - stroker.first_face.usr_vector.y = -stroker.first_face.usr_vector.y; - stroker.first_face.dev_vector.dx = -stroker.first_face.dev_vector.dx; - stroker.first_face.dev_vector.dy = -stroker.first_face.dev_vector.dy; - t = stroker.first_face.cw; - stroker.first_face.cw = stroker.first_face.ccw; - stroker.first_face.ccw = t; - status = _cairo_stroker_cap (&stroker, &stroker.first_face); - if (status) - goto BAIL; - } - - if (stroker.has_current_face) { - status = _cairo_stroker_cap (&stroker, &stroker.current_face); - if (status) - goto BAIL; - } + status = _cairo_stroker_add_caps (&stroker); BAIL: _cairo_stroker_fini (&stroker); diff --git a/gfx/cairo/cairo/src/cairo-path.c b/gfx/cairo/cairo/src/cairo-path.c index 0940c4d1ea8..669e587acd5 100644 --- a/gfx/cairo/cairo/src/cairo-path.c +++ b/gfx/cairo/cairo/src/cairo-path.c @@ -132,6 +132,17 @@ _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, return CAIRO_STATUS_SUCCESS; } +cairo_path_fixed_t * +_cairo_path_fixed_create (void) +{ + cairo_path_fixed_t *path = malloc (sizeof (cairo_path_fixed_t)); + + if (!path) + return NULL; + _cairo_path_fixed_init (path); + return path; +} + void _cairo_path_fixed_fini (cairo_path_fixed_t *path) { @@ -155,6 +166,13 @@ _cairo_path_fixed_fini (cairo_path_fixed_t *path) path->has_current_point = 0; } +void +_cairo_path_fixed_destroy (cairo_path_fixed_t *path) +{ + _cairo_path_fixed_fini (path); + free (path); +} + cairo_status_t _cairo_path_fixed_move_to (cairo_path_fixed_t *path, cairo_fixed_t x, diff --git a/gfx/cairo/cairo/src/cairo-pattern.c b/gfx/cairo/cairo/src/cairo-pattern.c index 82b409b6c18..162d6bf49c1 100644 --- a/gfx/cairo/cairo/src/cairo-pattern.c +++ b/gfx/cairo/cairo/src/cairo-pattern.c @@ -27,11 +27,6 @@ #include "cairoint.h" -typedef void (*cairo_shader_function_t) (unsigned char *color0, - unsigned char *color1, - cairo_fixed_t factor, - uint32_t *pixel); - typedef struct _cairo_shader_color_stop { cairo_fixed_t offset; cairo_fixed_48_16_t scale; @@ -43,59 +38,64 @@ typedef struct _cairo_shader_op { cairo_shader_color_stop_t *stops; int n_stops; cairo_extend_t extend; - cairo_shader_function_t shader_function; } cairo_shader_op_t; #define MULTIPLY_COLORCOMP(c1, c2) \ ((unsigned char) \ ((((unsigned char) (c1)) * (int) ((unsigned char) (c2))) / 0xff)) -const cairo_solid_pattern_t cairo_solid_pattern_nil = { +const cairo_solid_pattern_t cairo_pattern_nil = { { CAIRO_PATTERN_SOLID, /* type */ (unsigned int)-1, /* ref_count */ CAIRO_STATUS_NO_MEMORY, /* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_DEFAULT }, /* extend */ - { 0.0, 0.0, 0.0, 1.0, /* solid black */ - 0x0, 0x0, 0x0, 0xffff } }; -static const cairo_surface_pattern_t cairo_surface_pattern_nil = { - { CAIRO_PATTERN_SURFACE, /* type */ +static const cairo_solid_pattern_t cairo_pattern_nil_null_pointer = { + { CAIRO_PATTERN_SOLID, /* type */ (unsigned int)-1, /* ref_count */ - CAIRO_STATUS_NO_MEMORY, /* status */ + CAIRO_STATUS_NULL_POINTER,/* status */ { 1., 0., 0., 1., 0., 0., }, /* matrix */ CAIRO_FILTER_DEFAULT, /* filter */ CAIRO_EXTEND_DEFAULT }, /* extend */ - NULL /* surface */ }; -static const cairo_linear_pattern_t cairo_linear_pattern_nil = { - { { CAIRO_PATTERN_LINEAR, /* type */ - (unsigned int)-1, /* ref_count */ - CAIRO_STATUS_NO_MEMORY, /* status */ - { 1., 0., 0., 1., 0., 0., }, /* matrix */ - CAIRO_FILTER_DEFAULT, /* filter */ - CAIRO_EXTEND_DEFAULT }, /* extend */ - NULL, /* stops */ - 0 }, /* n_stops */ - { 0., 0. }, { 1.0, 1.0 } /* point0, point1 */ +static const cairo_solid_pattern_t cairo_pattern_nil_file_not_found = { + { CAIRO_PATTERN_SOLID, /* type */ + (unsigned int)-1, /* ref_count */ + CAIRO_STATUS_FILE_NOT_FOUND, /* status */ + { 1., 0., 0., 1., 0., 0., }, /* matrix */ + CAIRO_FILTER_DEFAULT, /* filter */ + CAIRO_EXTEND_DEFAULT }, /* extend */ }; -static const cairo_radial_pattern_t cairo_radial_pattern_nil = { - { { CAIRO_PATTERN_RADIAL, /* type */ - (unsigned int)-1, /* ref_count */ - CAIRO_STATUS_NO_MEMORY, /* status */ - { 1., 0., 0., 1., 0., 0., }, /* matrix */ - CAIRO_FILTER_DEFAULT, /* filter */ - CAIRO_EXTEND_DEFAULT }, /* extend */ - NULL, /* stops */ - 0 }, /* n_stops */ - { 0., 0. }, { 0.0, 0.0 }, /* center0, center1 */ - 1.0, 1.0, /* radius0, radius1 */ +static const cairo_solid_pattern_t cairo_pattern_nil_read_error = { + { CAIRO_PATTERN_SOLID, /* type */ + (unsigned int)-1, /* ref_count */ + CAIRO_STATUS_READ_ERROR, /* status */ + { 1., 0., 0., 1., 0., 0., }, /* matrix */ + CAIRO_FILTER_DEFAULT, /* filter */ + CAIRO_EXTEND_DEFAULT }, /* extend */ }; +static const cairo_pattern_t * +_cairo_pattern_nil_for_status (cairo_status_t status) +{ + switch (status) { + case CAIRO_STATUS_NULL_POINTER: + return &cairo_pattern_nil_null_pointer.base; + case CAIRO_STATUS_FILE_NOT_FOUND: + return &cairo_pattern_nil_file_not_found.base; + case CAIRO_STATUS_READ_ERROR: + return &cairo_pattern_nil_read_error.base; + default: + case CAIRO_STATUS_NO_MEMORY: + return &cairo_pattern_nil.base; + } +} + /** * _cairo_pattern_set_error: * @pattern: a pattern @@ -116,7 +116,11 @@ static void _cairo_pattern_set_error (cairo_pattern_t *pattern, cairo_status_t status) { - pattern->status = status; + /* Don't overwrite an existing error. This preserves the first + * error, which is the most significant. It also avoids attempting + * to write to read-only data (eg. from a nil pattern). */ + if (pattern->status == CAIRO_STATUS_SUCCESS) + pattern->status = status; _cairo_error (status); } @@ -152,17 +156,11 @@ _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern, *dst = *src; } - if (other->base.status) - _cairo_pattern_set_error (&pattern->base, other->base.status); - if (other->n_stops) { pattern->stops = malloc (other->n_stops * sizeof (cairo_color_stop_t)); if (pattern->stops == NULL) { - if (other->base.type == CAIRO_PATTERN_LINEAR) - _cairo_gradient_pattern_init_copy (pattern, &cairo_linear_pattern_nil.base); - else - _cairo_gradient_pattern_init_copy (pattern, &cairo_radial_pattern_nil.base); + _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY); return; } @@ -175,6 +173,11 @@ void _cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other) { + if (other->status) { + _cairo_pattern_set_error (pattern, other->status); + return; + } + switch (other->type) { case CAIRO_PATTERN_SOLID: { cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern; @@ -208,16 +211,18 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) case CAIRO_PATTERN_SOLID: break; case CAIRO_PATTERN_SURFACE: { - cairo_surface_pattern_t *fini = (cairo_surface_pattern_t *) pattern; + cairo_surface_pattern_t *surface_pattern = + (cairo_surface_pattern_t *) pattern; - cairo_surface_destroy (fini->surface); + cairo_surface_destroy (surface_pattern->surface); } break; case CAIRO_PATTERN_LINEAR: case CAIRO_PATTERN_RADIAL: { - cairo_gradient_pattern_t *fini = (cairo_gradient_pattern_t *) pattern; + cairo_gradient_pattern_t *gradient = + (cairo_gradient_pattern_t *) pattern; - if (fini->n_stops) - free (fini->stops); + if (gradient->stops) + free (gradient->stops); } break; } } @@ -234,6 +239,13 @@ void _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern, cairo_surface_t *surface) { + if (surface->status) { + /* Force to solid to simplify the pattern_fini process. */ + pattern->base.type = CAIRO_PATTERN_SOLID; + _cairo_pattern_set_error (&pattern->base, surface->status); + return; + } + _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_SURFACE); pattern->surface = cairo_surface_reference (surface); @@ -245,7 +257,7 @@ _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern, { _cairo_pattern_init (&pattern->base, type); - pattern->stops = 0; + pattern->stops = NULL; pattern->n_stops = 0; } @@ -283,7 +295,7 @@ _cairo_pattern_create_solid (const cairo_color_t *color) pattern = malloc (sizeof (cairo_solid_pattern_t)); if (pattern == NULL) - return (cairo_pattern_t *) &cairo_solid_pattern_nil.base; + return (cairo_pattern_t *) &cairo_pattern_nil.base; _cairo_pattern_init_solid (pattern, color); @@ -324,7 +336,7 @@ cairo_pattern_create_rgb (double red, double green, double blue) pattern = _cairo_pattern_create_solid (&color); if (pattern->status) - _cairo_pattern_set_error (pattern, pattern->status); + _cairo_error (pattern->status); return pattern; } @@ -366,7 +378,7 @@ cairo_pattern_create_rgba (double red, double green, double blue, pattern = _cairo_pattern_create_solid (&color); if (pattern->status) - _cairo_pattern_set_error (pattern, pattern->status); + _cairo_error (pattern->status); return pattern; } @@ -391,10 +403,16 @@ cairo_pattern_create_for_surface (cairo_surface_t *surface) { cairo_surface_pattern_t *pattern; + if (surface == NULL) + return (cairo_pattern_t*) _cairo_pattern_nil_for_status (CAIRO_STATUS_NULL_POINTER); + + if (surface->status) + return (cairo_pattern_t*) _cairo_pattern_nil_for_status (surface->status); + pattern = malloc (sizeof (cairo_surface_pattern_t)); if (pattern == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *)&cairo_surface_pattern_nil.base; + return (cairo_pattern_t *)&cairo_pattern_nil.base; } _cairo_pattern_init_for_surface (pattern, surface); @@ -436,7 +454,7 @@ cairo_pattern_create_linear (double x0, double y0, double x1, double y1) pattern = malloc (sizeof (cairo_linear_pattern_t)); if (pattern == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *) &cairo_linear_pattern_nil.base; + return (cairo_pattern_t *) &cairo_pattern_nil.base; } _cairo_pattern_init_linear (pattern, x0, y0, x1, y1); @@ -481,7 +499,7 @@ cairo_pattern_create_radial (double cx0, double cy0, double radius0, pattern = malloc (sizeof (cairo_radial_pattern_t)); if (pattern == NULL) { _cairo_error (CAIRO_STATUS_NO_MEMORY); - return (cairo_pattern_t *) &cairo_radial_pattern_nil.base; + return (cairo_pattern_t *) &cairo_pattern_nil.base; } _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1); @@ -508,6 +526,8 @@ cairo_pattern_reference (cairo_pattern_t *pattern) if (pattern->ref_count == (unsigned int)-1) return pattern; + assert (pattern->ref_count > 0); + pattern->ref_count++; return pattern; @@ -546,6 +566,8 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) if (pattern->ref_count == (unsigned int)-1) return; + assert (pattern->ref_count > 0); + pattern->ref_count--; if (pattern->ref_count) return; @@ -596,7 +618,7 @@ _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern, * * Note: If the pattern is not a gradient pattern, (eg. a linear or * radial pattern), then the pattern will be put into an error status - * with a status of CAIRO_STATUS_PATTERN_MISMATCH. + * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. **/ void cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, @@ -647,7 +669,7 @@ cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, * * Note: If the pattern is not a gradient pattern, (eg. a linear or * radial pattern), then the pattern will be put into an error status - * with a status of CAIRO_STATUS_PATTERN_MISMATCH. + * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. */ void cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, @@ -703,8 +725,8 @@ cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, * it does by default the correct code to use is: * * - * cairo_matrix_init_scale (&matrix, 0.5, 0.5); - * cairo_pattern_set_matrix (pattern, &matrix); + * cairo_matrix_init_scale (&matrix, 0.5, 0.5); + * cairo_pattern_set_matrix (pattern, &matrix); * * * Meanwhile, using values of 2.0 rather than 0.5 in the code above @@ -717,10 +739,8 @@ void cairo_pattern_set_matrix (cairo_pattern_t *pattern, const cairo_matrix_t *matrix) { - if (pattern->status) { - _cairo_pattern_set_error (pattern, pattern->status); + if (pattern->status) return; - } pattern->matrix = *matrix; } @@ -741,10 +761,8 @@ cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix) void cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter) { - if (pattern->status) { - _cairo_pattern_set_error (pattern, pattern->status); + if (pattern->status) return; - } pattern->filter = filter; } @@ -758,10 +776,8 @@ cairo_pattern_get_filter (cairo_pattern_t *pattern) void cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend) { - if (pattern->status) { - _cairo_pattern_set_error (pattern, pattern->status); + if (pattern->status) return; - } pattern->extend = extend; } @@ -781,24 +797,6 @@ _cairo_pattern_transform (cairo_pattern_t *pattern, cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix); } -#define INTERPOLATE_COLOR_NEAREST(c1, c2, factor) \ - ((factor < 32768)? c1: c2) - -static void -_cairo_pattern_shader_nearest (unsigned char *color0, - unsigned char *color1, - cairo_fixed_t factor, - uint32_t *pixel) -{ - *pixel = - ((INTERPOLATE_COLOR_NEAREST (color0[3], color1[3], factor) << 24) | - (INTERPOLATE_COLOR_NEAREST (color0[0], color1[0], factor) << 16) | - (INTERPOLATE_COLOR_NEAREST (color0[1], color1[1], factor) << 8) | - (INTERPOLATE_COLOR_NEAREST (color0[2], color1[2], factor) << 0)); -} - -#undef INTERPOLATE_COLOR_NEAREST - #define INTERPOLATE_COLOR_LINEAR(c1, c2, factor) \ (((c2 * factor) + (c1 * (65536 - factor))) / 65536) @@ -814,24 +812,6 @@ _cairo_pattern_shader_linear (unsigned char *color0, (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0)); } -#define E_MINUS_ONE 1.7182818284590452354 - -static void -_cairo_pattern_shader_gaussian (unsigned char *color0, - unsigned char *color1, - cairo_fixed_t factor, - uint32_t *pixel) -{ - double f = ((double) factor) / 65536.0; - - factor = (cairo_fixed_t) (((exp (f * f) - 1.0) / E_MINUS_ONE) * 65536); - - *pixel = ((INTERPOLATE_COLOR_LINEAR (color0[3], color1[3], factor) << 24) | - (INTERPOLATE_COLOR_LINEAR (color0[0], color1[0], factor) << 16) | - (INTERPOLATE_COLOR_LINEAR (color0[1], color1[1], factor) << 8) | - (INTERPOLATE_COLOR_LINEAR (color0[2], color1[2], factor) << 0)); -} - #undef INTERPOLATE_COLOR_LINEAR static int @@ -889,24 +869,6 @@ _cairo_pattern_shader_init (cairo_gradient_pattern_t *pattern, op->n_stops = pattern->n_stops; op->extend = pattern->base.extend; - /* XXX: this is wrong, the filter should not be used for selecting - color stop interpolation function. function should always be 'linear' - and filter should be used for computing pixels. */ - switch (pattern->base.filter) { - case CAIRO_FILTER_FAST: - case CAIRO_FILTER_NEAREST: - op->shader_function = _cairo_pattern_shader_nearest; - break; - case CAIRO_FILTER_GAUSSIAN: - op->shader_function = _cairo_pattern_shader_gaussian; - break; - case CAIRO_FILTER_GOOD: - case CAIRO_FILTER_BEST: - case CAIRO_FILTER_BILINEAR: - op->shader_function = _cairo_pattern_shader_linear; - break; - } - return CAIRO_STATUS_SUCCESS; } @@ -982,9 +944,9 @@ _cairo_pattern_calc_color_at_pixel (cairo_shader_op_t *op, factor = ((cairo_fixed_48_16_t) factor << 16) / stops[1]->scale; - op->shader_function (stops[0]->color_char, - stops[1]->color_char, - factor, pixel); + _cairo_pattern_shader_linear (stops[0]->color_char, + stops[1]->color_char, + factor, pixel); /* multiply alpha */ if (((unsigned char) (*pixel >> 24)) != 0xff) { @@ -1050,7 +1012,7 @@ _cairo_image_data_set_linear (cairo_linear_pattern_t *pattern, factor = ((dx * qx + dy * qy) - start) * scale; - _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++); + _cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++); } } @@ -1233,7 +1195,7 @@ _cairo_image_data_set_radial (cairo_radial_pattern_t *pattern, } } - _cairo_pattern_calc_color_at_pixel (&op, factor * 65536, pixels++); + _cairo_pattern_calc_color_at_pixel (&op, _cairo_fixed_from_double (factor), pixels++); } } @@ -1268,8 +1230,15 @@ _cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern, height = 1; repeat = TRUE; } - if (is_vertical) { - width = 1; + /* width-1 repeating patterns are quite slow with scan-line based + * compositing code, so we use a wider strip and spend some extra + * expense in computing the gradient. It's possible that for narrow + * gradients we'd be better off using a 2 or 4 pixel strip; the + * wider the gradient, the more it's worth spending extra time + * computing a sample. + */ + if (is_vertical && width > 8) { + width = 8; repeat = TRUE; } } @@ -1457,8 +1426,11 @@ _cairo_pattern_acquire_surface (cairo_pattern_t *pattern, { cairo_status_t status; - if (pattern->status) + if (pattern->status) { + *surface_out = NULL; + attributes->acquired = FALSE; return pattern->status; + } switch (pattern->type) { case CAIRO_PATTERN_SOLID: { diff --git a/gfx/cairo/cairo/src/cairo-pdf-surface.c b/gfx/cairo/cairo/src/cairo-pdf-surface.c index 6b863721ee4..cff965bb23a 100644 --- a/gfx/cairo/cairo/src/cairo-pdf-surface.c +++ b/gfx/cairo/cairo/src/cairo-pdf-surface.c @@ -336,6 +336,16 @@ cairo_pdf_surface_create (const char *filename, return _cairo_pdf_surface_create_for_stream_internal (stream, width, height); } +/** + * cairo__surface_set_dpi: + * @surface: a postscript cairo_surface_t + * @x_dpi: horizontal dpi + * @y_dpi: vertical dpi + * + * Set horizontal and vertical resolution for image fallbacks. When + * the pdf backend needs to fall back to image overlays, it will use + * this resolution. + **/ void cairo_pdf_surface_set_dpi (cairo_surface_t *surface, double x_dpi, @@ -1296,6 +1306,7 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_output_stream_t *output = document->output_stream; cairo_font_subset_t *pdf_font; int i, index; + double det; /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */ if (! _cairo_scaled_font_is_ft (scaled_font)) @@ -1305,6 +1316,13 @@ _cairo_pdf_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (pdf_font == NULL) return CAIRO_STATUS_NO_MEMORY; + /* Some PDF viewers (at least older versions of xpdf) have trouble with + * size 0 fonts. If the font size is less than 1/1000pt, ignore the + * font */ + _cairo_matrix_compute_determinant (&scaled_font->scale, &det); + if (fabs (det) < 0.000001) + return CAIRO_STATUS_SUCCESS; + emit_pattern (surface, pattern); _cairo_output_stream_printf (output, diff --git a/gfx/cairo/cairo/src/cairo-pdf.h b/gfx/cairo/cairo/src/cairo-pdf.h index 61bf7a841e7..d611fb2caf3 100644 --- a/gfx/cairo/cairo/src/cairo-pdf.h +++ b/gfx/cairo/cairo/src/cairo-pdf.h @@ -43,18 +43,18 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_pdf_surface_create (const char *filename, double width_in_points, double height_in_points); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_pdf_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points); -void +cairo_public void cairo_pdf_surface_set_dpi (cairo_surface_t *surface, double x_dpi, double y_dpi); diff --git a/gfx/cairo/cairo/src/cairo-pen.c b/gfx/cairo/cairo/src/cairo-pen.c index 18b9ddb5926..d1a3c6117be 100644 --- a/gfx/cairo/cairo/src/cairo-pen.c +++ b/gfx/cairo/cairo/src/cairo-pen.c @@ -173,130 +173,13 @@ device space. We construct the pen by computing points along the circumference using equally spaced angles. -We show below that this approximation to the ellipse has -maximum error at the major axis of the ellipse. -So, we need to compute the length of the major axis and then -use that to compute the number of sides needed in our pen. - -Thanks to Walter Brisken for this -derivation: - -1. First some notation: - -All capital letters represent vectors in two dimensions. A prime ' -represents a transformed coordinate. Matrices are written in underlined -form, ie _R_. Lowercase letters represent scalar real values. - -The letter t is used to represent the greek letter theta. - -2. The question has been posed: What is the maximum expansion factor -achieved by the linear transformation - -X' = _R_ X - -where _R_ is a real-valued 2x2 matrix with entries: - -_R_ = [a b] - [c d] . - -In other words, what is the maximum radius, MAX[ |X'| ], reached for any -X on the unit circle ( |X| = 1 ) ? - - -3. Some useful formulae - -(A) through (C) below are standard double-angle formulae. (D) is a lesser -known result and is derived below: - -(A) sin^2(t) = (1 - cos(2*t))/2 -(B) cos^2(t) = (1 + cos(2*t))/2 -(C) sin(t)*cos(t) = sin(2*t)/2 -(D) MAX[a*cos(t) + b*sin(t)] = sqrt(a^2 + b^2) - -Proof of (D): - -find the maximum of the function by setting the derivative to zero: - - -a*sin(t)+b*cos(t) = 0 - -From this it follows that - - tan(t) = b/a - -and hence - - sin(t) = b/sqrt(a^2 + b^2) - -and - - cos(t) = a/sqrt(a^2 + b^2) - -Thus the maximum value is - - MAX[a*cos(t) + b*sin(t)] = (a^2 + b^2)/sqrt(a^2 + b^2) - = sqrt(a^2 + b^2) - - -4. Derivation of maximum expansion - -To find MAX[ |X'| ] we search brute force method using calculus. The unit -circle on which X is constrained is to be parameterized by t: - - X(t) = (cos(t), sin(t)) - -Thus - - X'(t) = (a*cos(t) + b*sin(t), c*cos(t) + d*sin(t)) . - -Define - - r(t) = |X'(t)| - -Thus - - r^2(t) = (a*cos(t) + b*sin(t))^2 + (c*cos(t) + d*sin(t))^2 - = (a^2 + c^2)*cos^2(t) + (b^2 + d^2)*sin^2(t) - + 2*(a*b + c*d)*cos(t)*sin(t) - -Now apply the double angle formulae (A) to (C) from above: - - r^2(t) = (a^2 + b^2 + c^2 + d^2)/2 - + (a^2 - b^2 + c^2 - d^2)*cos(2*t)/2 - + (a*b + c*d)*sin(2*t) - = f + g*cos(u) + h*sin(u) - -Where - - f = (a^2 + b^2 + c^2 + d^2)/2 - g = (a^2 - b^2 + c^2 - d^2)/2 - h = (a*b + c*d) - u = 2*t - -It is clear that MAX[ |X'| ] = sqrt(MAX[ r^2 ]). Here we determine MAX[ r^2 ] -using (D) from above: - - MAX[ r^2 ] = f + sqrt(g^2 + h^2) - -And finally - - MAX[ |X'| ] = sqrt( f + sqrt(g^2 + h^2) ) - -Which is the solution to this problem. - - -Walter Brisken -2004/10/08 - -(Note that the minor axis length is at the minimum of the above solution, -which is just sqrt (f - sqrt (g^2 + h^2)) given the symmetry of (D)). - -Now to compute how many sides to use for the pen formed by -a regular polygon. +We show that this approximation to the ellipse has maximum error at the +major axis of the ellipse. Set - M = major axis length (computed by above formula) - m = minor axis length (computed by above formula) + M = major axis length + m = minor axis length Align 'M' along the X axis and 'm' along the Y axis and draw an ellipse parameterized by angle 't': @@ -361,12 +244,11 @@ We must make maximum error ≤ tolerance, so compute the ∆ needed: Remembering that ∆ is half of our angle between vertices, the number of vertices is then -vertices = ceil(2Ï€/2∆). - = ceil(Ï€/∆). + vertices = ceil(2Ï€/2∆). + = ceil(Ï€/∆). Note that this also equation works for M == m (a circle) as it doesn't matter where on the circle the error is computed. - */ static int @@ -374,28 +256,14 @@ _cairo_pen_vertices_needed (double tolerance, double radius, cairo_matrix_t *matrix) { - double a = matrix->xx, b = matrix->yx; - double c = matrix->xy, d = matrix->yy; - - double i = a*a + c*c; - double j = b*b + d*d; - - double f = 0.5 * (i + j); - double g = 0.5 * (i - j); - double h = a*b + c*d; - /* - * compute major and minor axes lengths for - * a pen with the specified radius + * the pen is a circle that gets transformed to an ellipse by matrix. + * compute major axis length for a pen with the specified radius. + * we don't need the minor axis length. */ - double major_axis = radius * sqrt (f + sqrt (g*g+h*h)); + double major_axis = _cairo_matrix_transformed_circle_major_axis(matrix, radius); - /* - * we don't need the minor axis length, which is - * double min = radius * sqrt (f - sqrt (g*g+h*h)); - */ - /* * compute number of vertices needed */ diff --git a/gfx/cairo/cairo/src/cairo-platform.h b/gfx/cairo/cairo/src/cairo-platform.h new file mode 100644 index 00000000000..c07066d9340 --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-platform.h @@ -0,0 +1,84 @@ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2005 Mozilla Foundation + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is University of Southern + * California. + * + * Contributor(s): + * Stuart Parmenter + */ + +#ifndef CAIRO_PLATFORM_H +#define CAIRO_PLATFORM_H + +#if defined(_MSC_VER) + +#define cairo_public extern __declspec(dllexport) +#define CCALLBACK +#define CCALLBACK_DECL +#define CSTATIC_CALLBACK(__x) static __x + +#elif defined(XP_BEOS) + +#define cairo_public extern __declspec(dllexport) +#define CCALLBACK +#define CCALLBACK_DECL +#define CSTATIC_CALLBACK(__x) static __x + +#elif defined(XP_MAC) + +#define cairo_public extern __declspec(export) +#define CCALLBACK +#define CCALLBACK_DECL +#define CSTATIC_CALLBACK(__x) static __x + +#elif defined(XP_OS2_VACPP) + +#define cairo_public extern +#define CCALLBACK _Optlink +#define CCALLBACK_DECL +#define CSTATIC_CALLBACK(__x) static __x CCALLBACK + +#else /* Unix */ + +#ifdef HAVE_VISIBILITY_PRAGMA +#define CVISIBILITY_DEFAULT __attribute__((visibility("default"))) +#else +#define CVISIBILITY_DEFAULT +#endif + +#define cairo_public extern CVISIBILITY_DEFAULT +#define CCALLBACK +#define CCALLBACK_DECL +#define CSTATIC_CALLBACK(__x) static __x + +#endif + + +#endif /* CAIRO_PLATFORM_H */ diff --git a/gfx/cairo/cairo/src/cairo-png.c b/gfx/cairo/cairo/src/cairo-png.c index afe9e6ea1f5..f0aaebe6175 100644 --- a/gfx/cairo/cairo/src/cairo-png.c +++ b/gfx/cairo/cairo/src/cairo-png.c @@ -288,6 +288,13 @@ cairo_surface_write_to_png_stream (cairo_surface_t *surface, return write_png (surface, stream_write_func, &png_closure); } +static INLINE int +multiply_alpha (int alpha, int color) +{ + int temp = (alpha * color) + 0x80; + return ((temp + (temp >> 8)) >> 8); +} + /* Premultiplies data and converts RGBA bytes => native endian */ static void premultiply_data (png_structp png, @@ -298,16 +305,23 @@ premultiply_data (png_structp png, for (i = 0; i < row_info->rowbytes; i += 4) { uint8_t *base = &data[i]; - uint8_t red = base[0]; - uint8_t green = base[1]; - uint8_t blue = base[2]; uint8_t alpha = base[3]; uint32_t p; - red = ((unsigned) red * (unsigned) alpha + 127) / 255; - green = ((unsigned) green * (unsigned) alpha + 127) / 255; - blue = ((unsigned) blue * (unsigned) alpha + 127) / 255; - p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); + if (alpha == 0) { + p = 0; + } else { + uint8_t red = base[0]; + uint8_t green = base[1]; + uint8_t blue = base[2]; + + if (alpha != 0xff) { + red = multiply_alpha (alpha, red); + green = multiply_alpha (alpha, green); + blue = multiply_alpha (alpha, blue); + } + p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0); + } memcpy (base, &p, sizeof (uint32_t)); } } diff --git a/gfx/cairo/cairo/src/cairo-ps-surface.c b/gfx/cairo/cairo/src/cairo-ps-surface.c index 79ab6595301..14445293c5c 100644 --- a/gfx/cairo/cairo/src/cairo-ps-surface.c +++ b/gfx/cairo/cairo/src/cairo-ps-surface.c @@ -102,6 +102,8 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream, surface->height = height; surface->x_dpi = PS_SURFACE_DPI_DEFAULT; surface->y_dpi = PS_SURFACE_DPI_DEFAULT; + surface->base.device_x_scale = surface->x_dpi / 72.0; + surface->base.device_y_scale = surface->y_dpi / 72.0; surface->current_page = _cairo_meta_surface_create (width, height); @@ -154,6 +156,29 @@ cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, height_in_points); } +/** + * cairo_ps_surface_set_dpi: + * @surface: a postscript cairo_surface_t + * @x_dpi: horizontal dpi + * @y_dpi: vertical dpi + * + * Set horizontal and vertical resolution for image fallbacks. When + * the postscript backend needs to fall back to image overlays, it + * will use this resolution. + **/ +void +cairo_ps_surface_set_dpi (cairo_surface_t *surface, + double x_dpi, + double y_dpi) +{ + cairo_ps_surface_t *ps_surface = (cairo_ps_surface_t *) surface; + + ps_surface->x_dpi = x_dpi; + ps_surface->y_dpi = y_dpi; + ps_surface->base.device_x_scale = ps_surface->x_dpi / 72.0; + ps_surface->base.device_y_scale = ps_surface->y_dpi / 72.0; +} + static cairo_status_t _cairo_ps_surface_finish (void *abstract_surface) { @@ -164,7 +189,7 @@ _cairo_ps_surface_finish (void *abstract_surface) int i; time_t now; - now = time (0); + now = time (NULL); /* Document header */ _cairo_output_stream_printf (surface->stream, @@ -610,6 +635,12 @@ color_is_gray (cairo_color_t *color) fabs (color->red - color->blue) < epsilon); } +static cairo_bool_t +color_is_translucent (const cairo_color_t *color) +{ + return color->alpha < 0.999; +} + static cairo_bool_t pattern_is_translucent (cairo_pattern_t *abstract_pattern) { @@ -618,7 +649,7 @@ pattern_is_translucent (cairo_pattern_t *abstract_pattern) pattern = (cairo_pattern_union_t *) abstract_pattern; switch (pattern->base.type) { case CAIRO_PATTERN_SOLID: - return pattern->solid.color.alpha < 0.9; + return color_is_translucent (&pattern->solid.color); case CAIRO_PATTERN_SURFACE: case CAIRO_PATTERN_LINEAR: case CAIRO_PATTERN_RADIAL: @@ -658,6 +689,7 @@ emit_image (cairo_ps_surface_t *surface, unsigned char *rgb, *compressed; unsigned long rgb_size, compressed_size; cairo_surface_t *opaque; + cairo_image_surface_t *opaque_image; cairo_pattern_union_t pattern; cairo_matrix_t d2i; int x, y, i; @@ -668,31 +700,35 @@ emit_image (cairo_ps_surface_t *surface, if (image->base.status) return image->base.status; - opaque = _cairo_surface_create_similar_solid (&image->base, - CAIRO_CONTENT_COLOR, - image->width, - image->height, - CAIRO_COLOR_WHITE); - if (opaque->status) { - status = CAIRO_STATUS_NO_MEMORY; - goto bail0; + if (image->format != CAIRO_FORMAT_RGB24) { + opaque = cairo_image_surface_create (CAIRO_FORMAT_RGB24, + image->width, + image->height); + if (opaque->status) { + status = CAIRO_STATUS_NO_MEMORY; + goto bail0; + } + + _cairo_pattern_init_for_surface (&pattern.surface, &image->base); + + _cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER, + &pattern.base, + NULL, + opaque, + 0, 0, + 0, 0, + 0, 0, + image->width, + image->height); + + _cairo_pattern_fini (&pattern.base); + opaque_image = (cairo_image_surface_t *) opaque; + } else { + opaque = &image->base; + opaque_image = image; } - _cairo_pattern_init_for_surface (&pattern.surface, &image->base); - - _cairo_surface_composite (CAIRO_OPERATOR_DEST_OVER, - &pattern.base, - NULL, - opaque, - 0, 0, - 0, 0, - 0, 0, - image->width, - image->height); - - _cairo_pattern_fini (&pattern.base); - - rgb_size = 3 * image->width * image->height; + rgb_size = 3 * opaque_image->width * opaque_image->height; rgb = malloc (rgb_size); if (rgb == NULL) { status = CAIRO_STATUS_NO_MEMORY; @@ -700,9 +736,9 @@ emit_image (cairo_ps_surface_t *surface, } i = 0; - for (y = 0; y < image->height; y++) { - pixman_bits_t *pixel = (pixman_bits_t *) (image->data + y * image->stride); - for (x = 0; x < image->width; x++, pixel++) { + for (y = 0; y < opaque_image->height; y++) { + pixman_bits_t *pixel = (pixman_bits_t *) (opaque_image->data + y * opaque_image->stride); + for (x = 0; x < opaque_image->width; x++, pixel++) { rgb[i++] = (*pixel & 0x00ff0000) >> 16; rgb[i++] = (*pixel & 0x0000ff00) >> 8; rgb[i++] = (*pixel & 0x000000ff) >> 0; @@ -718,7 +754,7 @@ emit_image (cairo_ps_surface_t *surface, /* matrix transforms from user space to image space. We need to * transform from device space to image space to compensate for * postscripts coordinate system. */ - cairo_matrix_init (&d2i, 1, 0, 0, -1, 0, surface->height); + cairo_matrix_init (&d2i, 1, 0, 0, 1, 0, 0); cairo_matrix_multiply (&d2i, &d2i, matrix); _cairo_output_stream_printf (surface->stream, @@ -733,8 +769,8 @@ emit_image (cairo_ps_surface_t *surface, " /ImageMatrix [ %f %f %f %f %f %f ]\n" ">>\n" "image\n", - image->width, - image->height, + opaque_image->width, + opaque_image->height, d2i.xx, d2i.yx, d2i.xy, d2i.yy, d2i.x0, d2i.y0); @@ -750,7 +786,8 @@ emit_image (cairo_ps_surface_t *surface, bail2: free (rgb); bail1: - cairo_surface_destroy (opaque); + if (opaque_image != image) + cairo_surface_destroy (opaque); bail0: return status; } @@ -842,7 +879,7 @@ _ps_output_composite (cairo_operator_t operator, * need pixmap fallbacks for this, though. */ _cairo_output_stream_printf (stream, "%% _ps_output_composite: with mask\n"); - return CAIRO_STATUS_SUCCESS; + goto bail; } status = CAIRO_STATUS_SUCCESS; @@ -850,7 +887,7 @@ _ps_output_composite (cairo_operator_t operator, case CAIRO_PATTERN_SOLID: _cairo_output_stream_printf (stream, "%% _ps_output_composite: solid\n"); - break; + goto bail; case CAIRO_PATTERN_SURFACE: surface_pattern = (cairo_surface_pattern_t *) src_pattern; @@ -858,7 +895,7 @@ _ps_output_composite (cairo_operator_t operator, if (src_pattern->extend != CAIRO_EXTEND_NONE) { _cairo_output_stream_printf (stream, "%% _ps_output_composite: repeating image\n"); - break; + goto bail; } @@ -868,7 +905,7 @@ _ps_output_composite (cairo_operator_t operator, if (status == CAIRO_INT_STATUS_UNSUPPORTED) { _cairo_output_stream_printf (stream, "%% _ps_output_composite: src_pattern not available as image\n"); - break; + goto bail; } else if (status) { break; } @@ -881,10 +918,12 @@ _ps_output_composite (cairo_operator_t operator, case CAIRO_PATTERN_RADIAL: _cairo_output_stream_printf (stream, "%% _ps_output_composite: gradient\n"); - break; + goto bail; } return status; +bail: + return _ps_output_add_fallback_area (surface, dst_x, dst_y, width, height); } static cairo_int_status_t @@ -899,6 +938,24 @@ _ps_output_fill_rectangles (void *abstract_surface, cairo_solid_pattern_t solid; int i; + if (!num_rects) + return CAIRO_STATUS_SUCCESS; + + if (color_is_translucent (color)) { + int min_x = rects[0].x; + int min_y = rects[0].y; + int max_x = rects[0].x + rects[0].width; + int max_y = rects[0].y + rects[0].height; + + for (i = 1; i < num_rects; i++) { + if (rects[i].x < min_x) min_x = rects[i].x; + if (rects[i].y < min_y) min_y = rects[i].y; + if (rects[i].x + rects[i].width > max_x) max_x = rects[i].x + rects[i].width; + if (rects[i].y + rects[i].height > max_y) max_y = rects[i].y + rects[i].height; + } + return _ps_output_add_fallback_area (surface, min_x, min_y, max_x - min_x, max_y - min_y); + } + _cairo_output_stream_printf (stream, "%% _ps_output_fill_rectangles\n"); @@ -909,9 +966,8 @@ _ps_output_fill_rectangles (void *abstract_surface, _cairo_output_stream_printf (stream, "["); for (i = 0; i < num_rects; i++) { _cairo_output_stream_printf (stream, - " %d %f %d %d", - rects[i].x, - (double)(surface->parent->height - rects[i].y - rects[i].height), + " %d %d %d %d", + rects[i].x, rects[i].y, rects[i].width, rects[i].height); } @@ -962,8 +1018,8 @@ _ps_output_composite_trapezoids (cairo_operator_t operator, left_x2 = intersect (&traps[i].left, traps[i].bottom); right_x1 = intersect (&traps[i].right, traps[i].top); right_x2 = intersect (&traps[i].right, traps[i].bottom); - top = surface->parent->height - _cairo_fixed_to_double (traps[i].top); - bottom = surface->parent->height - _cairo_fixed_to_double (traps[i].bottom); + top = _cairo_fixed_to_double (traps[i].top); + bottom = _cairo_fixed_to_double (traps[i].bottom); _cairo_output_stream_printf (stream, @@ -983,7 +1039,6 @@ _ps_output_composite_trapezoids (cairo_operator_t operator, typedef struct { - double height; cairo_output_stream_t *output_stream; cairo_bool_t has_current_point; } ps_output_path_info_t; @@ -996,7 +1051,7 @@ _ps_output_path_move_to (void *closure, cairo_point_t *point) _cairo_output_stream_printf (info->output_stream, "%f %f moveto ", _cairo_fixed_to_double (point->x), - info->height - _cairo_fixed_to_double (point->y)); + _cairo_fixed_to_double (point->y)); info->has_current_point = TRUE; return CAIRO_STATUS_SUCCESS; @@ -1016,7 +1071,7 @@ _ps_output_path_line_to (void *closure, cairo_point_t *point) _cairo_output_stream_printf (info->output_stream, "%f %f %s ", _cairo_fixed_to_double (point->x), - info->height - _cairo_fixed_to_double (point->y), + _cairo_fixed_to_double (point->y), ps_operator); info->has_current_point = TRUE; @@ -1034,11 +1089,11 @@ _ps_output_path_curve_to (void *closure, _cairo_output_stream_printf (info->output_stream, "%f %f %f %f %f %f curveto ", _cairo_fixed_to_double (b->x), - info->height - _cairo_fixed_to_double (b->y), + _cairo_fixed_to_double (b->y), _cairo_fixed_to_double (c->x), - info->height - _cairo_fixed_to_double (c->y), + _cairo_fixed_to_double (c->y), _cairo_fixed_to_double (d->x), - info->height - _cairo_fixed_to_double (d->y)); + _cairo_fixed_to_double (d->y)); return CAIRO_STATUS_SUCCESS; } @@ -1078,7 +1133,6 @@ _ps_output_intersect_clip_path (void *abstract_surface, info.output_stream = stream; info.has_current_point = FALSE; - info.height = surface->parent->height; status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, @@ -1150,7 +1204,7 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font, scaled_font->scale.xx, scaled_font->scale.yx, scaled_font->scale.xy, - scaled_font->scale.yy); + -scaled_font->scale.yy); /* FIXME: Need to optimize per glyph code. Should detect when * glyphs share the same baseline and when the spacing corresponds @@ -1161,7 +1215,7 @@ _ps_output_show_glyphs (cairo_scaled_font_t *scaled_font, _cairo_output_stream_printf (stream, "%f %f moveto (\\%o) show\n", glyphs[i].x, - surface->parent->height - glyphs[i].y, + glyphs[i].y, subset_index); } @@ -1183,6 +1237,11 @@ _ps_output_fill_path (cairo_operator_t operator, ps_output_path_info_t info; const char *ps_operator; + if (pattern_is_translucent (pattern)) + return _ps_output_add_fallback_area (surface, + 0, 0, + surface->parent->width, + surface->parent->height); _cairo_output_stream_printf (stream, "%% _ps_output_fill_path\n"); @@ -1190,7 +1249,6 @@ _ps_output_fill_path (cairo_operator_t operator, info.output_stream = stream; info.has_current_point = FALSE; - info.height = surface->parent->height; status = _cairo_path_fixed_interpret (path, CAIRO_DIRECTION_FORWARD, @@ -1312,8 +1370,11 @@ _cairo_ps_surface_render_page (cairo_ps_surface_t *surface, _cairo_output_stream_printf (surface->stream, "%%%%Page: %d\n" - "gsave\n", - page_number); + "gsave %f %f translate %f %f scale \n", + page_number, + 0.0, surface->height, + 1.0/surface->base.device_x_scale, + -1.0/surface->base.device_y_scale); ps_output = _ps_output_surface_create (surface); if (ps_output->status) diff --git a/gfx/cairo/cairo/src/cairo-ps.h b/gfx/cairo/cairo/src/cairo-ps.h index ea2d53d092d..036c4b2c270 100644 --- a/gfx/cairo/cairo/src/cairo-ps.h +++ b/gfx/cairo/cairo/src/cairo-ps.h @@ -47,18 +47,18 @@ CAIRO_BEGIN_DECLS /* PS-surface functions */ -cairo_surface_t * +cairo_public cairo_surface_t * cairo_ps_surface_create (const char *filename, double width_in_points, double height_in_points); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_ps_surface_create_for_stream (cairo_write_func_t write_func, void *closure, double width_in_points, double height_in_points); -void +cairo_public void cairo_ps_surface_set_dpi (cairo_surface_t *surface, double x_dpi, double y_dpi); diff --git a/gfx/cairo/cairo/src/cairo-quartz-surface.c b/gfx/cairo/cairo/src/cairo-quartz-surface.c index 70f408a3b7b..b023d34dcfb 100644 --- a/gfx/cairo/cairo/src/cairo-quartz-surface.c +++ b/gfx/cairo/cairo/src/cairo-quartz-surface.c @@ -125,8 +125,8 @@ _cairo_quartz_surface_acquire_source_image(void *abstract_surface, surface->width, surface->height, rowBytes); if (surface->image->base.status) { - /* XXX: I assume we're leaking memory here, but I don't know - * the right call to use to clean up from CGImageCreate. */ + if (surface->cgImage) + CGImageRelease(surface->cgImage); return CAIRO_STATUS_NO_MEMORY; } diff --git a/gfx/cairo/cairo/src/cairo-quartz.h b/gfx/cairo/cairo/src/cairo-quartz.h index dd929b29715..02992dced86 100644 --- a/gfx/cairo/cairo/src/cairo-quartz.h +++ b/gfx/cairo/cairo/src/cairo-quartz.h @@ -45,7 +45,7 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_quartz_surface_create (CGContextRef context, int width, int height); diff --git a/gfx/cairo/cairo/src/cairo-scaled-font.c b/gfx/cairo/cairo/src/cairo-scaled-font.c new file mode 100644 index 00000000000..e83bcebd00f --- /dev/null +++ b/gfx/cairo/cairo/src/cairo-scaled-font.c @@ -0,0 +1,1193 @@ +/* $Id: cairo-scaled-font.c,v 1.1 2005-10-06 04:02:06 vladimir%pobox.com Exp $ + * + * Copyright © 2005 Keith Packard + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Keith Packard + * + * Contributor(s): + * Keith Packard + * Carl D. Worth + * Graydon Hoare + * Owen Taylor + */ + +#include "cairoint.h" + +static cairo_bool_t +_cairo_scaled_glyph_keys_equal (void *abstract_key_a, void *abstract_key_b) +{ + cairo_scaled_glyph_t *key_a = abstract_key_a; + cairo_scaled_glyph_t *key_b = abstract_key_b; + + return (_cairo_scaled_glyph_index (key_a) == + _cairo_scaled_glyph_index (key_b)); +} + +static void +_cairo_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph) +{ + cairo_scaled_font_t *scaled_font = scaled_glyph->scaled_font; + const cairo_surface_backend_t *surface_backend = scaled_font->surface_backend; + + if (surface_backend != NULL && surface_backend->scaled_glyph_fini != NULL) + surface_backend->scaled_glyph_fini (scaled_glyph, scaled_font); + if (scaled_glyph->surface != NULL) + cairo_surface_destroy (&scaled_glyph->surface->base); + if (scaled_glyph->path != NULL) + _cairo_path_fixed_destroy (scaled_glyph->path); +} + +static void +_cairo_scaled_glyph_destroy (void *abstract_glyph) +{ + cairo_scaled_glyph_t *scaled_glyph = abstract_glyph; + _cairo_scaled_glyph_fini (scaled_glyph); + free (scaled_glyph); +} + +static const cairo_scaled_font_t _cairo_scaled_font_nil = { + { 0 }, /* hash_entry */ + CAIRO_STATUS_NO_MEMORY, /* status */ + -1, /* ref_count */ + NULL, /* font_face */ + { 1., 0., 0., 1., 0, 0}, /* font_matrix */ + { 1., 0., 0., 1., 0, 0}, /* ctm */ + { CAIRO_ANTIALIAS_DEFAULT, /* options */ + CAIRO_SUBPIXEL_ORDER_DEFAULT, + CAIRO_HINT_STYLE_DEFAULT, + CAIRO_HINT_METRICS_DEFAULT} , + { 1., 0., 0., 1., 0, 0}, /* scale */ + { 0., 0., 0., 0., 0. }, /* extents */ + NULL, /* glyphs */ + NULL, /* surface_backend */ + NULL, /* surface_private */ + CAIRO_SCALED_FONT_BACKEND_DEFAULT, +}; + +/** + * _cairo_scaled_font_set_error: + * @scaled_font: a scaled_font + * @status: a status value indicating an error, (eg. not + * CAIRO_STATUS_SUCCESS) + * + * Sets scaled_font->status to @status and calls _cairo_error; + * + * All assignments of an error status to scaled_font->status should happen + * through _cairo_scaled_font_set_error() or else _cairo_error() should be + * called immediately after the assignment. + * + * The purpose of this function is to allow the user to set a + * breakpoint in _cairo_error() to generate a stack trace for when the + * user causes cairo to detect an error. + **/ +void +_cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font, + cairo_status_t status) +{ + /* Don't overwrite an existing error. This preserves the first + * error, which is the most significant. It also avoids attempting + * to write to read-only data (eg. from a nil scaled_font). */ + if (scaled_font->status == CAIRO_STATUS_SUCCESS) + scaled_font->status = status; + + _cairo_error (status); +} + +/** + * cairo_scaled_font_status: + * @scaled_font: a #cairo_scaled_font_t + * + * Checks whether an error has previously occurred for this + * scaled_font. + * + * Return value: %CAIRO_STATUS_SUCCESS or another error such as + * %CAIRO_STATUS_NO_MEMORY. + **/ +cairo_status_t +cairo_scaled_font_status (cairo_scaled_font_t *scaled_font) +{ + return scaled_font->status; +} + +/* Here we keep a unique mapping from + * cairo_font_face_t/matrix/ctm/options => cairo_scaled_font_t. + * + * Here are the things that we want to map: + * + * a) All otherwise referenced cairo_scaled_font_t's + * b) Some number of not otherwise referenced cairo_scaled_font_t's + * + * The implementation uses a hash table which covers (a) + * completely. Then, for (b) we have an array of otherwise + * unreferenced fonts (holdovers) which are expired in + * least-recently-used order. + * + * The cairo_scaled_font_create code gets to treat this like a regular + * hash table. All of the magic for the little holdover cache is in + * cairo_scaled_font_reference and cairo_scaled_font_destroy. + */ + +/* This defines the size of the holdover array ... that is, the number + * of scaled fonts we keep around even when not otherwise referenced + */ +#define CAIRO_SCALED_FONT_MAX_HOLDOVERS 256 + +typedef struct _cairo_scaled_font_map { + cairo_hash_table_t *hash_table; + cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS]; + int num_holdovers; +} cairo_scaled_font_map_t; + +static cairo_scaled_font_map_t *cairo_scaled_font_map = NULL; + +CAIRO_MUTEX_DECLARE (cairo_scaled_font_map_mutex); + +static int +_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b); + +static cairo_scaled_font_map_t * +_cairo_scaled_font_map_lock (void) +{ + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); + + if (cairo_scaled_font_map == NULL) { + cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); + if (cairo_scaled_font_map == NULL) + goto CLEANUP_MUTEX_LOCK; + + cairo_scaled_font_map->hash_table = + _cairo_hash_table_create (_cairo_scaled_font_keys_equal); + + if (cairo_scaled_font_map->hash_table == NULL) + goto CLEANUP_SCALED_FONT_MAP; + + cairo_scaled_font_map->num_holdovers = 0; + } + + return cairo_scaled_font_map; + + CLEANUP_SCALED_FONT_MAP: + free (cairo_scaled_font_map); + CLEANUP_MUTEX_LOCK: + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); + return NULL; +} + +static void +_cairo_scaled_font_map_unlock (void) +{ + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); +} + +void +_cairo_scaled_font_map_destroy (void) +{ + int i; + cairo_scaled_font_map_t *font_map = cairo_scaled_font_map; + cairo_scaled_font_t *scaled_font; + + if (font_map == NULL) + return; + + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); + + for (i = 0; i < font_map->num_holdovers; i++) { + scaled_font = font_map->holdovers[i]; + /* We should only get here through the reset_static_data path + * and there had better not be any active references at that + * point. */ + assert (scaled_font->ref_count == 0); + _cairo_hash_table_remove (font_map->hash_table, + &scaled_font->hash_entry); + _cairo_scaled_font_fini (scaled_font); + free (scaled_font); + } + + _cairo_hash_table_destroy (font_map->hash_table); + + free (cairo_scaled_font_map); + cairo_scaled_font_map = NULL; +} + +/* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/) + * + * Not necessarily better than a lot of other hashes, but should be OK, and + * well tested with binary data. + */ + +#define FNV_32_PRIME ((uint32_t)0x01000193) +#define FNV1_32_INIT ((uint32_t)0x811c9dc5) + +static uint32_t +_hash_bytes_fnv (unsigned char *buffer, + int len, + uint32_t hval) +{ + while (len--) { + hval *= FNV_32_PRIME; + hval ^= *buffer++; + } + + return hval; +} + +static void +_cairo_scaled_font_init_key (cairo_scaled_font_t *scaled_font, + cairo_font_face_t *font_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options) +{ + uint32_t hash = FNV1_32_INIT; + + scaled_font->status = CAIRO_STATUS_SUCCESS; + scaled_font->font_face = font_face; + scaled_font->font_matrix = *font_matrix; + scaled_font->ctm = *ctm; + scaled_font->options = *options; + + /* We do a bytewise hash on the font matrices, ignoring the + * translation values in the ctm */ + hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->font_matrix.xx), + sizeof(cairo_matrix_t), hash); + hash = _hash_bytes_fnv ((unsigned char *)(&scaled_font->ctm.xx), + sizeof(double) * 4, hash); + + hash ^= (unsigned long) scaled_font->font_face; + + hash ^= cairo_font_options_hash (&scaled_font->options); + + scaled_font->hash_entry.hash = hash; +} + +static cairo_bool_t +_cairo_scaled_font_keys_equal (void *abstract_key_a, void *abstract_key_b) +{ + cairo_scaled_font_t *key_a = abstract_key_a; + cairo_scaled_font_t *key_b = abstract_key_b; + + return (key_a->font_face == key_b->font_face && + memcmp ((unsigned char *)(&key_a->font_matrix.xx), + (unsigned char *)(&key_b->font_matrix.xx), + sizeof(cairo_matrix_t)) == 0 && + memcmp ((unsigned char *)(&key_a->ctm.xx), + (unsigned char *)(&key_b->ctm.xx), + sizeof(double) * 4) == 0 && + cairo_font_options_equal (&key_a->options, &key_b->options)); +} + +/* + * Basic cairo_scaled_font_t object management + */ + +cairo_status_t +_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, + cairo_font_face_t *font_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + const cairo_scaled_font_backend_t *backend) +{ + scaled_font->ref_count = 1; + + _cairo_scaled_font_init_key (scaled_font, font_face, + font_matrix, ctm, options); + + cairo_font_face_reference (font_face); + + cairo_matrix_multiply (&scaled_font->scale, + &scaled_font->font_matrix, + &scaled_font->ctm); + + scaled_font->glyphs = _cairo_cache_create (_cairo_scaled_glyph_keys_equal, + _cairo_scaled_glyph_destroy, + 256); + + scaled_font->surface_backend = NULL; + scaled_font->surface_private = NULL; + + scaled_font->backend = backend; + + return CAIRO_STATUS_SUCCESS; +} + +void +_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, + cairo_font_extents_t *fs_metrics) +{ + double font_scale_x, font_scale_y; + + _cairo_matrix_compute_scale_factors (&scaled_font->font_matrix, + &font_scale_x, &font_scale_y, + /* XXX */ 1); + + /* + * The font responded in unscaled units, scale by the font + * matrix scale factors to get to user space + */ + + scaled_font->extents.ascent = fs_metrics->ascent * font_scale_y; + scaled_font->extents.descent = fs_metrics->descent * font_scale_y; + scaled_font->extents.height = fs_metrics->height * font_scale_y; + scaled_font->extents.max_x_advance = fs_metrics->max_x_advance * font_scale_x; + scaled_font->extents.max_y_advance = fs_metrics->max_y_advance * font_scale_y; +} + +void +_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font) +{ + if (scaled_font->font_face != NULL) + cairo_font_face_destroy (scaled_font->font_face); + + if (scaled_font->glyphs != NULL) + _cairo_cache_destroy (scaled_font->glyphs); + + if (scaled_font->surface_backend != NULL && + scaled_font->surface_backend->scaled_font_fini != NULL) + scaled_font->surface_backend->scaled_font_fini (scaled_font); + + scaled_font->backend->fini (scaled_font); + +} + +/** + * cairo_scaled_font_create: + * @font_face: a #cairo_font_face_t + * @font_matrix: font space to user space transformation matrix for the + * font. In the simplest case of a N point font, this matrix is + * just a scale by N, but it can also be used to shear the font + * or stretch it unequally along the two axes. See + * cairo_set_font_matrix(). + * @ctm: user to device transformation matrix with which the font will + * be used. + * @options: options to use when getting metrics for the font and + * rendering with it. + * + * Creates a #cairo_scaled_font_t object from a font face and matrices that + * describe the size of the font and the environment in which it will + * be used. + * + * Return value: a newly created #cairo_scaled_font_t. Destroy with + * cairo_scaled_font_destroy() + **/ +cairo_scaled_font_t * +cairo_scaled_font_create (cairo_font_face_t *font_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options) +{ + cairo_status_t status; + cairo_scaled_font_map_t *font_map; + cairo_scaled_font_t key, *scaled_font = NULL; + + font_map = _cairo_scaled_font_map_lock (); + if (font_map == NULL) + goto UNWIND; + + _cairo_scaled_font_init_key (&key, font_face, + font_matrix, ctm, options); + + /* Return existing scaled_font if it exists in the hash table. */ + if (_cairo_hash_table_lookup (font_map->hash_table, &key.hash_entry, + (cairo_hash_entry_t**) &scaled_font)) + { + _cairo_scaled_font_map_unlock (); + return cairo_scaled_font_reference (scaled_font); + } + + /* Otherwise create it and insert it into the hash table. */ + status = font_face->backend->scaled_font_create (font_face, font_matrix, + ctm, options, &scaled_font); + if (status) + goto UNWIND_FONT_MAP_LOCK; + + status = _cairo_hash_table_insert (font_map->hash_table, + &scaled_font->hash_entry); + if (status) + goto UNWIND_SCALED_FONT_CREATE; + + _cairo_scaled_font_map_unlock (); + + return scaled_font; + +UNWIND_SCALED_FONT_CREATE: + /* We can't call _cairo_scaled_font_destroy here since it expects + * that the font has already been successfully inserted into the + * hash table. */ + _cairo_scaled_font_fini (scaled_font); + free (scaled_font); +UNWIND_FONT_MAP_LOCK: + _cairo_scaled_font_map_unlock (); +UNWIND: + return NULL; +} + +/** + * cairo_scaled_font_reference: + * @scaled_font: a #cairo_scaled_font_t, (may be NULL in which case + * this function does nothing) + * + * Increases the reference count on @scaled_font by one. This prevents + * @scaled_font from being destroyed until a matching call to + * cairo_scaled_font_destroy() is made. + * + * Returns: the referenced #cairo_scaled_font_t + **/ +cairo_scaled_font_t * +cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font) +{ + cairo_scaled_font_map_t *font_map; + + if (scaled_font == NULL) + return NULL; + + if (scaled_font->ref_count == (unsigned int)-1) + return scaled_font; + + /* We would normally assert (scaled_font->ref_count > 0) here, but + * we are using ref_count == 0 as a legitimate case for the + * holdovers array. See below. */ + + /* cairo_scaled_font_t objects are cached and shared between + * threads. This works because these objects are immutable. Except + * that the reference count is mutable, so we have to do locking + * around any modification of the reference count. */ + font_map = _cairo_scaled_font_map_lock (); + { + /* If the original reference count is 0, then this font must have + * been found in font_map->holdovers, (which means this caching is + * actually working). So now we remove it from the holdovers + * array. */ + if (scaled_font->ref_count == 0) { + int i; + + for (i = 0; i < font_map->num_holdovers; i++) + if (font_map->holdovers[i] == scaled_font) + break; + assert (i < font_map->num_holdovers); + + font_map->num_holdovers--; + memmove (&font_map->holdovers[i], + &font_map->holdovers[i+1], + (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*)); + } + + scaled_font->ref_count++; + + } + _cairo_scaled_font_map_unlock (); + + return scaled_font; +} + +/** + * cairo_scaled_font_destroy: + * @scaled_font: a #cairo_scaled_font_t + * + * Decreases the reference count on @font by one. If the result + * is zero, then @font and all associated resources are freed. + * See cairo_scaled_font_reference(). + **/ +void +cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font) +{ + cairo_scaled_font_map_t *font_map; + + if (scaled_font == NULL) + return; + + if (scaled_font->ref_count == (unsigned int)-1) + return; + + /* cairo_scaled_font_t objects are cached and shared between + * threads. This works because these objects are immutable. Except + * that the reference count is mutable, so we have to do locking + * around any modification of the reference count. */ + font_map = _cairo_scaled_font_map_lock (); + { + assert (font_map != NULL); + + assert (scaled_font->ref_count > 0); + + if (--(scaled_font->ref_count) == 0) + { + /* Rather than immediately destroying this object, we put it into + * the font_map->holdovers array in case it will get used again + * soon. To make room for it, we do actually destroy the + * least-recently-used holdover. + */ + if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) { + cairo_scaled_font_t *lru; + + lru = font_map->holdovers[0]; + assert (lru->ref_count == 0); + + _cairo_hash_table_remove (font_map->hash_table, &lru->hash_entry); + + _cairo_scaled_font_fini (lru); + free (lru); + + font_map->num_holdovers--; + memmove (&font_map->holdovers[0], + &font_map->holdovers[1], + font_map->num_holdovers * sizeof (cairo_scaled_font_t*)); + } + + font_map->holdovers[font_map->num_holdovers] = scaled_font; + font_map->num_holdovers++; + } + } + _cairo_scaled_font_map_unlock (); +} + +/* Public font API follows. */ + +/** + * cairo_scaled_font_extents: + * @scaled_font: a #cairo_scaled_font_t + * @extents: a #cairo_font_extents_t which to store the retrieved extents. + * + * Gets the metrics for a #cairo_scaled_font_t. + **/ +void +cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, + cairo_font_extents_t *extents) +{ + *extents = scaled_font->extents; +} + +/** + * cairo_scaled_font_glyph_extents: + * @scaled_font: a #cairo_scaled_font_t + * @glyphs: an array of glyph IDs with X and Y offsets. + * @num_glyphs: the number of glyphs in the @glyphs array + * @extents: a #cairo_text_extents_t which to store the retrieved extents. + * + * cairo_font_glyph_extents() gets the overall metrics for a string of + * glyphs. The X and Y offsets in @glyphs are taken from an origin of 0,0. + **/ +void +cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_text_extents_t *extents) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + int i; + double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0; + double x_pos = 0.0, y_pos = 0.0; + + if (scaled_font->status) + return; + + if (!num_glyphs) { + extents->x_bearing = 0.0; + extents->y_bearing = 0.0; + extents->width = 0.0; + extents->height = 0.0; + extents->x_advance = 0.0; + extents->y_advance = 0.0; + + return; + } + + for (i = 0; i < num_glyphs; i++) { + cairo_scaled_glyph_t *scaled_glyph; + double left, top, right, bottom; + + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + if (status) { + _cairo_scaled_font_set_error (scaled_font, status); + return; + } + + left = scaled_glyph->metrics.x_bearing + glyphs[i].x; + right = left + scaled_glyph->metrics.width; + top = scaled_glyph->metrics.y_bearing + glyphs[i].y; + bottom = top + scaled_glyph->metrics.height; + + if (i == 0) { + min_x = left; + max_x = right; + min_y = top; + max_y = bottom; + } else { + if (left < min_x) min_x = left; + if (right > max_x) max_x = right; + if (top < min_y) min_y = top; + if (bottom > max_y) max_y = bottom; + } + x_pos = glyphs[i].x + scaled_glyph->metrics.x_advance; + y_pos = glyphs[i].y + scaled_glyph->metrics.y_advance; + } + + extents->x_bearing = min_x - glyphs[0].x; + extents->y_bearing = min_y - glyphs[0].y; + extents->width = max_x - min_x; + extents->height = max_y - min_y; + extents->x_advance = x_pos - glyphs[0].x; + extents->y_advance = y_pos - glyphs[0].y; +} + +cairo_status_t +_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, + double x, + double y, + const char *utf8, + cairo_glyph_t **glyphs, + int *num_glyphs) +{ + size_t i; + uint32_t *ucs4 = NULL; + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_scaled_glyph_t *scaled_glyph; + + if (scaled_font->backend->text_to_glyphs) { + status = scaled_font->backend->text_to_glyphs (scaled_font, + x, y, utf8, + glyphs, num_glyphs); + + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + } + + status = _cairo_utf8_to_ucs4 ((unsigned char*)utf8, -1, &ucs4, num_glyphs); + if (status) + return status; + + *glyphs = (cairo_glyph_t *) malloc ((*num_glyphs) * (sizeof (cairo_glyph_t))); + + if (*glyphs == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + goto FAIL; + } + + for (i = 0; i < *num_glyphs; i++) { + (*glyphs)[i].index = (*scaled_font->backend-> + ucs4_to_index) (scaled_font, ucs4[i]); + (*glyphs)[i].x = x; + (*glyphs)[i].y = y; + + status = _cairo_scaled_glyph_lookup (scaled_font, + (*glyphs)[i].index, + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + if (status) { + free (*glyphs); + *glyphs = NULL; + goto FAIL; + } + + x += scaled_glyph->metrics.x_advance; + y += scaled_glyph->metrics.y_advance; + } + + FAIL: + free (ucs4); + + return status; +} + +/* + * Compute a device-space bounding box for the glyphs. + */ +cairo_status_t +_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_rectangle_t *extents) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + int i; + int min_x = CAIRO_MAXSHORT, max_x = CAIRO_MINSHORT; + int min_y = CAIRO_MAXSHORT, max_y = CAIRO_MINSHORT; + + if (scaled_font->status) + return scaled_font->status; + + for (i = 0; i < num_glyphs; i++) { + cairo_scaled_glyph_t *scaled_glyph; + int left, top; + int right, bottom; + int x, y; + + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_METRICS, + &scaled_glyph); + if (status) { + _cairo_scaled_font_set_error (scaled_font, status); + return status; + } + + /* glyph images are snapped to pixel locations */ + x = (int) floor (glyphs[i].x + 0.5); + y = (int) floor (glyphs[i].y + 0.5); + + left = x + _cairo_fixed_integer_floor(scaled_glyph->bbox.p1.x); + top = y + _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); + right = x + _cairo_fixed_integer_ceil(scaled_glyph->bbox.p2.x); + bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); + + if (left < min_x) min_x = left; + if (right > max_x) max_x = right; + if (top < min_y) min_y = top; + if (bottom > max_y) max_y = bottom; + } + if (min_x < max_x && min_y < max_y) { + extents->x = min_x; + extents->width = max_x - min_x; + extents->y = min_y; + extents->height = max_y - min_y; + } else { + extents->x = extents->y = 0; + extents->width = extents->height = 0; + } + return CAIRO_STATUS_SUCCESS; +} + +cairo_status_t +_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_pattern_t *pattern, + cairo_surface_t *surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + cairo_glyph_t *glyphs, + int num_glyphs) +{ + cairo_status_t status; + cairo_surface_t *mask = NULL; + int i; + + /* These operators aren't interpreted the same way by the backends; + * they are implemented in terms of other operators in cairo-gstate.c + */ + assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR); + + if (scaled_font->status) + return scaled_font->status; + + if (scaled_font->backend->show_glyphs != NULL) { + status = scaled_font->backend->show_glyphs (scaled_font, + operator, pattern, + surface, + source_x, source_y, + dest_x, dest_y, + width, height, + glyphs, num_glyphs); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + } + + /* Font display routine either does not exist or failed. */ + + status = CAIRO_STATUS_SUCCESS; + + _cairo_cache_freeze (scaled_font->glyphs); + + for (i = 0; i < num_glyphs; i++) { + int x, y; + cairo_surface_pattern_t glyph_pattern; + cairo_image_surface_t *glyph_surface; + cairo_scaled_glyph_t *scaled_glyph; + + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + + if (status) + goto CLEANUP_MASK; + + glyph_surface = scaled_glyph->surface; + + /* Create the mask using the format from the first glyph */ + if (mask == NULL) { + mask = cairo_image_surface_create (glyph_surface->format, + width, height); + if (mask->status) { + status = mask->status; + goto CLEANUP_MASK; + } + + status = _cairo_surface_fill_rectangle (mask, + CAIRO_OPERATOR_CLEAR, + CAIRO_COLOR_TRANSPARENT, + 0, 0, + width, height); + if (status) + goto CLEANUP_MASK; + if (glyph_surface->format == CAIRO_FORMAT_ARGB32) + pixman_image_set_component_alpha (((cairo_image_surface_t*) mask)-> + pixman_image, TRUE); + + } + + /* round glyph locations to the nearest pixel */ + x = (int) floor (glyphs[i].x + + glyph_surface->base.device_x_offset + + 0.5); + y = (int) floor (glyphs[i].y + + glyph_surface->base.device_y_offset + + 0.5); + + _cairo_pattern_init_for_surface (&glyph_pattern, &glyph_surface->base); + + status = _cairo_surface_composite (CAIRO_OPERATOR_ADD, + &glyph_pattern.base, + NULL, + mask, + 0, 0, + 0, 0, + x - dest_x, + y - dest_y, + glyph_surface->width, + glyph_surface->height); + + _cairo_pattern_fini (&glyph_pattern.base); + if (status) + break; + } + + if (mask != NULL) { + cairo_surface_pattern_t mask_pattern; + + _cairo_pattern_init_for_surface (&mask_pattern, mask); + + status = _cairo_surface_composite (operator, pattern, &mask_pattern.base, + surface, + source_x, source_y, + 0, 0, + dest_x, dest_y, + width, height); + + _cairo_pattern_fini (&mask_pattern.base); + } + +CLEANUP_MASK: + _cairo_cache_thaw (scaled_font->glyphs); + + if (mask != NULL) + cairo_surface_destroy (mask); + return status; +} + +typedef struct _cairo_scaled_glyph_path_closure { + cairo_point_t offset; + cairo_path_fixed_t *path; +} cairo_scaled_glyph_path_closure_t; + +static cairo_status_t +_scaled_glyph_path_move_to (void *abstract_closure, cairo_point_t *point) +{ + cairo_scaled_glyph_path_closure_t *closure = abstract_closure; + + return _cairo_path_fixed_move_to (closure->path, + point->x + closure->offset.x, + point->y + closure->offset.y); +} + +static cairo_status_t +_scaled_glyph_path_line_to (void *abstract_closure, cairo_point_t *point) +{ + cairo_scaled_glyph_path_closure_t *closure = abstract_closure; + + return _cairo_path_fixed_line_to (closure->path, + point->x + closure->offset.x, + point->y + closure->offset.y); +} + +static cairo_status_t +_scaled_glyph_path_curve_to (void *abstract_closure, + cairo_point_t *p0, + cairo_point_t *p1, + cairo_point_t *p2) +{ + cairo_scaled_glyph_path_closure_t *closure = abstract_closure; + + return _cairo_path_fixed_curve_to (closure->path, + p0->x + closure->offset.x, + p0->y + closure->offset.y, + p1->x + closure->offset.x, + p1->y + closure->offset.y, + p2->x + closure->offset.x, + p2->y + closure->offset.y); +} + + +static cairo_status_t +_scaled_glyph_path_close_path (void *abstract_closure) +{ + cairo_scaled_glyph_path_closure_t *closure = abstract_closure; + + return _cairo_path_fixed_close_path (closure->path); +} + +cairo_status_t +_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_path_fixed_t *path) +{ + cairo_status_t status; + int i; + cairo_scaled_glyph_path_closure_t closure; + + if (scaled_font->status) + return scaled_font->status; + + closure.path = path; + for (i = 0; i < num_glyphs; i++) { + cairo_scaled_glyph_t *scaled_glyph; + + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_PATH, + &scaled_glyph); + if (status) + return status; + + closure.offset.x = _cairo_fixed_from_double (glyphs[i].x); + closure.offset.y = _cairo_fixed_from_double (glyphs[i].y); + + status = _cairo_path_fixed_interpret (scaled_glyph->path, + CAIRO_DIRECTION_FORWARD, + _scaled_glyph_path_move_to, + _scaled_glyph_path_line_to, + _scaled_glyph_path_curve_to, + _scaled_glyph_path_close_path, + &closure); + } + + return CAIRO_STATUS_SUCCESS; +} + +/** + * cairo_scaled_glyph_set_metrics: + * @scaled_glyph: a #cairo_scaled_glyph_t + * @scaled_font: a #cairo_scaled_font_t + * @fs_metrics: a #cairo_text_extents_t in font space + * + * _cairo_scaled_glyph_set_metrics() stores user space metrics + * for the specified glyph given font space metrics. It is + * called by the font backend when initializing a glyph with + * CAIRO_SCALED_GLYPH_INFO_METRICS. + **/ +void +_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_text_extents_t *fs_metrics) +{ + cairo_bool_t first = TRUE; + double hm, wm; + double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0; + double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0; + + for (hm = 0.0; hm <= 1.0; hm += 1.0) + for (wm = 0.0; wm <= 1.0; wm += 1.0) { + double x, y; + + /* Transform this corner to user space */ + x = fs_metrics->x_bearing + fs_metrics->width * wm; + y = fs_metrics->y_bearing + fs_metrics->height * hm; + cairo_matrix_transform_point (&scaled_font->font_matrix, + &x, &y); + if (first) { + min_user_x = max_user_x = x; + min_user_y = max_user_y = y; + } else { + if (x < min_user_x) min_user_x = x; + if (x > max_user_x) max_user_x = x; + if (y < min_user_y) min_user_y = y; + if (y > max_user_y) max_user_y = y; + } + + /* Transform this corner to device space from glyph origin */ + x = fs_metrics->x_bearing + fs_metrics->width * wm; + y = fs_metrics->y_bearing + fs_metrics->height * hm; + cairo_matrix_transform_distance (&scaled_font->scale, + &x, &y); + + if (first) { + min_device_x = max_device_x = x; + min_device_y = max_device_y = y; + } else { + if (x < min_device_x) min_device_x = x; + if (x > max_device_x) max_device_x = x; + if (y < min_device_y) min_device_y = y; + if (y > max_device_y) max_device_y = y; + } + first = FALSE; + } + scaled_glyph->metrics.x_bearing = min_user_x; + scaled_glyph->metrics.y_bearing = min_user_y; + scaled_glyph->metrics.width = max_user_x - min_user_x; + scaled_glyph->metrics.height = max_user_y - min_user_y; + + scaled_glyph->metrics.x_advance = fs_metrics->x_advance; + scaled_glyph->metrics.y_advance = fs_metrics->y_advance; + cairo_matrix_transform_point (&scaled_font->font_matrix, + &scaled_glyph->metrics.x_advance, + &scaled_glyph->metrics.y_advance); + + scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x); + scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y); + scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x); + scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y); +} + +void +_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_image_surface_t *surface) +{ + if (scaled_glyph->surface != NULL) + cairo_surface_destroy (&scaled_glyph->surface->base); + scaled_glyph->surface = surface; +} + +void +_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_path_fixed_t *path) +{ + if (scaled_glyph->path != NULL) + _cairo_path_fixed_destroy (scaled_glyph->path); + scaled_glyph->path = path; +} + +/** + * _cairo_scaled_glyph_lookup: + * @scaled_font: a #cairo_scaled_font_t + * @index: the glyph to create + * @info: a #cairo_scaled_glyph_info_t marking which portions of + * the glyph should be filled in. + * @scaled_glyph_ret: a #cairo_scaled_glyph_t * where the glyph + * is returned. + * + * Returns a glyph with the requested portions filled in. Glyph + * lookup is cached and glyph will be automatically freed along + * with the scaled_font so no explicit free is required. + * @info can be one or more of: + * %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box + * %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image + * %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space + **/ +cairo_status_t +_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, + unsigned long index, + cairo_scaled_glyph_info_t info, + cairo_scaled_glyph_t **scaled_glyph_ret) +{ + cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_cache_entry_t key; + cairo_scaled_glyph_t *scaled_glyph; + cairo_scaled_glyph_info_t need_info; + + if (scaled_font->status) + return scaled_font->status; + + CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); + + key.hash = index; + /* + * Check cache for glyph + */ + info |= CAIRO_SCALED_GLYPH_INFO_METRICS; + if (!_cairo_cache_lookup (scaled_font->glyphs, &key, + (cairo_cache_entry_t **) &scaled_glyph)) + { + /* + * On miss, create glyph and insert into cache + */ + scaled_glyph = malloc (sizeof (cairo_scaled_glyph_t)); + if (scaled_glyph == NULL) { + status = CAIRO_STATUS_NO_MEMORY; + goto CLEANUP; + } + + _cairo_scaled_glyph_set_index(scaled_glyph, index); + scaled_glyph->cache_entry.size = 1; /* XXX */ + scaled_glyph->scaled_font = scaled_font; + scaled_glyph->surface = NULL; + scaled_glyph->path = NULL; + scaled_glyph->surface_private = NULL; + + /* ask backend to initialize metrics and shape fields */ + status = (*scaled_font->backend-> + scaled_glyph_init) (scaled_font, scaled_glyph, info); + if (status) + goto CLEANUP; + + status = _cairo_cache_insert (scaled_font->glyphs, + &scaled_glyph->cache_entry); + if (status) + goto CLEANUP; + } + /* + * Check and see if the glyph, as provided, + * already has the requested data and ammend it if not + */ + need_info = 0; + if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0 && + scaled_glyph->surface == NULL) + need_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE; + + if (((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 && + scaled_glyph->path == NULL)) + need_info |= CAIRO_SCALED_GLYPH_INFO_PATH; + + if (need_info) { + status = (*scaled_font->backend-> + scaled_glyph_init) (scaled_font, scaled_glyph, need_info); + if (status) + goto CLEANUP; + } + + CLEANUP: + if (status) { + _cairo_scaled_font_set_error (scaled_font, status); + if (scaled_glyph) + _cairo_scaled_glyph_destroy (scaled_glyph); + *scaled_glyph_ret = NULL; + } else { + *scaled_glyph_ret = scaled_glyph; + } + + CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); + + return status; +} diff --git a/gfx/cairo/cairo/src/cairo-surface.c b/gfx/cairo/cairo/src/cairo-surface.c index 6ba25a7d26d..a05368da835 100644 --- a/gfx/cairo/cairo/src/cairo-surface.c +++ b/gfx/cairo/cairo/src/cairo-surface.c @@ -108,7 +108,11 @@ static void _cairo_surface_set_error (cairo_surface_t *surface, cairo_status_t status) { - surface->status = status; + /* Don't overwrite an existing error. This preserves the first + * error, which is the most significant. It also avoids attempting + * to write to read-only data (eg. from a nil surface). */ + if (surface->status == CAIRO_STATUS_SUCCESS) + surface->status = status; _cairo_error (status); } @@ -143,8 +147,10 @@ _cairo_surface_init (cairo_surface_t *surface, _cairo_user_data_array_init (&surface->user_data); - surface->device_x_offset = 0; - surface->device_y_offset = 0; + surface->device_x_offset = 0.0; + surface->device_y_offset = 0.0; + surface->device_x_scale = 1.0; + surface->device_y_scale = 1.0; surface->next_clip_serial = 0; surface->current_clip_serial = 0; @@ -264,6 +270,8 @@ cairo_surface_reference (cairo_surface_t *surface) if (surface->ref_count == (unsigned int)-1) return surface; + assert (surface->ref_count > 0); + surface->ref_count++; return surface; @@ -286,6 +294,8 @@ cairo_surface_destroy (cairo_surface_t *surface) if (surface->ref_count == (unsigned int)-1) return; + assert (surface->ref_count > 0); + surface->ref_count--; if (surface->ref_count) return; @@ -434,10 +444,8 @@ cairo_surface_get_font_options (cairo_surface_t *surface, void cairo_surface_flush (cairo_surface_t *surface) { - if (surface->status) { - _cairo_surface_set_error (surface, surface->status); + if (surface->status) return; - } if (surface->finished) { _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); @@ -487,10 +495,8 @@ cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, int width, int height) { - if (surface->status) { - _cairo_surface_set_error (surface, surface->status); + if (surface->status) return; - } if (surface->finished) { _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); @@ -530,27 +536,25 @@ cairo_surface_set_device_offset (cairo_surface_t *surface, double x_offset, double y_offset) { - if (surface->status) { - _cairo_surface_set_error (surface, surface->status); + if (surface->status) return; - } if (surface->finished) { _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED); return; } - surface->device_x_offset = x_offset; - surface->device_y_offset = y_offset; + surface->device_x_offset = x_offset * surface->device_x_scale; + surface->device_y_offset = y_offset * surface->device_y_scale; } /** * _cairo_surface_acquire_source_image: * @surface: a #cairo_surface_t - * @image_out: location to store a pointer to an image surface that includes at least - * the intersection of @interest_rect with the visible area of @surface. - * This surface could be @surface itself, a surface held internal to @surface, - * or it could be a new surface with a copy of the relevant portion of @surface. + * @image_out: location to store a pointer to an image surface that + * has identical contents to @surface. This surface could be @surface + * itself, a surface held internal to @surface, or it could be a new + * surface with a copy of the relevant portion of @surface. * @image_extra: location to store image specific backend data * * Gets an image surface to use when drawing as a fallback when drawing with @@ -574,7 +578,7 @@ _cairo_surface_acquire_source_image (cairo_surface_t *surface, /** * _cairo_surface_release_source_image: * @surface: a #cairo_surface_t - * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image() + * @image_extra: same as return from the matching _cairo_surface_acquire_source_image() * * Releases any resources obtained with _cairo_surface_acquire_source_image() **/ @@ -598,6 +602,8 @@ _cairo_surface_release_source_image (cairo_surface_t *surface, * the intersection of @interest_rect with the visible area of @surface. * This surface could be @surface itself, a surface held internal to @surface, * or it could be a new surface with a copy of the relevant portion of @surface. + * If a new surface is created, it should have the same channels and depth + * as @surface so that copying to and from it is exact. * @image_rect: location to store area of the original surface occupied * by the surface stored in @image. * @image_extra: location to store image specific backend data @@ -605,16 +611,16 @@ _cairo_surface_release_source_image (cairo_surface_t *surface, * Retrieves a local image for a surface for implementing a fallback drawing * operation. After calling this function, the implementation of the fallback * drawing operation draws the primitive to the surface stored in @image_out - * then calls _cairo_surface_release_dest_fallback(), + * then calls _cairo_surface_release_dest_image(), * which, if a temporary surface was created, copies the bits back to the * main surface and frees the temporary surface. - * + * * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY. * %CAIRO_INT_STATUS_UNSUPPORTED can be returned but this will mean that * the backend can't draw with fallbacks. It's possible for the routine * to store NULL in @local_out and return %CAIRO_STATUS_SUCCESS; * that indicates that no part of @interest_rect is visible, so no drawing - * is necessary. _cairo_surface_release_dest_fallback() should not be called in that + * is necessary. _cairo_surface_release_dest_image() should not be called in that * case. **/ cairo_status_t @@ -631,7 +637,7 @@ _cairo_surface_acquire_dest_image (cairo_surface_t *surface, } /** - * _cairo_surface_end_fallback: + * _cairo_surface_release_dest_image: * @surface: a #cairo_surface_t * @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image() * @image: same as returned from the matching _cairo_surface_acquire_dest_image() @@ -684,11 +690,12 @@ _cairo_surface_clone_similar (cairo_surface_t *surface, if (surface->finished) return CAIRO_STATUS_SURFACE_FINISHED; - if (surface->backend->clone_similar) { - status = surface->backend->clone_similar (surface, src, clone_out); - if (status != CAIRO_INT_STATUS_UNSUPPORTED) - return status; - } + if (surface->backend->clone_similar == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + status = surface->backend->clone_similar (surface, src, clone_out); + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; status = _cairo_surface_acquire_source_image (src, &image, &image_extra); if (status != CAIRO_STATUS_SUCCESS) @@ -817,6 +824,13 @@ _cairo_surface_composite (cairo_operator_t operator, { cairo_int_status_t status; + if (mask) { + /* These operators aren't interpreted the same way by the backends; + * they are implemented in terms of other operators in cairo-gstate.c + */ + assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR); + } + if (dst->status) return dst->status; @@ -1013,7 +1027,7 @@ _fallback_fill_rectangles (cairo_surface_t *surface, * * Applies an operator to a set of rectangles using a solid color * as the source. Note that even if the operator is an unbounded operator - * such as %CAIRO_OPERATOR_CLEAR, only the given set of rectangles + * such as %CAIRO_OPERATOR_IN, only the given set of rectangles * is affected. This differs from _cairo_surface_composite_trapezoids() * where the entire destination rectangle is cleared. * @@ -1152,6 +1166,11 @@ _cairo_surface_composite_trapezoids (cairo_operator_t operator, { cairo_int_status_t status; + /* These operators aren't interpreted the same way by the backends; + * they are implemented in terms of other operators in cairo-gstate.c + */ + assert (operator != CAIRO_OPERATOR_SOURCE && operator != CAIRO_OPERATOR_CLEAR); + if (dst->status) return dst->status; diff --git a/gfx/cairo/cairo/src/cairo-traps.c b/gfx/cairo/cairo/src/cairo-traps.c index 18b944c1d60..6afb499bd8a 100644 --- a/gfx/cairo/cairo/src/cairo-traps.c +++ b/gfx/cairo/cairo/src/cairo-traps.c @@ -827,16 +827,10 @@ _cairo_traps_extract_region (cairo_traps_t *traps, for (i = 0; i < traps->num_traps; i++) if (!(traps->traps[i].left.p1.x == traps->traps[i].left.p2.x && traps->traps[i].right.p1.x == traps->traps[i].right.p2.x - && traps->traps[i].left.p1.y == traps->traps[i].right.p1.y - && traps->traps[i].left.p2.y == traps->traps[i].right.p2.y + && _cairo_fixed_is_integer(traps->traps[i].top) + && _cairo_fixed_is_integer(traps->traps[i].bottom) && _cairo_fixed_is_integer(traps->traps[i].left.p1.x) - && _cairo_fixed_is_integer(traps->traps[i].left.p1.y) - && _cairo_fixed_is_integer(traps->traps[i].left.p2.x) - && _cairo_fixed_is_integer(traps->traps[i].left.p2.y) - && _cairo_fixed_is_integer(traps->traps[i].right.p1.x) - && _cairo_fixed_is_integer(traps->traps[i].right.p1.y) - && _cairo_fixed_is_integer(traps->traps[i].right.p2.x) - && _cairo_fixed_is_integer(traps->traps[i].right.p2.y))) { + && _cairo_fixed_is_integer(traps->traps[i].right.p1.x))) { *region = NULL; return CAIRO_STATUS_SUCCESS; } @@ -845,9 +839,9 @@ _cairo_traps_extract_region (cairo_traps_t *traps, for (i = 0; i < traps->num_traps; i++) { int x = _cairo_fixed_integer_part(traps->traps[i].left.p1.x); - int y = _cairo_fixed_integer_part(traps->traps[i].left.p1.y); + int y = _cairo_fixed_integer_part(traps->traps[i].top); int width = _cairo_fixed_integer_part(traps->traps[i].right.p1.x) - x; - int height = _cairo_fixed_integer_part(traps->traps[i].left.p2.y) - y; + int height = _cairo_fixed_integer_part(traps->traps[i].bottom) - y; /* XXX: Sometimes we get degenerate trapezoids from the tesellator, * if we call pixman_region_union_rect(), it bizarrly fails on such diff --git a/gfx/cairo/cairo/src/cairo-win32-font.c b/gfx/cairo/cairo/src/cairo-win32-font.c index 947f8c3c496..21adbedc2d2 100644 --- a/gfx/cairo/cairo/src/cairo-win32-font.c +++ b/gfx/cairo/cairo/src/cairo-win32-font.c @@ -101,6 +101,17 @@ typedef struct { } cairo_win32_scaled_font_t; +static cairo_status_t +_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font); + +static cairo_status_t +_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph); + +static cairo_status_t +_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph); + #define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.)) static void @@ -221,6 +232,7 @@ _win32_scaled_font_create (LOGFONTW *logfont, { cairo_win32_scaled_font_t *f; cairo_matrix_t scale; + cairo_status_t status; f = malloc (sizeof(cairo_win32_scaled_font_t)); if (f == NULL) @@ -252,6 +264,8 @@ _win32_scaled_font_create (LOGFONTW *logfont, else f->quality = ANTIALIASED_QUALITY; break; + case CAIRO_ANTIALIAS_DEFAULT: + ASSERT_NOT_REACHED; } } @@ -266,6 +280,12 @@ _win32_scaled_font_create (LOGFONTW *logfont, font_matrix, ctm, options, &cairo_win32_scaled_font_backend); + status = _cairo_win32_scaled_font_set_metrics (f); + if (status) { + cairo_scaled_font_destroy (&f->base); + return NULL; + } + return &f->base; } @@ -324,7 +344,7 @@ _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font) { if (!scaled_font->scaled_hfont) { LOGFONTW logfont = scaled_font->logfont; - logfont.lfHeight = scaled_font->logical_size; + logfont.lfHeight = -scaled_font->logical_size; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; @@ -379,7 +399,7 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, free (otm); logfont = scaled_font->logfont; - logfont.lfHeight = scaled_font->em_square; + logfont.lfHeight = -scaled_font->em_square; logfont.lfWidth = 0; logfont.lfEscapement = 0; logfont.lfOrientation = 0; @@ -496,7 +516,7 @@ _cairo_win32_scaled_font_create_toy (cairo_toy_font_face_t *toy_face, if (!logfont.lfFaceName) return CAIRO_STATUS_NO_MEMORY; - scaled_font = _win32_scaled_font_create (&logfont, toy_face, + scaled_font = _win32_scaled_font_create (&logfont, &toy_face->base, font_matrix, ctm, options); if (!scaled_font) return CAIRO_STATUS_NO_MEMORY; @@ -521,14 +541,10 @@ _cairo_win32_scaled_font_fini (void *abstract_font) DeleteObject (scaled_font->unscaled_hfont); } -static void -_cairo_win32_scaled_font_get_glyph_cache_key (void *abstract_font, - cairo_glyph_cache_key_t *key) -{ -} - -static cairo_status_t +static cairo_int_status_t _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, + double x, + double y, const char *utf8, cairo_glyph_t **glyphs, int *num_glyphs) @@ -541,9 +557,17 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, WCHAR *glyph_indices = NULL; int *dx = NULL; cairo_status_t status = CAIRO_STATUS_SUCCESS; - double x_pos; + double x_pos, y_pos; + double x_incr, y_incr; HDC hdc = NULL; + /* Compute a vector in user space along the baseline of length one logical space unit */ + x_incr = 1; + y_incr = 0; + cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr); + x_incr /= scaled_font->logical_scale; + y_incr /= scaled_font->logical_scale; + status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); if (status) return status; @@ -618,13 +642,16 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, goto FAIL2; } - x_pos = 0; + x_pos = x; + y_pos = y; + for (i = 0; i < gcp_results.nGlyphs; i++) { (*glyphs)[i].index = glyph_indices[i]; (*glyphs)[i].x = x_pos ; - (*glyphs)[i].y = 0; + (*glyphs)[i].y = y_pos; - x_pos += dx[i] / scaled_font->logical_scale; + x_pos += x_incr * dx[i]; + y_pos += y_incr * dx[i]; } FAIL2: @@ -642,11 +669,11 @@ _cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, } static cairo_status_t -_cairo_win32_scaled_font_font_extents (void *abstract_font, - cairo_font_extents_t *extents) +_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) { - cairo_win32_scaled_font_t *scaled_font = abstract_font; cairo_status_t status; + cairo_font_extents_t extents; + TEXTMETRIC metrics; HDC hdc; @@ -664,12 +691,12 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font, GetTextMetrics (hdc, &metrics); cairo_win32_scaled_font_done_font (&scaled_font->base); - extents->ascent = metrics.tmAscent / scaled_font->logical_scale; - extents->descent = metrics.tmDescent / scaled_font->logical_scale; + extents.ascent = metrics.tmAscent / scaled_font->logical_scale; + extents.descent = metrics.tmDescent / scaled_font->logical_scale; - extents->height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale; - extents->max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale; - extents->max_y_advance = 0; + extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale; + extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale; + extents.max_y_advance = 0; } else { /* For all other transformations, we use the design metrics @@ -683,39 +710,33 @@ _cairo_win32_scaled_font_font_extents (void *abstract_font, GetTextMetrics (hdc, &metrics); _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - extents->ascent = (double)metrics.tmAscent / scaled_font->em_square; - extents->descent = metrics.tmDescent * scaled_font->em_square; - extents->height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square; - extents->max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square; - extents->max_y_advance = 0; + extents.ascent = (double)metrics.tmAscent / scaled_font->em_square; + extents.descent = metrics.tmDescent * scaled_font->em_square; + extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square; + extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square; + extents.max_y_advance = 0; } + _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); + return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_win32_scaled_font_glyph_extents (void *abstract_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents) +_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) { - cairo_win32_scaled_font_t *scaled_font = abstract_font; static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; GLYPHMETRICS metrics; cairo_status_t status; + cairo_text_extents_t extents; HDC hdc; hdc = _get_global_font_dc (); if (!hdc) return CAIRO_STATUS_NO_MEMORY; - /* We handle only the case num_glyphs == 1, glyphs[i].x == glyphs[0].y == 0. - * This is all that the calling code triggers, and the backend interface - * will eventually be changed to match - */ - assert (num_glyphs == 1); - if (scaled_font->preserve_axes) { /* If we aren't rotating / skewing the axes, then we get the metrics * from the GDI in device space and convert to font space. @@ -723,34 +744,38 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font, status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); if (status) return status; - GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); + if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), + GGO_METRICS | GGO_GLYPH_INDEX, + &metrics, 0, NULL, &matrix) == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); + memset (&metrics, 0, sizeof (GLYPHMETRICS)); + } cairo_win32_scaled_font_done_font (&scaled_font->base); if (scaled_font->swap_axes) { - extents->x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents->y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents->width = metrics.gmBlackBoxY / scaled_font->y_scale; - extents->height = metrics.gmBlackBoxX / scaled_font->x_scale; - extents->x_advance = metrics.gmCellIncY / scaled_font->x_scale; - extents->y_advance = metrics.gmCellIncX / scaled_font->y_scale; + extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; + extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; + extents.width = metrics.gmBlackBoxY / scaled_font->y_scale; + extents.height = metrics.gmBlackBoxX / scaled_font->x_scale; + extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale; + extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale; } else { - extents->x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents->y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents->width = metrics.gmBlackBoxX / scaled_font->x_scale; - extents->height = metrics.gmBlackBoxY / scaled_font->y_scale; - extents->x_advance = metrics.gmCellIncX / scaled_font->x_scale; - extents->y_advance = metrics.gmCellIncY / scaled_font->y_scale; + extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; + extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; + extents.width = metrics.gmBlackBoxX / scaled_font->x_scale; + extents.height = metrics.gmBlackBoxY / scaled_font->y_scale; + extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale; + extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale; } if (scaled_font->swap_x) { - extents->x_bearing = (- extents->x_bearing - extents->width); - extents->x_advance = - extents->x_advance; + extents.x_bearing = (- extents.x_bearing - extents.width); + extents.x_advance = - extents.x_advance; } if (scaled_font->swap_y) { - extents->y_bearing = (- extents->y_bearing - extents->height); - extents->y_advance = - extents->y_advance; + extents.y_bearing = (- extents.y_bearing - extents.height); + extents.y_advance = - extents.y_advance; } } else { @@ -758,22 +783,35 @@ _cairo_win32_scaled_font_glyph_extents (void *abstract_font, * of the font. */ status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - GetGlyphOutlineW (hdc, glyphs[0].index, GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); + if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), + GGO_METRICS | GGO_GLYPH_INDEX, + &metrics, 0, NULL, &matrix) == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetGlyphOutlineW"); + memset (&metrics, 0, sizeof (GLYPHMETRICS)); + } _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - extents->x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square; - extents->y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square; - extents->width = (double)metrics.gmBlackBoxX / scaled_font->em_square; - extents->height = (double)metrics.gmBlackBoxY / scaled_font->em_square; - extents->x_advance = (double)metrics.gmCellIncX / scaled_font->em_square; - extents->y_advance = (double)metrics.gmCellIncY / scaled_font->em_square; + extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square; + extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square; + extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square; + extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square; + extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square; + extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square; } + _cairo_scaled_glyph_set_metrics (scaled_glyph, + &scaled_font->base, + &extents); + return CAIRO_STATUS_SUCCESS; } - +/* Not currently used code, but may be useful in the future if we add + * back the capability to the scaled font backend interface to get the + * actual device space bbox rather than computing it from the + * font-space metrics. + */ +#if 0 static cairo_status_t _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, const cairo_glyph_t *glyphs, @@ -808,10 +846,10 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, x1 = x + metrics.gmptGlyphOrigin.x; if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y) y1 = y - metrics.gmptGlyphOrigin.y; - if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + metrics.gmBlackBoxX) - x2 = x + metrics.gmptGlyphOrigin.x + metrics.gmBlackBoxX; - if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + metrics.gmBlackBoxY) - y2 = y - metrics.gmptGlyphOrigin.y + metrics.gmBlackBoxY; + if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX) + x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX; + if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY) + y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY; } cairo_win32_scaled_font_done_font (&scaled_font->base); @@ -824,6 +862,7 @@ _cairo_win32_scaled_font_glyph_bbox (void *abstract_font, return CAIRO_STATUS_SUCCESS; } +#endif typedef struct { cairo_win32_scaled_font_t *scaled_font; @@ -1027,7 +1066,35 @@ _compute_a8_mask (cairo_win32_surface_t *mask_surface) return &image8->base; } -static cairo_status_t + +static cairo_status_t +_cairo_win32_scaled_font_glyph_init (void *abstract_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info) +{ + cairo_win32_scaled_font_t *scaled_font = abstract_font; + cairo_status_t status; + + if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { + status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph); + if (status) + return status; + } + + if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) { + ASSERT_NOT_REACHED; + } + + if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { + status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph); + if (status) + return status; + } + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_int_status_t _cairo_win32_scaled_font_show_glyphs (void *abstract_font, cairo_operator_t operator, cairo_pattern_t *pattern, @@ -1148,141 +1215,137 @@ _cairo_fixed_from_FIXED (FIXED f) } static cairo_status_t -_cairo_win32_scaled_font_glyph_path (void *abstract_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path) +_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) { static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } }; - cairo_win32_scaled_font_t *scaled_font = abstract_font; cairo_status_t status; GLYPHMETRICS metrics; HDC hdc; - int i; + DWORD bytesGlyph; + unsigned char *buffer, *ptr; + cairo_path_fixed_t *path; hdc = _get_global_font_dc (); if (!hdc) return CAIRO_STATUS_NO_MEMORY; + path = _cairo_path_fixed_create (); + if (!path) + return CAIRO_STATUS_NO_MEMORY; + status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); if (status) - return status; - - for (i = 0; i < num_glyphs; i++) - { - DWORD bytesGlyph; - unsigned char *buffer, *ptr; - - cairo_fixed_t x = _cairo_fixed_from_double (glyphs[i].x); - cairo_fixed_t y = _cairo_fixed_from_double (glyphs[i].y); - - bytesGlyph = GetGlyphOutlineW (hdc, glyphs[i].index, - GGO_NATIVE | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); - - if (bytesGlyph == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); - goto FAIL; - } - - ptr = buffer = malloc (bytesGlyph); - - if (!buffer) { - status = CAIRO_STATUS_NO_MEMORY; - goto FAIL; - } - - if (GetGlyphOutlineW (hdc, glyphs[i].index, - GGO_NATIVE | GGO_GLYPH_INDEX, - &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); - free (buffer); - goto FAIL; - } - - while (ptr < buffer + bytesGlyph) { - TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr; - unsigned char *endPoly = ptr + header->cb; - - ptr += sizeof (TTPOLYGONHEADER); - - _cairo_path_fixed_move_to (path, - _cairo_fixed_from_FIXED (header->pfxStart.x) + x, - _cairo_fixed_from_FIXED (header->pfxStart.y) + y); - - while (ptr < endPoly) { - TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; - POINTFX *points = curve->apfx; - int i; - switch (curve->wType) { - case TT_PRIM_LINE: - for (i = 0; i < curve->cpfx; i++) { - _cairo_path_fixed_line_to (path, - _cairo_fixed_from_FIXED (points[i].x) + x, - _cairo_fixed_from_FIXED (points[i].y) + y); - } - break; - case TT_PRIM_QSPLINE: - for (i = 0; i < curve->cpfx - 1; i++) { - cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; - _cairo_path_fixed_get_current_point (path, &p1x, &p1y); - cx = _cairo_fixed_from_FIXED (points[i].x) + x; - cy = _cairo_fixed_from_FIXED (points[i].y) + y; - - if (i + 1 == curve->cpfx - 1) { - p2x = _cairo_fixed_from_FIXED (points[i + 1].x) + x; - p2y = _cairo_fixed_from_FIXED (points[i + 1].y) + y; - } else { - /* records with more than one curve use interpolation for - control points, per http://support.microsoft.com/kb/q87115/ */ - p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x) + x) / 2; - p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y) + y) / 2; - } - - c1x = 2 * cx / 3 + p1x / 3; - c1y = 2 * cy / 3 + p1y / 3; - c2x = 2 * cx / 3 + p2x / 3; - c2y = 2 * cy / 3 + p2y / 3; - - _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y); - } - break; - case TT_PRIM_CSPLINE: - for (i = 0; i < curve->cpfx - 2; i += 2) { - _cairo_path_fixed_curve_to (path, - _cairo_fixed_from_FIXED (points[i].x) + x, - _cairo_fixed_from_FIXED (points[i].y) + y, - _cairo_fixed_from_FIXED (points[i + 1].x) + x, - _cairo_fixed_from_FIXED (points[i + 1].y) + y, - _cairo_fixed_from_FIXED (points[i + 2].x) + x, - _cairo_fixed_from_FIXED (points[i + 2].y) + y); - } - break; - } - ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1); - } - _cairo_path_fixed_close_path (path); - } - free(buffer); + goto CLEANUP_PATH; + + bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), + GGO_NATIVE | GGO_GLYPH_INDEX, + &metrics, 0, NULL, &matrix); + + if (bytesGlyph == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); + goto CLEANUP_FONT; } -FAIL: + ptr = buffer = malloc (bytesGlyph); + + if (!buffer) { + status = CAIRO_STATUS_NO_MEMORY; + goto CLEANUP_FONT; + } + + if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), + GGO_NATIVE | GGO_GLYPH_INDEX, + &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { + status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); + free (buffer); + goto CLEANUP_FONT; + } + + while (ptr < buffer + bytesGlyph) { + TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr; + unsigned char *endPoly = ptr + header->cb; + + ptr += sizeof (TTPOLYGONHEADER); + + _cairo_path_fixed_move_to (path, + _cairo_fixed_from_FIXED (header->pfxStart.x), + _cairo_fixed_from_FIXED (header->pfxStart.y)); + + while (ptr < endPoly) { + TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; + POINTFX *points = curve->apfx; + int i; + switch (curve->wType) { + case TT_PRIM_LINE: + for (i = 0; i < curve->cpfx; i++) { + _cairo_path_fixed_line_to (path, + _cairo_fixed_from_FIXED (points[i].x), + _cairo_fixed_from_FIXED (points[i].y)); + } + break; + case TT_PRIM_QSPLINE: + for (i = 0; i < curve->cpfx - 1; i++) { + cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; + _cairo_path_fixed_get_current_point (path, &p1x, &p1y); + cx = _cairo_fixed_from_FIXED (points[i].x); + cy = _cairo_fixed_from_FIXED (points[i].y); + + if (i + 1 == curve->cpfx - 1) { + p2x = _cairo_fixed_from_FIXED (points[i + 1].x); + p2y = _cairo_fixed_from_FIXED (points[i + 1].y); + } else { + /* records with more than one curve use interpolation for + control points, per http://support.microsoft.com/kb/q87115/ */ + p2x = (cx + _cairo_fixed_from_FIXED (points[i + 1].x)) / 2; + p2y = (cy + _cairo_fixed_from_FIXED (points[i + 1].y)) / 2; + } + + c1x = 2 * cx / 3 + p1x / 3; + c1y = 2 * cy / 3 + p1y / 3; + c2x = 2 * cx / 3 + p2x / 3; + c2y = 2 * cy / 3 + p2y / 3; + + _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y); + } + break; + case TT_PRIM_CSPLINE: + for (i = 0; i < curve->cpfx - 2; i += 2) { + _cairo_path_fixed_curve_to (path, + _cairo_fixed_from_FIXED (points[i].x), + _cairo_fixed_from_FIXED (points[i].y), + _cairo_fixed_from_FIXED (points[i + 1].x), + _cairo_fixed_from_FIXED (points[i + 1].y), + _cairo_fixed_from_FIXED (points[i + 2].x), + _cairo_fixed_from_FIXED (points[i + 2].y)); + } + break; + } + ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1); + } + _cairo_path_fixed_close_path (path); + } + free(buffer); + +CLEANUP_FONT: cairo_win32_scaled_font_done_font (&scaled_font->base); + CLEANUP_PATH: + + if (status != CAIRO_STATUS_SUCCESS) + _cairo_path_fixed_destroy (path); + return status; } const cairo_scaled_font_backend_t cairo_win32_scaled_font_backend = { _cairo_win32_scaled_font_create_toy, _cairo_win32_scaled_font_fini, - _cairo_win32_scaled_font_font_extents, + _cairo_win32_scaled_font_glyph_init, _cairo_win32_scaled_font_text_to_glyphs, - _cairo_win32_scaled_font_glyph_extents, - _cairo_win32_scaled_font_glyph_bbox, + NULL, /* ucs4_to_index */ _cairo_win32_scaled_font_show_glyphs, - _cairo_win32_scaled_font_glyph_path, - _cairo_win32_scaled_font_get_glyph_cache_key }; /* cairo_win32_font_face_t */ @@ -1311,7 +1374,7 @@ _cairo_win32_font_face_scaled_font_create (void *abstract_face, cairo_win32_font_face_t *font_face = abstract_face; *font = _win32_scaled_font_create (&font_face->logfont, - font_face, + &font_face->base, font_matrix, ctm, options); if (*font) return CAIRO_STATUS_SUCCESS; @@ -1390,10 +1453,8 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, HFONT old_hfont = NULL; int old_mode; - if (scaled_font->status) { - _cairo_scaled_font_set_error (scaled_font, scaled_font->status); + if (scaled_font->status) return scaled_font->status; - } hfont = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font); if (!hfont) @@ -1401,11 +1462,11 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, old_hfont = SelectObject (hdc, hfont); if (!old_hfont) - return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font"); + return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject"); old_mode = SetGraphicsMode (hdc, GM_ADVANCED); if (!old_mode) { - status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font"); + status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode"); SelectObject (hdc, old_hfont); return status; } diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h index 71e677ad148..a229147c7dc 100644 --- a/gfx/cairo/cairo/src/cairo-win32-private.h +++ b/gfx/cairo/cairo/src/cairo-win32-private.h @@ -36,12 +36,6 @@ #ifndef CAIRO_WIN32_PRIVATE_H #define CAIRO_WIN32_PRIVATE_H -/* We depend on various features introduced with Win2k and Win98, - * like AlphaBlend. If it turns out to be a problem, we could - * use GetProcAddress() to look them up. - */ -#define WINVER 0x0500 - #include #include diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c index c2a99e360b6..13d6b3401a1 100644 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c @@ -124,8 +124,8 @@ _create_dc_and_bitmap (cairo_win32_surface_t *surface, } bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - bitmap_info->bmiHeader.biWidth = width; - bitmap_info->bmiHeader.biHeight = - height; /* top-down */ + bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width; + bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */ bitmap_info->bmiHeader.biSizeImage = 0; bitmap_info->bmiHeader.biXPelsPerMeter = 72. / 0.0254; /* unused here */ bitmap_info->bmiHeader.biYPelsPerMeter = 72. / 0.0254; /* unused here */ @@ -524,9 +524,6 @@ _cairo_win32_surface_release_dest_image (void *abstract_surfac cairo_surface_destroy ((cairo_surface_t *)local); } -// AlphaBlend is not available or useable on older versions of Win32 - -/* for compatibility with VC++ 5 */ #if !defined(AC_SRC_OVER) #define AC_SRC_OVER 0x00 #pragma pack(1) @@ -544,21 +541,77 @@ typedef struct { #define AC_SRC_ALPHA 0x01 #endif -typedef BOOL (WINAPI *ALPHABLENDPROC)( - HDC hdcDest, - int nXOriginDest, - int nYOriginDest, - int nWidthDest, - int hHeightDest, - HDC hdcSrc, - int nXOriginSrc, - int nYOriginSrc, - int nWidthSrc, - int nHeightSrc, - BLENDFUNCTION blendFunction); +typedef BOOL (WINAPI *cairo_alpha_blend_func_t) (HDC hdcDest, + int nXOriginDest, + int nYOriginDest, + int nWidthDest, + int hHeightDest, + HDC hdcSrc, + int nXOriginSrc, + int nYOriginSrc, + int nWidthSrc, + int nHeightSrc, + BLENDFUNCTION blendFunction); -static unsigned gAlphaBlendChecked = FALSE; -static ALPHABLENDPROC gAlphaBlend; +static cairo_int_status_t +_composite_alpha_blend (cairo_win32_surface_t *dst, + cairo_win32_surface_t *src, + int alpha, + int src_x, + int src_y, + int dst_x, + int dst_y, + int width, + int height) +{ + static unsigned alpha_blend_checked = FALSE; + static cairo_alpha_blend_func_t alpha_blend = NULL; + + BLENDFUNCTION blend_function; + + /* Check for AlphaBlend dynamically to allow compiling on + * MSVC 6 and use on older windows versions + */ + if (!alpha_blend_checked) { + OSVERSIONINFO os; + + os.dwOSVersionInfoSize = sizeof (os); + GetVersionEx (&os); + + /* If running on Win98, disable using AlphaBlend() + * to avoid Win98 AlphaBlend() bug */ + if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId || + os.dwMajorVersion != 4 || os.dwMinorVersion != 10) + { + HMODULE msimg32_dll = LoadLibrary ("msimg32"); + + if (msimg32_dll != NULL) + alpha_blend = (cairo_alpha_blend_func_t)GetProcAddress (msimg32_dll, + "AlphaBlend"); + } + + alpha_blend_checked = TRUE; + } + + if (alpha_blend == NULL) + return CAIRO_INT_STATUS_UNSUPPORTED; + + blend_function.BlendOp = AC_SRC_OVER; + blend_function.BlendFlags = 0; + blend_function.SourceConstantAlpha = alpha; + blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0; + + if (!alpha_blend (dst->dc, + dst_x, dst_y, + width, height, + src->dc, + src_x, src_y, + width, height, + blend_function)) + return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite"); + + return CAIRO_STATUS_SUCCESS; +} static cairo_int_status_t _cairo_win32_surface_composite (cairo_operator_t operator, @@ -581,21 +634,6 @@ _cairo_win32_surface_composite (cairo_operator_t operator, int integer_transform; int itx, ity; - if (!gAlphaBlendChecked) { - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof(os); - GetVersionEx(&os); - // If running on Win98, disable using AlphaBlend() - // to avoid Win98 AlphaBlend() bug - if (VER_PLATFORM_WIN32_WINDOWS != os.dwPlatformId || - os.dwMajorVersion != 4 || os.dwMinorVersion != 10) { - gAlphaBlend = (ALPHABLENDPROC)GetProcAddress(LoadLibrary("msimg32"), - "AlphaBlend"); - } - gAlphaBlendChecked = TRUE; - } - if (pattern->type != CAIRO_PATTERN_SURFACE || pattern->extend != CAIRO_EXTEND_NONE) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -642,26 +680,9 @@ _cairo_win32_surface_composite (cairo_operator_t operator, dst->format == CAIRO_FORMAT_RGB24 && operator == CAIRO_OPERATOR_OVER) { - BLENDFUNCTION blend_function; - - blend_function.BlendOp = AC_SRC_OVER; - blend_function.BlendFlags = 0; - blend_function.SourceConstantAlpha = alpha; - blend_function.AlphaFormat = src->format == CAIRO_FORMAT_ARGB32 ? AC_SRC_ALPHA : 0; - - if (!gAlphaBlend) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!gAlphaBlend(dst->dc, - dst_x, dst_y, - width, height, - src->dc, - src_x + itx, src_y + ity, - width, height, - blend_function)) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_composite"); - - return CAIRO_STATUS_SUCCESS; + return _composite_alpha_blend (dst, src, alpha, + src_x + itx, src_y + ity, + dst_x, dst_y, width, height); } return CAIRO_INT_STATUS_UNSUPPORTED; @@ -1030,3 +1051,37 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = { _cairo_win32_surface_flush, NULL /* mark_dirty_rectangle */ }; + +/* + * Without pthread, on win32 we need to initialize all the 'mutex'es + * before use. It is guaranteed that DllMain will get called single + * threaded before any other function. + * Initializing more than finally needed should not matter much. + */ +#ifndef HAVE_PTHREAD_H +CRITICAL_SECTION cairo_toy_font_face_hash_table_mutex; +CRITICAL_SECTION cairo_scaled_font_map_mutex; +CRITICAL_SECTION cairo_ft_unscaled_font_map_mutex; + +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, + DWORD fdwReason, + LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + /* every 'mutex' from CAIRO_MUTEX_DECALRE needs to be initialized here */ + InitializeCriticalSection (&cairo_toy_font_face_hash_table_mutex); + InitializeCriticalSection (&cairo_scaled_font_map_mutex); + InitializeCriticalSection (&cairo_ft_unscaled_font_map_mutex); + break; + case DLL_PROCESS_DETACH: + DeleteCriticalSection (&cairo_toy_font_face_hash_table_mutex); + DeleteCriticalSection (&cairo_scaled_font_map_mutex); + DeleteCriticalSection (&cairo_ft_unscaled_font_map_mutex); + break; + } + return TRUE; +} +#endif diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h index 93983456fca..8d43bb74fea 100644 --- a/gfx/cairo/cairo/src/cairo-win32.h +++ b/gfx/cairo/cairo/src/cairo-win32.h @@ -44,20 +44,20 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_win32_surface_create (HDC hdc); -cairo_font_face_t * +cairo_public cairo_font_face_t * cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont); -cairo_status_t +cairo_public cairo_status_t cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, HDC hdc); -void +cairo_public void cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font); -double +cairo_public double cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font); CAIRO_END_DECLS diff --git a/gfx/cairo/cairo/src/cairo-xcb-xrender.h b/gfx/cairo/cairo/src/cairo-xcb-xrender.h index ef4baa99123..bb2a79af8f0 100644 --- a/gfx/cairo/cairo/src/cairo-xcb-xrender.h +++ b/gfx/cairo/cairo/src/cairo-xcb-xrender.h @@ -46,7 +46,7 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xcb_surface_create_with_xrender_format (XCBConnection *c, XCBDRAWABLE drawable, XCBRenderPICTFORMINFO *format, diff --git a/gfx/cairo/cairo/src/cairo-xcb.h b/gfx/cairo/cairo/src/cairo-xcb.h index 17dfafa0264..a39d7b60c89 100644 --- a/gfx/cairo/cairo/src/cairo-xcb.h +++ b/gfx/cairo/cairo/src/cairo-xcb.h @@ -45,20 +45,20 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xcb_surface_create (XCBConnection *c, XCBDRAWABLE drawable, XCBVISUALTYPE *visual, int width, int height); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xcb_surface_create_for_bitmap (XCBConnection *c, XCBPIXMAP bitmap, int width, int height); -void +cairo_public void cairo_xcb_surface_set_size (cairo_surface_t *surface, int width, int height); diff --git a/gfx/cairo/cairo/src/cairo-xlib-screen.c b/gfx/cairo/cairo/src/cairo-xlib-screen.c index e71d10ecc16..8ac6d89c159 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-screen.c +++ b/gfx/cairo/cairo/src/cairo-xlib-screen.c @@ -247,6 +247,9 @@ CAIRO_MUTEX_DECLARE(_xlib_screen_mutex); static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL; +/* XXX: From this function we should also run through and cleanup + * anything else that still has a pointer to this Display*. For + * example, we should clean up any Xlib-specific glyph caches. */ static int _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) { diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index e778857ebbc..69c4050d8b0 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -60,6 +60,9 @@ _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface); static cairo_bool_t _cairo_surface_is_xlib (cairo_surface_t *surface); +static cairo_bool_t +_native_byte_order_lsb (void); + /* * Instead of taking two round trips for each blending request, * assume that if a particular drawable fails GetImage that it will @@ -192,16 +195,15 @@ _CAIRO_FORMAT_XRENDER_FORMAT(Display *dpy, cairo_format_t format) } static cairo_surface_t * -_cairo_xlib_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) +_cairo_xlib_surface_create_similar_with_format (void *abstract_src, + cairo_format_t format, + int width, + int height) { cairo_xlib_surface_t *src = abstract_src; Display *dpy = src->dpy; Pixmap pix; cairo_xlib_surface_t *surface; - cairo_format_t format = _cairo_format_from_content (content); int depth = _CAIRO_FORMAT_DEPTH (format); XRenderPictFormat *xrender_format = _CAIRO_FORMAT_XRENDER_FORMAT (dpy, format); @@ -221,7 +223,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, cairo_xlib_surface_create_with_xrender_format (dpy, pix, src->screen, xrender_format, width, height); - if (surface->base.status) { + if (surface->base.status != CAIRO_STATUS_SUCCESS) { _cairo_error (CAIRO_STATUS_NO_MEMORY); return (cairo_surface_t*) &_cairo_surface_nil; } @@ -231,23 +233,36 @@ _cairo_xlib_surface_create_similar (void *abstract_src, return &surface->base; } +static cairo_surface_t * +_cairo_xlib_surface_create_similar (void *abstract_src, + cairo_content_t content, + int width, + int height) +{ + cairo_format_t format = _cairo_format_from_content (content); + return _cairo_xlib_surface_create_similar_with_format (abstract_src, + format, + width, + height); +} + static cairo_status_t _cairo_xlib_surface_finish (void *abstract_surface) { cairo_xlib_surface_t *surface = abstract_surface; - if (surface->dst_picture) + if (surface->dst_picture != None) XRenderFreePicture (surface->dpy, surface->dst_picture); - if (surface->src_picture) + if (surface->src_picture != None) XRenderFreePicture (surface->dpy, surface->src_picture); if (surface->owns_pixmap) XFreePixmap (surface->dpy, surface->drawable); - if (surface->gc) + if (surface->gc != NULL) XFreeGC (surface->dpy, surface->gc); - if (surface->clip_rects) + if (surface->clip_rects != NULL) free (surface->clip_rects); surface->dpy = NULL; @@ -302,6 +317,116 @@ _CAIRO_MASK_FORMAT (cairo_format_masks_t *masks, cairo_format_t *format) return False; } +static void +_swap_ximage_2bytes (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint16_t *p = (uint16_t *)line; + for (i = ximage->width; i; i--) { + *p = (((*p & 0x00ff) << 8) | + ((*p) >> 8)); + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_4bytes (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + + for (j = ximage->height; j; j--) { + uint32_t *p = (uint32_t *)line; + for (i = ximage->width; i; i--) { + *p = (((*p & 0x000000ff) << 24) | + ((*p & 0x0000ff00) << 8) | + ((*p & 0x00ff0000) >> 8) | + ((*p) >> 24)); + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_bits (XImage *ximage) +{ + int i, j; + char *line = ximage->data; + int unit = ximage->bitmap_unit; + int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8; + + for (j = ximage->height; j; j--) { + char *p = line; + + for (i = line_bytes; i; i--) { + char b = *p; + b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); + b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); + b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); + *p = b; + + p++; + } + + line += ximage->bytes_per_line; + } +} + +static void +_swap_ximage_to_native (XImage *ximage) +{ + int unit_bytes = 0; + int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; + + if (ximage->bits_per_pixel == 1 && + ximage->bitmap_bit_order != native_byte_order) { + _swap_ximage_bits (ximage); + if (ximage->bitmap_bit_order == ximage->byte_order) + return; + } + + if (ximage->byte_order == native_byte_order) + return; + + switch (ximage->bits_per_pixel) { + case 1: + unit_bytes = ximage->bitmap_unit / 8; + break; + case 8: + case 16: + case 32: + unit_bytes = ximage->bits_per_pixel / 8; + break; + default: + /* This could be hit on some uncommon but possible cases, + * such as bpp=4. These are cases that libpixman can't deal + * with in any case. + */ + ASSERT_NOT_REACHED; + } + + switch (unit_bytes) { + case 1: + return; + case 2: + _swap_ximage_2bytes (ximage); + break; + case 4: + _swap_ximage_4bytes (ximage); + break; + default: + ASSERT_NOT_REACHED; + } +} + static cairo_status_t _get_image_surface (cairo_xlib_surface_t *surface, cairo_rectangle_t *interest_rect, @@ -374,7 +499,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, else { surface->use_pixmap--; - ximage = 0; + ximage = NULL; } if (!ximage) @@ -405,6 +530,8 @@ _get_image_surface (cairo_xlib_surface_t *surface, } if (!ximage) return CAIRO_STATUS_NO_MEMORY; + + _swap_ximage_to_native (ximage); /* * Compute the pixel format masks from either a visual or a @@ -545,40 +672,35 @@ _draw_image_surface (cairo_xlib_surface_t *surface, int dst_x, int dst_y) { - XImage *ximage; - unsigned bitmap_pad; - - /* XXX this is wrong */ - if (image->depth > 16) - bitmap_pad = 32; - else if (image->depth > 8) - bitmap_pad = 16; - else - bitmap_pad = 8; - - ximage = XCreateImage (surface->dpy, - DefaultVisual(surface->dpy, DefaultScreen(surface->dpy)), - image->depth, - ZPixmap, - 0, - (char *) image->data, - image->width, - image->height, - bitmap_pad, - image->stride); - if (ximage == NULL) - return CAIRO_STATUS_NO_MEMORY; + XImage ximage; + int bpp, alpha, red, green, blue; + int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; + + pixman_format_get_masks (pixman_image_get_format (image->pixman_image), + &bpp, &alpha, &red, &green, &blue); + + ximage.width = image->width; + ximage.height = image->height; + ximage.format = ZPixmap; + ximage.data = (char *)image->data; + ximage.byte_order = native_byte_order; + ximage.bitmap_unit = 32; /* always for libpixman */ + ximage.bitmap_bit_order = native_byte_order; + ximage.bitmap_pad = 32; /* always for libpixman */ + ximage.depth = image->depth; + ximage.bytes_per_line = image->stride; + ximage.bits_per_pixel = bpp; + ximage.red_mask = red; + ximage.green_mask = green; + ximage.blue_mask = blue; + XInitImage (&ximage); + _cairo_xlib_surface_ensure_gc (surface); XPutImage(surface->dpy, surface->drawable, surface->gc, - ximage, 0, 0, dst_x, dst_y, + &ximage, 0, 0, dst_x, dst_y, image->width, image->height); - /* Foolish XDestroyImage thinks it can free my data, but I won't - stand for it. */ - ximage->data = NULL; - XDestroyImage (ximage); - return CAIRO_STATUS_SUCCESS; } @@ -676,10 +798,9 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, } } else if (_cairo_surface_is_image (src)) { cairo_image_surface_t *image_src = (cairo_image_surface_t *)src; - cairo_content_t content = _cairo_content_from_format (image_src->format); clone = (cairo_xlib_surface_t *) - _cairo_xlib_surface_create_similar (surface, content, + _cairo_xlib_surface_create_similar_with_format (surface, image_src->format, image_src->width, image_src->height); if (clone->base.status) return CAIRO_STATUS_NO_MEMORY; @@ -1140,15 +1261,6 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, width, height); } - if (!_cairo_operator_bounded (operator)) - status = _cairo_surface_composite_fixup_unbounded (&dst->base, - &src_attr, src->width, src->height, - mask ? &mask_attr : NULL, - mask ? mask->width : 0, - mask ? mask->height : 0, - src_x, src_y, - mask_x, mask_y, - dst_x, dst_y, width, height); break; case DO_XCOPYAREA: @@ -1188,6 +1300,18 @@ _cairo_xlib_surface_composite (cairo_operator_t operator, ASSERT_NOT_REACHED; } + if (!_cairo_operator_bounded (operator) || + operator == CAIRO_OPERATOR_SOURCE || + operator == CAIRO_OPERATOR_CLEAR) + status = _cairo_surface_composite_fixup_unbounded (&dst->base, + &src_attr, src->width, src->height, + mask ? &mask_attr : NULL, + mask ? mask->width : 0, + mask ? mask->height : 0, + src_x, src_y, + mask_x, mask_y, + dst_x, dst_y, width, height); + FAIL: if (mask) @@ -1239,7 +1363,8 @@ _create_a8_picture (cairo_xlib_surface_t *surface, unsigned long mask = 0; Pixmap pixmap = XCreatePixmap (surface->dpy, surface->drawable, - width, height, + width <= 0 ? 1 : width, + height <= 0 ? 1 : height, 8); Picture picture; @@ -1542,6 +1667,13 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs); +static void +_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font); + +static void +_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font); + static const cairo_surface_backend_t cairo_xlib_surface_backend = { _cairo_xlib_surface_create_similar, _cairo_xlib_surface_finish, @@ -1560,7 +1692,11 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = { _cairo_xlib_surface_get_extents, _cairo_xlib_surface_show_glyphs, NULL, /* fill_path */ - _cairo_xlib_surface_get_font_options + _cairo_xlib_surface_get_font_options, + NULL, /* flush */ + NULL, /* mark_dirty_rectangle */ + _cairo_xlib_surface_scaled_font_fini, + _cairo_xlib_surface_scaled_glyph_fini, }; /** @@ -1643,11 +1779,11 @@ _cairo_xlib_surface_create_internal (Display *dpy, } surface->buggy_repeat = FALSE; - if (strcmp (ServerVendor (dpy), "The X.Org Foundation") == 0) { + if (strstr (ServerVendor (dpy), "X.Org") != NULL) { if (VendorRelease (dpy) <= 60802000) surface->buggy_repeat = TRUE; - } else if (strcmp (ServerVendor (dpy), "The XFree86 Project, Inc") == 0) { - if (VendorRelease (dpy) <= 40400000) + } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) { + if (VendorRelease (dpy) <= 40500000) surface->buggy_repeat = TRUE; } @@ -1827,6 +1963,8 @@ cairo_xlib_surface_set_size (cairo_surface_t *surface, * cairo_xlib_surface_set_drawable: * @surface: a #cairo_surface_t for the XLib backend * @drawable: the new drawable for the surface + * @width: the width of the new drawable + * @height: the height of the new drawable * * Informs cairo of a new X Drawable underlying the * surface. The drawable must match the display, screen @@ -1867,37 +2005,54 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, surface->height = height; } -/* RENDER glyphset cache code */ +typedef struct _cairo_xlib_surface_font_private { + Display *dpy; + GlyphSet glyphset; + XRenderPictFormat *format; +} cairo_xlib_surface_font_private_t; -typedef struct glyphset_cache { - cairo_cache_t base; - - Display *display; - Glyph counter; - - XRenderPictFormat *a1_pict_format; - GlyphSet a1_glyphset; - - XRenderPictFormat *a8_pict_format; - GlyphSet a8_glyphset; - - XRenderPictFormat *argb32_pict_format; - GlyphSet argb32_glyphset; - - struct glyphset_cache *next; -} glyphset_cache_t; - -typedef struct { - cairo_glyph_cache_key_t key; - GlyphSet glyphset; - Glyph glyph; - cairo_glyph_size_t size; -} glyphset_cache_entry_t; - -static Glyph -_next_xlib_glyph (glyphset_cache_t *cache) +static cairo_status_t +_cairo_xlib_surface_font_init (Display *dpy, + cairo_scaled_font_t *scaled_font, + cairo_format_t format) { - return ++(cache->counter); + cairo_xlib_surface_font_private_t *font_private; + + font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); + if (!font_private) + return CAIRO_STATUS_NO_MEMORY; + + font_private->dpy = dpy; + font_private->format = _CAIRO_FORMAT_XRENDER_FORMAT(dpy, format); + font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->format); + scaled_font->surface_private = font_private; + scaled_font->surface_backend = &cairo_xlib_surface_backend; + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) +{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + + if (font_private) { + XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset); + free (font_private); + } +} + +static void +_cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font) +{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + + if (font_private != NULL && scaled_glyph->surface_private != NULL) { + unsigned long glyph_index = _cairo_scaled_glyph_index(scaled_glyph); + XRenderFreeGlyphs (font_private->dpy, + font_private->glyphset, + &glyph_index, 1); + } } static cairo_bool_t @@ -1909,59 +2064,24 @@ _native_byte_order_lsb (void) } static cairo_status_t -_xlib_glyphset_cache_create_entry (void *abstract_cache, - void *abstract_key, - void **return_entry) +_cairo_xlib_surface_add_glyph (Display *dpy, + cairo_scaled_font_t *scaled_font, + cairo_scaled_glyph_t *scaled_glyph) { - glyphset_cache_t *cache = abstract_cache; - cairo_glyph_cache_key_t *key = abstract_key; - glyphset_cache_entry_t *entry; XGlyphInfo glyph_info; + unsigned long glyph_index; unsigned char *data; - cairo_status_t status; + cairo_xlib_surface_font_private_t *font_private; + cairo_image_surface_t *glyph_surface = scaled_glyph->surface; - cairo_cache_t *im_cache; - cairo_image_glyph_cache_entry_t *im; - - entry = malloc (sizeof (glyphset_cache_entry_t)); - _cairo_lock_global_image_glyph_cache (); - im_cache = _cairo_get_global_image_glyph_cache (); - - if (cache == NULL || entry == NULL || im_cache == NULL) { - _cairo_unlock_global_image_glyph_cache (); - if (entry) - free (entry); - return CAIRO_STATUS_NO_MEMORY; + if (scaled_font->surface_private == NULL) { + status = _cairo_xlib_surface_font_init (dpy, scaled_font, + glyph_surface->format); + if (status) + return status; } - - status = _cairo_cache_lookup (im_cache, key, (void **) (&im), NULL); - if (status != CAIRO_STATUS_SUCCESS || im == NULL) { - _cairo_unlock_global_image_glyph_cache (); - free (entry); - return CAIRO_STATUS_NO_MEMORY; - } - - entry->key = *key; - _cairo_unscaled_font_reference (entry->key.unscaled); - - if (!im->image) { - entry->glyph = None; - entry->glyphset = None; - entry->key.base.memory = 0; - entry->size.x = entry->size.y = entry->size.width = entry->size.height = 0; - - goto out; - } - - entry->glyph = _next_xlib_glyph (cache); - - data = im->image->data; - - entry->size = im->size; - - glyph_info.width = im->size.width; - glyph_info.height = im->size.height; + font_private = scaled_font->surface_private; /* * Most of the font rendering system thinks of glyph tiles as having @@ -1999,18 +2119,21 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache, * sitting around for x and y. */ - glyph_info.x = -im->size.x; - glyph_info.y = -im->size.y; + glyph_info.x = -(int) glyph_surface->base.device_x_offset; + glyph_info.y = -(int) glyph_surface->base.device_y_offset; + glyph_info.width = glyph_surface->width; + glyph_info.height = glyph_surface->height; glyph_info.xOff = 0; glyph_info.yOff = 0; - switch (im->image->format) { + data = glyph_surface->data; + + /* flip formats around */ + switch (scaled_glyph->surface->format) { case CAIRO_FORMAT_A1: /* local bitmaps are always stored with bit == byte */ - if (_native_byte_order_lsb() != - (BitmapBitOrder (cache->display) == LSBFirst)) - { - int c = im->image->stride * im->size.height; + if (_native_byte_order_lsb() != (BitmapBitOrder (dpy) == LSBFirst)) { + int c = glyph_surface->stride * glyph_surface->height; unsigned char *d; unsigned char *new, *n; @@ -2029,21 +2152,17 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache, } data = new; } - entry->glyphset = cache->a1_glyphset; break; case CAIRO_FORMAT_A8: - entry->glyphset = cache->a8_glyphset; break; case CAIRO_FORMAT_ARGB32: - if (_native_byte_order_lsb() != - (ImageByteOrder (cache->display) == LSBFirst)) - { - int c = im->image->stride * im->size.height; + if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) { + int c = glyph_surface->stride * glyph_surface->height; unsigned char *d; unsigned char *new, *n; new = malloc (c); - if (!new) + if (new == NULL) return CAIRO_STATUS_NO_MEMORY; n = new; d = data; @@ -2058,7 +2177,6 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache, } data = new; } - entry->glyphset = cache->argb32_glyphset; break; case CAIRO_FORMAT_RGB24: default: @@ -2067,511 +2185,207 @@ _xlib_glyphset_cache_create_entry (void *abstract_cache, } /* XXX assume X server wants pixman padding. Xft assumes this as well */ - XRenderAddGlyphs (cache->display, entry->glyphset, - &(entry->glyph), &(glyph_info), 1, + glyph_index = _cairo_scaled_glyph_index (scaled_glyph); + + XRenderAddGlyphs (dpy, font_private->glyphset, + &glyph_index, &(glyph_info), 1, (char *) data, - im->image->stride * glyph_info.height); + glyph_surface->stride * glyph_surface->height); - if (data != im->image->data) + if (data != glyph_surface->data) free (data); - entry->key.base.memory = im->image->height * im->image->stride; - - out: - *return_entry = entry; - _cairo_unlock_global_image_glyph_cache (); - return CAIRO_STATUS_SUCCESS; } -static void -_xlib_glyphset_cache_destroy_cache (void *cache) -{ - /* FIXME: will we ever release glyphset caches? */ -} - -static void -_xlib_glyphset_cache_destroy_entry (void *abstract_cache, - void *abstract_entry) -{ - glyphset_cache_t *cache = abstract_cache; - glyphset_cache_entry_t *entry = abstract_entry; - - _cairo_unscaled_font_destroy (entry->key.unscaled); - if (entry->glyph) - XRenderFreeGlyphs (cache->display, entry->glyphset, - &(entry->glyph), 1); - free (entry); -} - -static const cairo_cache_backend_t _xlib_glyphset_cache_backend = { - _cairo_glyph_cache_hash, - _cairo_glyph_cache_keys_equal, - _xlib_glyphset_cache_create_entry, - _xlib_glyphset_cache_destroy_entry, - _xlib_glyphset_cache_destroy_cache -}; - -CAIRO_MUTEX_DECLARE(_xlib_glyphset_caches_mutex); - -static glyphset_cache_t * -_xlib_glyphset_caches = NULL; - -static void -_lock_xlib_glyphset_caches (void) -{ - CAIRO_MUTEX_LOCK(_xlib_glyphset_caches_mutex); -} - -static void -_unlock_xlib_glyphset_caches (glyphset_cache_t *cache) -{ - if (cache) { - _cairo_cache_shrink_to (&cache->base, - CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT); - } - CAIRO_MUTEX_UNLOCK(_xlib_glyphset_caches_mutex); -} - -static glyphset_cache_t * -_get_glyphset_cache (Display *d) -{ - /* - * There should usually only be one, or a very small number, of - * displays. So we just do a linear scan. - */ - glyphset_cache_t *cache; - - /* XXX: This is not thread-safe. Xft has example code to get - * per-display data via Xlib extension mechanisms. */ - for (cache = _xlib_glyphset_caches; cache != NULL; cache = cache->next) { - if (cache->display == d) - return cache; - } - - cache = malloc (sizeof (glyphset_cache_t)); - if (cache == NULL) - goto ERR; - - if (_cairo_cache_init (&cache->base, - &_xlib_glyphset_cache_backend, 0)) - goto FREE_GLYPHSET_CACHE; - - cache->display = d; - cache->counter = 0; - - cache->a1_pict_format = XRenderFindStandardFormat (d, PictStandardA1); - cache->a1_glyphset = XRenderCreateGlyphSet (d, cache->a1_pict_format); - - cache->a8_pict_format = XRenderFindStandardFormat (d, PictStandardA8); - cache->a8_glyphset = XRenderCreateGlyphSet (d, cache->a8_pict_format); - - cache->argb32_pict_format = XRenderFindStandardFormat (d, PictStandardARGB32); - cache->argb32_glyphset = XRenderCreateGlyphSet (d, cache->argb32_pict_format);; - - cache->next = _xlib_glyphset_caches; - _xlib_glyphset_caches = cache; - - return cache; - - FREE_GLYPHSET_CACHE: - free (cache); - - ERR: - return NULL; -} - #define N_STACK_BUF 1024 -static XRenderPictFormat * -_select_text_mask_format (glyphset_cache_t *cache, - cairo_bool_t have_a1_glyphs, - cairo_bool_t have_a8_glyphs, - cairo_bool_t have_argb32_glyphs) -{ - if (have_a8_glyphs) - return cache->a8_pict_format; - - if (have_a1_glyphs && have_argb32_glyphs) - return cache->a8_pict_format; - - if (have_a1_glyphs) - return cache->a1_pict_format; - - if (have_argb32_glyphs) - return cache->argb32_pict_format; - - /* when there are no glyphs to draw, just pick something */ - return cache->a8_pict_format; -} - static cairo_status_t -_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font, +_cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font, cairo_operator_t operator, - glyphset_cache_t *cache, - cairo_glyph_cache_key_t *key, cairo_xlib_surface_t *src, cairo_xlib_surface_t *self, int source_x, int source_y, const cairo_glyph_t *glyphs, - glyphset_cache_entry_t **entries, int num_glyphs) { - XGlyphElt32 *elts = NULL; - XGlyphElt32 stack_elts [N_STACK_BUF]; - - unsigned int *chars = NULL; - unsigned int stack_chars [N_STACK_BUF]; - - int i, count; - int thisX, thisY; - int lastX = 0, lastY = 0; - - cairo_bool_t have_a1, have_a8, have_argb32; - XRenderPictFormat *mask_format; - - /* Acquire arrays of suitable sizes. */ - if (num_glyphs < N_STACK_BUF) { - elts = stack_elts; - chars = stack_chars; - - } else { - elts = malloc (num_glyphs * sizeof (XGlyphElt32)); - if (elts == NULL) - goto FAIL; - - chars = malloc (num_glyphs * sizeof (unsigned int)); - if (chars == NULL) - goto FREE_ELTS; - - } - - have_a1 = FALSE; - have_a8 = FALSE; - have_argb32 = FALSE; - count = 0; - - for (i = 0; i < num_glyphs; ++i) { - GlyphSet glyphset; - - if (!entries[i]->glyph) - continue; - - glyphset = entries[i]->glyphset; - - if (glyphset == cache->a1_glyphset) - have_a1 = TRUE; - else if (glyphset == cache->a8_glyphset) - have_a8 = TRUE; - else if (glyphset == cache->argb32_glyphset) - have_argb32 = TRUE; - - chars[count] = entries[i]->glyph; - elts[count].chars = &(chars[count]); - elts[count].nchars = 1; - elts[count].glyphset = glyphset; - thisX = (int) floor (glyphs[i].x + 0.5); - thisY = (int) floor (glyphs[i].y + 0.5); - elts[count].xOff = thisX - lastX; - elts[count].yOff = thisY - lastY; - lastX = thisX; - lastY = thisY; - count++; - } - - mask_format = _select_text_mask_format (cache, - have_a1, have_a8, have_argb32); - - XRenderCompositeText32 (self->dpy, - _render_operator (operator), - src->src_picture, - self->dst_picture, - mask_format, - source_x, source_y, - 0, 0, - elts, count); - - if (num_glyphs >= N_STACK_BUF) { - free (chars); - free (elts); - } - - return CAIRO_STATUS_SUCCESS; - - FREE_ELTS: - if (num_glyphs >= N_STACK_BUF) - free (elts); - - FAIL: - return CAIRO_STATUS_NO_MEMORY; -} - - -static cairo_status_t -_cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font, - cairo_operator_t operator, - glyphset_cache_t *cache, - cairo_glyph_cache_key_t *key, - cairo_xlib_surface_t *src, - cairo_xlib_surface_t *self, - int source_x, - int source_y, - const cairo_glyph_t *glyphs, - glyphset_cache_entry_t **entries, - int num_glyphs) -{ - XGlyphElt16 *elts = NULL; - XGlyphElt16 stack_elts [N_STACK_BUF]; - - unsigned short *chars = NULL; - unsigned short stack_chars [N_STACK_BUF]; - - int i, count; - int thisX, thisY; - int lastX = 0, lastY = 0; - - cairo_bool_t have_a1, have_a8, have_argb32; - XRenderPictFormat *mask_format; - - /* Acquire arrays of suitable sizes. */ - if (num_glyphs < N_STACK_BUF) { - elts = stack_elts; - chars = stack_chars; - - } else { - elts = malloc (num_glyphs * sizeof (XGlyphElt16)); - if (elts == NULL) - goto FAIL; - - chars = malloc (num_glyphs * sizeof (unsigned short)); - if (chars == NULL) - goto FREE_ELTS; - - } - - have_a1 = FALSE; - have_a8 = FALSE; - have_argb32 = FALSE; - count = 0; - - for (i = 0; i < num_glyphs; ++i) { - GlyphSet glyphset; - - if (!entries[i]->glyph) - continue; - - glyphset = entries[i]->glyphset; - - if (glyphset == cache->a1_glyphset) - have_a1 = TRUE; - else if (glyphset == cache->a8_glyphset) - have_a8 = TRUE; - else if (glyphset == cache->argb32_glyphset) - have_argb32 = TRUE; - - chars[count] = entries[i]->glyph; - elts[count].chars = &(chars[count]); - elts[count].nchars = 1; - elts[count].glyphset = glyphset; - thisX = (int) floor (glyphs[i].x + 0.5); - thisY = (int) floor (glyphs[i].y + 0.5); - elts[count].xOff = thisX - lastX; - elts[count].yOff = thisY - lastY; - lastX = thisX; - lastY = thisY; - count++; - } - - mask_format = _select_text_mask_format (cache, - have_a1, have_a8, have_argb32); - - XRenderCompositeText16 (self->dpy, - _render_operator (operator), - src->src_picture, - self->dst_picture, - mask_format, - source_x, source_y, - 0, 0, - elts, count); - - if (num_glyphs >= N_STACK_BUF) { - free (chars); - free (elts); - } - - return CAIRO_STATUS_SUCCESS; - - FREE_ELTS: - if (num_glyphs >= N_STACK_BUF) - free (elts); - - FAIL: - return CAIRO_STATUS_NO_MEMORY; -} - -static cairo_status_t -_cairo_xlib_surface_show_glyphs8 (cairo_scaled_font_t *scaled_font, - cairo_operator_t operator, - glyphset_cache_t *cache, - cairo_glyph_cache_key_t *key, - cairo_xlib_surface_t *src, - cairo_xlib_surface_t *self, - int source_x, - int source_y, - const cairo_glyph_t *glyphs, - glyphset_cache_entry_t **entries, - int num_glyphs) -{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; XGlyphElt8 *elts = NULL; XGlyphElt8 stack_elts [N_STACK_BUF]; char *chars = NULL; char stack_chars [N_STACK_BUF]; - int i, count; + int i; int thisX, thisY; int lastX = 0, lastY = 0; - cairo_bool_t have_a1, have_a8, have_argb32; - XRenderPictFormat *mask_format; - - if (num_glyphs == 0) - return CAIRO_STATUS_SUCCESS; - /* Acquire arrays of suitable sizes. */ if (num_glyphs < N_STACK_BUF) { elts = stack_elts; chars = stack_chars; - } else { - elts = malloc (num_glyphs * sizeof (XGlyphElt8)); + elts = malloc (num_glyphs * sizeof (XGlyphElt8) + + num_glyphs * sizeof (unsigned char)); if (elts == NULL) - goto FAIL; - - chars = malloc (num_glyphs * sizeof (char)); - if (chars == NULL) - goto FREE_ELTS; + return CAIRO_STATUS_NO_MEMORY; + chars = (char *) (elts + num_glyphs); } - have_a1 = FALSE; - have_a8 = FALSE; - have_argb32 = FALSE; - count = 0; - for (i = 0; i < num_glyphs; ++i) { - GlyphSet glyphset; - - if (!entries[i]->glyph) - continue; - - glyphset = entries[i]->glyphset; - - if (glyphset == cache->a1_glyphset) - have_a1 = TRUE; - else if (glyphset == cache->a8_glyphset) - have_a8 = TRUE; - else if (glyphset == cache->argb32_glyphset) - have_argb32 = TRUE; - - chars[count] = entries[i]->glyph; - elts[count].chars = &(chars[count]); - elts[count].nchars = 1; - elts[count].glyphset = glyphset; + chars[i] = glyphs[i].index; + elts[i].chars = &(chars[i]); + elts[i].nchars = 1; + elts[i].glyphset = font_private->glyphset; thisX = (int) floor (glyphs[i].x + 0.5); thisY = (int) floor (glyphs[i].y + 0.5); - elts[count].xOff = thisX - lastX; - elts[count].yOff = thisY - lastY; + elts[i].xOff = thisX - lastX; + elts[i].yOff = thisY - lastY; lastX = thisX; lastY = thisY; - count++; } - mask_format = _select_text_mask_format (cache, - have_a1, have_a8, have_argb32); + XRenderCompositeText8 (self->dpy, + _render_operator (operator), + src->src_picture, + self->dst_picture, + font_private->format, + source_x + elts[0].xOff, source_y + elts[0].yOff, + 0, 0, + elts, num_glyphs); + + if (elts != stack_elts) + free (elts); - XRenderCompositeText8 (self->dpy, - _render_operator (operator), - src->src_picture, - self->dst_picture, - mask_format, - source_x, source_y, - 0, 0, - elts, count); - - if (num_glyphs >= N_STACK_BUF) { - free (chars); - free (elts); - } - return CAIRO_STATUS_SUCCESS; - - FREE_ELTS: - if (num_glyphs >= N_STACK_BUF) - free (elts); - - FAIL: - return CAIRO_STATUS_NO_MEMORY; } -/* Handles clearing the regions that are outside of the temporary - * mask created by XRenderCompositeText[N] but should be affected - * by an unbounded operator like CAIRO_OPERATOR_SOURCE. - */ static cairo_status_t -_show_glyphs_fixup_unbounded (cairo_xlib_surface_t *self, - cairo_surface_attributes_t *src_attr, - cairo_xlib_surface_t *src, - const cairo_glyph_t *glyphs, - glyphset_cache_entry_t **entries, - int num_glyphs, - int src_x, - int src_y, - int dst_x, - int dst_y, - int width, - int height) +_cairo_xlib_surface_show_glyphs16 (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_xlib_surface_t *src, + cairo_xlib_surface_t *self, + int source_x, + int source_y, + const cairo_glyph_t *glyphs, + int num_glyphs) { - int x1 = INT_MAX; - int x2 = INT_MIN; - int y1 = INT_MAX; - int y2 = INT_MIN; - int i; + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + XGlyphElt16 *elts = NULL; + XGlyphElt16 stack_elts [N_STACK_BUF]; + + unsigned short *chars = NULL; + unsigned short stack_chars [N_STACK_BUF]; + + int i; + int thisX, thisY; + int lastX = 0, lastY = 0; + + /* Acquire arrays of suitable sizes. */ + if (num_glyphs < N_STACK_BUF) { + elts = stack_elts; + chars = stack_chars; + } else { + elts = malloc (num_glyphs * sizeof (XGlyphElt16) + + num_glyphs * sizeof (unsigned short)); + if (elts == NULL) + return CAIRO_STATUS_NO_MEMORY; + + chars = (unsigned short *) (elts + num_glyphs); + } - /* Compute the size of the glyph mask as the bounding box - * of all the glyphs. - */ for (i = 0; i < num_glyphs; ++i) { - int thisX, thisY; - - if (entries[i] == NULL || !entries[i]->glyph) - continue; - + chars[i] = glyphs[i].index; + elts[i].chars = &(chars[i]); + elts[i].nchars = 1; + elts[i].glyphset = font_private->glyphset; thisX = (int) floor (glyphs[i].x + 0.5); thisY = (int) floor (glyphs[i].y + 0.5); - - if (thisX + entries[i]->size.x < x1) - x1 = thisX + entries[i]->size.x; - if (thisX + entries[i]->size.x + entries[i]->size.width > x2) - x2 = thisX + entries[i]->size.x + entries[i]->size.width; - if (thisY + entries[i]->size.y < y1) - y1 = thisY + entries[i]->size.y; - if (thisY + entries[i]->size.y + entries[i]->size.height > y2) - y2 = thisY + entries[i]->size.y + entries[i]->size.height; + elts[i].xOff = thisX - lastX; + elts[i].yOff = thisY - lastY; + lastX = thisX; + lastY = thisY; } - if (x1 >= x2 || y1 >= y2) - x1 = x2 = y1 = y2 = 0; + XRenderCompositeText16 (self->dpy, + _render_operator (operator), + src->src_picture, + self->dst_picture, + font_private->format, + source_x + elts[0].xOff, source_y + elts[0].yOff, + 0, 0, + elts, num_glyphs); - return _cairo_surface_composite_shape_fixup_unbounded (&self->base, - src_attr, src->width, src->height, - x2 - x1, y2 - y1, - src_x, src_y, - dst_x - x1, dst_y - y1, - dst_x, dst_y, width, height); + if (elts != stack_elts) + free (elts); + + return CAIRO_STATUS_SUCCESS; } - + +static cairo_status_t +_cairo_xlib_surface_show_glyphs32 (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_xlib_surface_t *src, + cairo_xlib_surface_t *self, + int source_x, + int source_y, + const cairo_glyph_t *glyphs, + int num_glyphs) +{ + cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + XGlyphElt32 *elts = NULL; + XGlyphElt32 stack_elts [N_STACK_BUF]; + + unsigned int *chars = NULL; + unsigned int stack_chars [N_STACK_BUF]; + + int i; + int thisX, thisY; + int lastX = 0, lastY = 0; + + /* Acquire arrays of suitable sizes. */ + if (num_glyphs < N_STACK_BUF) { + elts = stack_elts; + chars = stack_chars; + } else { + elts = malloc (num_glyphs * sizeof (XGlyphElt32) + + num_glyphs * sizeof (unsigned int)); + if (elts == NULL) + return CAIRO_STATUS_NO_MEMORY; + + chars = (unsigned int *) (elts + num_glyphs); + } + + for (i = 0; i < num_glyphs; ++i) { + chars[i] = glyphs[i].index; + elts[i].chars = &(chars[i]); + elts[i].nchars = 1; + elts[i].glyphset = font_private->glyphset; + thisX = (int) floor (glyphs[i].x + 0.5); + thisY = (int) floor (glyphs[i].y + 0.5); + elts[i].xOff = thisX - lastX; + elts[i].yOff = thisY - lastY; + lastX = thisX; + lastY = thisY; + } + + XRenderCompositeText32 (self->dpy, + _render_operator (operator), + src->src_picture, + self->dst_picture, + font_private->format, + source_x + elts[0].xOff, source_y + elts[0].yOff, + 0, 0, + elts, num_glyphs); + + if (elts != stack_elts) + free (elts); + + return CAIRO_STATUS_SUCCESS; +} + static cairo_int_status_t _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_operator_t operator, @@ -2588,15 +2402,14 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, { cairo_surface_attributes_t attributes; cairo_int_status_t status; - unsigned int elt_size; cairo_xlib_surface_t *self = abstract_surface; cairo_xlib_surface_t *src; - glyphset_cache_t *cache; - cairo_glyph_cache_key_t key; - glyphset_cache_entry_t **entries; - glyphset_cache_entry_t *stack_entries [N_STACK_BUF]; composite_operation_t operation; + cairo_scaled_glyph_t *scaled_glyph; + cairo_xlib_surface_font_private_t *font_private; int i; + unsigned long max_index = 0; + if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (self) || !self->format) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2605,6 +2418,12 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (operation == DO_UNSUPPORTED) return CAIRO_INT_STATUS_UNSUPPORTED; + font_private = scaled_font->surface_private; + if ((scaled_font->surface_backend != NULL && + scaled_font->surface_backend != &cairo_xlib_surface_backend) || + (font_private != NULL && font_private->dpy != self->dpy)) + return CAIRO_INT_STATUS_UNSUPPORTED; + status = _cairo_pattern_acquire_surface (pattern, &self->base, source_x, source_y, width, height, (cairo_surface_t **) &src, @@ -2622,102 +2441,58 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font, if (status) goto FAIL; - /* Acquire an entry array of suitable size. */ - if (num_glyphs < N_STACK_BUF) { - entries = stack_entries; - - } else { - entries = malloc (num_glyphs * sizeof (glyphset_cache_entry_t *)); - if (entries == NULL) - goto FAIL; - } - - _lock_xlib_glyphset_caches (); - cache = _get_glyphset_cache (self->dpy); - if (cache == NULL) - goto UNLOCK; - - /* Work out the index size to use. */ - elt_size = 8; - status = _cairo_scaled_font_get_glyph_cache_key (scaled_font, &key); - if (status) - goto UNLOCK; - - for (i = 0; i < num_glyphs; ++i) { - key.index = glyphs[i].index; - status = _cairo_cache_lookup (&cache->base, &key, (void **) (&entries[i]), NULL); - if (status != CAIRO_STATUS_SUCCESS || entries[i] == NULL) - goto UNLOCK; - - if (elt_size == 8 && entries[i]->glyph > 0xff) - elt_size = 16; - if (elt_size == 16 && entries[i]->glyph > 0xffff) { - elt_size = 32; - break; + /* Send all unsent glyphs to the server */ + for (i = 0; i < num_glyphs; i++) { + if (glyphs[i].index > max_index) + max_index = glyphs[i].index; + status = _cairo_scaled_glyph_lookup (scaled_font, + glyphs[i].index, + CAIRO_SCALED_GLYPH_INFO_SURFACE, + &scaled_glyph); + if (status != CAIRO_STATUS_SUCCESS) + return status; + if (scaled_glyph->surface_private == NULL) { + _cairo_xlib_surface_add_glyph (self->dpy, scaled_font, scaled_glyph); + scaled_glyph->surface_private = (void *) 1; } } - + + _cairo_xlib_surface_ensure_dst_picture (self); /* Call the appropriate sub-function. */ - _cairo_xlib_surface_ensure_dst_picture (self); - if (elt_size == 8) - { - status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, cache, &key, src, self, - source_x + attributes.x_offset, - source_y + attributes.y_offset, - glyphs, entries, num_glyphs); - } - else if (elt_size == 16) - { - status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, cache, &key, src, self, - source_x + attributes.x_offset, - source_y + attributes.y_offset, - glyphs, entries, num_glyphs); - } + if (max_index < 256) + status = _cairo_xlib_surface_show_glyphs8 (scaled_font, operator, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs, num_glyphs); + else if (max_index < 65536) + status = _cairo_xlib_surface_show_glyphs16 (scaled_font, operator, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs, num_glyphs); else - { - status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, cache, &key, src, self, - source_x + attributes.x_offset, - source_y + attributes.y_offset, - glyphs, entries, num_glyphs); + status = _cairo_xlib_surface_show_glyphs32 (scaled_font, operator, src, self, + source_x + attributes.x_offset - dest_x, + source_y + attributes.y_offset - dest_y, + glyphs, num_glyphs); + + if (status == CAIRO_STATUS_SUCCESS && !_cairo_operator_bounded (operator)) { + cairo_rectangle_t extents; + status = _cairo_scaled_font_glyph_device_extents (scaled_font, + glyphs, + num_glyphs, + &extents); + if (status == CAIRO_STATUS_SUCCESS) + status = _cairo_surface_composite_shape_fixup_unbounded + (&self->base, &attributes, src->width, src->height, + extents.width, extents.height, + source_x, source_y, + dest_x - extents.x, dest_y - extents.y, + dest_x, dest_y, + width, height); } - - if (status == CAIRO_STATUS_SUCCESS && - !_cairo_operator_bounded (operator)) - status = _show_glyphs_fixup_unbounded (self, - &attributes, src, - glyphs, entries, num_glyphs, - source_x, source_y, - dest_x, dest_y, width, height); - - UNLOCK: - _unlock_xlib_glyphset_caches (cache); - - if (num_glyphs >= N_STACK_BUF) - free (entries); - FAIL: _cairo_pattern_release_surface (pattern, &src->base, &attributes); return status; } - -static void -_destroy_glyphset_cache_recurse (glyphset_cache_t *cache) -{ - if (cache == NULL) - return; - - _destroy_glyphset_cache_recurse (cache->next); - _cairo_cache_destroy (&cache->base); - free (cache); -} - -void -_cairo_xlib_surface_reset_static_data (void) -{ - _lock_xlib_glyphset_caches (); - _destroy_glyphset_cache_recurse (_xlib_glyphset_caches); - _xlib_glyphset_caches = NULL; - _unlock_xlib_glyphset_caches (NULL); -} diff --git a/gfx/cairo/cairo/src/cairo-xlib-xrender.h b/gfx/cairo/cairo/src/cairo-xlib-xrender.h index 71b2397728e..cc1064fc0ba 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-xrender.h +++ b/gfx/cairo/cairo/src/cairo-xlib-xrender.h @@ -45,7 +45,7 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xlib_surface_create_with_xrender_format (Display *dpy, Drawable drawable, Screen *screen, diff --git a/gfx/cairo/cairo/src/cairo-xlib.h b/gfx/cairo/cairo/src/cairo-xlib.h index 5cdf1378b5f..078fe1d5009 100644 --- a/gfx/cairo/cairo/src/cairo-xlib.h +++ b/gfx/cairo/cairo/src/cairo-xlib.h @@ -45,26 +45,26 @@ CAIRO_BEGIN_DECLS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xlib_surface_create (Display *dpy, Drawable drawable, Visual *visual, int width, int height); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_xlib_surface_create_for_bitmap (Display *dpy, Pixmap bitmap, Screen *screen, int width, int height); -void +cairo_public void cairo_xlib_surface_set_size (cairo_surface_t *surface, int width, int height); -void +cairo_public void cairo_xlib_surface_set_drawable (cairo_surface_t *surface, Drawable drawable, int width, diff --git a/gfx/cairo/cairo/src/cairo.c b/gfx/cairo/cairo/src/cairo.c index 8d759eadaf2..aa50439fcd7 100644 --- a/gfx/cairo/cairo/src/cairo.c +++ b/gfx/cairo/cairo/src/cairo.c @@ -62,7 +62,7 @@ static const cairo_t cairo_nil = { * a bit of a pain, but it should be easy to always catch as long as * one adds a new test case to test a trigger of the new status value. */ -#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_FILE_NOT_FOUND +#define CAIRO_STATUS_LAST_STATUS CAIRO_STATUS_INVALID_DASH /** * _cairo_error: @@ -82,6 +82,8 @@ static const cairo_t cairo_nil = { void _cairo_error (cairo_status_t status) { + fprintf (stderr, "#### Cairo Error: %d\n", status); + assert (status > CAIRO_STATUS_SUCCESS && status <= CAIRO_STATUS_LAST_STATUS); } @@ -105,7 +107,11 @@ _cairo_error (cairo_status_t status) static void _cairo_set_error (cairo_t *cr, cairo_status_t status) { - cr->status = status; + /* Don't overwrite an existing error. This preserves the first + * error, which is the most significant. It also avoids attempting + * to write to read-only data (eg. from a nil cairo_t). */ + if (cr->status == CAIRO_STATUS_SUCCESS) + cr->status = status; _cairo_error (status); } @@ -159,22 +165,12 @@ cairo_version_string (void) * Creates a new #cairo_t with all graphics state parameters set to * default values and with @target as a target surface. The target * surface should be constructed with a backend-specific function such - * as cairo_image_surface_create (or any other - * cairo_<backend>_surface_create variant). + * as cairo_image_surface_create() (or any other + * cairo_<backend>_surface_create variant). * * This function references @target, so you can immediately * call cairo_surface_destroy() on it if you don't need to * maintain a separate reference to it. - * - * Note that there are restrictions on using the same surface in - * multiple contexts at the same time. If, after creating @cr_a with - * @surface you also create @cr_b with the same surface, you must - * ensure that @cr_b has finished using @surface before resuming use - * of @cr_a. Currently, the only way time at which this is guaranteed - * is when the the last reference to @cr_b is released with - * cairo_destroy(). (XXX: We need to add a cairo_finish() call to - * provide a way to achieve this explicitly). See also the - * %CAIRO_STATUS_BAD_NESTING status. * * Return value: a newly allocated #cairo_t with a reference * count of 1. The initial reference count should be released @@ -228,6 +224,8 @@ cairo_reference (cairo_t *cr) { if (cr->ref_count == (unsigned int)-1) return cr; + + assert (cr->ref_count > 0); cr->ref_count++; @@ -247,6 +245,8 @@ cairo_destroy (cairo_t *cr) { if (cr->ref_count == (unsigned int)-1) return; + + assert (cr->ref_count > 0); cr->ref_count--; if (cr->ref_count) @@ -285,10 +285,8 @@ cairo_save (cairo_t *cr) { cairo_gstate_t *top; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } top = _cairo_gstate_clone (cr->gstate); @@ -315,10 +313,8 @@ cairo_restore (cairo_t *cr) { cairo_gstate_t *top; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } top = cr->gstate; cr->gstate = top->next; @@ -330,6 +326,28 @@ cairo_restore (cairo_t *cr) } slim_hidden_def(cairo_restore); +/** + * cairo_set_target: + * @cr: a #cairo_t + * @target: a #cairo_surface_t + * + * Change the destination surface of rendering to @cr to @target. + * @target must not be %NULL, or an error will be set on @cr. + */ +void +cairo_set_target (cairo_t *cr, cairo_surface_t *target) +{ + if (cr->status) + return; + + if (target == NULL) { + _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); + return; + } + + _cairo_gstate_set_target (cr->gstate, target); +} + /* XXX: I want to rethink this API void cairo_push_group (cairo_t *cr) @@ -365,7 +383,7 @@ cairo_pop_group (cairo_t *cr) * * Sets the compositing operator to be used for all drawing * operations. See #cairo_operator_t for details on the semantics of - * each available drawing operator. + * each available compositing operator. * * XXX: I'd also like to direct the reader's attention to some * (not-yet-written) section on cairo's imaging model. How would I do @@ -374,10 +392,8 @@ cairo_pop_group (cairo_t *cr) void cairo_set_operator (cairo_t *cr, cairo_operator_t op) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_operator (cr->gstate, op); if (cr->status) @@ -404,10 +420,8 @@ cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue) { cairo_pattern_t *pattern; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } pattern = cairo_pattern_create_rgb (red, green, blue); cairo_set_source (cr, pattern); @@ -437,10 +451,8 @@ cairo_set_source_rgba (cairo_t *cr, { cairo_pattern_t *pattern; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } pattern = cairo_pattern_create_rgba (red, green, blue, alpha); cairo_set_source (cr, pattern); @@ -465,7 +477,7 @@ cairo_set_source_rgba (cairo_t *cr, * * Other than the initial translation pattern matrix, as described * above, all other pattern attributes, (such as its extend mode), are - * set to the default values as in cairo_pattern_create_for_surface. + * set to the default values as in cairo_pattern_create_for_surface(). * The resulting pattern can be queried with cairo_get_source() so * that these attributes can be modified if desired, (eg. to create a * repeating pattern with cairo_pattern_set_extend()). @@ -479,10 +491,8 @@ cairo_set_source_surface (cairo_t *cr, cairo_pattern_t *pattern; cairo_matrix_t matrix; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } pattern = cairo_pattern_create_for_surface (surface); @@ -505,8 +515,8 @@ cairo_set_source_surface (cairo_t *cr, * * Note: The pattern's transformation matrix will be locked to the * user space in effect at the time of cairo_set_source(). This means - * that further modifications of the CTM will not affect the source - * pattern. See cairo_pattern_set_matrix(). + * that further modifications of the current transformation matrix + * will not affect the source pattern. See cairo_pattern_set_matrix(). * * XXX: I'd also like to direct the reader's attention to some * (not-yet-written) section on cairo's imaging model. How would I do @@ -515,10 +525,8 @@ cairo_set_source_surface (cairo_t *cr, void cairo_set_source (cairo_t *cr, cairo_pattern_t *source) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (source == NULL) { _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); @@ -549,7 +557,7 @@ cairo_pattern_t * cairo_get_source (cairo_t *cr) { if (cr->status) - return (cairo_pattern_t*) &cairo_solid_pattern_nil.base; + return (cairo_pattern_t*) &cairo_pattern_nil.base; return _cairo_gstate_get_source (cr->gstate); } @@ -570,10 +578,8 @@ cairo_get_source (cairo_t *cr) void cairo_set_tolerance (cairo_t *cr, double tolerance) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_restrict_value (&tolerance, CAIRO_TOLERANCE_MINIMUM, tolerance); @@ -598,10 +604,8 @@ cairo_set_tolerance (cairo_t *cr, double tolerance) void cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_antialias (cr->gstate, antialias); if (cr->status) @@ -622,10 +626,8 @@ cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias) void cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_fill_rule (cr->gstate, fill_rule); if (cr->status) @@ -649,10 +651,8 @@ cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule) void cairo_set_line_width (cairo_t *cr, double width) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_restrict_value (&width, 0.0, width); @@ -678,10 +678,8 @@ cairo_set_line_width (cairo_t *cr, double width) void cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_line_cap (cr->gstate, line_cap); if (cr->status) @@ -705,25 +703,48 @@ cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap) void cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_line_join (cr->gstate, line_join); if (cr->status) _cairo_set_error (cr, cr->status); } +/** + * cairo_set_dash: + * @cr: a cairo context + * @dashes: an array specifying alternate lengths of on and off po + * @num_dashes: the length of the dashes array + * @offset: an offset into the dash pattern at which the stroke should start + * + * Sets the dash pattern to be used by cairo_stroke(). A dash pattern + * is specified by @dashes, an array of positive values. Each value + * provides the user-space length of altenate "on" and "off" portions + * of the stroke. The @offset specifies an offset into the pattern at + * which the stroke begins. + * + * If @num_dashes is 0 dashing is disabled. + * + * If @num_dashes is 1 a symmetric pattern is assumed with alternating + * on and off portions of the size specified by the single value in + * @dashes. + * + * If any value in @dashes is negative, or if all values are 0, then + * @cairo_t will be put into an error state with a status of + * #CAIRO_STATUS_INVALID_DASH. + **/ void -cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset) +cairo_set_dash (cairo_t *cr, + double *dashes, + int num_dashes, + double offset) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } - cr->status = _cairo_gstate_set_dash (cr->gstate, dashes, ndash, offset); + cr->status = _cairo_gstate_set_dash (cr->gstate, + dashes, num_dashes, offset); if (cr->status) _cairo_set_error (cr, cr->status); } @@ -731,10 +752,8 @@ cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset) void cairo_set_miter_limit (cairo_t *cr, double limit) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_miter_limit (cr->gstate, limit); if (cr->status) @@ -757,10 +776,8 @@ cairo_set_miter_limit (cairo_t *cr, double limit) void cairo_translate (cairo_t *cr, double tx, double ty) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_translate (cr->gstate, tx, ty); if (cr->status) @@ -781,10 +798,8 @@ cairo_translate (cairo_t *cr, double tx, double ty) void cairo_scale (cairo_t *cr, double sx, double sy) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_scale (cr->gstate, sx, sy); if (cr->status) @@ -807,10 +822,8 @@ cairo_scale (cairo_t *cr, double sx, double sy) void cairo_rotate (cairo_t *cr, double angle) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_rotate (cr->gstate, angle); if (cr->status) @@ -830,10 +843,8 @@ void cairo_transform (cairo_t *cr, const cairo_matrix_t *matrix) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_transform (cr->gstate, matrix); if (cr->status) @@ -852,10 +863,8 @@ void cairo_set_matrix (cairo_t *cr, const cairo_matrix_t *matrix) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_matrix (cr->gstate, matrix); if (cr->status) @@ -874,10 +883,8 @@ cairo_set_matrix (cairo_t *cr, void cairo_identity_matrix (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_identity_matrix (cr->gstate); if (cr->status) @@ -897,10 +904,8 @@ cairo_identity_matrix (cairo_t *cr) void cairo_user_to_device (cairo_t *cr, double *x, double *y) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_user_to_device (cr->gstate, x, y); if (cr->status) @@ -921,10 +926,8 @@ cairo_user_to_device (cairo_t *cr, double *x, double *y) void cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_user_to_device_distance (cr->gstate, dx, dy); if (cr->status) @@ -944,10 +947,8 @@ cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy) void cairo_device_to_user (cairo_t *cr, double *x, double *y) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_device_to_user (cr->gstate, x, y); if (cr->status) @@ -968,37 +969,47 @@ cairo_device_to_user (cairo_t *cr, double *x, double *y) void cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_device_to_user_distance (cr->gstate, dx, dy); if (cr->status) _cairo_set_error (cr, cr->status); } +/** + * cairo_new_path: + * @cr: a cairo context + * + * Clears the current path. After this call there will be no current + * point. + **/ void cairo_new_path (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_path_fixed_fini (&cr->path); } slim_hidden_def(cairo_new_path); +/** + * cairo_move_to: + * @cr: a cairo context + * @x: the X coordinate of the new position + * @y: the Y coordinate of the new position + * + * If the current subpath is not empty, begin a new subpath. After + * this call the current point will be (@x, @y). + **/ void cairo_move_to (cairo_t *cr, double x, double y) { cairo_fixed_t x_fixed, y_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_backend (cr->gstate, &x, &y); x_fixed = _cairo_fixed_from_double (x); @@ -1010,15 +1021,23 @@ cairo_move_to (cairo_t *cr, double x, double y) } slim_hidden_def(cairo_move_to); +/** + * cairo_line_to: + * @cr: a cairo context + * @x: the X coordinate of the end of the new line + * @y: the Y coordinate of the end of the new line + * + * Adds a line to the path from the current point to position (@x, @y) + * in user-space coordinates. After this call the current point + * will be (@x, @y). + **/ void cairo_line_to (cairo_t *cr, double x, double y) { cairo_fixed_t x_fixed, y_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_backend (cr->gstate, &x, &y); x_fixed = _cairo_fixed_from_double (x); @@ -1029,6 +1048,21 @@ cairo_line_to (cairo_t *cr, double x, double y) _cairo_set_error (cr, cr->status); } +/** + * cairo_curve_to: + * @cr: a cairo context + * @x1: the X coordinate of the first control point + * @y1: the Y coordinate of the first control point + * @x2: the X coordinate of the second control point + * @y2: the Y coordinate of the second control point + * @x3: the X coordinate of the end of the curve + * @y3: the Y coordinate of the end of the curve + * + * Adds a cubic Bézier spline to the path from the current point to + * position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and + * (@x2, @y2) as the control points. After this call the current point + * will be (@x3, @y3). + **/ void cairo_curve_to (cairo_t *cr, double x1, double y1, @@ -1039,10 +1073,8 @@ cairo_curve_to (cairo_t *cr, cairo_fixed_t x2_fixed, y2_fixed; cairo_fixed_t x3_fixed, y3_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_backend (cr->gstate, &x1, &y1); _cairo_gstate_user_to_backend (cr->gstate, &x2, &y2); @@ -1074,22 +1106,35 @@ cairo_curve_to (cairo_t *cr, * @angle1: the start angle, in radians * @angle2: the end angle, in radians * - * Adds an arc from @angle1 to @angle2 to the current path. If there - * is a current point, that point is connected to the start of the arc - * by a straight line segment. Angles are measured in radians with an - * angle of 0 along the X axis and an angle of %M_PI radians (90 - * degrees) along the Y axis, so with the default transformation - * matrix, positive angles are clockwise. (To convert from degrees to - * radians, use degrees * (M_PI / 180.).) This - * function gives the arc in the direction of increasing angle; see - * cairo_arc_negative() to get the arc in the direction of decreasing - * angle. + * Adds a circular arc of the given @radius to the current path. The + * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in + * the direction of increasing angles to end at @angle2. If @angle2 is + * less than @angle1 it will be progressively increased by 2*M_PI + * until it is greater than @angle1. + * + * If there is a current point, an initial line segment will be added + * to the path to connect the current point to the beginning of the + * arc. + * + * Angles are measured in radians. An angle of 0 is in the direction + * of the positive X axis (in user-space). An angle of %M_PI radians + * (90 degrees) is in the direction of the positive Y axis (in + * user-space). Angles increase in the direction from the positive X + * axis toward the positive Y axis. So with the default transformation + * matrix, angles increase in a clockwise direction. + * + * (To convert from degrees to radians, use degrees * (M_PI / + * 180.).) + * + * This function gives the arc in the direction of increasing angles; + * see cairo_arc_negative() to get the arc in the direction of + * decreasing angles. + * + * The arc is circular in user-space. To achieve an elliptical arc, + * you can scale the current transformation matrix by different + * amounts in the X and Y directions. For example, to draw an ellipse + * in the box given by @x, @y, @width, @height: * - * A full arc is drawn as a circle. To make an oval arc, you can scale - * the current transformation matrix by different amounts in the X and - * Y directions. For example, to draw a full oval in the box given - * by @x, @y, @width, @height: - * * cairo_save (cr); * cairo_translate (x + width / 2., y + height / 2.); @@ -1104,10 +1149,8 @@ cairo_arc (cairo_t *cr, double radius, double angle1, double angle2) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } /* Do nothing, successfully, if radius is <= 0 */ if (radius <= 0.0) @@ -1133,10 +1176,14 @@ cairo_arc (cairo_t *cr, * @angle1: the start angle, in radians * @angle2: the end angle, in radians * - * Adds an arc from @angle1 to @angle2 to the current path. The - * function behaves identically to cairo_arc() except that instead of - * giving the arc in the direction of increasing angle, it gives - * the arc in the direction of decreasing angle. + * Adds a circular arc of the given @radius to the current path. The + * arc is centered at (@xc, @yc), begins at @angle1 and proceeds in + * the direction of decreasing angles to end at @angle2. If @angle2 is + * greater than @angle1 it will be progressively decreased by 2*M_PI + * until it is greater than @angle1. + * + * See cairo_arc() for more details. This function differs only in the + * direction of the arc between the two angles. **/ void cairo_arc_negative (cairo_t *cr, @@ -1144,10 +1191,8 @@ cairo_arc_negative (cairo_t *cr, double radius, double angle1, double angle2) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } /* Do nothing, successfully, if radius is <= 0 */ if (radius <= 0.0) @@ -1181,15 +1226,25 @@ cairo_arc_to (cairo_t *cr, } */ +/** + * cairo_rel_move_to: + * @cr: a cairo context + * @dx: the X offset + * @dy: the Y offset + * + * If the current subpath is not empty, begin a new subpath. After + * this call the current point will offset by (@x, @y). + * + * Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy) + * is logically equivalent to cairo_move_to (@cr, x + @dx, y + @dy). + **/ void cairo_rel_move_to (cairo_t *cr, double dx, double dy) { cairo_fixed_t dx_fixed, dy_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); dx_fixed = _cairo_fixed_from_double (dx); @@ -1200,15 +1255,27 @@ cairo_rel_move_to (cairo_t *cr, double dx, double dy) _cairo_set_error (cr, cr->status); } +/** + * cairo_rel_line_to: + * @cr: a cairo context + * @dx: the X offset to the end of the new line + * @dy: the Y offset to the end of the new line + * + * Relative-coordinate version of cairo_line_to(). Adds a line to the + * path from the current point to a point that is offset from the + * current point by (@dx, @dy) in user space. After this call the + * current point will be offset by (@dx, @dy). + * + * Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy) + * is logically equivalent to cairo_line_to (@cr, x + @dx, y + @dy). + **/ void cairo_rel_line_to (cairo_t *cr, double dx, double dy) { cairo_fixed_t dx_fixed, dy_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_device_distance (cr->gstate, &dx, &dy); dx_fixed = _cairo_fixed_from_double (dx); @@ -1220,6 +1287,28 @@ cairo_rel_line_to (cairo_t *cr, double dx, double dy) } slim_hidden_def(cairo_rel_line_to); +/** + * cairo_rel_curve_to: + * @cr: a cairo context + * @dx1: the X offset to the first control point + * @dy1: the Y offset to the first control point + * @dx2: the X offset to the second control point + * @dy2: the Y offset to the second control point + * @dx3: the X offset to the end of the curve + * @dy3: the Y offset to the end of the curve + * + * Relative-coordinate version of cairo_curve_to(). All offsets are + * relative to the current point. Adds a cubic Bézier spline to the + * path from the current point to a point offset from the current + * point by (@dx3, @dy3), using points offset by (@dx1, @dy1) and + * (@dx2, @dy2) as the control points. After this call the current + * point will be offset by (@dx3, @dy3). + * + * Given a current point of (x, y), cairo_rel_curve_to (@cr, @dx1, + * @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to + * cairo_curve_to (@cr, x + @dx1, y + @dy1, x + @dx2, y + @dy2, x + + * @dx3, y + @dy3). + **/ void cairo_rel_curve_to (cairo_t *cr, double dx1, double dy1, @@ -1230,10 +1319,8 @@ cairo_rel_curve_to (cairo_t *cr, cairo_fixed_t dx2_fixed, dy2_fixed; cairo_fixed_t dx3_fixed, dy3_fixed; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } _cairo_gstate_user_to_device_distance (cr->gstate, &dx1, &dy1); _cairo_gstate_user_to_device_distance (cr->gstate, &dx2, &dy2); @@ -1256,15 +1343,33 @@ cairo_rel_curve_to (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_rectangle: + * @cr: a cairo context + * @x: the X coordinate of the top left corner of the rectangle + * @y: the Y coordinate to the top left corner of the rectangle + * @width: the width of the rectangle + * @height: the height of the rectangle + * + * Adds a closed-subpath rectangle of the given size to the current + * path at position (@x, @y) in user-space coordinates. + * + * This function is logically equivalent to: + * + * cairo_move_to (cr, x, y); + * cairo_rel_line_to (cr, width, 0); + * cairo_rel_line_to (cr, 0, height); + * cairo_rel_line_to (cr, -width, 0); + * cairo_close_path (cr); + * + **/ void cairo_rectangle (cairo_t *cr, double x, double y, double width, double height) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cairo_move_to (cr, x, y); cairo_rel_line_to (cr, width, 0); @@ -1286,13 +1391,25 @@ cairo_stroke_to_path (cairo_t *cr) } */ +/** + * cairo_close_path: + * @cr: a cairo context + * + * Adds a line segment to the path from the current point to the + * beginning of the current subpath, (the most recent point passed to + * cairo_move_to()), and closes this subpath. + * + * The behavior of cairo_close_path() is distinct from simply calling + * cairo_line_to() with the equivalent coordinate in the case of + * stroking. When a closed subpath is stroked, there are no caps on + * the ends of the subpath. Instead, their is a line join connecting + * the final and initial segments of the subpath. + **/ void cairo_close_path (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_path_fixed_close_path (&cr->path); if (cr->status) @@ -1310,10 +1427,8 @@ slim_hidden_def(cairo_close_path); void cairo_paint (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_paint (cr->gstate); if (cr->status) @@ -1337,16 +1452,18 @@ cairo_paint_with_alpha (cairo_t *cr, cairo_color_t color; cairo_pattern_union_t pattern; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (CAIRO_ALPHA_IS_OPAQUE (alpha)) { cairo_paint (cr); return; } + if (CAIRO_ALPHA_IS_ZERO (alpha)) { + return; + } + _cairo_color_init_rgba (&color, 1., 1., 1., alpha); _cairo_pattern_init_solid (&pattern.solid, &color); @@ -1371,10 +1488,8 @@ void cairo_mask (cairo_t *cr, cairo_pattern_t *pattern) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (pattern == NULL) { _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); @@ -1412,10 +1527,8 @@ cairo_mask_surface (cairo_t *cr, cairo_pattern_t *pattern; cairo_matrix_t matrix; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } pattern = cairo_pattern_create_for_surface (surface); @@ -1462,10 +1575,8 @@ cairo_stroke (cairo_t *cr) void cairo_stroke_preserve (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_stroke (cr->gstate, &cr->path); if (cr->status) @@ -1505,10 +1616,8 @@ cairo_fill (cairo_t *cr) void cairo_fill_preserve (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_fill (cr->gstate, &cr->path); if (cr->status) @@ -1519,10 +1628,8 @@ slim_hidden_def(cairo_fill_preserve); void cairo_copy_page (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_copy_page (cr->gstate); if (cr->status) @@ -1532,10 +1639,8 @@ cairo_copy_page (cairo_t *cr) void cairo_show_page (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_show_page (cr->gstate); if (cr->status) @@ -1547,18 +1652,14 @@ cairo_in_stroke (cairo_t *cr, double x, double y) { int inside; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return 0; - } cr->status = _cairo_gstate_in_stroke (cr->gstate, &cr->path, x, y, &inside); - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return 0; - } return inside; } @@ -1568,10 +1669,8 @@ cairo_in_fill (cairo_t *cr, double x, double y) { int inside; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return 0; - } cr->status = _cairo_gstate_in_fill (cr->gstate, &cr->path, @@ -1588,10 +1687,8 @@ void cairo_stroke_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_stroke_extents (cr->gstate, &cr->path, @@ -1604,10 +1701,8 @@ void cairo_fill_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_fill_extents (cr->gstate, &cr->path, @@ -1671,10 +1766,8 @@ cairo_clip (cairo_t *cr) void cairo_clip_preserve (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_clip (cr->gstate, &cr->path); if (cr->status) @@ -1701,10 +1794,8 @@ slim_hidden_def(cairo_clip_preserve); void cairo_reset_clip (cairo_t *cr) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_reset_clip (cr->gstate); if (cr->status) @@ -1732,10 +1823,8 @@ cairo_select_font_face (cairo_t *cr, cairo_font_slant_t slant, cairo_font_weight_t weight) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_select_font_face (cr->gstate, family, slant, weight); if (cr->status) @@ -1758,10 +1847,8 @@ cairo_get_font_face (cairo_t *cr) { cairo_font_face_t *font_face; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return (cairo_font_face_t*) &_cairo_font_face_nil; - } cr->status = _cairo_gstate_get_font_face (cr->gstate, &font_face); if (cr->status) { @@ -1784,10 +1871,8 @@ void cairo_font_extents (cairo_t *cr, cairo_font_extents_t *extents) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_get_font_extents (cr->gstate, extents); if (cr->status) @@ -1807,10 +1892,8 @@ void cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_font_face (cr->gstate, font_face); if (cr->status) @@ -1831,10 +1914,8 @@ cairo_set_font_face (cairo_t *cr, void cairo_set_font_size (cairo_t *cr, double size) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_font_size (cr->gstate, size); if (cr->status) @@ -1858,10 +1939,8 @@ void cairo_set_font_matrix (cairo_t *cr, const cairo_matrix_t *matrix) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_font_matrix (cr->gstate, matrix); if (cr->status) @@ -1897,10 +1976,8 @@ void cairo_set_font_options (cairo_t *cr, const cairo_font_options_t *options) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_set_font_options (cr->gstate, options); if (cr->status) @@ -1928,15 +2005,15 @@ cairo_get_font_options (cairo_t *cr, /** * cairo_text_extents: * @cr: a #cairo_t - * @utf8: a string of text, encoded in utf-8 + * @utf8: a string of text, encoded in UTF-8 * @extents: a #cairo_text_extents_t object into which the results - * will be stored. + * will be stored * * Gets the extents for a string of text. The extents describe a * user-space rectangle that encloses the "inked" portion of the text, - * (as it would be drawn by cairo_show_text). Additionally, the + * (as it would be drawn by cairo_show_text()). Additionally, the * x_advance and y_advance values indicate the amount by which the - * current point would be advanced by cairo_show_text. + * current point would be advanced by cairo_show_text(). * * Note that whitespace characters do not directly contribute to the * size of the rectangle (extents.width and extents.height). They do @@ -1954,10 +2031,8 @@ cairo_text_extents (cairo_t *cr, int num_glyphs; double x, y; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (utf8 == NULL) { extents->x_bearing = 0.0; @@ -2000,7 +2075,7 @@ cairo_text_extents (cairo_t *cr, * * Gets the extents for an array of glyphs. The extents describe a * user-space rectangle that encloses the "inked" portion of the - * glyphs, (as they would be drawn by cairo_show_glyphs). + * glyphs, (as they would be drawn by cairo_show_glyphs()). * Additionally, the x_advance and y_advance values indicate the * amount by which the current point would be advanced by * cairo_show_glyphs. @@ -2014,10 +2089,8 @@ cairo_glyph_extents (cairo_t *cr, int num_glyphs, cairo_text_extents_t *extents) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_glyph_extents (cr->gstate, glyphs, num_glyphs, extents); @@ -2025,17 +2098,43 @@ cairo_glyph_extents (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_show_text: + * @cr: a cairo context + * @utf8: a string of text encoded in UTF-8 + * + * A drawing operator that generates the shape from a string of UTF-8 + * characters, rendered according to the current font_face, font_size + * (font_matrix), and font_options. + * + * This function first computes a set of glyphs for the string of + * text. The first glyph is placed so that its origin is at the + * current point. The origin of each subsequent glyph is offset from + * that of the previous glyph by the advance values of the previous + * glyph. + * + * After this call the current point is moved to the origin of where + * the next glyph would be placed in this same progression. That is, + * the current point will be at the origin of the final glyph offset + * by its advance values. This allows for easy display of a single + * logical string with multiple calls to cairo_show_text(). + * + * NOTE: The cairo_show_text() function call is part of what the cairo + * designers call the "toy" text API. It is convenient for short demos + * and simple programs, but it is not expected to be adequate for the + * most serious of text-using applications. See cairo_show_glyphs() + * for the "real" text display API in cairo. + **/ void cairo_show_text (cairo_t *cr, const char *utf8) { - cairo_glyph_t *glyphs = NULL; + cairo_text_extents_t extents; + cairo_glyph_t *glyphs = NULL, *last_glyph; int num_glyphs; double x, y; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (utf8 == NULL) return; @@ -2045,16 +2144,28 @@ cairo_show_text (cairo_t *cr, const char *utf8) cr->status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, x, y, &glyphs, &num_glyphs); + if (cr->status) + goto BAIL; - if (cr->status) { - if (glyphs) - free (glyphs); - _cairo_set_error (cr, cr->status); + if (num_glyphs == 0) return; - } cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs); + if (cr->status) + goto BAIL; + last_glyph = &glyphs[num_glyphs - 1]; + cr->status = _cairo_gstate_glyph_extents (cr->gstate, + last_glyph, 1, + &extents); + if (cr->status) + goto BAIL; + + x = last_glyph->x + extents.x_advance; + y = last_glyph->y + extents.y_advance; + cairo_move_to (cr, x, y); + + BAIL: if (glyphs) free (glyphs); @@ -2065,10 +2176,8 @@ cairo_show_text (cairo_t *cr, const char *utf8) void cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_show_glyphs (cr->gstate, glyphs, num_glyphs); if (cr->status) @@ -2082,10 +2191,8 @@ cairo_text_path (cairo_t *cr, const char *utf8) int num_glyphs; double x, y; - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cairo_get_current_point (cr, &x, &y); @@ -2108,16 +2215,13 @@ cairo_text_path (cairo_t *cr, const char *utf8) if (cr->status) _cairo_set_error (cr, cr->status); - } void cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } cr->status = _cairo_gstate_glyph_path (cr->gstate, glyphs, num_glyphs, @@ -2302,14 +2406,15 @@ cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix) * * Gets the target surface for the cairo context as passed to * cairo_create(). - * - * Return value: the target surface. This object is owned by cairo. To - * keep a reference to it, you must call cairo_surface_reference(). * * This function will always return a valid pointer, but the result * can be a "nil" surface if @cr is already in an error state, - * (ie. cairo_status(cr) != CAIRO_STATUS_SUCCESS). A nil surface is - * indicated by cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS. + * (ie. cairo_status() != %CAIRO_STATUS_SUCCESS). + * A nil surface is indicated by cairo_surface_status() + * != %CAIRO_STATUS_SUCCESS. + * + * Return value: the target surface. This object is owned by cairo. To + * keep a reference to it, you must call cairo_surface_reference(). **/ cairo_surface_t * cairo_get_target (cairo_t *cr) @@ -2333,15 +2438,22 @@ cairo_get_target (cairo_t *cr) * with it. * * This function will always return a valid pointer, but the result - * will have no data, (data==NULL and num_data==0), if either of the - * following conditions hold: + * will have no data (data==NULL and + * num_data==0), if either of the following + * conditions hold: * - * 1) If there is insufficient memory to copy the path. + * + * If there is insufficient memory to copy the path. + * If @cr is already in an error state. + * * - * 2) If @cr is already in an error state. + * In either case, path->status will be set to + * %CAIRO_STATUS_NO_MEMORY (regardless of what the error status in + * @cr might have been). * - * In either case, path->status will be set to CAIRO_STATUS_NO_MEMORY, - * (regardless of what the error status in @cr might have been). + * Return value: the copy of the current path. The caller owns the + * returned object and should call cairo_path_destroy() when finished + * with it. **/ cairo_path_t * cairo_copy_path (cairo_t *cr) @@ -2364,23 +2476,26 @@ cairo_copy_path (cairo_t *cr) * in the path will be approximated with piecewise-linear * approximations, (accurate to within the current tolerance * value). That is, the result is guaranteed to not have any elements - * of type CAIRO_PATH_CURVE_TO which will instead be replaced by a - * series of CAIRO_PATH_LINE_TO elements. + * of type %CAIRO_PATH_CURVE_TO which will instead be replaced by a + * series of %CAIRO_PATH_LINE_TO elements. + * + * This function will always return a valid pointer, but the result + * will have no data (data==NULL and + * num_data==0), if either of the following + * conditions hold: + * + * + * If there is insufficient memory to copy the path. In this + * case path->status will be set to + * %CAIRO_STATUS_NO_MEMORY. + * If @cr is already in an error state. In this case + * path->status will contain the same status that + * would be returned by cairo_status(). + * * * Return value: the copy of the current path. The caller owns the * returned object and should call cairo_path_destroy() when finished * with it. - * - * This function will always return a valid pointer, but the result - * will have no data, (data==NULL and num_data==0), if either of the - * following conditions hold: - * - * 1) If there is insufficient memory to copy the path. In this case - * path->status will be set to CAIRO_STATUS_NO_MEMORY. - * - * 2) If @cr is already in an error state. In this case path->status - * will contain the same status that would be returned by - * cairo_status(cr). **/ cairo_path_t * cairo_copy_path_flat (cairo_t *cr) @@ -2400,17 +2515,15 @@ cairo_copy_path_flat (cairo_t *cr) * return value from one of cairo_copy_path() or * cairo_copy_path_flat() or it may be constructed manually. See * #cairo_path_t for details on how the path data structure should be - * initialized, and note that path->status must be initialized to - * CAIRO_STATUS_SUCCESS. + * initialized, and note that path->status must be + * initialized to %CAIRO_STATUS_SUCCESS. **/ void cairo_append_path (cairo_t *cr, cairo_path_t *path) { - if (cr->status) { - _cairo_set_error (cr, cr->status); + if (cr->status) return; - } if (path == NULL) { _cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER); @@ -2435,12 +2548,28 @@ cairo_append_path (cairo_t *cr, _cairo_set_error (cr, cr->status); } +/** + * cairo_status: + * @cr: a cairo context + * + * Checks whether an error has previously occurred for this context. + * + * Returns the current status of this context, see #cairo_status_t + **/ cairo_status_t cairo_status (cairo_t *cr) { return cr->status; } +/** + * cairo_status_to_string: + * @status: a cairo status + * + * Provides a human-readable description of a #cairo_status_t. + * + * Returns a string representation of the status + */ const char * cairo_status_to_string (cairo_status_t status) { @@ -2483,6 +2612,8 @@ cairo_status_to_string (cairo_status_t status) return "invalid value for an input Visual*"; case CAIRO_STATUS_FILE_NOT_FOUND: return "file not found"; + case CAIRO_STATUS_INVALID_DASH: + return "invalid value for a dash setting"; } return ""; diff --git a/gfx/cairo/cairo/src/cairo.h b/gfx/cairo/cairo/src/cairo.h index 06a6d6a085c..0ebefa285fa 100644 --- a/gfx/cairo/cairo/src/cairo.h +++ b/gfx/cairo/cairo/src/cairo.h @@ -52,10 +52,10 @@ CAIRO_BEGIN_DECLS CAIRO_VERSION_MINOR, \ CAIRO_VERSION_MICRO) -int +cairo_public int cairo_version (void); -const char* +cairo_public const char* cairo_version_string (void); /** @@ -106,11 +106,11 @@ typedef struct _cairo_surface cairo_surface_t; * @y0: Y translation component of the affine transformation * * A #cairo_matrix_t holds an affine transformation, such as a scale, - * rotation, or shear, or a combination of those. The transformation is given - * by: + * rotation, shear, or a combination of those. The transformation of + * a point (x, y) is given by: * - * x_new = xx * x + xy * y + x0; - * y_new = yx * x + yy * y + y0; + * x_new = xx * x + xy * y + x0; + * y_new = yx * x + yy * y + y0; * **/ typedef struct _cairo_matrix { @@ -166,6 +166,7 @@ typedef struct _cairo_user_data_key { * @CAIRO_STATUS_INVALID_FORMAT: invalid value for an input cairo_format_t * @CAIRO_STATUS_INVALID_VISUAL: invalid value for an input Visual* * @CAIRO_STATUS_FILE_NOT_FOUND: file not found + * @CAIRO_STATUS_INVALID_DASH: invalid value for a dash setting * * #cairo_status_t is used to indicate errors that can occur when * using Cairo. In some cases it is returned directly by functions. @@ -191,7 +192,8 @@ typedef enum _cairo_status { CAIRO_STATUS_INVALID_CONTENT, CAIRO_STATUS_INVALID_FORMAT, CAIRO_STATUS_INVALID_VISUAL, - CAIRO_STATUS_FILE_NOT_FOUND + CAIRO_STATUS_FILE_NOT_FOUND, + CAIRO_STATUS_INVALID_DASH } cairo_status_t; /** @@ -235,26 +237,29 @@ typedef cairo_status_t (*cairo_read_func_t) (void *closure, unsigned int length); /* Functions for manipulating state objects */ -cairo_t * +cairo_public cairo_t * cairo_create (cairo_surface_t *target); -cairo_t * +cairo_public cairo_t * cairo_reference (cairo_t *cr); -void +cairo_public void cairo_destroy (cairo_t *cr); -void +cairo_public void cairo_save (cairo_t *cr); -void +cairo_public void cairo_restore (cairo_t *cr); +cairo_public void +cairo_set_target (cairo_t *cr, cairo_surface_t *target); + /* XXX: I want to rethink this API -void +cairo_public void cairo_push_group (cairo_t *cr); -void +cairo_public void cairo_pop_group (cairo_t *cr); */ @@ -280,27 +285,27 @@ typedef enum _cairo_operator { CAIRO_OPERATOR_SATURATE } cairo_operator_t; -void +cairo_public void cairo_set_operator (cairo_t *cr, cairo_operator_t op); -void +cairo_public void cairo_set_source (cairo_t *cr, cairo_pattern_t *source); -void +cairo_public void cairo_set_source_rgb (cairo_t *cr, double red, double green, double blue); -void +cairo_public void cairo_set_source_rgba (cairo_t *cr, double red, double green, double blue, double alpha); -void +cairo_public void cairo_set_source_surface (cairo_t *cr, cairo_surface_t *surface, double x, double y); -void +cairo_public void cairo_set_tolerance (cairo_t *cr, double tolerance); /** @@ -323,7 +328,7 @@ typedef enum _cairo_antialias { CAIRO_ANTIALIAS_SUBPIXEL } cairo_antialias_t; -void +cairo_public void cairo_set_antialias (cairo_t *cr, cairo_antialias_t antialias); /** @@ -352,10 +357,10 @@ typedef enum _cairo_fill_rule { CAIRO_FILL_RULE_EVEN_ODD } cairo_fill_rule_t; -void +cairo_public void cairo_set_fill_rule (cairo_t *cr, cairo_fill_rule_t fill_rule); -void +cairo_public void cairo_set_line_width (cairo_t *cr, double width); @@ -373,7 +378,7 @@ typedef enum _cairo_line_cap { CAIRO_LINE_CAP_SQUARE } cairo_line_cap_t; -void +cairo_public void cairo_set_line_cap (cairo_t *cr, cairo_line_cap_t line_cap); typedef enum _cairo_line_join { @@ -382,170 +387,173 @@ typedef enum _cairo_line_join { CAIRO_LINE_JOIN_BEVEL } cairo_line_join_t; -void +cairo_public void cairo_set_line_join (cairo_t *cr, cairo_line_join_t line_join); -void -cairo_set_dash (cairo_t *cr, double *dashes, int ndash, double offset); +cairo_public void +cairo_set_dash (cairo_t *cr, + double *dashes, + int num_dashes, + double offset); -void +cairo_public void cairo_set_miter_limit (cairo_t *cr, double limit); -void +cairo_public void cairo_translate (cairo_t *cr, double tx, double ty); -void +cairo_public void cairo_scale (cairo_t *cr, double sx, double sy); -void +cairo_public void cairo_rotate (cairo_t *cr, double angle); -void +cairo_public void cairo_transform (cairo_t *cr, const cairo_matrix_t *matrix); -void +cairo_public void cairo_set_matrix (cairo_t *cr, const cairo_matrix_t *matrix); -void +cairo_public void cairo_identity_matrix (cairo_t *cr); -void +cairo_public void cairo_user_to_device (cairo_t *cr, double *x, double *y); -void +cairo_public void cairo_user_to_device_distance (cairo_t *cr, double *dx, double *dy); -void +cairo_public void cairo_device_to_user (cairo_t *cr, double *x, double *y); -void +cairo_public void cairo_device_to_user_distance (cairo_t *cr, double *dx, double *dy); /* Path creation functions */ -void +cairo_public void cairo_new_path (cairo_t *cr); -void +cairo_public void cairo_move_to (cairo_t *cr, double x, double y); -void +cairo_public void cairo_line_to (cairo_t *cr, double x, double y); -void +cairo_public void cairo_curve_to (cairo_t *cr, double x1, double y1, double x2, double y2, double x3, double y3); -void +cairo_public void cairo_arc (cairo_t *cr, double xc, double yc, double radius, double angle1, double angle2); -void +cairo_public void cairo_arc_negative (cairo_t *cr, double xc, double yc, double radius, double angle1, double angle2); /* XXX: NYI -void +cairo_public void cairo_arc_to (cairo_t *cr, double x1, double y1, double x2, double y2, double radius); */ -void +cairo_public void cairo_rel_move_to (cairo_t *cr, double dx, double dy); -void +cairo_public void cairo_rel_line_to (cairo_t *cr, double dx, double dy); -void +cairo_public void cairo_rel_curve_to (cairo_t *cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3); -void +cairo_public void cairo_rectangle (cairo_t *cr, double x, double y, double width, double height); /* XXX: NYI -void +cairo_public void cairo_stroke_to_path (cairo_t *cr); */ -void +cairo_public void cairo_close_path (cairo_t *cr); /* Painting functions */ -void +cairo_public void cairo_paint (cairo_t *cr); -void +cairo_public void cairo_paint_with_alpha (cairo_t *cr, double alpha); -void +cairo_public void cairo_mask (cairo_t *cr, cairo_pattern_t *pattern); -void +cairo_public void cairo_mask_surface (cairo_t *cr, cairo_surface_t *surface, double surface_x, double surface_y); -void +cairo_public void cairo_stroke (cairo_t *cr); -void +cairo_public void cairo_stroke_preserve (cairo_t *cr); -void +cairo_public void cairo_fill (cairo_t *cr); -void +cairo_public void cairo_fill_preserve (cairo_t *cr); -void +cairo_public void cairo_copy_page (cairo_t *cr); -void +cairo_public void cairo_show_page (cairo_t *cr); /* Insideness testing */ -cairo_bool_t +cairo_public cairo_bool_t cairo_in_stroke (cairo_t *cr, double x, double y); -cairo_bool_t +cairo_public cairo_bool_t cairo_in_fill (cairo_t *cr, double x, double y); /* Rectangular extents */ -void +cairo_public void cairo_stroke_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2); -void +cairo_public void cairo_fill_extents (cairo_t *cr, double *x1, double *y1, double *x2, double *y2); /* Clipping */ -void +cairo_public void cairo_reset_clip (cairo_t *cr); -void +cairo_public void cairo_clip (cairo_t *cr); -void +cairo_public void cairo_clip_preserve (cairo_t *cr); /* Font/Text functions */ @@ -772,130 +780,130 @@ typedef enum _cairo_hint_metrics { typedef struct _cairo_font_options cairo_font_options_t; -cairo_font_options_t * +cairo_public cairo_font_options_t * cairo_font_options_create (void); -cairo_font_options_t * +cairo_public cairo_font_options_t * cairo_font_options_copy (const cairo_font_options_t *original); -void +cairo_public void cairo_font_options_destroy (cairo_font_options_t *options); -cairo_status_t +cairo_public cairo_status_t cairo_font_options_status (cairo_font_options_t *options); -void +cairo_public void cairo_font_options_merge (cairo_font_options_t *options, const cairo_font_options_t *other); -cairo_bool_t +cairo_public cairo_bool_t cairo_font_options_equal (const cairo_font_options_t *options, const cairo_font_options_t *other); -unsigned long +cairo_public unsigned long cairo_font_options_hash (const cairo_font_options_t *options); -void +cairo_public void cairo_font_options_set_antialias (cairo_font_options_t *options, cairo_antialias_t antialias); -cairo_antialias_t +cairo_public cairo_antialias_t cairo_font_options_get_antialias (const cairo_font_options_t *options); -void +cairo_public void cairo_font_options_set_subpixel_order (cairo_font_options_t *options, cairo_subpixel_order_t subpixel_order); -cairo_subpixel_order_t +cairo_public cairo_subpixel_order_t cairo_font_options_get_subpixel_order (const cairo_font_options_t *options); -void +cairo_public void cairo_font_options_set_hint_style (cairo_font_options_t *options, cairo_hint_style_t hint_style); -cairo_hint_style_t +cairo_public cairo_hint_style_t cairo_font_options_get_hint_style (const cairo_font_options_t *options); -void +cairo_public void cairo_font_options_set_hint_metrics (cairo_font_options_t *options, cairo_hint_metrics_t hint_metrics); -cairo_hint_metrics_t +cairo_public cairo_hint_metrics_t cairo_font_options_get_hint_metrics (const cairo_font_options_t *options); /* This interface is for dealing with text as text, not caring about the font object inside the the cairo_t. */ -void +cairo_public void cairo_select_font_face (cairo_t *cr, const char *family, cairo_font_slant_t slant, cairo_font_weight_t weight); -void +cairo_public void cairo_set_font_size (cairo_t *cr, double size); -void +cairo_public void cairo_set_font_matrix (cairo_t *cr, const cairo_matrix_t *matrix); -void +cairo_public void cairo_get_font_matrix (cairo_t *cr, cairo_matrix_t *matrix); -void +cairo_public void cairo_set_font_options (cairo_t *cr, const cairo_font_options_t *options); -void +cairo_public void cairo_get_font_options (cairo_t *cr, cairo_font_options_t *options); -void +cairo_public void cairo_show_text (cairo_t *cr, const char *utf8); -void +cairo_public void cairo_show_glyphs (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs); -cairo_font_face_t * +cairo_public cairo_font_face_t * cairo_get_font_face (cairo_t *cr); -void +cairo_public void cairo_font_extents (cairo_t *cr, cairo_font_extents_t *extents); -void +cairo_public void cairo_set_font_face (cairo_t *cr, cairo_font_face_t *font_face); -void +cairo_public void cairo_text_extents (cairo_t *cr, const char *utf8, cairo_text_extents_t *extents); -void +cairo_public void cairo_glyph_extents (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs, cairo_text_extents_t *extents); -void +cairo_public void cairo_text_path (cairo_t *cr, const char *utf8); -void +cairo_public void cairo_glyph_path (cairo_t *cr, cairo_glyph_t *glyphs, int num_glyphs); /* Generic identifier for a font style */ -cairo_font_face_t * +cairo_public cairo_font_face_t * cairo_font_face_reference (cairo_font_face_t *font_face); -void +cairo_public void cairo_font_face_destroy (cairo_font_face_t *font_face); -cairo_status_t +cairo_public cairo_status_t cairo_font_face_status (cairo_font_face_t *font_face); -void * +cairo_public void * cairo_font_face_get_user_data (cairo_font_face_t *font_face, const cairo_user_data_key_t *key); -cairo_status_t +cairo_public cairo_status_t cairo_font_face_set_user_data (cairo_font_face_t *font_face, const cairo_user_data_key_t *key, void *user_data, @@ -903,26 +911,26 @@ cairo_font_face_set_user_data (cairo_font_face_t *font_face, /* Portable interface to general font features. */ -cairo_scaled_font_t * +cairo_public cairo_scaled_font_t * cairo_scaled_font_create (cairo_font_face_t *font_face, const cairo_matrix_t *font_matrix, const cairo_matrix_t *ctm, const cairo_font_options_t *options); -cairo_scaled_font_t * +cairo_public cairo_scaled_font_t * cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font); -void +cairo_public void cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font); -cairo_status_t +cairo_public cairo_status_t cairo_scaled_font_status (cairo_scaled_font_t *scaled_font); -void +cairo_public void cairo_scaled_font_extents (cairo_scaled_font_t *scaled_font, cairo_font_extents_t *extents); -void +cairo_public void cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, cairo_glyph_t *glyphs, int num_glyphs, @@ -930,53 +938,60 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, /* Query functions */ -cairo_operator_t +cairo_public cairo_operator_t cairo_get_operator (cairo_t *cr); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_get_source (cairo_t *cr); -double +cairo_public double cairo_get_tolerance (cairo_t *cr); -cairo_antialias_t +cairo_public cairo_antialias_t cairo_get_antialias (cairo_t *cr); -void +cairo_public void cairo_get_current_point (cairo_t *cr, double *x, double *y); -cairo_fill_rule_t +cairo_public cairo_fill_rule_t cairo_get_fill_rule (cairo_t *cr); -double +cairo_public double cairo_get_line_width (cairo_t *cr); -cairo_line_cap_t +cairo_public cairo_line_cap_t cairo_get_line_cap (cairo_t *cr); -cairo_line_join_t +cairo_public cairo_line_join_t cairo_get_line_join (cairo_t *cr); -double +cairo_public double cairo_get_miter_limit (cairo_t *cr); /* XXX: How to do cairo_get_dash??? Do we want to switch to a cairo_dash object? */ -void +cairo_public void cairo_get_matrix (cairo_t *cr, cairo_matrix_t *matrix); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_get_target (cairo_t *cr); +typedef enum _cairo_path_data_type { + CAIRO_PATH_MOVE_TO, + CAIRO_PATH_LINE_TO, + CAIRO_PATH_CURVE_TO, + CAIRO_PATH_CLOSE_PATH +} cairo_path_data_type_t; + /** * cairo_path_data_t: * - * A data structure for holding path data---appears within + * #cairo_path_data_t is used to represent the path data inside a * #cairo_path_t. * * The data structure is designed to try to balance the demands of * efficiency and ease-of-use. A path is represented as an array of - * cairo_path_data_t which is a union of headers and points. + * #cairo_path_data_t, which is a union of headers and points. * * Each portion of the path is represented by one or more elements in * the array, (one header followed by 0 or more points). The length @@ -985,10 +1000,12 @@ cairo_get_target (cairo_t *cr); * where the number of points for each element type must be as * follows: * - * CAIRO_PATH_MOVE_TO: 1 point - * CAIRO_PATH_LINE_TO: 1 point - * CAIRO_PATH_CURVE_TO: 3 points - * CAIRO_PATH_CLOSE_PATH: 0 points + * + * %CAIRO_PATH_MOVE_TO: 1 point + * %CAIRO_PATH_LINE_TO: 1 point + * %CAIRO_PATH_CURVE_TO: 3 points + * %CAIRO_PATH_CLOSE_PATH: 0 points + * * * The semantics and ordering of the coordinate values are consistent * with cairo_move_to(), cairo_line_to(), cairo_curve_to(), and @@ -998,42 +1015,35 @@ cairo_get_target (cairo_t *cr); * * * int i; - * cairo_path_t *path; + * cairo_path_t *path; * cairo_path_data_t *data; - * - * path = cairo_copy_path (cr); - * + *   + * path = cairo_copy_path (cr); + *   * for (i=0; i < path->num_data; i += path->data[i].header.length) { - * data = &path->data[i]; - * switch (data->header.type) { - * case CAIRO_PATH_MOVE_TO: - * do_move_to_things (data[1].point.x, data[1].point.y); - * break; - * case CAIRO_PATH_LINE_TO: - * do_line_to_things (data[1].point.x, data[1].point.y); - * break; - * case CAIRO_PATH_CURVE_TO: - * do_curve_to_things (data[1].point.x, data[1].point.y, - * data[2].point.x, data[2].point.y, - * data[3].point.x, data[3].point.y); - * break; - * case CAIRO_PATH_CLOSE_PATH: - * do_close_path_things (); - * break; - * } - * } - * - * cairo_path_destroy (path); + * data = &path->data[i]; + * switch (data->header.type) { + * case CAIRO_PATH_MOVE_TO: + * do_move_to_things (data[1].point.x, data[1].point.y); + * break; + * case CAIRO_PATH_LINE_TO: + * do_line_to_things (data[1].point.x, data[1].point.y); + * break; + * case CAIRO_PATH_CURVE_TO: + * do_curve_to_things (data[1].point.x, data[1].point.y, + * data[2].point.x, data[2].point.y, + * data[3].point.x, data[3].point.y); + * break; + * case CAIRO_PATH_CLOSE_PATH: + * do_close_path_things (); + * break; + * } + * } + * cairo_path_destroy (path); * - */ -typedef enum _cairo_path_data_type { - CAIRO_PATH_MOVE_TO, - CAIRO_PATH_LINE_TO, - CAIRO_PATH_CURVE_TO, - CAIRO_PATH_CLOSE_PATH -} cairo_path_data_type_t; - -typedef union { + **/ +typedef union _cairo_path_data_t cairo_path_data_t; +union _cairo_path_data_t { struct { cairo_path_data_type_t type; int length; @@ -1041,7 +1051,7 @@ typedef union { struct { double x, y; } point; -} cairo_path_data_t; +}; /** * cairo_path_t: @@ -1059,7 +1069,7 @@ typedef union { * * The num_data member gives the number of elements in the data * array. This number is larger than the number of independent path - * portions (MOVE_TO, LINE_TO, CURVE_TO, CLOSE_PATH), since the data + * portions (defined in #cairo_path_data_type_t), since the data * includes both headers and coordinates for each portion. **/ typedef struct cairo_path { @@ -1068,25 +1078,25 @@ typedef struct cairo_path { int num_data; } cairo_path_t; -cairo_path_t * +cairo_public cairo_path_t * cairo_copy_path (cairo_t *cr); -cairo_path_t * +cairo_public cairo_path_t * cairo_copy_path_flat (cairo_t *cr); -void +cairo_public void cairo_append_path (cairo_t *cr, cairo_path_t *path); -void +cairo_public void cairo_path_destroy (cairo_path_t *path); /* Error status queries */ -cairo_status_t +cairo_public cairo_status_t cairo_status (cairo_t *cr); -const char * +cairo_public const char * cairo_status_to_string (cairo_status_t status); /* Surface manipulation */ @@ -1111,71 +1121,65 @@ typedef enum _cairo_content { CAIRO_CONTENT_COLOR_ALPHA = 0x3000 } cairo_content_t; -#define CAIRO_CONTENT_VALID(content) ((content) && \ - (((content) & ~(CAIRO_CONTENT_COLOR | \ - CAIRO_CONTENT_ALPHA | \ - CAIRO_CONTENT_COLOR_ALPHA))\ - == 0)) - -cairo_surface_t * +cairo_public cairo_surface_t * cairo_surface_create_similar (cairo_surface_t *other, cairo_content_t content, int width, int height); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_surface_reference (cairo_surface_t *surface); -void +cairo_public void cairo_surface_destroy (cairo_surface_t *surface); -cairo_status_t +cairo_public cairo_status_t cairo_surface_status (cairo_surface_t *surface); -void +cairo_public void cairo_surface_finish (cairo_surface_t *surface); #if CAIRO_HAS_PNG_FUNCTIONS -cairo_status_t +cairo_public cairo_status_t cairo_surface_write_to_png (cairo_surface_t *surface, const char *filename); -cairo_status_t +cairo_public cairo_status_t cairo_surface_write_to_png_stream (cairo_surface_t *surface, cairo_write_func_t write_func, void *closure); #endif -void * +cairo_public void * cairo_surface_get_user_data (cairo_surface_t *surface, const cairo_user_data_key_t *key); -cairo_status_t +cairo_public cairo_status_t cairo_surface_set_user_data (cairo_surface_t *surface, const cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t destroy); -void +cairo_public void cairo_surface_get_font_options (cairo_surface_t *surface, cairo_font_options_t *options); -void +cairo_public void cairo_surface_flush (cairo_surface_t *surface); -void +cairo_public void cairo_surface_mark_dirty (cairo_surface_t *surface); -void +cairo_public void cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface, int x, int y, int width, int height); -void +cairo_public void cairo_surface_set_device_offset (cairo_surface_t *surface, double x_offset, double y_offset); @@ -1211,33 +1215,30 @@ typedef enum _cairo_format { CAIRO_FORMAT_A1 } cairo_format_t; -#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \ - (format) <= CAIRO_FORMAT_A1) - -cairo_surface_t * +cairo_public cairo_surface_t * cairo_image_surface_create (cairo_format_t format, int width, int height); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, int width, int height, int stride); -int +cairo_public int cairo_image_surface_get_width (cairo_surface_t *surface); -int +cairo_public int cairo_image_surface_get_height (cairo_surface_t *surface); #if CAIRO_HAS_PNG_FUNCTIONS -cairo_surface_t * +cairo_public cairo_surface_t * cairo_image_surface_create_from_png (const char *filename); -cairo_surface_t * +cairo_public cairo_surface_t * cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, void *closure); @@ -1245,49 +1246,49 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func, /* Pattern creation functions */ -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_create_rgb (double red, double green, double blue); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_create_rgba (double red, double green, double blue, double alpha); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_create_for_surface (cairo_surface_t *surface); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_create_linear (double x0, double y0, double x1, double y1); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_create_radial (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1); -cairo_pattern_t * +cairo_public cairo_pattern_t * cairo_pattern_reference (cairo_pattern_t *pattern); -void +cairo_public void cairo_pattern_destroy (cairo_pattern_t *pattern); -cairo_status_t +cairo_public cairo_status_t cairo_pattern_status (cairo_pattern_t *pattern); -void +cairo_public void cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern, double offset, double red, double green, double blue); -void +cairo_public void cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern, double offset, double red, double green, double blue, double alpha); -void +cairo_public void cairo_pattern_set_matrix (cairo_pattern_t *pattern, const cairo_matrix_t *matrix); -void +cairo_public void cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix); @@ -1297,10 +1298,10 @@ typedef enum _cairo_extend { CAIRO_EXTEND_REFLECT } cairo_extend_t; -void +cairo_public void cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend); -cairo_extend_t +cairo_public cairo_extend_t cairo_pattern_get_extend (cairo_pattern_t *pattern); typedef enum _cairo_filter { @@ -1312,59 +1313,59 @@ typedef enum _cairo_filter { CAIRO_FILTER_GAUSSIAN } cairo_filter_t; -void +cairo_public void cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter); -cairo_filter_t +cairo_public cairo_filter_t cairo_pattern_get_filter (cairo_pattern_t *pattern); /* Matrix functions */ -void +cairo_public void cairo_matrix_init (cairo_matrix_t *matrix, double xx, double yx, double xy, double yy, double x0, double y0); -void +cairo_public void cairo_matrix_init_identity (cairo_matrix_t *matrix); -void +cairo_public void cairo_matrix_init_translate (cairo_matrix_t *matrix, double tx, double ty); -void +cairo_public void cairo_matrix_init_scale (cairo_matrix_t *matrix, double sx, double sy); -void +cairo_public void cairo_matrix_init_rotate (cairo_matrix_t *matrix, double radians); -void +cairo_public void cairo_matrix_translate (cairo_matrix_t *matrix, double tx, double ty); -void +cairo_public void cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy); -void +cairo_public void cairo_matrix_rotate (cairo_matrix_t *matrix, double radians); -cairo_status_t +cairo_public cairo_status_t cairo_matrix_invert (cairo_matrix_t *matrix); -void +cairo_public void cairo_matrix_multiply (cairo_matrix_t *result, const cairo_matrix_t *a, const cairo_matrix_t *b); /* XXX: Need a new name here perhaps. */ -void +cairo_public void cairo_matrix_transform_distance (const cairo_matrix_t *matrix, double *dx, double *dy); /* XXX: Need a new name here perhaps. */ -void +cairo_public void cairo_matrix_transform_point (const cairo_matrix_t *matrix, double *x, double *y); diff --git a/gfx/cairo/cairo/src/cairoint.h b/gfx/cairo/cairo/src/cairoint.h index 2a97b934dca..9852c822339 100644 --- a/gfx/cairo/cairo/src/cairoint.h +++ b/gfx/cairo/cairo/src/cairoint.h @@ -62,10 +62,6 @@ #include #include -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - #include "cairo.h" #include "cairo-debug.h" #include @@ -128,6 +124,12 @@ #define __attribute__(x) #endif +#if defined(__GNUC__) +#define INLINE __inline__ +#else +#define INLINE +#endif + #if HAVE_PTHREAD_H # include # define CAIRO_MUTEX_DECLARE(name) static pthread_mutex_t name = PTHREAD_MUTEX_INITIALIZER @@ -136,15 +138,31 @@ # define CAIRO_MUTEX_UNLOCK(name) pthread_mutex_unlock (&name) #endif +#if !defined(CAIRO_MUTEX_DECLARE) && defined CAIRO_HAS_WIN32_SURFACE +# define WIN32_LEAN_AND_MEAN +# include + /* the real initialization must take place in DllMain */ +# define CAIRO_MUTEX_DECLARE(name) extern CRITICAL_SECTION name; +# define CAIRO_MUTEX_DECLARE_GLOBAL(name) extern LPCRITICAL_SECTION name; +# define CAIRO_MUTEX_LOCK(name) EnterCriticalSection (&name) +# define CAIRO_MUTEX_UNLOCK(name) LeaveCriticalSection (&name) +#endif + #ifndef CAIRO_MUTEX_DECLARE -/*# warning "No mutex declarations, assuming single-threaded code" */ +#if 0 +# error "No mutex declarations. Cairo will not work with multiple threads." \ + "(Remove this #error directive to acknowledge & accept this limitation)." +#endif # define CAIRO_MUTEX_DECLARE(name) # define CAIRO_MUTEX_DECLARE_GLOBAL(name) # define CAIRO_MUTEX_LOCK(name) # define CAIRO_MUTEX_UNLOCK(name) #endif +#undef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) + +#undef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #ifndef FALSE @@ -176,8 +194,10 @@ typedef cairo_fixed_16_16_t cairo_fixed_t; #define CAIRO_MINSHORT SHRT_MIN #define CAIRO_ALPHA_IS_OPAQUE(alpha) ((alpha) >= ((double)0xff00 / (double)0xffff)) +#define CAIRO_ALPHA_IS_ZERO(alpha) ((alpha) <= 0.0) #include "cairo-hash-private.h" +#include "cairo-cache-private.h" typedef struct _cairo_point { cairo_fixed_t x; @@ -221,7 +241,8 @@ typedef struct _cairo_rectangle { typedef enum cairo_int_status { CAIRO_INT_STATUS_DEGENERATE = 1000, CAIRO_INT_STATUS_UNSUPPORTED, - CAIRO_INT_STATUS_NOTHING_TO_DO + CAIRO_INT_STATUS_NOTHING_TO_DO, + CAIRO_INT_STATUS_CACHE_EMPTY } cairo_int_status_t; typedef enum cairo_direction { @@ -282,6 +303,8 @@ typedef struct _cairo_pen { typedef struct _cairo_color cairo_color_t; typedef struct _cairo_image_surface cairo_image_surface_t; +typedef struct _cairo_surface_backend cairo_surface_backend_t; + cairo_private void _cairo_box_round_to_rectangle (cairo_box_t *box, cairo_rectangle_t *rectangle); @@ -342,108 +365,9 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array, void *user_data, cairo_destroy_func_t destroy); -/* cairo_cache.c structures and functions */ - -typedef struct _cairo_cache_backend { - - unsigned long (*hash) (void *cache, - void *key); - - int (*keys_equal) (void *cache, - void *k1, - void *k2); - - cairo_status_t (*create_entry) (void *cache, - void *key, - void **entry_return); - - void (*destroy_entry) (void *cache, - void *entry); - - void (*destroy_cache) (void *cache); - -} cairo_cache_backend_t; - -/* - * The cairo_cache system makes the following assumptions about - * entries in its cache: - * - * - a pointer to an entry can be cast to a cairo_cache_entry_base_t. - * - a pointer to an entry can also be cast to the "key type". - * - * The practical effect of this is that your entries must be laid - * out this way: - * - * struct my_entry { - * cairo_cache_entry_base_t; - * my_key_value_1; - * my_key_value_2; - * ... - * my_value; - * }; - */ - -typedef struct { - unsigned long memory; - unsigned long hashcode; -} cairo_cache_entry_base_t; - -typedef struct { - unsigned long high_water_mark; - unsigned long size; - unsigned long rehash; -} cairo_cache_arrangement_t; - -#undef CAIRO_MEASURE_CACHE_PERFORMANCE - -typedef struct { - const cairo_cache_backend_t *backend; - const cairo_cache_arrangement_t *arrangement; - cairo_cache_entry_base_t **entries; - - unsigned long max_memory; - unsigned long used_memory; - unsigned long live_entries; - -#ifdef CAIRO_MEASURE_CACHE_PERFORMANCE - unsigned long hits; - unsigned long misses; - unsigned long probes; -#endif -} cairo_cache_t; - -cairo_private cairo_status_t -_cairo_cache_init (cairo_cache_t *cache, - const cairo_cache_backend_t *backend, - unsigned long max_memory); - -cairo_private void -_cairo_cache_destroy (cairo_cache_t *cache); - -cairo_private void -_cairo_cache_shrink_to (cairo_cache_t *cache, - unsigned long max_memory); - -cairo_private cairo_status_t -_cairo_cache_lookup (cairo_cache_t *cache, - void *key, - void **entry_return, - int *created_entry); - -cairo_private cairo_status_t -_cairo_cache_remove (cairo_cache_t *cache, - void *key); - -cairo_private void * -_cairo_cache_random_entry (cairo_cache_t *cache, - int (*predicate) (void*)); - cairo_private unsigned long _cairo_hash_string (const char *c); -#define CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT 0x100000 -#define CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT 0x100000 - typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t; typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t; typedef struct _cairo_font_face_backend cairo_font_face_backend_t; @@ -465,16 +389,47 @@ struct _cairo_font_options { cairo_hint_metrics_t hint_metrics; }; +typedef struct _cairo_scaled_glyph { + cairo_cache_entry_t cache_entry; /* hash is glyph index */ + cairo_scaled_font_t *scaled_font; /* font the glyph lives in */ + cairo_text_extents_t metrics; /* user-space metrics */ + cairo_box_t bbox; /* device-space bounds */ + cairo_image_surface_t *surface; /* device-space image */ + cairo_path_fixed_t *path; /* device-space outline */ + void *surface_private; /* for the surface backend */ +} cairo_scaled_glyph_t; + +#define _cairo_scaled_glyph_index(g) ((g)->cache_entry.hash) +#define _cairo_scaled_glyph_set_index(g,i) ((g)->cache_entry.hash = (i)) + struct _cairo_scaled_font { + /* must be first to be stored in a hash table */ cairo_hash_entry_t hash_entry; + + /* useful bits for _cairo_scaled_font_nil */ cairo_status_t status; int ref_count; + + /* hash key members */ cairo_font_face_t *font_face; /* may be NULL */ cairo_matrix_t font_matrix; /* font space => user space */ cairo_matrix_t ctm; /* user space => device space */ - cairo_matrix_t scale; /* font space => device space */ cairo_font_options_t options; - + + /* "live" scaled_font members */ + cairo_matrix_t scale; /* font space => device space */ + cairo_font_extents_t extents; /* user space */ + cairo_cache_t *glyphs; /* glyph index -> cairo_scaled_glyph_t */ + + /* + * One surface backend may store data in each glyph. + * Whichever surface manages to store its pointer here + * first gets to store data in each glyph + */ + const cairo_surface_backend_t *surface_backend; + void *surface_private; + + /* font backend managing this scaled font */ const cairo_scaled_font_backend_t *backend; }; @@ -486,40 +441,6 @@ struct _cairo_font_face { const cairo_font_face_backend_t *backend; }; -/* cairo_font.c is responsible for a global glyph cache: - * - * - glyph entries: [[[base], cairo_unscaled_font_t, scale, flags, index], - * image, size, extents] - * - * Surfaces may build their own glyph caches if they have surface-specific - * glyph resources to maintain; those caches can feed off of the global - * caches if need be (eg. cairo_xlib_surface.c does this). - */ - -typedef struct { - cairo_cache_entry_base_t base; - cairo_unscaled_font_t *unscaled; - cairo_matrix_t scale; /* translation is ignored */ - int flags; - unsigned long index; -} cairo_glyph_cache_key_t; - -typedef struct { - cairo_glyph_cache_key_t key; - cairo_image_surface_t *image; - cairo_glyph_size_t size; - cairo_text_extents_t extents; -} cairo_image_glyph_cache_entry_t; - -cairo_private void -_cairo_lock_global_image_glyph_cache (void); - -cairo_private void -_cairo_unlock_global_image_glyph_cache (void); - -cairo_private cairo_cache_t * -_cairo_get_global_image_glyph_cache (void); - cairo_private void _cairo_font_reset_static_data (void); @@ -532,22 +453,10 @@ _cairo_xlib_surface_reset_static_data (void); cairo_private void _cairo_xlib_screen_reset_static_data (void); -/* Some glyph cache functions you can reuse. */ - -cairo_private unsigned long -_cairo_glyph_cache_hash (void *cache, void *key); - -cairo_private int -_cairo_glyph_cache_keys_equal (void *cache, - void *k1, - void *k2); - /* the font backend interface */ struct _cairo_unscaled_font_backend { void (*destroy) (void *unscaled_font); - cairo_status_t (*create_glyph) (void *unscaled_font, - cairo_image_glyph_cache_entry_t *entry); }; /* cairo_toy_font_face_t - simple family/slant/weight font faces used for @@ -562,6 +471,12 @@ typedef struct _cairo_toy_font_face { cairo_font_weight_t weight; } cairo_toy_font_face_t; +typedef enum _cairo_scaled_glyph_info { + CAIRO_SCALED_GLYPH_INFO_METRICS = (1 << 0), + CAIRO_SCALED_GLYPH_INFO_SURFACE = (1 << 1), + CAIRO_SCALED_GLYPH_INFO_PATH = (1 << 2) +} cairo_scaled_glyph_info_t; + struct _cairo_scaled_font_backend { cairo_status_t (*create_toy) (cairo_toy_font_face_t *toy_face, @@ -574,28 +489,26 @@ struct _cairo_scaled_font_backend { (*fini) (void *scaled_font); cairo_status_t - (*font_extents) (void *scaled_font, - cairo_font_extents_t *extents); + (*scaled_glyph_init) (void *scaled_font, + cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_glyph_info_t info); - cairo_status_t - (*text_to_glyphs) (void *scaled_font, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs); - - cairo_status_t - (*glyph_extents) (void *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents); - - cairo_status_t - (*glyph_bbox) (void *scaled_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox); - - cairo_status_t + /* A backend only needs to implement this or ucs4_to_index(), not + * both. This allows the backend to do something more sophisticated + * then just converting characters one by one. + */ + cairo_int_status_t + (*text_to_glyphs) (void *scaled_font, + double x, + double y, + const char *utf8, + cairo_glyph_t **glyphs, + int *num_glyphs); + + unsigned long + (*ucs4_to_index) (void *scaled_font, + uint32_t ucs4); + cairo_int_status_t (*show_glyphs) (void *scaled_font, cairo_operator_t operator, cairo_pattern_t *pattern, @@ -609,15 +522,6 @@ struct _cairo_scaled_font_backend { const cairo_glyph_t *glyphs, int num_glyphs); - cairo_status_t - (*glyph_path) (void *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path); - - void - (*get_glyph_cache_key) (void *scaled_font, - cairo_glyph_cache_key_t *key); }; struct _cairo_font_face_backend { @@ -654,7 +558,7 @@ extern const cairo_private struct _cairo_scaled_font_backend cairo_atsui_scaled_ #endif -typedef struct _cairo_surface_backend { +struct _cairo_surface_backend { cairo_surface_t * (*create_similar) (void *surface, cairo_content_t content, @@ -687,7 +591,7 @@ typedef struct _cairo_surface_backend { cairo_image_surface_t *image, cairo_rectangle_t *image_rect, void *image_extra); - + cairo_status_t (*clone_similar) (void *surface, cairo_surface_t *src, @@ -790,8 +694,8 @@ typedef struct _cairo_surface_backend { /* * This is an optional entry to let the surface manage its own glyph - * resources. If null, the font will be asked to render against this - * surface, using image surfaces as glyphs. + * resources. If null, render against this surface, using image + * surfaces as glyphs. */ cairo_int_status_t (*show_glyphs) (cairo_scaled_font_t *font, @@ -829,7 +733,13 @@ typedef struct _cairo_surface_backend { int width, int height); -} cairo_surface_backend_t; + void + (*scaled_font_fini) (cairo_scaled_font_t *scaled_font); + + void + (*scaled_glyph_fini) (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font); +}; typedef struct _cairo_format_masks { int bpp; @@ -849,6 +759,8 @@ struct _cairo_surface { double device_x_offset; double device_y_offset; + double device_x_scale; + double device_y_scale; /* * Each time a clip region is modified, it gets the next value in this @@ -940,7 +852,7 @@ typedef struct _cairo_solid_pattern { cairo_color_t color; } cairo_solid_pattern_t; -extern const cairo_private cairo_solid_pattern_t cairo_solid_pattern_nil; +extern const cairo_private cairo_solid_pattern_t cairo_pattern_nil; typedef struct _cairo_surface_pattern { cairo_pattern_t base; @@ -1085,6 +997,9 @@ _cairo_gstate_destroy (cairo_gstate_t *gstate); cairo_private cairo_gstate_t * _cairo_gstate_clone (cairo_gstate_t *gstate); +cairo_private void +_cairo_gstate_set_target (cairo_gstate_t *gstate, cairo_surface_t *target); + cairo_private cairo_status_t _cairo_gstate_begin_group (cairo_gstate_t *gstate); @@ -1376,63 +1291,6 @@ _cairo_unscaled_font_reference (cairo_unscaled_font_t *font); cairo_private void _cairo_unscaled_font_destroy (cairo_unscaled_font_t *font); -cairo_private void -_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - const cairo_scaled_font_backend_t *backend); - -void -_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font); - -cairo_private cairo_status_t -_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font, - cairo_font_extents_t *extents); - -cairo_private cairo_status_t -_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs); - -cairo_private cairo_status_t -_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_text_extents_t *extents); - -cairo_private cairo_status_t -_cairo_scaled_font_glyph_bbox (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox); - -cairo_private cairo_status_t -_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, - cairo_operator_t operator, - cairo_pattern_t *source, - cairo_surface_t *surface, - int source_x, - int source_y, - int dest_x, - int dest_y, - unsigned int width, - unsigned int height, - cairo_glyph_t *glyphs, - int num_glyphs); - -cairo_private cairo_status_t -_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_path_fixed_t *path); - -cairo_private cairo_status_t -_cairo_scaled_font_get_glyph_cache_key (cairo_scaled_font_t *scaled_font, - cairo_glyph_cache_key_t *key); - /* cairo-font-options.c */ cairo_private void @@ -1450,9 +1308,15 @@ cairo_private cairo_status_t _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, cairo_path_fixed_t *other); +cairo_path_fixed_t * +_cairo_path_fixed_create (void); + cairo_private void _cairo_path_fixed_fini (cairo_path_fixed_t *path); +void +_cairo_path_fixed_destroy (cairo_path_fixed_t *path); + cairo_private cairo_status_t _cairo_path_fixed_move_to (cairo_path_fixed_t *path, cairo_fixed_t x, @@ -1537,6 +1401,91 @@ _cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path, cairo_gstate_t *gstate, cairo_traps_t *traps); +/* cairo-scaled-font.c */ + +cairo_private cairo_status_t +_cairo_scaled_font_init (cairo_scaled_font_t *scaled_font, + cairo_font_face_t *font_face, + const cairo_matrix_t *font_matrix, + const cairo_matrix_t *ctm, + const cairo_font_options_t *options, + const cairo_scaled_font_backend_t *backend); + +cairo_private void +_cairo_scaled_font_set_metrics (cairo_scaled_font_t *scaled_font, + cairo_font_extents_t *fs_metrics); + +cairo_private void +_cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font); + +cairo_private cairo_status_t +_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font, + cairo_font_extents_t *extents); + +cairo_private cairo_status_t +_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, + double x, + double y, + const char *utf8, + cairo_glyph_t **glyphs, + int *num_glyphs); + +cairo_private cairo_status_t +_cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_text_extents_t *extents); + +cairo_private cairo_status_t +_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_rectangle_t *extents); + +cairo_private cairo_status_t +_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, + cairo_operator_t operator, + cairo_pattern_t *source, + cairo_surface_t *surface, + int source_x, + int source_y, + int dest_x, + int dest_y, + unsigned int width, + unsigned int height, + cairo_glyph_t *glyphs, + int num_glyphs); + +cairo_private cairo_status_t +_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font, + cairo_glyph_t *glyphs, + int num_glyphs, + cairo_path_fixed_t *path); + +cairo_private void +_cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_text_extents_t *fs_metrics); + +cairo_private void +_cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_image_surface_t *surface); + +cairo_private void +_cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph, + cairo_scaled_font_t *scaled_font, + cairo_path_fixed_t *path); + +cairo_status_t +_cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font, + unsigned long index, + cairo_scaled_glyph_info_t info, + cairo_scaled_glyph_t **scaled_glyph_ret); + +cairo_private void +_cairo_scaled_font_map_destroy (void); + /* cairo-surface.c */ extern const cairo_private cairo_surface_t _cairo_surface_nil; @@ -1741,6 +1690,15 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst, /* cairo_image_surface.c */ +#define CAIRO_FORMAT_VALID(format) ((format) >= CAIRO_FORMAT_ARGB32 && \ + (format) <= CAIRO_FORMAT_A1) + +#define CAIRO_CONTENT_VALID(content) ((content) && \ + (((content) & ~(CAIRO_CONTENT_COLOR | \ + CAIRO_CONTENT_ALPHA | \ + CAIRO_CONTENT_COLOR_ALPHA))\ + == 0)) + cairo_private cairo_format_t _cairo_format_from_content (cairo_content_t content); @@ -1851,10 +1809,6 @@ _cairo_matrix_transform_bounding_box (const cairo_matrix_t *matrix, cairo_private void _cairo_matrix_compute_determinant (const cairo_matrix_t *matrix, double *det); -cairo_private void -_cairo_matrix_compute_eigen_values (const cairo_matrix_t *matrix, - double *lambda1, double *lambda2); - cairo_private cairo_status_t _cairo_matrix_compute_scale_factors (const cairo_matrix_t *matrix, double *sx, double *sy, int x_major); @@ -1863,6 +1817,9 @@ cairo_private cairo_bool_t _cairo_matrix_is_integer_translation(const cairo_matrix_t *matrix, int *itx, int *ity); +cairo_private double +_cairo_matrix_transformed_circle_major_axis(cairo_matrix_t *matrix, double radius); + /* cairo_traps.c */ cairo_private void _cairo_traps_init (cairo_traps_t *traps); diff --git a/gfx/cairo/glitz/src/Makefile.in b/gfx/cairo/glitz/src/Makefile.in index 223daa206aa..2c4b2dc2e81 100644 --- a/gfx/cairo/glitz/src/Makefile.in +++ b/gfx/cairo/glitz/src/Makefile.in @@ -42,6 +42,8 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk +VISIBILITY_FLAGS = + MODULE = glitz LIBRARY_NAME = mozglitz LIBXUL_LIBRARY = 1 diff --git a/gfx/cairo/glitz/src/agl/glitz-agl.h b/gfx/cairo/glitz/src/agl/glitz-agl.h index 7bc6031c039..afbdf4181e8 100644 --- a/gfx/cairo/glitz/src/agl/glitz-agl.h +++ b/gfx/cairo/glitz/src/agl/glitz-agl.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -42,28 +42,28 @@ glitz_agl_init (void); void glitz_agl_fini (void); - - + + /* glitz_agl_format.c */ glitz_drawable_format_t * glitz_agl_find_drawable_format (unsigned long mask, - const glitz_drawable_format_t *templ, - int count); - + const glitz_drawable_format_t *templ, + int count); + /* glitz_agl_drawable.c */ glitz_drawable_t * glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format, - WindowRef window, - unsigned int width, - unsigned int height); + WindowRef window, + unsigned int width, + unsigned int height); glitz_drawable_t * glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + unsigned int width, + unsigned int height); #if defined(__cplusplus) || defined(c_plusplus) diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_context.c b/gfx/cairo/glitz/src/agl/glitz_agl_context.c index f917dca375c..f6491d673c6 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_context.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_context.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -34,439 +34,479 @@ extern glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address; static CFBundleRef _glitz_agl_get_bundle (const char *name) { - CFBundleRef bundle = 0; - FSRefParam ref_param; - unsigned char framework_name[256]; + CFBundleRef bundle = 0; + FSRefParam ref_param; + unsigned char framework_name[256]; - framework_name[0] = strlen (name); - strcpy (&framework_name[1], name); - - memset (&ref_param, 0, sizeof (ref_param)); + framework_name[0] = strlen (name); + strcpy (&framework_name[1], name); - if (FindFolder (kSystemDomain, - kFrameworksFolderType, - kDontCreateFolder, - &ref_param.ioVRefNum, - &ref_param.ioDirID) == noErr) { - FSRef ref; + memset (&ref_param, 0, sizeof (ref_param)); - memset (&ref, 0, sizeof (ref)); + if (FindFolder (kSystemDomain, + kFrameworksFolderType, + kDontCreateFolder, + &ref_param.ioVRefNum, + &ref_param.ioDirID) == noErr) { + FSRef ref; - ref_param.ioNamePtr = framework_name; - ref_param.newRef = &ref; + memset (&ref, 0, sizeof (ref)); - if (PBMakeFSRefSync (&ref_param) == noErr) { - CFURLRef url; + ref_param.ioNamePtr = framework_name; + ref_param.newRef = &ref; - url = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref); - if (url) { - bundle = CFBundleCreate (kCFAllocatorDefault, url); - CFRelease (url); + if (PBMakeFSRefSync (&ref_param) == noErr) { + CFURLRef url; - if (!CFBundleLoadExecutable (bundle)) { - CFRelease (bundle); - return (CFBundleRef) 0; - } - } + url = CFURLCreateFromFSRef (kCFAllocatorDefault, &ref); + if (url) { + bundle = CFBundleCreate (kCFAllocatorDefault, url); + CFRelease (url); + + if (!CFBundleLoadExecutable (bundle)) { + CFRelease (bundle); + return (CFBundleRef) 0; + } + } + } } - } - - return bundle; + + return bundle; } static void _glitz_agl_release_bundle (CFBundleRef bundle) { - if (bundle) { - CFBundleUnloadExecutable (bundle); - CFRelease (bundle); - } + if (bundle) { + CFBundleUnloadExecutable (bundle); + CFRelease (bundle); + } } +static void +_glitz_agl_notify_dummy (void *abstract_drawable, + glitz_surface_t *surface) {} + static glitz_function_pointer_t _glitz_agl_get_proc_address (const char *name, void *closure) { - glitz_function_pointer_t address = NULL; - CFBundleRef bundle = (CFBundleRef) closure; - CFStringRef str; - - if (bundle) { - str = CFStringCreateWithCString (kCFAllocatorDefault, name, - kCFStringEncodingMacRoman); + glitz_function_pointer_t address = NULL; + CFBundleRef bundle = (CFBundleRef) closure; + CFStringRef str; - address = CFBundleGetFunctionPointerForName (bundle, str); + if (bundle) { + str = CFStringCreateWithCString (kCFAllocatorDefault, name, + kCFStringEncodingMacRoman); - CFRelease (str); - } - - return address; + address = CFBundleGetFunctionPointerForName (bundle, str); + + CFRelease (str); + } + + return address; } static glitz_context_t * _glitz_agl_create_context (void *abstract_drawable, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; - glitz_agl_thread_info_t *thread_info = drawable->thread_info; - glitz_agl_context_t *context; - - context = malloc (sizeof (glitz_agl_context_t)); - if (!context) - return NULL; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; + glitz_agl_thread_info_t *thread_info = drawable->thread_info; + glitz_agl_context_t *context; - context->context = - aglCreateContext (thread_info->pixel_formats[format->id], - thread_info->root_context); - - _glitz_context_init (&context->base, &drawable->base); + context = malloc (sizeof (glitz_agl_context_t)); + if (!context) + return NULL; - context->pbuffer = 0; + context->context = + aglCreateContext (thread_info->pixel_formats[format->id], + thread_info->root_context); - return (glitz_context_t *) context; + _glitz_context_init (&context->base, &drawable->base); + + context->pbuffer = 0; + + return (glitz_context_t *) context; } static void _glitz_agl_context_destroy (void *abstract_context) { - glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) - context->base.drawable; + glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + context->base.drawable; - if (drawable->thread_info->cctx == &context->base) - { - aglSetCurrentContext (NULL); + if (drawable->thread_info->cctx == &context->base) + { + aglSetCurrentContext (NULL); - drawable->thread_info->cctx = NULL; - } + drawable->thread_info->cctx = NULL; + } - aglDestroyContext (context->context); + aglDestroyContext (context->context); - _glitz_context_fini (&context->base); - - free (context); + _glitz_context_fini (&context->base); + + free (context); } static void _glitz_agl_copy_context (void *abstract_src, - void *abstract_dst, - unsigned long mask) + void *abstract_dst, + unsigned long mask) { - glitz_agl_context_t *src = (glitz_agl_context_t *) abstract_src; - glitz_agl_context_t *dst = (glitz_agl_context_t *) abstract_dst; + glitz_agl_context_t *src = (glitz_agl_context_t *) abstract_src; + glitz_agl_context_t *dst = (glitz_agl_context_t *) abstract_dst; - aglCopyContext (src->context, dst->context, mask); + aglCopyContext (src->context, dst->context, mask); } static void -_glitz_agl_make_current (void *abstract_context, - void *abstract_drawable) +_glitz_agl_make_current (void *abstract_drawable, + void *abstract_context) { - glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; - int update = 0; - - if (aglGetCurrentContext () != context->context) - { - update = 1; - } - else - { - if (drawable->pbuffer) - { - AGLPbuffer pbuffer; - GLuint unused; + glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; + int update = 0; - aglGetPBuffer (context->context, &pbuffer, - &unused, &unused, &unused); - - if (pbuffer != drawable->pbuffer) - update = 1; - - } - else if (drawable->drawable) - { - if (aglGetDrawable (context->context) != drawable->drawable) - update = 1; - } - } - - if (update) - { - if (drawable->thread_info->cctx) - { - glitz_context_t *ctx = drawable->thread_info->cctx; + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_agl_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); - if (ctx->lose_current) - ctx->lose_current (ctx->closure); - } - - if (drawable->pbuffer) { - aglSetPBuffer (context->context, drawable->pbuffer, 0, 0, - aglGetVirtualScreen (context->context)); - context->pbuffer = 1; - } - else - { - if (context->pbuffer) { - aglSetDrawable (context->context, NULL); - context->pbuffer = 0; - } - aglSetDrawable (context->context, drawable->drawable); - } - - aglSetCurrentContext (context->context); - } - - drawable->thread_info->cctx = &context->base; + if (aglGetCurrentContext () != context->context) + { + update = 1; + } + else + { + if (drawable->pbuffer) + { + AGLPbuffer pbuffer; + GLuint unused; + + aglGetPBuffer (context->context, &pbuffer, + &unused, &unused, &unused); + + if (pbuffer != drawable->pbuffer) + update = 1; + + } + else if (drawable->drawable) + { + if (aglGetDrawable (context->context) != drawable->drawable) + update = 1; + } + } + + if (update) + { + if (drawable->thread_info->cctx) + { + glitz_context_t *ctx = drawable->thread_info->cctx; + + if (ctx->lose_current) + ctx->lose_current (ctx->closure); + } + + if (drawable->pbuffer) { + aglSetPBuffer (context->context, drawable->pbuffer, 0, 0, + aglGetVirtualScreen (context->context)); + context->pbuffer = 1; + } + else + { + if (context->pbuffer) { + aglSetDrawable (context->context, NULL); + context->pbuffer = 0; + } + aglSetDrawable (context->context, drawable->drawable); + } + + aglSetCurrentContext (context->context); + } + + drawable->thread_info->cctx = &context->base; } static glitz_function_pointer_t _glitz_agl_context_get_proc_address (void *abstract_context, - const char *name) + const char *name) { - glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) - context->base.drawable; - glitz_function_pointer_t func; - CFBundleRef bundle; + glitz_agl_context_t *context = (glitz_agl_context_t *) abstract_context; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + context->base.drawable; + glitz_function_pointer_t func; + CFBundleRef bundle; - _glitz_agl_make_current (context, drawable); + _glitz_agl_make_current (drawable, context, NULL); - bundle = _glitz_agl_get_bundle ("OpenGL.framework"); + bundle = _glitz_agl_get_bundle ("OpenGL.framework"); - func = _glitz_agl_get_proc_address (name, (void *) bundle); + func = _glitz_agl_get_proc_address (name, (void *) bundle); - _glitz_agl_release_bundle (bundle); + _glitz_agl_release_bundle (bundle); - return func; + return func; } glitz_agl_context_t * glitz_agl_context_get (glitz_agl_thread_info_t *thread_info, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_agl_context_t *context; - glitz_agl_context_t **contexts = thread_info->contexts; - int index, n_contexts = thread_info->n_contexts; + glitz_agl_context_t *context; + glitz_agl_context_t **contexts = thread_info->contexts; + int index, n_contexts = thread_info->n_contexts; - for (; n_contexts; n_contexts--, contexts++) - if ((*contexts)->id == format->id) - return *contexts; - - index = thread_info->n_contexts++; + for (; n_contexts; n_contexts--, contexts++) + if ((*contexts)->id == format->id) + return *contexts; - thread_info->contexts = - realloc (thread_info->contexts, - sizeof (glitz_agl_context_t *) * thread_info->n_contexts); - if (!thread_info->contexts) - return NULL; + index = thread_info->n_contexts++; - context = malloc (sizeof (glitz_agl_context_t)); - if (!context) - return NULL; - - thread_info->contexts[index] = context; + thread_info->contexts = + realloc (thread_info->contexts, + sizeof (glitz_agl_context_t *) * thread_info->n_contexts); + if (!thread_info->contexts) + return NULL; - context->context = - aglCreateContext (thread_info->pixel_formats[format->id], - thread_info->root_context); - if (!context->context) { - free (context); - return NULL; - } - - context->id = format->id; - context->pbuffer = 0; + context = malloc (sizeof (glitz_agl_context_t)); + if (!context) + return NULL; - if (!thread_info->root_context) - thread_info->root_context = context->context; + thread_info->contexts[index] = context; - memcpy (&context->backend.gl, - &_glitz_agl_gl_proc_address, - sizeof (glitz_gl_proc_address_list_t)); + context->context = + aglCreateContext (thread_info->pixel_formats[format->id], + thread_info->root_context); + if (!context->context) { + free (context); + return NULL; + } - context->backend.create_pbuffer = glitz_agl_create_pbuffer; - context->backend.destroy = glitz_agl_destroy; - context->backend.push_current = glitz_agl_push_current; - context->backend.pop_current = glitz_agl_pop_current; - context->backend.swap_buffers = glitz_agl_swap_buffers; + context->id = format->id; + context->pbuffer = 0; - context->backend.create_context = _glitz_agl_create_context; - context->backend.destroy_context = _glitz_agl_context_destroy; - context->backend.copy_context = _glitz_agl_copy_context; - context->backend.make_current = _glitz_agl_make_current; - context->backend.get_proc_address = _glitz_agl_context_get_proc_address; - - context->backend.drawable_formats = thread_info->formats; - context->backend.n_drawable_formats = thread_info->n_formats; + if (!thread_info->root_context) + thread_info->root_context = context->context; - context->backend.texture_formats = NULL; - context->backend.formats = NULL; - context->backend.n_formats = 0; - - context->backend.program_map = &thread_info->program_map; - context->backend.feature_mask = 0; + context->backend.gl = &_glitz_agl_gl_proc_address; - context->initialized = 0; - - return context; + context->backend.create_pbuffer = glitz_agl_create_pbuffer; + context->backend.destroy = glitz_agl_destroy; + context->backend.push_current = glitz_agl_push_current; + context->backend.pop_current = glitz_agl_pop_current; + context->backend.attach_notify = _glitz_agl_notify_dummy; + context->backend.detach_notify = _glitz_agl_notify_dummy; + context->backend.swap_buffers = glitz_agl_swap_buffers; + + context->backend.create_context = _glitz_agl_create_context; + context->backend.destroy_context = _glitz_agl_context_destroy; + context->backend.copy_context = _glitz_agl_copy_context; + context->backend.make_current = _glitz_agl_make_current; + context->backend.get_proc_address = _glitz_agl_context_get_proc_address; + + context->backend.drawable_formats = NULL; + context->backend.n_drawable_formats = 0; + + if (screen_info->n_formats) + { + int size; + + size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats; + context->backend.drawable_formats = malloc (size); + if (context->backend.drawable_formats) + { + memcpy (context->backend.drawable_formats, screen_info->formats, + size); + context->backend.n_drawable_formats = screen_info->n_formats; + } + } + + context->backend.texture_formats = NULL; + context->backend.formats = NULL; + context->backend.n_formats = 0; + + context->backend.program_map = &thread_info->program_map; + context->backend.feature_mask = 0; + + context->initialized = 0; + + return context; } void glitz_agl_context_destroy (glitz_agl_thread_info_t *thread_info, - glitz_agl_context_t *context) + glitz_agl_context_t *context) { - if (context->backend.formats) - free (context->backend.formats); + if (context->backend.drawable_formats) + free (context->backend.drawable_formats); - if (context->backend.texture_formats) - free (context->backend.texture_formats); - - aglDestroyContext (context->context); - - free (context); + if (context->backend.formats) + free (context->backend.formats); + + if (context->backend.texture_formats) + free (context->backend.texture_formats); + + aglDestroyContext (context->context); + + free (context); } static void _glitz_agl_context_initialize (glitz_agl_thread_info_t *thread_info, - glitz_agl_context_t *context) + glitz_agl_context_t *context) { - CFBundleRef bundle; - - bundle = _glitz_agl_get_bundle ("OpenGL.framework"); + CFBundleRef bundle; - glitz_backend_init (&context->backend, - _glitz_agl_get_proc_address, - (void *) bundle); + bundle = _glitz_agl_get_bundle ("OpenGL.framework"); - _glitz_agl_release_bundle (bundle); + glitz_backend_init (&context->backend, + _glitz_agl_get_proc_address, + (void *) bundle); - context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS, - context->max_viewport_dims); + _glitz_agl_release_bundle (bundle); - glitz_initiate_state (&_glitz_agl_gl_proc_address); - - context->initialized = 1; + glitz_initiate_state (&_glitz_agl_gl_proc_address); + + context->initialized = 1; } static void _glitz_agl_context_make_current (glitz_agl_drawable_t *drawable, - glitz_bool_t finish) + glitz_bool_t finish) { - if (finish) - glFinish (); + if (finish) + glFinish (); - if (drawable->thread_info->cctx) - { - glitz_context_t *ctx = drawable->thread_info->cctx; + if (drawable->thread_info->cctx) + { + glitz_context_t *ctx = drawable->thread_info->cctx; - if (ctx->lose_current) - ctx->lose_current (ctx->closure); + if (ctx->lose_current) + ctx->lose_current (ctx->closure); - drawable->thread_info->cctx = NULL; - } - - if (drawable->pbuffer) { - aglSetPBuffer (drawable->context->context, drawable->pbuffer, 0, 0, - aglGetVirtualScreen (drawable->context->context)); - drawable->context->pbuffer = 1; - } else { - if (drawable->context->pbuffer) { - aglSetDrawable (drawable->context->context, NULL); - drawable->context->pbuffer = 0; + drawable->thread_info->cctx = NULL; } - - aglSetDrawable (drawable->context->context, drawable->drawable); - } - aglSetCurrentContext (drawable->context->context); + if (drawable->pbuffer) { + aglSetPBuffer (drawable->context->context, drawable->pbuffer, 0, 0, + aglGetVirtualScreen (drawable->context->context)); + drawable->context->pbuffer = 1; + } else { + if (drawable->context->pbuffer) { + aglSetDrawable (drawable->context->context, NULL); + drawable->context->pbuffer = 0; + } - drawable->base.update_all = 1; - - if (!drawable->context->initialized) - _glitz_agl_context_initialize (drawable->thread_info, drawable->context); + aglSetDrawable (drawable->context->context, drawable->drawable); + } + + aglSetCurrentContext (drawable->context->context); + + drawable->base.update_all = 1; + + if (!drawable->context->initialized) + _glitz_agl_context_initialize (drawable->thread_info, + drawable->context); } static void _glitz_agl_context_update (glitz_agl_drawable_t *drawable, - glitz_constraint_t constraint) + glitz_constraint_t constraint) { - AGLContext context; + AGLContext context; - switch (constraint) { - case GLITZ_NONE: - break; - case GLITZ_ANY_CONTEXT_CURRENT: - context = aglGetCurrentContext (); - if (context == (AGLContext) 0) - _glitz_agl_context_make_current (drawable, 0); - break; - case GLITZ_CONTEXT_CURRENT: - context = aglGetCurrentContext (); - if (context != drawable->context->context) - _glitz_agl_context_make_current (drawable, (context)? 1: 0); - break; - case GLITZ_DRAWABLE_CURRENT: - context = aglGetCurrentContext (); - if (context != drawable->context->context) { - _glitz_agl_context_make_current (drawable, (context)? 1: 0); - } else { - if (drawable->pbuffer) { - AGLPbuffer pbuffer; - GLuint unused; + switch (constraint) { + case GLITZ_NONE: + break; + case GLITZ_ANY_CONTEXT_CURRENT: + context = aglGetCurrentContext (); + if (context == (AGLContext) 0) + _glitz_agl_context_make_current (drawable, 0); + break; + case GLITZ_CONTEXT_CURRENT: + context = aglGetCurrentContext (); + if (context != drawable->context->context) + _glitz_agl_context_make_current (drawable, (context)? 1: 0); + break; + case GLITZ_DRAWABLE_CURRENT: + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_agl_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); - aglGetPBuffer (drawable->context->context, &pbuffer, - &unused, &unused, &unused); - - if (pbuffer != drawable->pbuffer) - _glitz_agl_context_make_current (drawable, (context)? 1: 0); - - } else if (drawable->drawable) { - if (aglGetDrawable (drawable->context->context) != drawable->drawable) - _glitz_agl_context_make_current (drawable, (context)? 1: 0); - } + context = aglGetCurrentContext (); + if (context != drawable->context->context) { + _glitz_agl_context_make_current (drawable, (context)? 1: 0); + } else { + if (drawable->pbuffer) { + AGLPbuffer pbuffer; + GLuint unused; + + aglGetPBuffer (drawable->context->context, &pbuffer, + &unused, &unused, &unused); + + if (pbuffer != drawable->pbuffer) + _glitz_agl_context_make_current (drawable, + (context)? 1: 0); + + } else if (drawable->drawable) { + if (aglGetDrawable (drawable->context->context) != + drawable->drawable) + _glitz_agl_context_make_current (drawable, + (context)? 1: 0); + } + } + break; } - break; - } } -void +glitz_bool_t glitz_agl_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint) + glitz_surface_t *surface, + glitz_constraint_t constraint) { - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; - glitz_agl_context_info_t *context_info; - int index; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; + glitz_agl_context_info_t *context_info; + int index; - index = drawable->thread_info->context_stack_size++; + index = drawable->thread_info->context_stack_size++; - context_info = &drawable->thread_info->context_stack[index]; - context_info->drawable = drawable; - context_info->surface = surface; - context_info->constraint = constraint; - - _glitz_agl_context_update (context_info->drawable, constraint); + context_info = &drawable->thread_info->context_stack[index]; + context_info->drawable = drawable; + context_info->surface = surface; + context_info->constraint = constraint; + + _glitz_agl_context_update (context_info->drawable, constraint); + + return 1; } glitz_surface_t * glitz_agl_pop_current (void *abstract_drawable) { - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; - glitz_agl_context_info_t *context_info = NULL; - int index; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; + glitz_agl_context_info_t *context_info = NULL; + int index; - drawable->thread_info->context_stack_size--; - index = drawable->thread_info->context_stack_size - 1; + drawable->thread_info->context_stack_size--; + index = drawable->thread_info->context_stack_size - 1; - context_info = &drawable->thread_info->context_stack[index]; + context_info = &drawable->thread_info->context_stack[index]; - if (context_info->drawable) - _glitz_agl_context_update (context_info->drawable, - context_info->constraint); - - if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) - return context_info->surface; - - return NULL; + if (context_info->drawable) + _glitz_agl_context_update (context_info->drawable, + context_info->constraint); + + if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) + return context_info->surface; + + return NULL; } diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_drawable.c b/gfx/cairo/glitz/src/agl/glitz_agl_drawable.c index ada714a6d4a..d2fe8261676 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_drawable.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_drawable.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,189 +31,222 @@ static glitz_agl_drawable_t * _glitz_agl_create_drawable (glitz_agl_thread_info_t *thread_info, - glitz_agl_context_t *context, - glitz_drawable_format_t *format, - AGLDrawable agl_drawable, - AGLPbuffer agl_pbuffer, - unsigned int width, - unsigned int height) + glitz_agl_context_t *context, + glitz_drawable_format_t *format, + AGLDrawable agl_drawable, + AGLPbuffer agl_pbuffer, + unsigned int width, + unsigned int height) { - glitz_agl_drawable_t *drawable; - - if (width <= 0 || height <= 0) - return NULL; + glitz_agl_drawable_t *drawable; - drawable = (glitz_agl_drawable_t *) malloc (sizeof (glitz_agl_drawable_t)); - if (drawable == NULL) - return NULL; + drawable = (glitz_agl_drawable_t *) malloc (sizeof (glitz_agl_drawable_t)); + if (drawable == NULL) + return NULL; - drawable->base.ref_count = 1; - drawable->thread_info = thread_info; - drawable->context = context; - drawable->drawable = agl_drawable; - drawable->pbuffer = agl_pbuffer; - drawable->base.format = format; - drawable->base.backend = &context->backend; + drawable->thread_info = thread_info; + drawable->context = context; + drawable->drawable = agl_drawable; + drawable->pbuffer = agl_pbuffer; + drawable->width = width; + drawable->height = height; - glitz_drawable_update_size (&drawable->base, width, height); - - if (!context->initialized) { - glitz_agl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT); - glitz_agl_pop_current (drawable); - } - - if (width > context->max_viewport_dims[0] || - height > context->max_viewport_dims[1]) { - free (drawable); - return NULL; - } + _glitz_drawable_init (&drawable->base, + format, + &context->backend, + width, height); - thread_info->drawables++; - - return drawable; + if (!context->initialized) { + glitz_agl_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT); + glitz_agl_pop_current (drawable); + } + + if (width > context->backend.max_viewport_dims[0] || + height > context->backend.max_viewport_dims[1]) { + free (drawable); + return NULL; + } + + thread_info->drawables++; + + return drawable; +} + +glitz_bool_t +_glitz_agl_drawable_update_size (glitz_agl_drawable_t *drawable, + int width, + int height) +{ + if (drawable->pbuffer) + { + glitz_agl_pbuffer_destroy (drawable->thread_info, drawable->pbuffer); + drawable->pbuffer = + glitz_agl_pbuffer_create (drawable->thread_info, + drawable->context->fbconfig, + (int) width, (int) height); + if (!drawable->pbuffer) + return 0; + } + + drawable->width = width; + drawable->height = height; + + return 1; } static glitz_drawable_t * _glitz_agl_create_pbuffer_drawable (glitz_agl_thread_info_t *thread_info, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_agl_drawable_t *drawable; - glitz_agl_context_t *context; - AGLPbuffer pbuffer; + glitz_agl_drawable_t *drawable; + glitz_agl_context_t *context; + AGLPbuffer pbuffer; - if (!format->types.pbuffer) - return NULL; - - context = glitz_agl_context_get (thread_info, format); - if (!context) - return NULL; + if (!format->types.pbuffer) + return NULL; - pbuffer = glitz_agl_pbuffer_create (thread_info, (int) width, (int) height); - if (!pbuffer) - return NULL; - - drawable = _glitz_agl_create_drawable (thread_info, context, format, - (AGLDrawable) 0, pbuffer, - width, height); - if (!drawable) { - glitz_agl_pbuffer_destroy (pbuffer); - return NULL; - } - - return &drawable->base; + context = glitz_agl_context_get (thread_info, format); + if (!context) + return NULL; + + pbuffer = glitz_agl_pbuffer_create (thread_info, + (int) width, (int) height); + if (!pbuffer) + return NULL; + + drawable = _glitz_agl_create_drawable (thread_info, context, format, + (AGLDrawable) 0, pbuffer, + width, height); + if (!drawable) { + glitz_agl_pbuffer_destroy (pbuffer); + return NULL; + } + + return &drawable->base; } glitz_drawable_t * glitz_agl_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_agl_drawable_t *templ = (glitz_agl_drawable_t *) abstract_templ; + glitz_agl_drawable_t *templ = (glitz_agl_drawable_t *) abstract_templ; - return _glitz_agl_create_pbuffer_drawable (templ->thread_info, format, - width, height); + return _glitz_agl_create_pbuffer_drawable (templ->thread_info, format, + width, height); } glitz_drawable_t * glitz_agl_create_drawable_for_window (glitz_drawable_format_t *format, - WindowRef window, - unsigned int width, - unsigned int height) + WindowRef window, + unsigned int width, + unsigned int height) { - glitz_agl_drawable_t *drawable; - glitz_agl_thread_info_t *thread_info; - glitz_agl_context_t *context; - AGLDrawable agl_drawable; + glitz_agl_drawable_t *drawable; + glitz_agl_thread_info_t *thread_info; + glitz_agl_context_t *context; + AGLDrawable agl_drawable; - agl_drawable = (AGLDrawable) GetWindowPort (window); - if (!agl_drawable) - return NULL; + agl_drawable = (AGLDrawable) GetWindowPort (window); + if (!agl_drawable) + return NULL; - thread_info = glitz_agl_thread_info_get (); - if (!thread_info) - return NULL; + thread_info = glitz_agl_thread_info_get (); + if (!thread_info) + return NULL; - context = glitz_agl_context_get (thread_info, format); - if (!context) - return NULL; + if (format->id >= screen_info->n_formats) + return NULL; - drawable = _glitz_agl_create_drawable (thread_info, context, format, - agl_drawable, (AGLPbuffer) 0, - width, height); - if (!drawable) - return NULL; + context = glitz_agl_context_get (thread_info, format); + if (!context) + return NULL; - return &drawable->base; + drawable = _glitz_agl_create_drawable (thread_info, context, format, + agl_drawable, (AGLPbuffer) 0, + width, height); + if (!drawable) + return NULL; + + return &drawable->base; } slim_hidden_def(glitz_agl_create_drawable_for_window); glitz_drawable_t * glitz_agl_create_pbuffer_drawable (glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + unsigned int width, + unsigned int height) { - glitz_agl_thread_info_t *thread_info; + glitz_agl_thread_info_t *thread_info; - thread_info = glitz_agl_thread_info_get (); - if (!thread_info) - return NULL; + thread_info = glitz_agl_thread_info_get (); + if (!thread_info) + return NULL; - return _glitz_agl_create_pbuffer_drawable (thread_info, format, - width, height); + if (format->id >= screen_info->n_formats) + return NULL; + + return _glitz_agl_create_pbuffer_drawable (thread_info, format, + width, height); } slim_hidden_def(glitz_agl_create_pbuffer_drawable); void glitz_agl_destroy (void *abstract_drawable) { - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; - drawable->thread_info->drawables--; - if (drawable->thread_info->drawables == 0) { - /* - * Last drawable? We have to destroy all fragment programs as this may - * be our last chance to have a context current. - */ - glitz_agl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT); - glitz_program_map_fini (&drawable->base.backend->gl, - &drawable->thread_info->program_map); - glitz_agl_pop_current (abstract_drawable); - } - - if (drawable->drawable || drawable->pbuffer) { - AGLContext context = aglGetCurrentContext (); - - if (context == drawable->context->context) { - if (drawable->pbuffer) { - AGLPbuffer pbuffer; - GLuint unused; - - aglGetPBuffer (context, &pbuffer, &unused, &unused, &unused); - - if (pbuffer == drawable->pbuffer) - aglSetCurrentContext (NULL); - } else { - if (aglGetDrawable (context) == drawable->drawable) - aglSetCurrentContext (NULL); - } + drawable->thread_info->drawables--; + if (drawable->thread_info->drawables == 0) { + /* + * Last drawable? We have to destroy all fragment programs as this may + * be our last chance to have a context current. + */ + glitz_agl_push_current (abstract_drawable, NULL, + GLITZ_CONTEXT_CURRENT); + glitz_program_map_fini (&drawable->base.backend->gl, + &drawable->thread_info->program_map); + glitz_agl_pop_current (abstract_drawable); } - - if (drawable->pbuffer) - glitz_agl_pbuffer_destroy (drawable->pbuffer); - } - - free (drawable); + + if (drawable->drawable || drawable->pbuffer) { + AGLContext context = aglGetCurrentContext (); + + if (context == drawable->context->context) { + if (drawable->pbuffer) { + AGLPbuffer pbuffer; + GLuint unused; + + aglGetPBuffer (context, &pbuffer, &unused, &unused, &unused); + + if (pbuffer == drawable->pbuffer) + aglSetCurrentContext (NULL); + } else { + if (aglGetDrawable (context) == drawable->drawable) + aglSetCurrentContext (NULL); + } + } + + if (drawable->pbuffer) + glitz_agl_pbuffer_destroy (drawable->pbuffer); + } + + free (drawable); } -void +glitz_bool_t glitz_agl_swap_buffers (void *abstract_drawable) { - glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) abstract_drawable; + glitz_agl_drawable_t *drawable = (glitz_agl_drawable_t *) + abstract_drawable; - glitz_agl_push_current (abstract_drawable, NULL, GLITZ_DRAWABLE_CURRENT); - aglSwapBuffers (drawable->context->context); - glitz_agl_pop_current (abstract_drawable); + glitz_agl_push_current (abstract_drawable, NULL, GLITZ_DRAWABLE_CURRENT); + aglSwapBuffers (drawable->context->context); + glitz_agl_pop_current (abstract_drawable); + + return 1; } diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_extension.c b/gfx/cairo/glitz/src/agl/glitz_agl_extension.c index c564be87ca3..0456ee19eb3 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_extension.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_extension.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -30,63 +30,65 @@ #include "glitz_aglint.h" static glitz_extension_map agl_extensions[] = { - { 0.0, "GL_APPLE_pixel_buffer", GLITZ_AGL_FEATURE_PBUFFER_MASK }, - { 0.0, "GL_ARB_multisample", GLITZ_AGL_FEATURE_MULTISAMPLE_MASK }, - { 0.0, "GL_ARB_texture_rectangle", - GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, "GL_EXT_texture_rectangle", - GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, "GL_NV_texture_rectangle", GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, NULL, 0 } + { 0.0, "GL_APPLE_pixel_buffer", GLITZ_AGL_FEATURE_PBUFFER_MASK }, + { 0.0, "GL_ARB_multisample", GLITZ_AGL_FEATURE_MULTISAMPLE_MASK }, + { 0.0, "GL_ARB_texture_rectangle", + GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, "GL_EXT_texture_rectangle", + GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, "GL_NV_texture_rectangle", + GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, NULL, 0 } }; glitz_status_t glitz_agl_query_extensions (glitz_agl_thread_info_t *thread_info) { - GLint attrib[] = { - AGL_RGBA, - AGL_NO_RECOVERY, - AGL_NONE - }; - AGLPixelFormat pf; - AGLContext context; + GLint attrib[] = { + AGL_RGBA, + AGL_NO_RECOVERY, + AGL_NONE + }; + AGLPixelFormat pf; + AGLContext context; - thread_info->agl_feature_mask = 0; + thread_info->agl_feature_mask = 0; - pf = aglChoosePixelFormat (NULL, 0, attrib); - context = aglCreateContext (pf, NULL); - - if (context) { - const char *gl_extensions_string; + pf = aglChoosePixelFormat (NULL, 0, attrib); + context = aglCreateContext (pf, NULL); - aglSetCurrentContext (context); - - gl_extensions_string = (const char *) glGetString (GL_EXTENSIONS); + if (context) { + const char *gl_extensions_string; - thread_info->agl_feature_mask = - glitz_extensions_query (0.0, - gl_extensions_string, - agl_extensions); + aglSetCurrentContext (context); - if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) { - const char *vendor; + gl_extensions_string = (const char *) glGetString (GL_EXTENSIONS); - vendor = glGetString (GL_VENDOR); - - if (vendor) { - - /* NVIDIA's driver seem to support multisample with pbuffers */ - if (!strncmp ("NVIDIA", vendor, 6)) - thread_info->agl_feature_mask |= - GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK; - } + thread_info->agl_feature_mask = + glitz_extensions_query (0.0, + gl_extensions_string, + agl_extensions); + + if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) + { + const char *vendor; + + vendor = glGetString (GL_VENDOR); + + if (vendor) { + + /* NVIDIA's driver seem to support multisample with pbuffers */ + if (!strncmp ("NVIDIA", vendor, 6)) + thread_info->agl_feature_mask |= + GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK; + } + } + + aglSetCurrentContext (NULL); + aglDestroyContext (context); } - aglSetCurrentContext (NULL); - aglDestroyContext (context); - } + aglDestroyPixelFormat (pf); - aglDestroyPixelFormat (pf); - - return GLITZ_STATUS_SUCCESS; + return GLITZ_STATUS_SUCCESS; } diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_format.c b/gfx/cairo/glitz/src/agl/glitz_agl_format.c index 3a10c112bb9..e66c8fbc2ab 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_format.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_format.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -33,301 +33,303 @@ #include static GLint _attribs[] = { - AGL_RGBA, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_NONE + AGL_RGBA, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_NONE }; static GLint _db_attribs[] = { - AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_NONE + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_NONE }; static GLint _stencil_attribs[] = { - AGL_RGBA, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_DEPTH_SIZE, 8, - AGL_STENCIL_SIZE, 8, - AGL_NONE + AGL_RGBA, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_DEPTH_SIZE, 8, + AGL_STENCIL_SIZE, 8, + AGL_NONE }; static GLint _db_stencil_attribs[] = { - AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_NONE + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_NONE }; static GLint _ms2_attribs[] = { - AGL_RGBA, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 2, - AGL_NONE + AGL_RGBA, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 2, + AGL_NONE }; static GLint _db_ms2_attribs[] = { - AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 2, - AGL_NONE + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 2, + AGL_NONE }; static GLint _ms4_attribs[] = { - AGL_RGBA, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 4, - AGL_NONE + AGL_RGBA, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 4, + AGL_NONE }; static GLint _db_ms4_attribs[] = { - AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 4, - AGL_NONE + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 4, + AGL_NONE }; static GLint _ms6_attribs[] = { - AGL_RGBA, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 6, - AGL_NONE + AGL_RGBA, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 6, + AGL_NONE }; static GLint _db_ms6_attribs[] = { - AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_ALPHA_SIZE, 16, - AGL_RED_SIZE, 16, - AGL_STENCIL_SIZE, 8, - AGL_SAMPLE_BUFFERS_ARB, 1, - AGL_SAMPLES_ARB, 6, - AGL_NONE + AGL_RGBA, + AGL_DOUBLEBUFFER, + AGL_ALPHA_SIZE, 16, + AGL_RED_SIZE, 16, + AGL_STENCIL_SIZE, 8, + AGL_SAMPLE_BUFFERS_ARB, 1, + AGL_SAMPLES_ARB, 6, + AGL_NONE }; static GLint *_attribs_list[] = { - _attribs, - _db_attribs, - _stencil_attribs, - _db_stencil_attribs, - _ms2_attribs, - _db_ms2_attribs, - _ms4_attribs, - _db_ms4_attribs, - _ms6_attribs, - _db_ms6_attribs + _attribs, + _db_attribs, + _stencil_attribs, + _db_stencil_attribs, + _ms2_attribs, + _db_ms2_attribs, + _ms4_attribs, + _db_ms4_attribs, + _ms6_attribs, + _db_ms6_attribs }; static int _glitz_agl_format_compare (const void *elem1, - const void *elem2) + const void *elem2) { - int i, score[2]; - glitz_drawable_format_t *format[2]; - - format[0] = (glitz_drawable_format_t *) elem1; - format[1] = (glitz_drawable_format_t *) elem2; - i = score[0] = score[1] = 0; + int i, score[2]; + glitz_drawable_format_t *format[2]; - for (; i < 2; i++) { - if (format[i]->color.red_size) { - if (format[i]->color.red_size == 8) - score[i] += 5; - score[i] += 10; + format[0] = (glitz_drawable_format_t *) elem1; + format[1] = (glitz_drawable_format_t *) elem2; + i = score[0] = score[1] = 0; + + for (; i < 2; i++) { + if (format[i]->color.red_size) { + if (format[i]->color.red_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->color.green_size) { + if (format[i]->color.green_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->color.alpha_size) { + if (format[i]->color.alpha_size == 8) + score[i] += 5; + score[i] += 10; + } + + if (format[i]->stencil_size) + score[i] += 5; + + if (format[i]->depth_size) + score[i] += 5; + + if (format[i]->doublebuffer) + score[i] += 10; + + if (format[i]->types.window) + score[i] += 10; + + if (format[i]->types.pbuffer) + score[i] += 10; + + if (format[i]->samples > 1) + score[i] -= (20 - format[i]->samples); } - if (format[i]->color.green_size) { - if (format[i]->color.green_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->color.alpha_size) { - if (format[i]->color.alpha_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->stencil_size) - score[i] += 5; - - if (format[i]->depth_size) - score[i] += 5; - - if (format[i]->doublebuffer) - score[i] += 10; - - if (format[i]->types.window) - score[i] += 10; - - if (format[i]->types.pbuffer) - score[i] += 10; - - if (format[i]->samples > 1) - score[i] -= (20 - format[i]->samples); - } - - return score[1] - score[0]; + return score[1] - score[0]; } static void _glitz_add_format (glitz_agl_thread_info_t *thread_info, - glitz_drawable_format_t *format, - AGLPixelFormat pixel_format) + glitz_drawable_format_t *format, + AGLPixelFormat pixel_format) { - if (!glitz_drawable_format_find (thread_info->formats, - thread_info->n_formats, - GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK, - format, 0)) { - int n = thread_info->n_formats; - - thread_info->formats = - realloc (thread_info->formats, - sizeof (glitz_drawable_format_t) * (n + 1)); - thread_info->pixel_formats = - realloc (thread_info->pixel_formats, - sizeof (AGLPixelFormat) * (n + 1)); + if (!glitz_drawable_format_find (thread_info->formats, + thread_info->n_formats, + GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK, + format, 0)) { + int n = thread_info->n_formats; - if (thread_info->formats && thread_info->pixel_formats) { - thread_info->formats[n] = *format; - thread_info->formats[n].id = n; - thread_info->pixel_formats[n] = pixel_format; - thread_info->n_formats++; + thread_info->formats = + realloc (thread_info->formats, + sizeof (glitz_drawable_format_t) * (n + 1)); + thread_info->pixel_formats = + realloc (thread_info->pixel_formats, + sizeof (AGLPixelFormat) * (n + 1)); + + if (thread_info->formats && thread_info->pixel_formats) { + thread_info->formats[n] = *format; + thread_info->formats[n].id = n; + thread_info->pixel_formats[n] = pixel_format; + thread_info->n_formats++; + } } - } } void glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info) { - glitz_drawable_format_t format; - AGLPixelFormat pixel_format, *new_pfs; - int n_attribs_list, i; + glitz_drawable_format_t format; + AGLPixelFormat pixel_format, *new_pfs; + int n_attribs_list, i; - format.types.window = 1; - format.id = 0; + format.types.window = 1; + format.id = 0; - n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *); + n_attribs_list = sizeof (_attribs_list) / sizeof (GLint *); - for (i = 0; i < n_attribs_list; i++) { - GLint value; - - pixel_format = aglChoosePixelFormat (NULL, 0, _attribs_list[i]); + for (i = 0; i < n_attribs_list; i++) { + GLint value; - /* Stereo is not supported yet */ - if (!(aglDescribePixelFormat (pixel_format, AGL_STEREO, &value)) || - value) { - aglDestroyPixelFormat (pixel_format); - continue; + pixel_format = aglChoosePixelFormat (NULL, 0, _attribs_list[i]); + + /* Stereo is not supported yet */ + if (!(aglDescribePixelFormat (pixel_format, AGL_STEREO, &value)) || + value) { + aglDestroyPixelFormat (pixel_format); + continue; + } + + aglDescribePixelFormat (pixel_format, AGL_DOUBLEBUFFER, &value); + format.doublebuffer = (value)? 1: 0; + + aglDescribePixelFormat (pixel_format, AGL_RED_SIZE, &value); + format.color.red_size = (unsigned short) value; + aglDescribePixelFormat (pixel_format, AGL_GREEN_SIZE, &value); + format.color.green_size = (unsigned short) value; + aglDescribePixelFormat (pixel_format, AGL_BLUE_SIZE, &value); + format.color.blue_size = (unsigned short) value; + aglDescribePixelFormat (pixel_format, AGL_ALPHA_SIZE, &value); + format.color.alpha_size = (unsigned short) value; + aglDescribePixelFormat (pixel_format, AGL_DEPTH_SIZE, &value); + format.depth_size = (unsigned short) value; + aglDescribePixelFormat (pixel_format, AGL_STENCIL_SIZE, &value); + format.stencil_size = (unsigned short) value; + + if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) + { + aglDescribePixelFormat (pixel_format, AGL_SAMPLE_BUFFERS_ARB, + &value); + if (value) { + aglDescribePixelFormat (pixel_format, AGL_SAMPLES_ARB, &value); + format.samples = (unsigned short) (value > 1)? value: 1; + } else + format.samples = 1; + } else + format.samples = 1; + + if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_PBUFFER_MASK) { + if (format.color.red_size && format.color.green_size && + format.color.blue_size && format.color.alpha_size && + format.doublebuffer == 0 && format.stencil_size == 0 && + format.depth_size == 0) { + + if (thread_info->agl_feature_mask & + GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK) + format.types.pbuffer = 1; + else if (format.samples == 1) + format.types.pbuffer = 1; + else + format.types.pbuffer = 0; + } else + format.types.pbuffer = 0; + } else + format.types.pbuffer = 0; + + if (format.color.red_size || + format.color.green_size || + format.color.blue_size || + format.color.alpha_size) + _glitz_add_format (thread_info, &format, pixel_format); } - - aglDescribePixelFormat (pixel_format, AGL_DOUBLEBUFFER, &value); - format.doublebuffer = (value)? 1: 0; - - aglDescribePixelFormat (pixel_format, AGL_RED_SIZE, &value); - format.color.red_size = (unsigned short) value; - aglDescribePixelFormat (pixel_format, AGL_GREEN_SIZE, &value); - format.color.green_size = (unsigned short) value; - aglDescribePixelFormat (pixel_format, AGL_BLUE_SIZE, &value); - format.color.blue_size = (unsigned short) value; - aglDescribePixelFormat (pixel_format, AGL_ALPHA_SIZE, &value); - format.color.alpha_size = (unsigned short) value; - aglDescribePixelFormat (pixel_format, AGL_DEPTH_SIZE, &value); - format.depth_size = (unsigned short) value; - aglDescribePixelFormat (pixel_format, AGL_STENCIL_SIZE, &value); - format.stencil_size = (unsigned short) value; - if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_MULTISAMPLE_MASK) { - aglDescribePixelFormat (pixel_format, AGL_SAMPLE_BUFFERS_ARB, &value); - if (value) { - aglDescribePixelFormat (pixel_format, AGL_SAMPLES_ARB, &value); - format.samples = (unsigned short) (value > 1)? value: 1; - } else - format.samples = 1; - } else - format.samples = 1; + if (!thread_info->n_formats) + return; - if (thread_info->agl_feature_mask & GLITZ_AGL_FEATURE_PBUFFER_MASK) { - if (format.color.red_size && format.color.green_size && - format.color.blue_size && format.color.alpha_size && - format.doublebuffer == 0 && format.stencil_size == 0 && - format.depth_size == 0) { - - if (thread_info->agl_feature_mask & - GLITZ_AGL_FEATURE_PBUFFER_MULTISAMPLE_MASK) - format.types.pbuffer = 1; - else if (format.samples == 1) - format.types.pbuffer = 1; - else - format.types.pbuffer = 0; - } else - format.types.pbuffer = 0; - } else - format.types.pbuffer = 0; + qsort (thread_info->formats, thread_info->n_formats, + sizeof (glitz_drawable_format_t), _glitz_agl_format_compare); - if (format.color.red_size || - format.color.green_size || - format.color.blue_size || - format.color.alpha_size) - _glitz_add_format (thread_info, &format, pixel_format); - } + /* + * Update AGLPixelFormat list so that it matches the sorted format list. + */ + new_pfs = malloc (sizeof (AGLPixelFormat) * thread_info->n_formats); + if (!new_pfs) { + thread_info->n_formats = 0; + return; + } - if (!thread_info->n_formats) - return; + for (i = 0; i < thread_info->n_formats; i++) { + new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].id]; + thread_info->formats[i].id = i; + } - qsort (thread_info->formats, thread_info->n_formats, - sizeof (glitz_drawable_format_t), _glitz_agl_format_compare); - - /* - * Update AGLPixelFormat list so that it matches the sorted format list. - */ - new_pfs = malloc (sizeof (AGLPixelFormat) * thread_info->n_formats); - if (!new_pfs) { - thread_info->n_formats = 0; - return; - } - - for (i = 0; i < thread_info->n_formats; i++) { - new_pfs[i] = thread_info->pixel_formats[thread_info->formats[i].id]; - thread_info->formats[i].id = i; - } - - free (thread_info->pixel_formats); - thread_info->pixel_formats = new_pfs; + free (thread_info->pixel_formats); + thread_info->pixel_formats = new_pfs; } glitz_drawable_format_t * glitz_agl_find_drawable_format (unsigned long mask, - const glitz_drawable_format_t *templ, - int count) + const glitz_drawable_format_t *templ, + int count) { - glitz_agl_thread_info_t *thread_info = glitz_agl_thread_info_get (); + glitz_agl_thread_info_t *thread_info = glitz_agl_thread_info_get (); - return glitz_drawable_format_find (thread_info->formats, - thread_info->n_formats, - mask, templ, count); + return glitz_drawable_format_find (thread_info->formats, + thread_info->n_formats, + mask, templ, count); } slim_hidden_def(glitz_agl_find_drawable_format); diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_info.c b/gfx/cairo/glitz/src/agl/glitz_agl_info.c index d921c57ecfe..7438bd17abf 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_info.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_info.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -33,85 +33,97 @@ glitz_gl_proc_address_list_t _glitz_agl_gl_proc_address = { - /* core */ - (glitz_gl_enable_t) glEnable, - (glitz_gl_disable_t) glDisable, - (glitz_gl_get_error_t) glGetError, - (glitz_gl_get_string_t) glGetString, - (glitz_gl_enable_client_state_t) glEnableClientState, - (glitz_gl_disable_client_state_t) glDisableClientState, - (glitz_gl_vertex_pointer_t) glVertexPointer, - (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, - (glitz_gl_draw_arrays_t) glDrawArrays, - (glitz_gl_tex_env_f_t) glTexEnvf, - (glitz_gl_tex_env_fv_t) glTexEnvfv, - (glitz_gl_tex_gen_i_t) glTexGeni, - (glitz_gl_tex_gen_fv_t) glTexGenfv, - (glitz_gl_color_4us_t) glColor4us, - (glitz_gl_color_4f_t) glColor4f, - (glitz_gl_scissor_t) glScissor, - (glitz_gl_blend_func_t) glBlendFunc, - (glitz_gl_clear_t) glClear, - (glitz_gl_clear_color_t) glClearColor, - (glitz_gl_clear_stencil_t) glClearStencil, - (glitz_gl_stencil_func_t) glStencilFunc, - (glitz_gl_stencil_op_t) glStencilOp, - (glitz_gl_push_attrib_t) glPushAttrib, - (glitz_gl_pop_attrib_t) glPopAttrib, - (glitz_gl_matrix_mode_t) glMatrixMode, - (glitz_gl_push_matrix_t) glPushMatrix, - (glitz_gl_pop_matrix_t) glPopMatrix, - (glitz_gl_load_identity_t) glLoadIdentity, - (glitz_gl_load_matrix_f_t) glLoadMatrixf, - (glitz_gl_depth_range_t) glDepthRange, - (glitz_gl_viewport_t) glViewport, - (glitz_gl_raster_pos_2f_t) glRasterPos2f, - (glitz_gl_bitmap_t) glBitmap, - (glitz_gl_read_buffer_t) glReadBuffer, - (glitz_gl_draw_buffer_t) glDrawBuffer, - (glitz_gl_copy_pixels_t) glCopyPixels, - (glitz_gl_flush_t) glFlush, - (glitz_gl_finish_t) glFinish, - (glitz_gl_pixel_store_i_t) glPixelStorei, - (glitz_gl_ortho_t) glOrtho, - (glitz_gl_scale_f_t) glScalef, - (glitz_gl_translate_f_t) glTranslatef, - (glitz_gl_hint_t) glHint, - (glitz_gl_depth_mask_t) glDepthMask, - (glitz_gl_polygon_mode_t) glPolygonMode, - (glitz_gl_shade_model_t) glShadeModel, - (glitz_gl_color_mask_t) glColorMask, - (glitz_gl_read_pixels_t) glReadPixels, - (glitz_gl_get_tex_image_t) glGetTexImage, - (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, - (glitz_gl_gen_textures_t) glGenTextures, - (glitz_gl_delete_textures_t) glDeleteTextures, - (glitz_gl_bind_texture_t) glBindTexture, - (glitz_gl_tex_image_2d_t) glTexImage2D, - (glitz_gl_tex_parameter_i_t) glTexParameteri, - (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, - (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, - (glitz_gl_get_integer_v_t) glGetIntegerv, + /* core */ + (glitz_gl_enable_t) glEnable, + (glitz_gl_disable_t) glDisable, + (glitz_gl_get_error_t) glGetError, + (glitz_gl_get_string_t) glGetString, + (glitz_gl_enable_client_state_t) glEnableClientState, + (glitz_gl_disable_client_state_t) glDisableClientState, + (glitz_gl_vertex_pointer_t) glVertexPointer, + (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, + (glitz_gl_draw_arrays_t) glDrawArrays, + (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, + (glitz_gl_tex_gen_i_t) glTexGeni, + (glitz_gl_tex_gen_fv_t) glTexGenfv, + (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4f_t) glColor4f, + (glitz_gl_scissor_t) glScissor, + (glitz_gl_blend_func_t) glBlendFunc, + (glitz_gl_clear_t) glClear, + (glitz_gl_clear_color_t) glClearColor, + (glitz_gl_clear_stencil_t) glClearStencil, + (glitz_gl_stencil_func_t) glStencilFunc, + (glitz_gl_stencil_op_t) glStencilOp, + (glitz_gl_push_attrib_t) glPushAttrib, + (glitz_gl_pop_attrib_t) glPopAttrib, + (glitz_gl_matrix_mode_t) glMatrixMode, + (glitz_gl_push_matrix_t) glPushMatrix, + (glitz_gl_pop_matrix_t) glPopMatrix, + (glitz_gl_load_identity_t) glLoadIdentity, + (glitz_gl_load_matrix_f_t) glLoadMatrixf, + (glitz_gl_depth_range_t) glDepthRange, + (glitz_gl_viewport_t) glViewport, + (glitz_gl_raster_pos_2f_t) glRasterPos2f, + (glitz_gl_bitmap_t) glBitmap, + (glitz_gl_read_buffer_t) glReadBuffer, + (glitz_gl_draw_buffer_t) glDrawBuffer, + (glitz_gl_copy_pixels_t) glCopyPixels, + (glitz_gl_flush_t) glFlush, + (glitz_gl_finish_t) glFinish, + (glitz_gl_pixel_store_i_t) glPixelStorei, + (glitz_gl_ortho_t) glOrtho, + (glitz_gl_scale_f_t) glScalef, + (glitz_gl_translate_f_t) glTranslatef, + (glitz_gl_hint_t) glHint, + (glitz_gl_depth_mask_t) glDepthMask, + (glitz_gl_polygon_mode_t) glPolygonMode, + (glitz_gl_shade_model_t) glShadeModel, + (glitz_gl_color_mask_t) glColorMask, + (glitz_gl_read_pixels_t) glReadPixels, + (glitz_gl_get_tex_image_t) glGetTexImage, + (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, + (glitz_gl_gen_textures_t) glGenTextures, + (glitz_gl_delete_textures_t) glDeleteTextures, + (glitz_gl_bind_texture_t) glBindTexture, + (glitz_gl_tex_image_2d_t) glTexImage2D, + (glitz_gl_tex_parameter_i_t) glTexParameteri, + (glitz_gl_tex_parameter_fv_t) glTexParameterfv, + (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, + (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, + (glitz_gl_get_integer_v_t) glGetIntegerv, - /* extensions */ - (glitz_gl_blend_color_t) 0, - (glitz_gl_active_texture_t) 0, - (glitz_gl_client_active_texture_t) 0, - (glitz_gl_multi_draw_arrays_t) 0, - (glitz_gl_gen_programs_t) 0, - (glitz_gl_delete_programs_t) 0, - (glitz_gl_program_string_t) 0, - (glitz_gl_bind_program_t) 0, - (glitz_gl_program_local_param_4fv_t) 0, - (glitz_gl_get_program_iv_t) 0, - (glitz_gl_gen_buffers_t) 0, - (glitz_gl_delete_buffers_t) 0, - (glitz_gl_bind_buffer_t) 0, - (glitz_gl_buffer_data_t) 0, - (glitz_gl_buffer_sub_data_t) 0, - (glitz_gl_get_buffer_sub_data_t) 0, - (glitz_gl_map_buffer_t) 0, - (glitz_gl_unmap_buffer_t) 0 + /* extensions */ + (glitz_gl_blend_color_t) 0, + (glitz_gl_active_texture_t) 0, + (glitz_gl_client_active_texture_t) 0, + (glitz_gl_multi_draw_arrays_t) 0, + (glitz_gl_gen_programs_t) 0, + (glitz_gl_delete_programs_t) 0, + (glitz_gl_program_string_t) 0, + (glitz_gl_bind_program_t) 0, + (glitz_gl_program_local_param_4fv_t) 0, + (glitz_gl_get_program_iv_t) 0, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_buffer_sub_data_t) 0, + (glitz_gl_get_buffer_sub_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0, + (glitz_gl_gen_framebuffers_t) 0, + (glitz_gl_delete_framebuffers_t) 0, + (glitz_gl_bind_framebuffer_t) 0, + (glitz_gl_framebuffer_renderbuffer_t) 0, + (glitz_gl_framebuffer_texture_2d_t) 0, + (glitz_gl_check_framebuffer_status_t) 0, + (glitz_gl_gen_renderbuffers_t) 0, + (glitz_gl_delete_renderbuffers_t) 0, + (glitz_gl_bind_renderbuffer_t) 0, + (glitz_gl_renderbuffer_storage_t) 0, + (glitz_gl_get_renderbuffer_parameter_iv_t) 0 }; static void @@ -132,79 +144,79 @@ static pthread_key_t info_tsd; static void glitz_agl_thread_info_destroy (glitz_agl_thread_info_t *thread_info) { - pthread_setspecific (info_tsd, NULL); - - if (thread_info) { - glitz_agl_thread_info_fini (thread_info); - free (thread_info); - } + pthread_setspecific (info_tsd, NULL); + + if (thread_info) { + glitz_agl_thread_info_fini (thread_info); + free (thread_info); + } } static void _tsd_destroy (void *p) { - if (p) { - glitz_agl_thread_info_fini ((glitz_agl_thread_info_t *) p); - free (p); - } + if (p) { + glitz_agl_thread_info_fini ((glitz_agl_thread_info_t *) p); + free (p); + } } glitz_agl_thread_info_t * glitz_agl_thread_info_get (void) { - glitz_agl_thread_info_t *thread_info; - void *p; - - if (!tsd_initialized) { - pthread_key_create (&info_tsd, _tsd_destroy); - tsd_initialized = 1; - } - - p = pthread_getspecific (info_tsd); + glitz_agl_thread_info_t *thread_info; + void *p; - if (p == NULL) { - thread_info = malloc (sizeof (glitz_agl_thread_info_t)); - glitz_agl_thread_info_init (thread_info); - - pthread_setspecific (info_tsd, thread_info); - } else - thread_info = (glitz_agl_thread_info_t *) p; - - return thread_info; + if (!tsd_initialized) { + pthread_key_create (&info_tsd, _tsd_destroy); + tsd_initialized = 1; + } + + p = pthread_getspecific (info_tsd); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_agl_thread_info_t)); + glitz_agl_thread_info_init (thread_info); + + pthread_setspecific (info_tsd, thread_info); + } else + thread_info = (glitz_agl_thread_info_t *) p; + + return thread_info; } #else /* not thread safe */ static glitz_agl_thread_info_t _thread_info = { - 0, - NULL, - NULL, - 0, - NULL, - 0, - { 0 }, - 0, - NULL, - 0, - NULL, - { 0 } + 0, + NULL, + NULL, + 0, + NULL, + 0, + { 0 }, + 0, + NULL, + 0, + NULL, + { 0 } }; static void glitz_agl_thread_info_destroy (glitz_agl_thread_info_t *thread_info) { - if (thread_info) - glitz_agl_thread_info_fini (thread_info); + if (thread_info) + glitz_agl_thread_info_fini (thread_info); } glitz_agl_thread_info_t * glitz_agl_thread_info_get (void) { - if (_thread_info.context_stack_size == 0) - glitz_agl_thread_info_init (&_thread_info); - - return &_thread_info; + if (_thread_info.context_stack_size == 0) + glitz_agl_thread_info_init (&_thread_info); + + return &_thread_info; } #endif @@ -212,58 +224,58 @@ glitz_agl_thread_info_get (void) static void glitz_agl_thread_info_init (glitz_agl_thread_info_t *thread_info) { - thread_info->formats = NULL; - thread_info->pixel_formats = (AGLPixelFormat *) 0; - thread_info->n_formats = 0; - thread_info->contexts = NULL; - thread_info->n_contexts = 0; + thread_info->formats = NULL; + thread_info->pixel_formats = (AGLPixelFormat *) 0; + thread_info->n_formats = 0; + thread_info->contexts = NULL; + thread_info->n_contexts = 0; - thread_info->context_stack_size = 1; - thread_info->context_stack->surface = NULL; - thread_info->context_stack->constraint = GLITZ_NONE; + thread_info->context_stack_size = 1; + thread_info->context_stack->surface = NULL; + thread_info->context_stack->constraint = GLITZ_NONE; - thread_info->root_context = NULL; + thread_info->root_context = NULL; - thread_info->agl_feature_mask = 0; + thread_info->agl_feature_mask = 0; - thread_info->cctx = NULL; + thread_info->cctx = NULL; - glitz_program_map_init (&thread_info->program_map); + glitz_program_map_init (&thread_info->program_map); - if (!glitz_agl_query_extensions (thread_info)) - glitz_agl_query_formats (thread_info); + if (!glitz_agl_query_extensions (thread_info)) + glitz_agl_query_formats (thread_info); } static void glitz_agl_thread_info_fini (glitz_agl_thread_info_t *thread_info) { - int i; + int i; - for (i = 0; i < thread_info->n_contexts; i++) - glitz_agl_context_destroy (thread_info, thread_info->contexts[i]); - - for (i = 0; i < thread_info->n_formats; i++) - aglDestroyPixelFormat (thread_info->pixel_formats[i]); - - if (thread_info->formats) - free (thread_info->formats); - - if (thread_info->pixel_formats) - free (thread_info->pixel_formats); + for (i = 0; i < thread_info->n_contexts; i++) + glitz_agl_context_destroy (thread_info, thread_info->contexts[i]); + + for (i = 0; i < thread_info->n_formats; i++) + aglDestroyPixelFormat (thread_info->pixel_formats[i]); + + if (thread_info->formats) + free (thread_info->formats); + + if (thread_info->pixel_formats) + free (thread_info->pixel_formats); } void glitz_agl_init (void) { - glitz_agl_thread_info_get (); + glitz_agl_thread_info_get (); } slim_hidden_def(glitz_agl_init); void glitz_agl_fini (void) { - glitz_agl_thread_info_t *info = glitz_agl_thread_info_get (); + glitz_agl_thread_info_t *info = glitz_agl_thread_info_get (); - glitz_agl_thread_info_destroy (info); + glitz_agl_thread_info_destroy (info); } slim_hidden_def(glitz_agl_fini); diff --git a/gfx/cairo/glitz/src/agl/glitz_agl_pbuffer.c b/gfx/cairo/glitz/src/agl/glitz_agl_pbuffer.c index 65ed9eb3cac..687bb2d1fac 100644 --- a/gfx/cairo/glitz/src/agl/glitz_agl_pbuffer.c +++ b/gfx/cairo/glitz/src/agl/glitz_agl_pbuffer.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,28 +31,28 @@ AGLPbuffer glitz_agl_pbuffer_create (glitz_agl_thread_info_t *thread_info, - int width, - int height) + int width, + int height) { - AGLPbuffer pbuffer; - glitz_gl_enum_t target; + AGLPbuffer pbuffer; + glitz_gl_enum_t target; - if (!POWER_OF_TWO (width) || !POWER_OF_TWO (height)) { - if (thread_info->agl_feature_mask & - GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK) - target = GLITZ_GL_TEXTURE_RECTANGLE; - else - return (AGLPbuffer) 0; - } else - target = GLITZ_GL_TEXTURE_2D; + if (!POWER_OF_TWO (width) || !POWER_OF_TWO (height)) { + if (thread_info->agl_feature_mask & + GLITZ_AGL_FEATURE_TEXTURE_RECTANGLE_MASK) + target = GLITZ_GL_TEXTURE_RECTANGLE; + else + return (AGLPbuffer) 0; + } else + target = GLITZ_GL_TEXTURE_2D; - aglCreatePBuffer (width, height, target, GLITZ_GL_RGBA, 0, &pbuffer); + aglCreatePBuffer (width, height, target, GLITZ_GL_RGBA, 0, &pbuffer); - return pbuffer; + return pbuffer; } -void +void glitz_agl_pbuffer_destroy (AGLPbuffer pbuffer) { - aglDestroyPBuffer (pbuffer); + aglDestroyPBuffer (pbuffer); } diff --git a/gfx/cairo/glitz/src/agl/glitz_aglint.h b/gfx/cairo/glitz/src/agl/glitz_aglint.h index d8d5d7c8455..00603192809 100644 --- a/gfx/cairo/glitz/src/agl/glitz_aglint.h +++ b/gfx/cairo/glitz/src/agl/glitz_aglint.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -43,47 +43,46 @@ typedef struct _glitz_agl_drawable glitz_agl_drawable_t; typedef struct _glitz_agl_context_info_t { - glitz_agl_drawable_t *drawable; - glitz_surface_t *surface; - glitz_constraint_t constraint; + glitz_agl_drawable_t *drawable; + glitz_surface_t *surface; + glitz_constraint_t constraint; } glitz_agl_context_info_t; typedef struct _glitz_agl_context_t { - glitz_context_t base; - AGLContext context; - glitz_format_id_t id; - AGLPixelFormat pixel_format; - glitz_bool_t pbuffer; - glitz_backend_t backend; - glitz_gl_int_t max_viewport_dims[2]; - glitz_gl_int_t max_texture_2d_size; - glitz_gl_int_t max_texture_rect_size; - glitz_bool_t initialized; + glitz_context_t base; + AGLContext context; + glitz_format_id_t id; + AGLPixelFormat pixel_format; + glitz_bool_t pbuffer; + glitz_backend_t backend; + glitz_bool_t initialized; } glitz_agl_context_t; typedef struct _glitz_agl_thread_info_t { - int drawables; - glitz_drawable_format_t *formats; - AGLPixelFormat *pixel_formats; - int n_formats; - glitz_agl_context_t **contexts; - int n_contexts; - glitz_agl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; - int context_stack_size; - AGLContext root_context; - unsigned long agl_feature_mask; - glitz_context_t *cctx; - glitz_program_map_t program_map; + int drawables; + glitz_int_drawable_format_t *formats; + AGLPixelFormat *pixel_formats; + int n_formats; + glitz_agl_context_t **contexts; + int n_contexts; + glitz_agl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; + int context_stack_size; + AGLContext root_context; + unsigned long agl_feature_mask; + glitz_context_t *cctx; + glitz_program_map_t program_map; } glitz_agl_thread_info_t; struct _glitz_agl_drawable { - glitz_drawable_t base; - - glitz_agl_thread_info_t *thread_info; - glitz_agl_context_t *context; - AGLDrawable drawable; - AGLPbuffer pbuffer; - WindowRef window; + glitz_drawable_t base; + + glitz_agl_thread_info_t *thread_info; + glitz_agl_context_t *context; + AGLDrawable drawable; + AGLPbuffer pbuffer; + WindowRef window; + int width; + int height; }; extern glitz_status_t __internal_linkage @@ -94,33 +93,33 @@ glitz_agl_thread_info_get (void); extern glitz_agl_context_t __internal_linkage * glitz_agl_context_get (glitz_agl_thread_info_t *thread_info, - glitz_drawable_format_t *format); + glitz_drawable_format_t *format); extern void __internal_linkage glitz_agl_context_destroy (glitz_agl_thread_info_t *thread_info, - glitz_agl_context_t *context); + glitz_agl_context_t *context); extern void __internal_linkage glitz_agl_query_formats (glitz_agl_thread_info_t *thread_info); extern AGLPbuffer __internal_linkage glitz_agl_pbuffer_create (glitz_agl_thread_info_t *thread_info, - int width, - int height); + int width, + int height); extern void __internal_linkage glitz_agl_pbuffer_destroy (AGLPbuffer pbuffer); extern glitz_drawable_t __internal_linkage * glitz_agl_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_agl_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint); + glitz_surface_t *surface, + glitz_constraint_t constraint); extern glitz_surface_t __internal_linkage * glitz_agl_pop_current (void *abstract_drawable); @@ -128,7 +127,7 @@ glitz_agl_pop_current (void *abstract_drawable); extern void __internal_linkage glitz_agl_destroy (void *abstract_drawable); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_agl_swap_buffers (void *abstract_drawable); /* Avoid unnecessary PLT entries. */ diff --git a/gfx/cairo/glitz/src/egl/glitz-egl.h b/gfx/cairo/glitz/src/egl/glitz-egl.h index 1b6bf8d4790..802c05f2c5a 100644 --- a/gfx/cairo/glitz/src/egl/glitz-egl.h +++ b/gfx/cairo/glitz/src/egl/glitz-egl.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -42,33 +42,41 @@ glitz_egl_init (const char *gl_library); void glitz_egl_fini (void); - - + + /* glitz_egl_config.c */ glitz_drawable_format_t * -glitz_egl_find_config (EGLDisplay egl_display, - EGLScreenMESA egl_screen, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count); +glitz_egl_find_window_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + +glitz_drawable_format_t * +glitz_egl_find_pbuffer_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + /* glitz_egl_surface.c */ glitz_drawable_t * glitz_egl_create_surface (EGLDisplay egl_display, - EGLScreenMESA egl_screen, - glitz_drawable_format_t *format, - EGLSurface egl_surface, - unsigned int width, - unsigned int height); + EGLScreenMESA egl_screen, + glitz_drawable_format_t *format, + EGLSurface egl_surface, + unsigned int width, + unsigned int height); glitz_drawable_t * glitz_egl_create_pbuffer_surface (EGLDisplay egl_display, - EGLScreenMESA egl_screen, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + EGLScreenMESA egl_screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); #if defined(__cplusplus) || defined(c_plusplus) diff --git a/gfx/cairo/glitz/src/egl/glitz_egl_config.c b/gfx/cairo/glitz/src/egl/glitz_egl_config.c index 671c6d910b4..729269f1965 100644 --- a/gfx/cairo/glitz/src/egl/glitz_egl_config.c +++ b/gfx/cairo/glitz/src/egl/glitz_egl_config.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -34,188 +34,210 @@ static int _glitz_egl_format_compare (const void *elem1, - const void *elem2) + const void *elem2) { - int i, score[2]; - glitz_drawable_format_t *format[2]; - - format[0] = (glitz_drawable_format_t *) elem1; - format[1] = (glitz_drawable_format_t *) elem2; - i = score[0] = score[1] = 0; + glitz_int_drawable_format_t *format[2]; + int i, score[2]; - for (; i < 2; i++) { - if (format[i]->color.red_size) { - if (format[i]->color.red_size == 8) - score[i] += 5; - score[i] += 10; + format[0] = (glitz_int_drawable_format_t *) elem1; + format[1] = (glitz_int_drawable_format_t *) elem2; + i = score[0] = score[1] = 0; + + for (; i < 2; i++) + { + if (format[i]->d.color.red_size) + { + if (format[i]->d.color.red_size >= 8) + score[i] += 5; + + score[i] += 10; + } + + if (format[i]->d.color.alpha_size) + { + if (format[i]->d.color.alpha_size >= 8) + score[i] += 5; + + score[i] += 10; + } + + if (format[i]->d.stencil_size) + score[i] += 5; + + if (format[i]->d.depth_size) + score[i] += 5; + + if (format[i]->d.doublebuffer) + score[i] += 10; + + if (format[i]->d.samples > 1) + score[i] -= (20 - format[i]->d.samples); + + if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK) + score[i] += 10; + + if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK) + score[i] += 10; + + if (format[i]->caveat) + score[i] -= 1000; } - if (format[i]->color.green_size) { - if (format[i]->color.green_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->color.alpha_size) { - if (format[i]->color.alpha_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->stencil_size) - score[i] += 5; - - if (format[i]->depth_size) - score[i] += 5; - - if (format[i]->doublebuffer) - score[i] += 10; - - if (format[i]->types.window) - score[i] += 10; - - if (format[i]->types.pbuffer) - score[i] += 10; - - if (format[i]->samples > 1) - score[i] -= (20 - format[i]->samples); - } - - return score[1] - score[0]; + return score[1] - score[0]; } static void -_glitz_add_format (glitz_egl_screen_info_t *screen_info, - glitz_drawable_format_t *format, - EGLConfig egl_id) +_glitz_add_format (glitz_egl_screen_info_t *screen_info, + glitz_int_drawable_format_t *format) { - if (!glitz_drawable_format_find (screen_info->formats, - screen_info->n_formats, - GLITZ_DRAWABLE_FORMAT_ALL_EXCEPT_ID_MASK, - format, 0)) { int n = screen_info->n_formats; - - screen_info->formats = - realloc (screen_info->formats, - sizeof (glitz_drawable_format_t) * (n + 1)); - screen_info->egl_config_ids = - realloc (screen_info->egl_config_ids, sizeof (EGLConfig) * (n + 1)); - if (screen_info->formats && screen_info->egl_config_ids) { - screen_info->formats[n] = *format; - screen_info->formats[n].id = n; - screen_info->egl_config_ids[n] = egl_id; - screen_info->n_formats++; + screen_info->formats = + realloc (screen_info->formats, + sizeof (glitz_int_drawable_format_t) * (n + 1)); + if (screen_info->formats) + { + screen_info->formats[n] = *format; + screen_info->formats[n].d.id = n; + screen_info->n_formats++; } - } } -static glitz_status_t +static void _glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info) { - EGLDisplay egl_display; - glitz_drawable_format_t format; - EGLConfig *egl_configs; - int i, num_configs; - EGLConfig egl_id; - - egl_display = screen_info->display_info->egl_display; + glitz_int_drawable_format_t format; + EGLDisplay egl_display; + EGLConfig *egl_configs; + int i, num_configs; - eglGetConfigs(egl_display, NULL, 0, &num_configs); - egl_configs = malloc(sizeof(*egl_configs) * num_configs); - eglGetConfigs(egl_display, egl_configs, num_configs, &num_configs); + egl_display = screen_info->display_info->egl_display; - for (i = 0; i < num_configs; i++) { - int value; - - eglGetConfigAttrib(egl_display, egl_configs[i], - EGL_SURFACE_TYPE, &value); - if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT))) - continue; - - format.types.window = (value & EGL_WINDOW_BIT)? 1: 0; - format.types.pbuffer = (value & EGL_PBUFFER_BIT)? 1: 0; - format.id = 0; - - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_CONFIG_ID, &value); - egl_id = (EGLConfig) value; + eglGetConfigs (egl_display, NULL, 0, &num_configs); + egl_configs = malloc (sizeof (EGLConfig) * num_configs); + if (!egl_configs) + return; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_RED_SIZE, &value); - format.color.red_size = (unsigned short) value; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_GREEN_SIZE, &value); - format.color.green_size = (unsigned short) value; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_BLUE_SIZE, &value); - format.color.blue_size = (unsigned short) value; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_ALPHA_SIZE, &value); - format.color.alpha_size = (unsigned short) value; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_DEPTH_SIZE, &value); - format.depth_size = (unsigned short) value; - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_STENCIL_SIZE, &value); - format.stencil_size = (unsigned short) value; + format.d.id = 0; + format.d.doublebuffer = 1; - format.doublebuffer = 1; + eglGetConfigs (egl_display, egl_configs, num_configs, &num_configs); - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLE_BUFFERS, &value); - if (value) { - eglGetConfigAttrib(egl_display, egl_configs[i], EGL_SAMPLES, &value); - format.samples = (unsigned short) (value > 1)? value: 1; - if (format.samples > 1) - format.types.pbuffer = 0; - } else - format.samples = 1; - - _glitz_add_format (screen_info, &format, egl_id); - } - - free(egl_configs); + for (i = 0; i < num_configs; i++) + { + int value; - return GLITZ_STATUS_SUCCESS; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SURFACE_TYPE, + &value); + if (!((value & EGL_WINDOW_BIT) || (value & EGL_PBUFFER_BIT))) + continue; + + format.types = 0; + if (value & EGL_WINDOW_BIT) + format.types |= GLITZ_DRAWABLE_TYPE_WINDOW_MASK; + + if (value & EGL_PBUFFER_BIT) + format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_CONFIG_ID, + &value); + format.u.uval = value; + + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_RED_SIZE, &value); + format.d.color.red_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_GREEN_SIZE, + &value); + format.d.color.green_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_BLUE_SIZE, + &value); + format.d.color.blue_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_ALPHA_SIZE, + &value); + format.d.color.alpha_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_DEPTH_SIZE, + &value); + format.d.depth_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_STENCIL_SIZE, + &value); + format.d.stencil_size = (unsigned short) value; + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_CONFIG_CAVEAT, + &value); + format.caveat = (unsigned short) value; + + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SAMPLE_BUFFERS, + &value); + if (value) + { + eglGetConfigAttrib (egl_display, egl_configs[i], EGL_SAMPLES, + &value); + format.d.samples = (unsigned short) (value > 1)? value: 1; + } + else + format.d.samples = 1; + + _glitz_add_format (screen_info, &format); + } + + free (egl_configs); } void glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info) { - EGLConfig *egl_new_ids; - int i; + int i; - _glitz_egl_query_configs (screen_info); + _glitz_egl_query_configs (screen_info); - if (!screen_info->n_formats) - return; + if (!screen_info->n_formats) + return; - qsort (screen_info->formats, screen_info->n_formats, - sizeof (glitz_drawable_format_t), _glitz_egl_format_compare); + qsort (screen_info->formats, screen_info->n_formats, + sizeof (glitz_int_drawable_format_t), _glitz_egl_format_compare); - /* - * Update XID list so that it matches the sorted format list. - */ - egl_new_ids = malloc (sizeof (EGLConfig) * screen_info->n_formats); - if (!egl_new_ids) { - screen_info->n_formats = 0; - return; - } - - for (i = 0; i < screen_info->n_formats; i++) { - egl_new_ids[i] = screen_info->egl_config_ids[screen_info->formats[i].id]; - screen_info->formats[i].id = i; - } - - free (screen_info->egl_config_ids); - screen_info->egl_config_ids = egl_new_ids; + for (i = 0; i < screen_info->n_formats; i++) + screen_info->formats[i].d.id = i; } glitz_drawable_format_t * -glitz_egl_find_config (EGLDisplay egl_display, - EGLScreenMESA egl_screen, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count) +glitz_egl_find_window_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) { - glitz_egl_screen_info_t *screen_info = - glitz_egl_screen_info_get (egl_display, egl_screen); + glitz_int_drawable_format_t itempl; + glitz_egl_screen_info_t *screen_info = + glitz_egl_screen_info_get (egl_display, egl_screen); - return glitz_drawable_format_find (screen_info->formats, - screen_info->n_formats, - mask, templ, count); + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK; + mask |= GLITZ_INT_FORMAT_WINDOW_MASK; + + return glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + mask, &itempl, count); } -slim_hidden_def(glitz_egl_find_config); +slim_hidden_def(glitz_egl_find_window_config); + +glitz_drawable_format_t * +glitz_egl_find_pbuffer_config (EGLDisplay egl_display, + EGLScreenMESA egl_screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) +{ + glitz_int_drawable_format_t itempl; + glitz_egl_screen_info_t *screen_info = + glitz_egl_screen_info_get (egl_display, egl_screen); + + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + mask |= GLITZ_INT_FORMAT_PBUFFER_MASK; + + return glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + mask, &itempl, count); +} +slim_hidden_def(glitz_egl_find_pbuffer_config); diff --git a/gfx/cairo/glitz/src/egl/glitz_egl_context.c b/gfx/cairo/glitz/src/egl/glitz_egl_context.c index 89d77d363d7..f64e8f76c80 100644 --- a/gfx/cairo/glitz/src/egl/glitz_egl_context.c +++ b/gfx/cairo/glitz/src/egl/glitz_egl_context.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -35,323 +35,368 @@ extern glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address; static void _glitz_egl_context_create (glitz_egl_screen_info_t *screen_info, - EGLConfig egl_config, - EGLContext egl_share_list, - glitz_egl_context_t *context) + EGLConfig egl_config, + EGLContext egl_share_list, + glitz_egl_context_t *context) { - context->id = egl_config; - context->egl_context = eglCreateContext (screen_info->display_info->egl_display, - egl_config, egl_share_list, NULL); + context->id = egl_config; + context->egl_context = + eglCreateContext (screen_info->display_info->egl_display, + egl_config, egl_share_list, NULL); } static glitz_context_t * _glitz_egl_create_context (void *abstract_drawable, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; - glitz_egl_screen_info_t *screen_info = drawable->screen_info; - int format_id = screen_info->egl_config_ids[format->id]; - glitz_egl_context_t *context; - - context = malloc (sizeof (glitz_egl_context_t)); - if (!context) - return NULL; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_screen_info_t *screen_info = drawable->screen_info; + int format_id = screen_info->formats[format->id].u.uval; + glitz_egl_context_t *context; - _glitz_context_init (&context->base, &drawable->base); - - _glitz_egl_context_create (screen_info, - format_id, - screen_info->egl_root_context, - context); + context = malloc (sizeof (glitz_egl_context_t)); + if (!context) + return NULL; - return (glitz_context_t *) context; + _glitz_context_init (&context->base, &drawable->base); + + _glitz_egl_context_create (screen_info, + format_id, + screen_info->egl_root_context, + context); + + return (glitz_context_t *) context; } static void _glitz_egl_context_destroy (void *abstract_context) { - glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) - context->base.drawable; - - if (drawable->screen_info->display_info->thread_info->cctx == &context->base) - { - eglMakeCurrent (drawable->screen_info->display_info->egl_display, - EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - drawable->screen_info->display_info->thread_info->cctx = NULL; - } + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + context->base.drawable; - eglDestroyContext (drawable->screen_info->display_info->egl_display, - context->egl_context); + if (drawable->screen_info->display_info->thread_info->cctx == + &context->base) + { + eglMakeCurrent (drawable->screen_info->display_info->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - _glitz_context_fini (&context->base); - - free (context); + drawable->screen_info->display_info->thread_info->cctx = NULL; + } + + eglDestroyContext (drawable->screen_info->display_info->egl_display, + context->egl_context); + + _glitz_context_fini (&context->base); + + free (context); } static void _glitz_egl_copy_context (void *abstract_src, - void *abstract_dst, - unsigned long mask) + void *abstract_dst, + unsigned long mask) { - glitz_egl_context_t *src = (glitz_egl_context_t *) abstract_src; - glitz_egl_context_t *dst = (glitz_egl_context_t *) abstract_dst; - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) - src->base.drawable; + glitz_egl_context_t *src = (glitz_egl_context_t *) abstract_src; + glitz_egl_context_t *dst = (glitz_egl_context_t *) abstract_dst; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + src->base.drawable; - eglCopyContextMESA (drawable->screen_info->display_info->egl_display, - src->egl_context, dst->egl_context, mask); + eglCopyContextMESA (drawable->screen_info->display_info->egl_display, + src->egl_context, dst->egl_context, mask); } static void -_glitz_egl_make_current (void *abstract_context, - void *abstract_drawable) +_glitz_egl_make_current (void *abstract_drawable, + void *abstract_context) { - glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; - glitz_egl_display_info_t *display_info = drawable->screen_info->display_info; - - if ((eglGetCurrentContext () != context->egl_context) || - (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) - eglMakeCurrent (display_info->egl_display, drawable->egl_surface, - drawable->egl_surface, context->egl_context); + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_display_info_t *display_info = + drawable->screen_info->display_info; - display_info->thread_info->cctx = &context->base; + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_egl_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); + + if ((eglGetCurrentContext () != context->egl_context) || + (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) + { + if (display_info->thread_info->cctx) + { + glitz_context_t *ctx = display_info->thread_info->cctx; + + if (ctx->lose_current) + ctx->lose_current (ctx->closure); + } + + eglMakeCurrent (display_info->egl_display, drawable->egl_surface, + drawable->egl_surface, context->egl_context); + } + + display_info->thread_info->cctx = &context->base; } +static void +_glitz_egl_notify_dummy (void *abstract_drawable, + glitz_surface_t *surface) {} + static glitz_function_pointer_t _glitz_egl_context_get_proc_address (void *abstract_context, - const char *name) + const char *name) { - glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) - context->base.drawable; + glitz_egl_context_t *context = (glitz_egl_context_t *) abstract_context; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) + context->base.drawable; - _glitz_egl_make_current (context, drawable); - - return glitz_egl_get_proc_address (name, drawable->screen_info); + _glitz_egl_make_current (drawable, context); + + return glitz_egl_get_proc_address (name, drawable->screen_info); } glitz_egl_context_t * glitz_egl_context_get (glitz_egl_screen_info_t *screen_info, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_egl_context_t *context; - glitz_egl_context_t **contexts = screen_info->contexts; - int index, n_contexts = screen_info->n_contexts; - EGLConfig egl_config_id; + glitz_egl_context_t *context; + glitz_egl_context_t **contexts = screen_info->contexts; + int index, n_contexts = screen_info->n_contexts; - for (; n_contexts; n_contexts--, contexts++) - if ((*contexts)->id == screen_info->egl_config_ids[format->id]) - return *contexts; + for (; n_contexts; n_contexts--, contexts++) + if ((*contexts)->id == screen_info->formats[format->id].u.uval) + return *contexts; - index = screen_info->n_contexts++; + index = screen_info->n_contexts++; - screen_info->contexts = - realloc (screen_info->contexts, - sizeof (glitz_egl_context_t *) * screen_info->n_contexts); - if (!screen_info->contexts) - return NULL; + screen_info->contexts = + realloc (screen_info->contexts, + sizeof (glitz_egl_context_t *) * screen_info->n_contexts); + if (!screen_info->contexts) + return NULL; - context = malloc (sizeof (glitz_egl_context_t)); - if (!context) - return NULL; - - screen_info->contexts[index] = context; + context = malloc (sizeof (glitz_egl_context_t)); + if (!context) + return NULL; - egl_config_id = screen_info->egl_config_ids[format->id]; + screen_info->contexts[index] = context; - _glitz_egl_context_create (screen_info, - egl_config_id, - screen_info->egl_root_context, - context); - - if (!screen_info->egl_root_context) - screen_info->egl_root_context = context->egl_context; + _glitz_egl_context_create (screen_info, + screen_info->formats[format->id].u.uval, + screen_info->egl_root_context, + context); - memcpy (&context->backend.gl, - &_glitz_egl_gl_proc_address, - sizeof (glitz_gl_proc_address_list_t)); + if (!screen_info->egl_root_context) + screen_info->egl_root_context = context->egl_context; - context->backend.create_pbuffer = glitz_egl_create_pbuffer; - context->backend.destroy = glitz_egl_destroy; - context->backend.push_current = glitz_egl_push_current; - context->backend.pop_current = glitz_egl_pop_current; - context->backend.swap_buffers = glitz_egl_swap_buffers; - - context->backend.create_context = _glitz_egl_create_context; - context->backend.destroy_context = _glitz_egl_context_destroy; - context->backend.copy_context = _glitz_egl_copy_context; - context->backend.make_current = _glitz_egl_make_current; - context->backend.get_proc_address = _glitz_egl_context_get_proc_address; - - context->backend.drawable_formats = screen_info->formats; - context->backend.n_drawable_formats = screen_info->n_formats; + context->backend.gl = &_glitz_egl_gl_proc_address; - context->backend.texture_formats = NULL; - context->backend.formats = NULL; - context->backend.n_formats = 0; - - context->backend.program_map = &screen_info->program_map; - context->backend.feature_mask = 0; + context->backend.create_pbuffer = glitz_egl_create_pbuffer; + context->backend.destroy = glitz_egl_destroy; + context->backend.push_current = glitz_egl_push_current; + context->backend.pop_current = glitz_egl_pop_current; + context->backend.attach_notify = _glitz_egl_notify_dummy; + context->backend.detach_notify = _glitz_egl_notify_dummy; + context->backend.swap_buffers = glitz_egl_swap_buffers; - context->initialized = 0; - - return context; + context->backend.create_context = _glitz_egl_create_context; + context->backend.destroy_context = _glitz_egl_context_destroy; + context->backend.copy_context = _glitz_egl_copy_context; + context->backend.make_current = _glitz_egl_make_current; + context->backend.get_proc_address = _glitz_egl_context_get_proc_address; + + context->backend.drawable_formats = NULL; + context->backend.n_drawable_formats = 0; + + if (screen_info->n_formats) + { + int size; + + size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats; + context->backend.drawable_formats = malloc (size); + if (context->backend.drawable_formats) + { + memcpy (context->backend.drawable_formats, screen_info->formats, + size); + context->backend.n_drawable_formats = screen_info->n_formats; + } + } + + context->backend.texture_formats = NULL; + context->backend.formats = NULL; + context->backend.n_formats = 0; + + context->backend.program_map = &screen_info->program_map; + context->backend.feature_mask = 0; + + context->initialized = 0; + + return context; } void glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info, - glitz_egl_context_t *context) + glitz_egl_context_t *context) { - if (context->backend.formats) - free (context->backend.formats); + if (context->backend.drawable_formats) + free (context->backend.drawable_formats); - if (context->backend.texture_formats) - free (context->backend.texture_formats); - - eglDestroyContext (screen_info->display_info->egl_display, - context->egl_context); - free (context); + if (context->backend.formats) + free (context->backend.formats); + + if (context->backend.texture_formats) + free (context->backend.texture_formats); + + eglDestroyContext (screen_info->display_info->egl_display, + context->egl_context); + free (context); } static void _glitz_egl_context_initialize (glitz_egl_screen_info_t *screen_info, - glitz_egl_context_t *context) + glitz_egl_context_t *context) { - const char *version; - - glitz_backend_init (&context->backend, - glitz_egl_get_proc_address, - (void *) screen_info); + const char *version; - context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS, - context->max_viewport_dims); + glitz_backend_init (&context->backend, + glitz_egl_get_proc_address, + (void *) screen_info); - glitz_initiate_state (&_glitz_egl_gl_proc_address); + glitz_initiate_state (&_glitz_egl_gl_proc_address); - version = (const char *) context->backend.gl.get_string (GLITZ_GL_VERSION); - if (version) - { - /* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures when - using nvidia's binary driver. Seems like a driver issue, but I'm not - sure yet. Turning of NPOT GL_TEXTURE_2D textures until this have been - solved. */ - if (strstr (version, "NVIDIA 61.11") || - strstr (version, "NVIDIA 66.29")) + version = (const char *) + context->backend.gl->get_string (GLITZ_GL_VERSION); + if (version) { - context->backend.feature_mask &= - ~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK; + /* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures + when using nvidia's binary driver. Seems like a driver issue, but + I'm not sure yet. Turning of NPOT GL_TEXTURE_2D textures until + this have been solved. */ + if (strstr (version, "NVIDIA 61.11") || + strstr (version, "NVIDIA 66.29")) + { + context->backend.feature_mask &= + ~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK; + } } - } - - context->initialized = 1; + + context->initialized = 1; } static void _glitz_egl_context_make_current (glitz_egl_surface_t *drawable, - glitz_bool_t finish) + glitz_bool_t finish) { - glitz_egl_display_info_t *display_info = drawable->screen_info->display_info; - - if (finish) - glFinish (); + glitz_egl_display_info_t *display_info = + drawable->screen_info->display_info; - if (display_info->thread_info->cctx) - { - glitz_context_t *ctx = display_info->thread_info->cctx; + if (finish) + glFinish (); - if (ctx->lose_current) - ctx->lose_current (ctx->closure); + if (display_info->thread_info->cctx) + { + glitz_context_t *ctx = display_info->thread_info->cctx; - display_info->thread_info->cctx = NULL; - } + if (ctx->lose_current) + ctx->lose_current (ctx->closure); - eglMakeCurrent (display_info->egl_display, - drawable->egl_surface, drawable->egl_surface, - drawable->context->egl_context); - - drawable->base.update_all = 1; - - if (!drawable->context->initialized) - _glitz_egl_context_initialize (drawable->screen_info, drawable->context); + display_info->thread_info->cctx = NULL; + } + + eglMakeCurrent (display_info->egl_display, + drawable->egl_surface, drawable->egl_surface, + drawable->context->egl_context); + + drawable->base.update_all = 1; + + if (!drawable->context->initialized) + _glitz_egl_context_initialize (drawable->screen_info, + drawable->context); } static void _glitz_egl_context_update (glitz_egl_surface_t *drawable, - glitz_constraint_t constraint) + glitz_constraint_t constraint) { - EGLContext egl_context; - - switch (constraint) { - case GLITZ_NONE: - break; - case GLITZ_ANY_CONTEXT_CURRENT: { - glitz_egl_display_info_t *dinfo = drawable->screen_info->display_info; - - if (dinfo->thread_info->cctx) - { - _glitz_egl_context_make_current (drawable, 0); - } - else - { - egl_context = eglGetCurrentContext (); - if (egl_context == (EGLContext) 0) - _glitz_egl_context_make_current (drawable, 0); - } + EGLContext egl_context; + + switch (constraint) { + case GLITZ_NONE: + break; + case GLITZ_ANY_CONTEXT_CURRENT: { + glitz_egl_display_info_t *dinfo = drawable->screen_info->display_info; + + if (dinfo->thread_info->cctx) + { + _glitz_egl_context_make_current (drawable, 0); + } + else + { + egl_context = eglGetCurrentContext (); + if (egl_context == (EGLContext) 0) + _glitz_egl_context_make_current (drawable, 0); + } } break; - case GLITZ_CONTEXT_CURRENT: - egl_context = eglGetCurrentContext (); - if (egl_context != drawable->context->egl_context) - _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); - break; - case GLITZ_DRAWABLE_CURRENT: - egl_context = eglGetCurrentContext (); - if ((egl_context != drawable->context->egl_context) || - (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) - _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); - break; - } + case GLITZ_CONTEXT_CURRENT: + egl_context = eglGetCurrentContext (); + if (egl_context != drawable->context->egl_context) + _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); + break; + case GLITZ_DRAWABLE_CURRENT: + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_egl_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); + + egl_context = eglGetCurrentContext (); + if ((egl_context != drawable->context->egl_context) || + (eglGetCurrentSurface ( 0 ) != drawable->egl_surface)) + _glitz_egl_context_make_current (drawable, (egl_context)? 1: 0); + break; + } } -void +glitz_bool_t glitz_egl_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint) + glitz_surface_t *surface, + glitz_constraint_t constraint) { - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; - glitz_egl_context_info_t *context_info; - int index; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_context_info_t *context_info; + int index; - index = drawable->screen_info->context_stack_size++; + index = drawable->screen_info->context_stack_size++; - context_info = &drawable->screen_info->context_stack[index]; - context_info->drawable = drawable; - context_info->surface = surface; - context_info->constraint = constraint; - - _glitz_egl_context_update (context_info->drawable, constraint); + context_info = &drawable->screen_info->context_stack[index]; + context_info->drawable = drawable; + context_info->surface = surface; + context_info->constraint = constraint; + + _glitz_egl_context_update (context_info->drawable, constraint); + + return 1; } glitz_surface_t * glitz_egl_pop_current (void *abstract_drawable) { - glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; - glitz_egl_context_info_t *context_info = NULL; - int index; + glitz_egl_surface_t *drawable = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_context_info_t *context_info = NULL; + int index; - drawable->screen_info->context_stack_size--; - index = drawable->screen_info->context_stack_size - 1; + drawable->screen_info->context_stack_size--; + index = drawable->screen_info->context_stack_size - 1; - context_info = &drawable->screen_info->context_stack[index]; + context_info = &drawable->screen_info->context_stack[index]; - if (context_info->drawable) - _glitz_egl_context_update (context_info->drawable, - context_info->constraint); - - if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) - return context_info->surface; - - return NULL; + if (context_info->drawable) + _glitz_egl_context_update (context_info->drawable, + context_info->constraint); + + if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) + return context_info->surface; + + return NULL; } diff --git a/gfx/cairo/glitz/src/egl/glitz_egl_info.c b/gfx/cairo/glitz/src/egl/glitz_egl_info.c index f8627b4a8de..c19555854dd 100644 --- a/gfx/cairo/glitz/src/egl/glitz_egl_info.c +++ b/gfx/cairo/glitz/src/egl/glitz_egl_info.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -35,111 +35,124 @@ glitz_gl_proc_address_list_t _glitz_egl_gl_proc_address = { - /* core */ - (glitz_gl_enable_t) glEnable, - (glitz_gl_disable_t) glDisable, - (glitz_gl_get_error_t) glGetError, - (glitz_gl_get_string_t) glGetString, - (glitz_gl_enable_client_state_t) glEnableClientState, - (glitz_gl_disable_client_state_t) glDisableClientState, - (glitz_gl_vertex_pointer_t) glVertexPointer, - (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, - (glitz_gl_draw_arrays_t) glDrawArrays, - (glitz_gl_tex_env_f_t) glTexEnvf, - (glitz_gl_tex_env_fv_t) glTexEnvfv, - (glitz_gl_tex_gen_i_t) glTexGeni, - (glitz_gl_tex_gen_fv_t) glTexGenfv, - (glitz_gl_color_4us_t) glColor4us, - (glitz_gl_color_4f_t) glColor4f, - (glitz_gl_scissor_t) glScissor, - (glitz_gl_blend_func_t) glBlendFunc, - (glitz_gl_clear_t) glClear, - (glitz_gl_clear_color_t) glClearColor, - (glitz_gl_clear_stencil_t) glClearStencil, - (glitz_gl_stencil_func_t) glStencilFunc, - (glitz_gl_stencil_op_t) glStencilOp, - (glitz_gl_push_attrib_t) glPushAttrib, - (glitz_gl_pop_attrib_t) glPopAttrib, - (glitz_gl_matrix_mode_t) glMatrixMode, - (glitz_gl_push_matrix_t) glPushMatrix, - (glitz_gl_pop_matrix_t) glPopMatrix, - (glitz_gl_load_identity_t) glLoadIdentity, - (glitz_gl_load_matrix_f_t) glLoadMatrixf, - (glitz_gl_depth_range_t) glDepthRange, - (glitz_gl_viewport_t) glViewport, - (glitz_gl_raster_pos_2f_t) glRasterPos2f, - (glitz_gl_bitmap_t) glBitmap, - (glitz_gl_read_buffer_t) glReadBuffer, - (glitz_gl_draw_buffer_t) glDrawBuffer, - (glitz_gl_copy_pixels_t) glCopyPixels, - (glitz_gl_flush_t) glFlush, - (glitz_gl_finish_t) glFinish, - (glitz_gl_pixel_store_i_t) glPixelStorei, - (glitz_gl_ortho_t) glOrtho, - (glitz_gl_scale_f_t) glScalef, - (glitz_gl_translate_f_t) glTranslatef, - (glitz_gl_hint_t) glHint, - (glitz_gl_depth_mask_t) glDepthMask, - (glitz_gl_polygon_mode_t) glPolygonMode, - (glitz_gl_shade_model_t) glShadeModel, - (glitz_gl_color_mask_t) glColorMask, - (glitz_gl_read_pixels_t) glReadPixels, - (glitz_gl_get_tex_image_t) glGetTexImage, - (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, - (glitz_gl_gen_textures_t) glGenTextures, - (glitz_gl_delete_textures_t) glDeleteTextures, - (glitz_gl_bind_texture_t) glBindTexture, - (glitz_gl_tex_image_2d_t) glTexImage2D, - (glitz_gl_tex_parameter_i_t) glTexParameteri, - (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, - (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, - (glitz_gl_get_integer_v_t) glGetIntegerv, + /* core */ + (glitz_gl_enable_t) glEnable, + (glitz_gl_disable_t) glDisable, + (glitz_gl_get_error_t) glGetError, + (glitz_gl_get_string_t) glGetString, + (glitz_gl_enable_client_state_t) glEnableClientState, + (glitz_gl_disable_client_state_t) glDisableClientState, + (glitz_gl_vertex_pointer_t) glVertexPointer, + (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, + (glitz_gl_draw_arrays_t) glDrawArrays, + (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, + (glitz_gl_tex_gen_i_t) glTexGeni, + (glitz_gl_tex_gen_fv_t) glTexGenfv, + (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4f_t) glColor4f, + (glitz_gl_scissor_t) glScissor, + (glitz_gl_blend_func_t) glBlendFunc, + (glitz_gl_clear_t) glClear, + (glitz_gl_clear_color_t) glClearColor, + (glitz_gl_clear_stencil_t) glClearStencil, + (glitz_gl_stencil_func_t) glStencilFunc, + (glitz_gl_stencil_op_t) glStencilOp, + (glitz_gl_push_attrib_t) glPushAttrib, + (glitz_gl_pop_attrib_t) glPopAttrib, + (glitz_gl_matrix_mode_t) glMatrixMode, + (glitz_gl_push_matrix_t) glPushMatrix, + (glitz_gl_pop_matrix_t) glPopMatrix, + (glitz_gl_load_identity_t) glLoadIdentity, + (glitz_gl_load_matrix_f_t) glLoadMatrixf, + (glitz_gl_depth_range_t) glDepthRange, + (glitz_gl_viewport_t) glViewport, + (glitz_gl_raster_pos_2f_t) glRasterPos2f, + (glitz_gl_bitmap_t) glBitmap, + (glitz_gl_read_buffer_t) glReadBuffer, + (glitz_gl_draw_buffer_t) glDrawBuffer, + (glitz_gl_copy_pixels_t) glCopyPixels, + (glitz_gl_flush_t) glFlush, + (glitz_gl_finish_t) glFinish, + (glitz_gl_pixel_store_i_t) glPixelStorei, + (glitz_gl_ortho_t) glOrtho, + (glitz_gl_scale_f_t) glScalef, + (glitz_gl_translate_f_t) glTranslatef, + (glitz_gl_hint_t) glHint, + (glitz_gl_depth_mask_t) glDepthMask, + (glitz_gl_polygon_mode_t) glPolygonMode, + (glitz_gl_shade_model_t) glShadeModel, + (glitz_gl_color_mask_t) glColorMask, + (glitz_gl_read_pixels_t) glReadPixels, + (glitz_gl_get_tex_image_t) glGetTexImage, + (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, + (glitz_gl_gen_textures_t) glGenTextures, + (glitz_gl_delete_textures_t) glDeleteTextures, + (glitz_gl_bind_texture_t) glBindTexture, + (glitz_gl_tex_image_2d_t) glTexImage2D, + (glitz_gl_tex_parameter_i_t) glTexParameteri, + (glitz_gl_tex_parameter_fv_t) glTexParameterfv, + (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, + (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, + (glitz_gl_get_integer_v_t) glGetIntegerv, - /* extensions */ - (glitz_gl_blend_color_t) 0, - (glitz_gl_active_texture_t) 0, - (glitz_gl_client_active_texture_t) 0, - (glitz_gl_multi_draw_arrays_t) 0, - (glitz_gl_gen_programs_t) 0, - (glitz_gl_delete_programs_t) 0, - (glitz_gl_program_string_t) 0, - (glitz_gl_bind_program_t) 0, - (glitz_gl_program_local_param_4fv_t) 0, - (glitz_gl_get_program_iv_t) 0, - (glitz_gl_gen_buffers_t) 0, - (glitz_gl_delete_buffers_t) 0, - (glitz_gl_bind_buffer_t) 0, - (glitz_gl_buffer_data_t) 0, - (glitz_gl_buffer_sub_data_t) 0, - (glitz_gl_get_buffer_sub_data_t) 0, - (glitz_gl_map_buffer_t) 0, - (glitz_gl_unmap_buffer_t) 0 + /* extensions */ + (glitz_gl_blend_color_t) 0, + (glitz_gl_active_texture_t) 0, + (glitz_gl_client_active_texture_t) 0, + (glitz_gl_multi_draw_arrays_t) 0, + (glitz_gl_gen_programs_t) 0, + (glitz_gl_delete_programs_t) 0, + (glitz_gl_program_string_t) 0, + (glitz_gl_bind_program_t) 0, + (glitz_gl_program_local_param_4fv_t) 0, + (glitz_gl_get_program_iv_t) 0, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_buffer_sub_data_t) 0, + (glitz_gl_get_buffer_sub_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0, + (glitz_gl_gen_framebuffers_t) 0, + (glitz_gl_delete_framebuffers_t) 0, + (glitz_gl_bind_framebuffer_t) 0, + (glitz_gl_framebuffer_renderbuffer_t) 0, + (glitz_gl_framebuffer_texture_2d_t) 0, + (glitz_gl_check_framebuffer_status_t) 0, + (glitz_gl_gen_renderbuffers_t) 0, + (glitz_gl_delete_renderbuffers_t) 0, + (glitz_gl_bind_renderbuffer_t) 0, + (glitz_gl_renderbuffer_storage_t) 0, + (glitz_gl_get_renderbuffer_parameter_iv_t) 0 }; glitz_function_pointer_t glitz_egl_get_proc_address (const char *name, - void *closure) + void *closure) { - glitz_egl_screen_info_t *screen_info = (glitz_egl_screen_info_t *) closure; - glitz_egl_thread_info_t *info = screen_info->display_info->thread_info; - glitz_function_pointer_t address = NULL; + glitz_egl_screen_info_t *screen_info = (glitz_egl_screen_info_t *) closure; + glitz_egl_thread_info_t *info = screen_info->display_info->thread_info; + glitz_function_pointer_t address = NULL; - if (screen_info->egl_feature_mask & GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK) - address = eglGetProcAddress ((char *) name); - - if (!address) { - if (!info->dlhand) - info->dlhand = dlopen (info->gl_library, RTLD_LAZY); - - if (info->dlhand) { - dlerror (); - address = (glitz_function_pointer_t) dlsym (info->dlhand, name); - if (dlerror () != NULL) - address = NULL; + if (screen_info->egl_feature_mask & + GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK) + address = eglGetProcAddress ((char *) name); + + if (!address) { + if (!info->dlhand) + info->dlhand = dlopen (info->gl_library, RTLD_LAZY); + + if (info->dlhand) { + dlerror (); + address = (glitz_function_pointer_t) dlsym (info->dlhand, name); + if (dlerror () != NULL) + address = NULL; + } } - } - - return address; + + return address; } static void @@ -151,27 +164,27 @@ _glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info); static void _glitz_egl_thread_info_fini (glitz_egl_thread_info_t *thread_info) { - int i; - - for (i = 0; i < thread_info->n_displays; i++) - _glitz_egl_display_destroy (thread_info->displays[i]); + int i; - free (thread_info->displays); - - thread_info->displays = NULL; - thread_info->n_displays = 0; + for (i = 0; i < thread_info->n_displays; i++) + _glitz_egl_display_destroy (thread_info->displays[i]); - if (thread_info->gl_library) { - free (thread_info->gl_library); - thread_info->gl_library = NULL; - } + free (thread_info->displays); - if (thread_info->dlhand) { - dlclose (thread_info->dlhand); - thread_info->dlhand = NULL; - } - - thread_info->cctx = NULL; + thread_info->displays = NULL; + thread_info->n_displays = 0; + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + if (thread_info->dlhand) { + dlclose (thread_info->dlhand); + thread_info->dlhand = NULL; + } + + thread_info->cctx = NULL; } #ifdef PTHREADS @@ -183,108 +196,108 @@ static pthread_key_t info_tsd; static void _glitz_egl_thread_info_init (glitz_egl_thread_info_t *thread_info) { - thread_info->displays = NULL; - thread_info->n_displays = 0; - thread_info->gl_library = NULL; - thread_info->dlhand = NULL; - thread_info->cctx = NULL; + thread_info->displays = NULL; + thread_info->n_displays = 0; + thread_info->gl_library = NULL; + thread_info->dlhand = NULL; + thread_info->cctx = NULL; } static void _glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info) { - pthread_setspecific (info_tsd, NULL); - - if (thread_info) { - _glitz_egl_thread_info_fini (thread_info); - free (thread_info); - } + pthread_setspecific (info_tsd, NULL); + + if (thread_info) { + _glitz_egl_thread_info_fini (thread_info); + free (thread_info); + } } static void _tsd_destroy (void *p) { - if (p) { - _glitz_egl_thread_info_fini ((glitz_egl_thread_info_t *) p); - free (p); - } + if (p) { + _glitz_egl_thread_info_fini ((glitz_egl_thread_info_t *) p); + free (p); + } } static glitz_egl_thread_info_t * _glitz_egl_thread_info_get (const char *gl_library) { - glitz_egl_thread_info_t *thread_info; - void *p; - - if (!tsd_initialized) { - pthread_key_create (&info_tsd, _tsd_destroy); - tsd_initialized = 1; - } + glitz_egl_thread_info_t *thread_info; + void *p; - p = pthread_getspecific (info_tsd); - - if (p == NULL) { - thread_info = malloc (sizeof (glitz_egl_thread_info_t)); - _glitz_egl_thread_info_init (thread_info); - - pthread_setspecific (info_tsd, thread_info); - } else - thread_info = (glitz_egl_thread_info_t *) p; - - if (gl_library) { - int len = strlen (gl_library); - - if (thread_info->gl_library) { - free (thread_info->gl_library); - thread_info->gl_library = NULL; + if (!tsd_initialized) { + pthread_key_create (&info_tsd, _tsd_destroy); + tsd_initialized = 1; } - - thread_info->gl_library = malloc (len + 1); - if (thread_info->gl_library) { - memcpy (thread_info->gl_library, gl_library, len); - thread_info->gl_library[len] = '\0'; - } - } - return thread_info; + p = pthread_getspecific (info_tsd); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_egl_thread_info_t)); + _glitz_egl_thread_info_init (thread_info); + + pthread_setspecific (info_tsd, thread_info); + } else + thread_info = (glitz_egl_thread_info_t *) p; + + if (gl_library) { + int len = strlen (gl_library); + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + thread_info->gl_library = malloc (len + 1); + if (thread_info->gl_library) { + memcpy (thread_info->gl_library, gl_library, len); + thread_info->gl_library[len] = '\0'; + } + } + + return thread_info; } #else /* not thread safe */ static glitz_egl_thread_info_t thread_info = { - NULL, - 0, - NULL, - NULL + NULL, + 0, + NULL, + NULL }; static void _glitz_egl_thread_info_destroy (glitz_egl_thread_info_t *thread_info) { - if (thread_info) - _glitz_egl_thread_info_fini (thread_info); + if (thread_info) + _glitz_egl_thread_info_fini (thread_info); } static glitz_egl_thread_info_t * _glitz_egl_thread_info_get (const char *gl_library) { - if (gl_library) { - int len = strlen (gl_library); + if (gl_library) { + int len = strlen (gl_library); - if (thread_info.gl_library) { - free (thread_info.gl_library); - thread_info.gl_library = NULL; + if (thread_info.gl_library) { + free (thread_info.gl_library); + thread_info.gl_library = NULL; + } + + thread_info.gl_library = malloc (len + 1); + if (thread_info.gl_library) { + memcpy (thread_info.gl_library, gl_library, len); + thread_info.gl_library[len] = '\0'; + } } - - thread_info.gl_library = malloc (len + 1); - if (thread_info.gl_library) { - memcpy (thread_info.gl_library, gl_library, len); - thread_info.gl_library[len] = '\0'; - } - } - - return &thread_info; + + return &thread_info; } #endif @@ -292,141 +305,145 @@ _glitz_egl_thread_info_get (const char *gl_library) static glitz_egl_display_info_t * _glitz_egl_display_info_get (EGLDisplay egl_display) { - glitz_egl_display_info_t *display_info; - glitz_egl_thread_info_t *thread_info = _glitz_egl_thread_info_get (NULL); - glitz_egl_display_info_t **displays = thread_info->displays; - int index, n_displays = thread_info->n_displays; + glitz_egl_display_info_t *display_info; + glitz_egl_thread_info_t *thread_info = _glitz_egl_thread_info_get (NULL); + glitz_egl_display_info_t **displays = thread_info->displays; + int index, n_displays = thread_info->n_displays; - for (; n_displays; n_displays--, displays++) - if ((*displays)->egl_display == egl_display) - return *displays; + for (; n_displays; n_displays--, displays++) + if ((*displays)->egl_display == egl_display) + return *displays; - index = thread_info->n_displays++; + index = thread_info->n_displays++; - thread_info->displays = - realloc (thread_info->displays, - sizeof (glitz_egl_display_info_t *) * thread_info->n_displays); + thread_info->displays = + realloc (thread_info->displays, + sizeof (glitz_egl_display_info_t *) * + thread_info->n_displays); - display_info = malloc (sizeof (glitz_egl_display_info_t)); - thread_info->displays[index] = display_info; - - display_info->thread_info = thread_info; - display_info->egl_display = egl_display; - display_info->screens = NULL; - display_info->n_screens = 0; - - return display_info; + display_info = malloc (sizeof (glitz_egl_display_info_t)); + thread_info->displays[index] = display_info; + + display_info->thread_info = thread_info; + display_info->egl_display = egl_display; + display_info->screens = NULL; + display_info->n_screens = 0; + + return display_info; } static void _glitz_egl_display_destroy (glitz_egl_display_info_t *display_info) { - int i; - - for (i = 0; i < display_info->n_screens; i++) - _glitz_egl_screen_destroy (display_info->screens[i]); + int i; - if (display_info->screens) - free (display_info->screens); - - free (display_info); + for (i = 0; i < display_info->n_screens; i++) + _glitz_egl_screen_destroy (display_info->screens[i]); + + if (display_info->screens) + free (display_info->screens); + + free (display_info); } glitz_egl_screen_info_t * glitz_egl_screen_info_get (EGLDisplay display, - EGLScreenMESA screen) + EGLScreenMESA screen) { - glitz_egl_screen_info_t *screen_info; - glitz_egl_display_info_t *display_info = - _glitz_egl_display_info_get (display); - glitz_egl_screen_info_t **screens = display_info->screens; - int index, n_screens = display_info->n_screens; + glitz_egl_screen_info_t *screen_info; + glitz_egl_display_info_t *display_info = + _glitz_egl_display_info_get (display); + glitz_egl_screen_info_t **screens = display_info->screens; + int index, n_screens = display_info->n_screens; + #if 0 - int error_base, event_base; -#endif - - for (; n_screens; n_screens--, screens++) - if ((*screens)->screen == screen) - return *screens; - - index = display_info->n_screens++; - - display_info->screens = - realloc (display_info->screens, - sizeof (glitz_egl_screen_info_t *) * display_info->n_screens); - - screen_info = malloc (sizeof (glitz_egl_screen_info_t)); - display_info->screens[index] = screen_info; - - screen_info->display_info = display_info; - screen_info->screen = screen; - screen_info->drawables = 0; - screen_info->formats = NULL; - screen_info->egl_config_ids = NULL; - screen_info->n_formats = 0; - - screen_info->contexts = NULL; - screen_info->n_contexts = 0; - - glitz_program_map_init (&screen_info->program_map); - - screen_info->egl_root_context = (EGLContext) 0; - screen_info->egl_feature_mask = 0; -#if 0 - if (eglQueryExtension (display, &error_base, &event_base)) { - int major, minor; - - if (eglQueryVersion (display, &major, &minor)) { - screen_info->egl_version = major + minor / 10.0f; - if (major > 1 || (major > 0 || minor >= 2)) { - glitz_egl_query_extensions (screen_info, screen_info->egl_version); - _glitz_egl_proc_address_lookup (screen_info); - glitz_egl_query_formats (screen_info); - } - } - } + int error_base, event_base; #endif - glitz_egl_query_extensions (screen_info, screen_info->egl_version); - glitz_egl_query_configs (screen_info); - - screen_info->context_stack_size = 1; - screen_info->context_stack->drawable = NULL; - screen_info->context_stack->surface = NULL; - screen_info->context_stack->constraint = GLITZ_NONE; - - return screen_info; + + for (; n_screens; n_screens--, screens++) + if ((*screens)->screen == screen) + return *screens; + + index = display_info->n_screens++; + + display_info->screens = + realloc (display_info->screens, + sizeof (glitz_egl_screen_info_t *) * display_info->n_screens); + + screen_info = malloc (sizeof (glitz_egl_screen_info_t)); + display_info->screens[index] = screen_info; + + screen_info->display_info = display_info; + screen_info->screen = screen; + screen_info->drawables = 0; + screen_info->formats = NULL; + screen_info->n_formats = 0; + + screen_info->contexts = NULL; + screen_info->n_contexts = 0; + + glitz_program_map_init (&screen_info->program_map); + + screen_info->egl_root_context = (EGLContext) 0; + screen_info->egl_feature_mask = 0; + +#if 0 + if (eglQueryExtension (display, &error_base, &event_base)) { + int major, minor; + + if (eglQueryVersion (display, &major, &minor)) { + screen_info->egl_version = major + minor / 10.0f; + if (major > 1 || (major > 0 || minor >= 2)) { + glitz_egl_query_extensions (screen_info, + screen_info->egl_version); + _glitz_egl_proc_address_lookup (screen_info); + glitz_egl_query_formats (screen_info); + } + } + } +#endif + + glitz_egl_query_extensions (screen_info, screen_info->egl_version); + glitz_egl_query_configs (screen_info); + + screen_info->context_stack_size = 1; + screen_info->context_stack->drawable = NULL; + screen_info->context_stack->surface = NULL; + screen_info->context_stack->constraint = GLITZ_NONE; + + return screen_info; } static void _glitz_egl_screen_destroy (glitz_egl_screen_info_t *screen_info) { - EGLDisplay egl_display = screen_info->display_info->egl_display; - int i; + EGLDisplay egl_display = screen_info->display_info->egl_display; + int i; - if (screen_info->egl_root_context) - eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - for (i = 0; i < screen_info->n_contexts; i++) - glitz_egl_context_destroy (screen_info, screen_info->contexts[i]); + if (screen_info->egl_root_context) + eglMakeCurrent (egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); - free (screen_info->contexts); - free (screen_info->formats); - free (screen_info->egl_config_ids); - free (screen_info); + for (i = 0; i < screen_info->n_contexts; i++) + glitz_egl_context_destroy (screen_info, screen_info->contexts[i]); + + free (screen_info->contexts); + free (screen_info->formats); + free (screen_info); } void glitz_egl_init (const char *gl_library) { - _glitz_egl_thread_info_get (gl_library); + _glitz_egl_thread_info_get (gl_library); } slim_hidden_def(glitz_egl_init); void glitz_egl_fini (void) { - glitz_egl_thread_info_t *info = _glitz_egl_thread_info_get (NULL); + glitz_egl_thread_info_t *info = _glitz_egl_thread_info_get (NULL); - _glitz_egl_thread_info_destroy (info); + _glitz_egl_thread_info_destroy (info); } slim_hidden_def(glitz_egl_fini); diff --git a/gfx/cairo/glitz/src/egl/glitz_egl_pbuffer.c b/gfx/cairo/glitz/src/egl/glitz_egl_pbuffer.c index cfe147af710..0bf1e2b777a 100644 --- a/gfx/cairo/glitz/src/egl/glitz_egl_pbuffer.c +++ b/gfx/cairo/glitz/src/egl/glitz_egl_pbuffer.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,37 +31,39 @@ EGLSurface glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info, - EGLConfig egl_config, - int width, - int height) + EGLConfig egl_config, + int width, + int height) { - if (egl_config) { - int attributes[9]; + if (egl_config) { + int attributes[9]; - attributes[0] = EGL_WIDTH; - attributes[1] = width; + attributes[0] = EGL_WIDTH; + attributes[1] = width; - attributes[2] = EGL_HEIGHT; - attributes[3] = height; -#if 0 - attributes[4] = EGL_LARGEST_PBUFFER; - attributes[5] = 0; + attributes[2] = EGL_HEIGHT; + attributes[3] = height; - attributes[6] = EGL_PRESERVED_CONTENTS; - attributes[7] = 1; - attributes[8] = 0; +#if 0 + attributes[4] = EGL_LARGEST_PBUFFER; + attributes[5] = 0; + + attributes[6] = EGL_PRESERVED_CONTENTS; + attributes[7] = 1; + attributes[8] = 0; #endif - return - eglCreatePbufferSurface(screen_info->display_info->egl_display, - egl_config, attributes); - } else - return (EGLSurface) 0; + + return + eglCreatePbufferSurface (screen_info->display_info->egl_display, + egl_config, attributes); + } else + return (EGLSurface) 0; } -void +void glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info, - EGLSurface egl_pbuffer) + EGLSurface egl_pbuffer) { - eglDestroySurface(screen_info->display_info->egl_display, - egl_pbuffer); + eglDestroySurface (screen_info->display_info->egl_display, + egl_pbuffer); } diff --git a/gfx/cairo/glitz/src/egl/glitz_egl_surface.c b/gfx/cairo/glitz/src/egl/glitz_egl_surface.c index 0aa93a5231c..d98be643c3d 100644 --- a/gfx/cairo/glitz/src/egl/glitz_egl_surface.c +++ b/gfx/cairo/glitz/src/egl/glitz_egl_surface.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,173 +31,213 @@ static glitz_egl_surface_t * _glitz_egl_create_surface (glitz_egl_screen_info_t *screen_info, - glitz_egl_context_t *context, - glitz_drawable_format_t *format, - EGLSurface egl_surface, - int width, - int height) + glitz_egl_context_t *context, + glitz_drawable_format_t *format, + EGLSurface egl_surface, + int width, + int height) { - glitz_egl_surface_t *surface; - - if (width <= 0 || height <= 0) - return NULL; + glitz_egl_surface_t *surface; - surface = (glitz_egl_surface_t *) malloc (sizeof (glitz_egl_surface_t)); - if (surface == NULL) - return NULL; + surface = (glitz_egl_surface_t *) malloc (sizeof (glitz_egl_surface_t)); + if (surface == NULL) + return NULL; - surface->base.ref_count = 1; - surface->screen_info = screen_info; - surface->context = context; - surface->egl_surface = egl_surface; - surface->base.format = format; - surface->base.backend = &context->backend; + surface->screen_info = screen_info; + surface->context = context; + surface->egl_surface = egl_surface; + surface->width = width; + surface->height = height; - glitz_drawable_update_size (&surface->base, width, height); + _glitz_drawable_init (&surface->base, + &screen_info->formats[format->id], + &context->backend, + width, height); - if (!context->initialized) { - glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT); - glitz_egl_pop_current (surface); - } - - if (width > context->max_viewport_dims[0] || - height > context->max_viewport_dims[1]) { - free (surface); - return NULL; - } - - screen_info->drawables++; - - return surface; + if (!context->initialized) { + glitz_egl_push_current (surface, NULL, GLITZ_CONTEXT_CURRENT); + glitz_egl_pop_current (surface); + } + + if (width > context->backend.max_viewport_dims[0] || + height > context->backend.max_viewport_dims[1]) { + free (surface); + return NULL; + } + + screen_info->drawables++; + + return surface; +} + +glitz_bool_t +_glitz_egl_drawable_update_size (glitz_egl_surface_t *drawable, + int width, + int height) +{ + if (drawable->egl_surface) + { + glitz_egl_pbuffer_destroy (drawable->screen_info, + drawable->egl_surface); + drawable->egl_surface = + glitz_egl_pbuffer_create (drawable->screen_info, + drawable->context->egl_config, + (int) width, (int) height); + if (!drawable->egl_surface) + return 0; + } + + drawable->width = width; + drawable->height = height; + + return 1; } static glitz_drawable_t * _glitz_egl_create_pbuffer_surface (glitz_egl_screen_info_t *screen_info, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_egl_surface_t *surface; - glitz_egl_context_t *context; - EGLSurface egl_pbuffer; + glitz_egl_surface_t *surface; + glitz_egl_context_t *context; + EGLSurface egl_pbuffer; - if (!format->types.pbuffer) - return NULL; - - context = glitz_egl_context_get (screen_info, format); - if (!context) - return NULL; + context = glitz_egl_context_get (screen_info, format); + if (!context) + return NULL; - egl_pbuffer = glitz_egl_pbuffer_create (screen_info, context->egl_config, - (int) width, (int) height); - if (!egl_pbuffer) - return NULL; - - surface = _glitz_egl_create_surface (screen_info, context, format, - egl_pbuffer, - width, height); - if (!surface) { - glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer); - return NULL; - } - - return &surface->base; + egl_pbuffer = glitz_egl_pbuffer_create (screen_info, context->egl_config, + (int) width, (int) height); + if (!egl_pbuffer) + return NULL; + + surface = _glitz_egl_create_surface (screen_info, context, format, + egl_pbuffer, + width, height); + if (!surface) + { + glitz_egl_pbuffer_destroy (screen_info, egl_pbuffer); + return NULL; + } + + return &surface->base; } glitz_drawable_t * glitz_egl_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_egl_surface_t *templ = (glitz_egl_surface_t *) abstract_templ; + glitz_egl_surface_t *templ = (glitz_egl_surface_t *) abstract_templ; - return _glitz_egl_create_pbuffer_surface (templ->screen_info, format, - width, height); + return _glitz_egl_create_pbuffer_surface (templ->screen_info, format, + width, height); } glitz_drawable_t * glitz_egl_create_surface (EGLDisplay egl_display, - EGLScreenMESA egl_screen, - glitz_drawable_format_t *format, - EGLSurface egl_surface, - unsigned int width, - unsigned int height) + EGLScreenMESA egl_screen, + glitz_drawable_format_t *format, + EGLSurface egl_surface, + unsigned int width, + unsigned int height) { - glitz_egl_surface_t *surface; - glitz_egl_screen_info_t *screen_info; - glitz_egl_context_t *context; + glitz_egl_surface_t *surface; + glitz_egl_screen_info_t *screen_info; + glitz_egl_context_t *context; + glitz_int_drawable_format_t *iformat; - screen_info = glitz_egl_screen_info_get (egl_display, egl_screen); - if (!screen_info) - return NULL; - - context = glitz_egl_context_get (screen_info, format); - if (!context) - return NULL; - - surface = _glitz_egl_create_surface (screen_info, context, format, - egl_surface, - width, height); - if (!surface) - return NULL; + screen_info = glitz_egl_screen_info_get (egl_display, egl_screen); + if (!screen_info) + return NULL; - return &surface->base; + if (format->id >= screen_info->n_formats) + return NULL; + + iformat = &screen_info->formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)) + return NULL; + + context = glitz_egl_context_get (screen_info, format); + if (!context) + return NULL; + + surface = _glitz_egl_create_surface (screen_info, context, format, + egl_surface, width, height); + if (!surface) + return NULL; + + return &surface->base; } slim_hidden_def(glitz_egl_create_surface); glitz_drawable_t * glitz_egl_create_pbuffer_surface (EGLDisplay display, - EGLScreenMESA screen, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + EGLScreenMESA screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_egl_screen_info_t *screen_info; + glitz_egl_screen_info_t *screen_info; + glitz_int_drawable_format_t *iformat; - screen_info = glitz_egl_screen_info_get (display, screen); - if (!screen_info) - return NULL; + screen_info = glitz_egl_screen_info_get (display, screen); + if (!screen_info) + return NULL; - return _glitz_egl_create_pbuffer_surface (screen_info, format, - width, height); + if (format->id >= screen_info->n_formats) + return NULL; + + iformat = &screen_info->formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)) + return NULL; + + return _glitz_egl_create_pbuffer_surface (screen_info, format, + width, height); } slim_hidden_def(glitz_egl_create_pbuffer_surface); void glitz_egl_destroy (void *abstract_drawable) { - EGLint value; - glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; + EGLint value; + glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; - surface->screen_info->drawables--; - if (surface->screen_info->drawables == 0) { - /* - * Last drawable? We have to destroy all fragment programs as this may - * be our last chance to have a context current. - */ - glitz_egl_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT); - glitz_program_map_fini (&surface->base.backend->gl, - &surface->screen_info->program_map); - glitz_egl_pop_current (abstract_drawable); - } + surface->screen_info->drawables--; + if (surface->screen_info->drawables == 0) { + /* + * Last drawable? We have to destroy all fragment programs as this may + * be our last chance to have a context current. + */ + glitz_egl_push_current (abstract_drawable, NULL, + GLITZ_CONTEXT_CURRENT); + glitz_program_map_fini (surface->base.backend->gl, + &surface->screen_info->program_map); + glitz_egl_pop_current (abstract_drawable); + } - if (eglGetCurrentSurface ( 0 ) == surface->egl_surface) - eglMakeCurrent (surface->screen_info->display_info->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - - eglQuerySurface (surface->screen_info->display_info->egl_display, surface->egl_surface, - EGL_SURFACE_TYPE, &value); - if (value == EGL_PBUFFER_BIT) - glitz_egl_pbuffer_destroy (surface->screen_info, surface->egl_surface); - - free (surface); + if (eglGetCurrentSurface (0) == surface->egl_surface) + eglMakeCurrent (surface->screen_info->display_info->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + eglQuerySurface (surface->screen_info->display_info->egl_display, + surface->egl_surface, + EGL_SURFACE_TYPE, &value); + if (value == EGL_PBUFFER_BIT) + glitz_egl_pbuffer_destroy (surface->screen_info, surface->egl_surface); + + free (surface); } -void +glitz_bool_t glitz_egl_swap_buffers (void *abstract_drawable) { - glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; + glitz_egl_surface_t *surface = (glitz_egl_surface_t *) abstract_drawable; - eglSwapBuffers (surface->screen_info->display_info->egl_display, - surface->egl_surface); + eglSwapBuffers (surface->screen_info->display_info->egl_display, + surface->egl_surface); + + return 1; } diff --git a/gfx/cairo/glitz/src/egl/glitz_eglext.h b/gfx/cairo/glitz/src/egl/glitz_eglext.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/gfx/cairo/glitz/src/egl/glitz_eglint.h b/gfx/cairo/glitz/src/egl/glitz_eglint.h index dc81b17e25e..f97896f5347 100644 --- a/gfx/cairo/glitz/src/egl/glitz_eglint.h +++ b/gfx/cairo/glitz/src/egl/glitz_eglint.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,8 +31,6 @@ #include "glitz-egl.h" -#include "glitz_eglext.h" - #define GLITZ_EGL_FEATURE_MAKE_CURRENT_READ_MASK (1L << 2) #define GLITZ_EGL_FEATURE_GET_PROC_ADDRESS_MASK (1L << 3) #define GLITZ_EGL_FEATURE_MULTISAMPLE_MASK (1L << 4) @@ -43,113 +41,116 @@ typedef struct _glitz_egl_screen_info_t glitz_egl_screen_info_t; typedef struct _glitz_egl_display_info_t glitz_egl_display_info_t; typedef struct _glitz_egl_thread_info_t { - glitz_egl_display_info_t **displays; - int n_displays; - char *gl_library; - void *dlhand; - glitz_context_t *cctx; + glitz_egl_display_info_t **displays; + int n_displays; + char *gl_library; + void *dlhand; + glitz_context_t *cctx; } glitz_egl_thread_info_t; struct _glitz_egl_display_info_t { - glitz_egl_thread_info_t *thread_info; - EGLDisplay egl_display; - glitz_egl_screen_info_t **screens; - int n_screens; + glitz_egl_thread_info_t *thread_info; + EGLDisplay egl_display; + glitz_egl_screen_info_t **screens; + int n_screens; }; typedef struct _glitz_egl_context_info_t { - glitz_egl_surface_t *drawable; - glitz_surface_t *surface; - glitz_constraint_t constraint; + glitz_egl_surface_t *drawable; + glitz_surface_t *surface; + glitz_constraint_t constraint; } glitz_egl_context_info_t; typedef struct _glitz_egl_context_t { - glitz_context_t base; - EGLContext egl_context; - glitz_format_id_t id; - EGLConfig egl_config; - glitz_backend_t backend; - glitz_gl_int_t max_viewport_dims[2]; - glitz_gl_int_t max_texture_2d_size; - glitz_gl_int_t max_texture_rect_size; - glitz_bool_t initialized; + glitz_context_t base; + EGLContext egl_context; + glitz_format_id_t id; + EGLConfig egl_config; + glitz_backend_t backend; + glitz_bool_t initialized; } glitz_egl_context_t; struct _glitz_egl_screen_info_t { - glitz_egl_display_info_t *display_info; - int screen; - int drawables; - glitz_drawable_format_t *formats; - EGLConfig *egl_config_ids; - int n_formats; - glitz_egl_context_t **contexts; - int n_contexts; - glitz_egl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; - int context_stack_size; - EGLContext egl_root_context; - unsigned long egl_feature_mask; - glitz_gl_float_t egl_version; - glitz_program_map_t program_map; + glitz_egl_display_info_t *display_info; + int screen; + int drawables; + glitz_int_drawable_format_t *formats; + int n_formats; + glitz_egl_context_t **contexts; + int n_contexts; + glitz_egl_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; + int context_stack_size; + EGLContext egl_root_context; + unsigned long egl_feature_mask; + glitz_gl_float_t egl_version; + glitz_program_map_t program_map; }; struct _glitz_egl_surface { - glitz_drawable_t base; - - glitz_egl_screen_info_t *screen_info; - glitz_egl_context_t *context; - EGLSurface egl_surface; + glitz_drawable_t base; + + glitz_egl_screen_info_t *screen_info; + glitz_egl_context_t *context; + EGLSurface egl_surface; + int width; + int height; }; extern void __internal_linkage glitz_egl_query_extensions (glitz_egl_screen_info_t *screen_info, - glitz_gl_float_t egl_version); + glitz_gl_float_t egl_version); extern glitz_egl_screen_info_t __internal_linkage * glitz_egl_screen_info_get (EGLDisplay egl_display, - EGLScreenMESA egl_screen); + EGLScreenMESA egl_screen); extern glitz_function_pointer_t __internal_linkage glitz_egl_get_proc_address (const char *name, - void *closure); + void *closure); extern glitz_egl_context_t __internal_linkage * glitz_egl_context_get (glitz_egl_screen_info_t *screen_info, - glitz_drawable_format_t *format); + glitz_drawable_format_t *format); extern void __internal_linkage glitz_egl_context_destroy (glitz_egl_screen_info_t *screen_info, - glitz_egl_context_t *context); + glitz_egl_context_t *context); extern void __internal_linkage glitz_egl_query_configs (glitz_egl_screen_info_t *screen_info); +extern glitz_bool_t __internal_linkage +_glitz_egl_drawable_update_size (glitz_egl_surface_t *drawable, + int width, + int height); + extern EGLSurface __internal_linkage glitz_egl_pbuffer_create (glitz_egl_screen_info_t *screen_info, - EGLConfig egl_config, - int width, - int height); + EGLConfig egl_config, + int width, + int height); extern void __internal_linkage glitz_egl_pbuffer_destroy (glitz_egl_screen_info_t *screen_info, - EGLSurface egl_pbuffer); + EGLSurface egl_pbuffer); extern glitz_drawable_t __internal_linkage * glitz_egl_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_egl_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint); + glitz_surface_t *surface, + glitz_constraint_t constraint); extern glitz_surface_t __internal_linkage * glitz_egl_pop_current (void *abstract_drawable); void glitz_egl_make_current (void *abstract_drawable, - glitz_constraint_t constraint); + glitz_constraint_t constraint); extern glitz_status_t __internal_linkage glitz_egl_make_current_read (void *abstract_surface); @@ -157,14 +158,15 @@ glitz_egl_make_current_read (void *abstract_surface); extern void __internal_linkage glitz_egl_destroy (void *abstract_drawable); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_egl_swap_buffers (void *abstract_drawable); -/* Avoid unnecessary PLT entries. */ +/* Avoid unnecessary PLT entries. */ slim_hidden_proto(glitz_egl_init) slim_hidden_proto(glitz_egl_fini) -slim_hidden_proto(glitz_egl_find_config) +slim_hidden_proto(glitz_egl_find_window_config) +slim_hidden_proto(glitz_egl_find_pbuffer_config) slim_hidden_proto(glitz_egl_create_surface) slim_hidden_proto(glitz_egl_create_pbuffer_surface) diff --git a/gfx/cairo/glitz/src/glitz.c b/gfx/cairo/glitz/src/glitz.c index 7bdaade7dec..dbe2ba272e3 100644 --- a/gfx/cairo/glitz/src/glitz.c +++ b/gfx/cairo/glitz/src/glitz.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -43,25 +43,26 @@ typedef struct _glitz_texture_unit_t { void glitz_composite (glitz_operator_t op, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst, - int x_src, - int y_src, - int x_mask, - int y_mask, - int x_dst, - int y_dst, - int width, - int height) + glitz_surface_t *src, + glitz_surface_t *mask, + glitz_surface_t *dst, + int x_src, + int y_src, + int x_mask, + int y_mask, + int x_dst, + int y_dst, + int width, + int height) { - glitz_composite_op_t comp_op; - int i, texture_nr = -1; - glitz_texture_t *stexture, *mtexture; - glitz_texture_unit_t textures[3]; - glitz_box_t bounds; - glitz_bool_t no_border_clamp; - unsigned long flags; + glitz_composite_op_t comp_op; + int i, texture_nr = -1; + glitz_texture_t *stexture, *mtexture; + glitz_texture_unit_t textures[3]; + glitz_texture_parameters_t param; + glitz_box_t bounds; + glitz_bool_t no_border_clamp; + unsigned long flags; GLITZ_GL_SURFACE (dst); @@ -69,279 +70,286 @@ glitz_composite (glitz_operator_t op, bounds.y1 = MAX (y_dst, 0); bounds.x2 = x_dst + width; bounds.y2 = y_dst + height; - + if (bounds.x2 > dst->box.x2) - bounds.x2 = dst->box.x2; + bounds.x2 = dst->box.x2; if (bounds.y2 > dst->box.y2) - bounds.y2 = dst->box.y2; + bounds.y2 = dst->box.y2; if (bounds.x1 >= bounds.x2 || bounds.y1 >= bounds.y2) - return; + return; if (dst->geometry.buffer && (!dst->geometry.count)) - return; - + return; + glitz_composite_op_init (&comp_op, op, src, mask, dst); if (comp_op.type == GLITZ_COMBINE_TYPE_NA) { - glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); - return; + glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); + return; } src = comp_op.src; mask = comp_op.mask; + param.border_color.red = param.border_color.green = + param.border_color.blue = param.border_color.alpha = 0; + if (src) { - stexture = glitz_surface_get_texture (src, 0); - if (!stexture) - return; + stexture = glitz_surface_get_texture (src, 0); + if (!stexture) + return; } else - stexture = NULL; + stexture = NULL; if (mask) { - mtexture = glitz_surface_get_texture (mask, 0); - if (!mtexture) - return; + mtexture = glitz_surface_get_texture (mask, 0); + if (!mtexture) + return; } else - mtexture = NULL; + mtexture = NULL; if (!glitz_surface_push_current (dst, GLITZ_DRAWABLE_CURRENT)) { - glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); - glitz_surface_pop_current (dst); - return; + glitz_surface_status_add (dst, GLITZ_STATUS_NOT_SUPPORTED_MASK); + glitz_surface_pop_current (dst); + return; } - + no_border_clamp = !(dst->drawable->backend->feature_mask & - GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK); + GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK); if (mtexture) { - textures[0].texture = mtexture; - textures[0].unit = _texture_units[0]; - textures[0].transform = 0; - texture_nr = 0; + textures[0].texture = mtexture; + textures[0].unit = _texture_units[0]; + textures[0].transform = 0; + texture_nr = 0; - glitz_texture_bind (gl, mtexture); + glitz_texture_bind (gl, mtexture); - flags = mask->flags | GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK; - if (dst->geometry.attributes & GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) - { - flags &= ~GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK; - - if (dst->geometry.u.v.mask.size == 2) - flags &= ~GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK; - } + flags = mask->flags | GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK; + if (dst->geometry.attributes & GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) + { + flags &= ~GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK; - glitz_texture_set_tex_gen (gl, - mtexture, - &dst->geometry, - x_dst - x_mask, - y_dst - y_mask, - flags, - &dst->geometry.u.v.mask); - - if (mask->transform) - { - textures[0].transform = 1; - gl->matrix_mode (GLITZ_GL_TEXTURE); - gl->load_matrix_f (SURFACE_EYE_COORDS (mask)? - mask->transform->m: mask->transform->t); - gl->matrix_mode (GLITZ_GL_MODELVIEW); - - if (SURFACE_LINEAR_TRANSFORM_FILTER (mask)) - glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_LINEAR); - else - glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_NEAREST); - } - else - { - if ((dst->geometry.attributes & - GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) && - SURFACE_LINEAR_TRANSFORM_FILTER (mask)) - glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_LINEAR); - else - glitz_texture_ensure_filter (gl, mtexture, GLITZ_GL_NEAREST); - } - - if (SURFACE_REPEAT (mask)) - { - if (SURFACE_MIRRORED (mask)) - glitz_texture_ensure_wrap (gl, mtexture, - GLITZ_GL_MIRRORED_REPEAT); - else - glitz_texture_ensure_wrap (gl, mtexture, GLITZ_GL_REPEAT); - } - else - { - if (no_border_clamp || SURFACE_PAD (mask)) - glitz_texture_ensure_wrap (gl, mtexture, - GLITZ_GL_CLAMP_TO_EDGE); - else - glitz_texture_ensure_wrap (gl, mtexture, - GLITZ_GL_CLAMP_TO_BORDER); - } + if (dst->geometry.u.v.mask.size == 2) + flags &= ~GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK; + } + + glitz_texture_set_tex_gen (gl, + mtexture, + &dst->geometry, + x_dst - x_mask, + y_dst - y_mask, + flags, + &dst->geometry.u.v.mask); + + if (mask->transform) + { + textures[0].transform = 1; + gl->matrix_mode (GLITZ_GL_TEXTURE); + gl->load_matrix_f (SURFACE_EYE_COORDS (mask)? + mask->transform->m: mask->transform->t); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + + if (SURFACE_LINEAR_TRANSFORM_FILTER (mask)) + param.filter[0] = GLITZ_GL_LINEAR; + else + param.filter[0] = GLITZ_GL_NEAREST; + } + else + { + if ((dst->geometry.attributes & + GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) && + SURFACE_LINEAR_TRANSFORM_FILTER (mask)) + param.filter[0] = GLITZ_GL_LINEAR; + else + param.filter[0] = GLITZ_GL_NEAREST; + } + + if (SURFACE_REPEAT (mask)) + { + if (SURFACE_MIRRORED (mask)) + param.wrap[0] = GLITZ_GL_MIRRORED_REPEAT; + else + param.wrap[0] = GLITZ_GL_REPEAT; + } + else + { + if (no_border_clamp || SURFACE_PAD (mask)) + param.wrap[0] = GLITZ_GL_CLAMP_TO_EDGE; + else + param.wrap[0] = GLITZ_GL_CLAMP_TO_BORDER; + } + + param.filter[1] = param.filter[0]; + param.wrap[1] = param.wrap[0]; + + glitz_texture_ensure_parameters (gl, mtexture, ¶m); } - + if (stexture) { - int last_texture_nr = comp_op.combine->texture_units - 1; - - while (texture_nr < last_texture_nr) - { - textures[++texture_nr].texture = stexture; - textures[texture_nr].unit = _texture_units[texture_nr]; - textures[texture_nr].transform = 0; - if (texture_nr > 0) - { - gl->active_texture (textures[texture_nr].unit); - gl->client_active_texture (textures[texture_nr].unit); - } - glitz_texture_bind (gl, stexture); - } + int last_texture_nr = comp_op.combine->texture_units - 1; - flags = src->flags | GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK; - if (dst->geometry.attributes & GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) - { - flags &= ~GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK; - - if (dst->geometry.u.v.src.size == 2) - flags &= ~GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK; - } - - glitz_texture_set_tex_gen (gl, - stexture, - &dst->geometry, - x_dst - x_src, - y_dst - y_src, - flags, - &dst->geometry.u.v.src); + while (texture_nr < last_texture_nr) + { + textures[++texture_nr].texture = stexture; + textures[texture_nr].unit = _texture_units[texture_nr]; + textures[texture_nr].transform = 0; + if (texture_nr > 0) + { + gl->active_texture (textures[texture_nr].unit); + gl->client_active_texture (textures[texture_nr].unit); + } + glitz_texture_bind (gl, stexture); + } - if (src->transform) - { - textures[texture_nr].transform = 1; - gl->matrix_mode (GLITZ_GL_TEXTURE); - gl->load_matrix_f (SURFACE_EYE_COORDS (src)? - src->transform->m: src->transform->t); - gl->matrix_mode (GLITZ_GL_MODELVIEW); + flags = src->flags | GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK; + if (dst->geometry.attributes & GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) + { + flags &= ~GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK; - if (SURFACE_LINEAR_TRANSFORM_FILTER (src)) - glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_LINEAR); - else - glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_NEAREST); - } - else - { - if ((dst->geometry.attributes & - GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) && - SURFACE_LINEAR_TRANSFORM_FILTER (src)) - glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_LINEAR); - else - glitz_texture_ensure_filter (gl, stexture, GLITZ_GL_NEAREST); - } - - if (SURFACE_REPEAT (src)) - { - if (SURFACE_MIRRORED (src)) - glitz_texture_ensure_wrap (gl, stexture, - GLITZ_GL_MIRRORED_REPEAT); - else - glitz_texture_ensure_wrap (gl, stexture, GLITZ_GL_REPEAT); - } - else - { - if (no_border_clamp || SURFACE_PAD (src)) - glitz_texture_ensure_wrap (gl, stexture, - GLITZ_GL_CLAMP_TO_EDGE); - else - glitz_texture_ensure_wrap (gl, stexture, - GLITZ_GL_CLAMP_TO_BORDER); - } + if (dst->geometry.u.v.src.size == 2) + flags &= ~GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK; + } + + glitz_texture_set_tex_gen (gl, + stexture, + &dst->geometry, + x_dst - x_src, + y_dst - y_src, + flags, + &dst->geometry.u.v.src); + + if (src->transform) + { + textures[texture_nr].transform = 1; + gl->matrix_mode (GLITZ_GL_TEXTURE); + gl->load_matrix_f (SURFACE_EYE_COORDS (src)? + src->transform->m: src->transform->t); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + + if (SURFACE_LINEAR_TRANSFORM_FILTER (src)) + param.filter[0] = GLITZ_GL_LINEAR; + else + param.filter[0] = GLITZ_GL_NEAREST; + } + else + { + if ((dst->geometry.attributes & + GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) && + SURFACE_LINEAR_TRANSFORM_FILTER (src)) + param.filter[0] = GLITZ_GL_LINEAR; + else + param.filter[0] = GLITZ_GL_NEAREST; + } + + if (SURFACE_REPEAT (src)) + { + if (SURFACE_MIRRORED (src)) + param.wrap[0] = GLITZ_GL_MIRRORED_REPEAT; + else + param.wrap[0] = GLITZ_GL_REPEAT; + } + else + { + if (no_border_clamp || SURFACE_PAD (src)) + param.wrap[0] = GLITZ_GL_CLAMP_TO_EDGE; + else + param.wrap[0] = GLITZ_GL_CLAMP_TO_BORDER; + } + + param.filter[1] = param.filter[0]; + param.wrap[1] = param.wrap[0]; + + glitz_texture_ensure_parameters (gl, stexture, ¶m); } glitz_geometry_enable (gl, dst, &bounds); if (comp_op.per_component) { - static unsigned short alpha_map[4][4] = { - { 0, 0, 0, 1 }, - { 0, 0, 1, 0 }, - { 0, 1, 0, 0 }, - { 1, 0, 0, 0 } - }; - static int damage[4] = { - GLITZ_DAMAGE_TEXTURE_MASK | GLITZ_DAMAGE_SOLID_MASK, - 0, - 0, - 0 - }; - glitz_color_t alpha = comp_op.alpha_mask; - int component = 4; - int cmask = 1; - - while (component--) - { - comp_op.alpha_mask.red = alpha_map[component][0] * alpha.red; - comp_op.alpha_mask.green = alpha_map[component][1] * alpha.green; - comp_op.alpha_mask.blue = alpha_map[component][2] * alpha.blue; - comp_op.alpha_mask.alpha = alpha_map[component][3] * alpha.alpha; - - gl->color_mask ((cmask & 1) , - (cmask & 2) >> 1, - (cmask & 4) >> 2, - (cmask & 8) >> 3); - - glitz_composite_enable (&comp_op); - glitz_geometry_draw_arrays (gl, dst, - dst->geometry.type, &bounds, - damage[component]); - cmask <<= 1; - } - - gl->color_mask (1, 1, 1, 1); + static unsigned short alpha_map[4][4] = { + { 0, 0, 0, 1 }, + { 0, 0, 1, 0 }, + { 0, 1, 0, 0 }, + { 1, 0, 0, 0 } + }; + static int damage[4] = { + GLITZ_DAMAGE_TEXTURE_MASK | GLITZ_DAMAGE_SOLID_MASK, + 0, + 0, + 0 + }; + glitz_color_t alpha = comp_op.alpha_mask; + int component = 4; + int cmask = 1; + + while (component--) + { + comp_op.alpha_mask.red = alpha_map[component][0] * alpha.red; + comp_op.alpha_mask.green = alpha_map[component][1] * alpha.green; + comp_op.alpha_mask.blue = alpha_map[component][2] * alpha.blue; + comp_op.alpha_mask.alpha = alpha_map[component][3] * alpha.alpha; + + gl->color_mask ((cmask & 1) , + (cmask & 2) >> 1, + (cmask & 4) >> 2, + (cmask & 8) >> 3); + + glitz_composite_enable (&comp_op); + glitz_geometry_draw_arrays (gl, dst, + dst->geometry.type, &bounds, + damage[component]); + cmask <<= 1; + } + + gl->color_mask (1, 1, 1, 1); } else { - glitz_composite_enable (&comp_op); - glitz_geometry_draw_arrays (gl, dst, dst->geometry.type, &bounds, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_SOLID_MASK); + glitz_composite_enable (&comp_op); + glitz_geometry_draw_arrays (gl, dst, dst->geometry.type, &bounds, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); } - + glitz_composite_disable (&comp_op); glitz_geometry_disable (dst); for (i = texture_nr; i >= 0; i--) { - glitz_texture_unbind (gl, textures[i].texture); - if (textures[i].transform) - { - gl->matrix_mode (GLITZ_GL_TEXTURE); - gl->load_identity (); - gl->matrix_mode (GLITZ_GL_MODELVIEW); - } + glitz_texture_unbind (gl, textures[i].texture); + if (textures[i].transform) + { + gl->matrix_mode (GLITZ_GL_TEXTURE); + gl->load_identity (); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + } - if (i > 0) - { - gl->client_active_texture (textures[i - 1].unit); - gl->active_texture (textures[i - 1].unit); - } + if (i > 0) + { + gl->client_active_texture (textures[i - 1].unit); + gl->active_texture (textures[i - 1].unit); + } } - + glitz_surface_pop_current (dst); } void glitz_copy_area (glitz_surface_t *src, - glitz_surface_t *dst, - int x_src, - int y_src, - int width, - int height, - int x_dst, - int y_dst) + glitz_surface_t *dst, + int x_src, + int y_src, + int width, + int height, + int x_dst, + int y_dst) { glitz_status_t status; glitz_box_t bounds; @@ -352,289 +360,302 @@ glitz_copy_area (glitz_surface_t *src, if (x_src < 0) { - bounds.x1 = x_dst - x_src; - width += x_src; + bounds.x1 = x_dst - x_src; + width += x_src; } else { - bounds.x1 = x_dst; - src_width -= x_src; + bounds.x1 = x_dst; + src_width -= x_src; } - + if (y_src < 0) { - bounds.y1 = y_dst - y_src; - height += y_src; + bounds.y1 = y_dst - y_src; + height += y_src; } else { - bounds.y1 = y_dst; - src_height -= y_src; + bounds.y1 = y_dst; + src_height -= y_src; } - + if (width > src_width) - bounds.x2 = bounds.x1 + src_width; + bounds.x2 = bounds.x1 + src_width; else - bounds.x2 = bounds.x1 + width; - + bounds.x2 = bounds.x1 + width; + if (height > src_height) - bounds.y2 = bounds.y1 + src_height; + bounds.y2 = bounds.y1 + src_height; else - bounds.y2 = bounds.y1 + height; + bounds.y2 = bounds.y1 + height; if (bounds.x1 < 0) - bounds.x1 = 0; + bounds.x1 = 0; if (bounds.y1 < 0) - bounds.y1 = 0; + bounds.y1 = 0; if (bounds.x2 > dst->box.x2) - bounds.x2 = dst->box.x2; + bounds.x2 = dst->box.x2; if (bounds.y2 > dst->box.y2) - bounds.y2 = dst->box.y2; + bounds.y2 = dst->box.y2; if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) - return; - + return; + status = GLITZ_STATUS_NOT_SUPPORTED; - if (glitz_surface_push_current (dst, GLITZ_DRAWABLE_CURRENT)) + if ((!src->attached) || + (src->attached == dst->attached) || + (dst->box.x2 * dst->box.y2 >= src->box.x2 * src->box.y2)) { - int target_height = SURFACE_DRAWABLE_HEIGHT (dst); - int source_height = SURFACE_DRAWABLE_HEIGHT (src); - - if (src == dst || (dst->attached && src->attached == dst->attached)) - { - glitz_box_t box, *clip = dst->clip; - int n_clip = dst->n_clip; + if (glitz_surface_push_current (dst, GLITZ_DRAWABLE_CURRENT)) + { + int target_height = dst->attached->height; - if (REGION_NOTEMPTY (&src->drawable_damage)) - { - glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT); - glitz_surface_pop_current (src); - } - - gl->read_buffer (src->buffer); - gl->draw_buffer (dst->buffer); - - glitz_set_operator (gl, GLITZ_OPERATOR_SRC); - - x_src += src->x; - y_src += src->y; + if (src->attached == dst->attached) + { + glitz_box_t box, *clip = dst->clip; + int n_clip = dst->n_clip; - while (n_clip--) - { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds.x1 > box.x1) - box.x1 = bounds.x1; - if (bounds.y1 > box.y1) - box.y1 = bounds.y1; - if (bounds.x2 < box.x2) - box.x2 = bounds.x2; - if (bounds.y2 < box.y2) - box.y2 = bounds.y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - glitz_set_raster_pos (gl, - dst->x + box.x1, - target_height - (dst->y + box.y2)); + if (REGION_NOTEMPTY (&src->drawable_damage)) + { + glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT); + glitz_surface_pop_current (src); + } - gl->scissor (dst->x + box.x1, - target_height - (dst->y + box.y2), - box.x2 - box.x1, - box.y2 - box.y1); + gl->read_buffer (src->buffer); + gl->draw_buffer (dst->buffer); - gl->copy_pixels (x_src + (box.x1 - x_dst), - source_height - - (y_src + (box.y2 - y_dst)), - box.x2 - box.x1, box.y2 - box.y1, - GLITZ_GL_COLOR); + glitz_set_operator (gl, GLITZ_OPERATOR_SRC); - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - - clip++; - } - } - else - { - glitz_texture_t *texture; + x_src += src->x; + y_src += src->y; - texture = glitz_surface_get_texture (src, 0); - if (texture) - { - glitz_texture_bind (gl, texture); + while (n_clip--) + { + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds.x1 > box.x1) + box.x1 = bounds.x1; + if (bounds.y1 > box.y1) + box.y1 = bounds.y1; + if (bounds.x2 < box.x2) + box.x2 = bounds.x2; + if (bounds.y2 < box.y2) + box.y2 = bounds.y2; - glitz_texture_set_tex_gen (gl, texture, NULL, - x_dst - x_src, - y_dst - y_src, - GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK, - NULL); + if (box.x1 < box.x2 && box.y1 < box.y2) + { + glitz_set_raster_pos (gl, + dst->x + box.x1, + target_height - (dst->y + box.y2)); - gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - gl->color_4us (0x0, 0x0, 0x0, 0xffff); - - glitz_texture_ensure_wrap (gl, texture, - GLITZ_GL_CLAMP_TO_EDGE); - glitz_texture_ensure_filter (gl, texture, GLITZ_GL_NEAREST); + gl->scissor (dst->x + box.x1, + target_height - (dst->y + box.y2), + box.x2 - box.x1, + box.y2 - box.y1); - glitz_set_operator (gl, GLITZ_OPERATOR_SRC); + gl->copy_pixels (x_src + (box.x1 - x_dst), + target_height - + (y_src + (box.y2 - y_dst)), + box.x2 - box.x1, box.y2 - box.y1, + GLITZ_GL_COLOR); - if (dst->n_clip > 1) - { - glitz_float_t *data; - void *ptr; - int vertices = 0; - glitz_box_t box, *clip = dst->clip; - int n_clip = dst->n_clip; + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } - ptr = malloc (n_clip * 8 * sizeof (glitz_float_t)); - if (!ptr) { - glitz_surface_pop_current (dst); - glitz_surface_status_add (dst, - GLITZ_STATUS_NO_MEMORY_MASK); - return; - } - - data = (glitz_float_t *) ptr; - - while (n_clip--) - { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds.x1 > box.x1) - box.x1 = bounds.x1; - if (bounds.y1 > box.y1) - box.y1 = bounds.y1; - if (bounds.x2 < box.x2) - box.x2 = bounds.x2; - if (bounds.y2 < box.y2) - box.y2 = bounds.y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - *data++ = (glitz_float_t) box.x1; - *data++ = (glitz_float_t) box.y1; - *data++ = (glitz_float_t) box.x2; - *data++ = (glitz_float_t) box.y1; - *data++ = (glitz_float_t) box.x2; - *data++ = (glitz_float_t) box.y2; - *data++ = (glitz_float_t) box.x1; - *data++ = (glitz_float_t) box.y2; + clip++; + } + } + else + { + glitz_texture_t *texture; - vertices += 4; - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - - clip++; - } + texture = glitz_surface_get_texture (src, 0); + if (texture) + { + glitz_texture_parameters_t param; + unsigned long mask; - if (vertices) - { - gl->scissor (bounds.x1 + dst->x, - (target_height - dst->y) - bounds.y2, - bounds.x2 - bounds.x1, - bounds.y2 - bounds.y1); + mask = GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK; - gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, ptr); - gl->draw_arrays (GLITZ_GL_QUADS, 0, vertices); - } - - free (ptr); - } - else - { - glitz_geometry_enable_none (gl, dst, &bounds); - glitz_geometry_draw_arrays (gl, dst, - GLITZ_GEOMETRY_TYPE_NONE, - &bounds, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - - glitz_texture_unbind (gl, texture); - } - } + glitz_texture_bind (gl, texture); - status = GLITZ_STATUS_SUCCESS; - } + glitz_texture_set_tex_gen (gl, texture, NULL, + x_dst - x_src, + y_dst - y_src, + mask, + NULL); - glitz_surface_pop_current (dst); + gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, + GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); - if (status && src->attached) - { - if (glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT)) - { - glitz_texture_t *texture; + gl->color_4us (0x0, 0x0, 0x0, 0xffff); - gl->read_buffer (src->buffer); + param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE; + param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST; - texture = glitz_surface_get_texture (dst, 1); - if (texture) - { - glitz_box_t box, *clip = dst->clip; - int n_clip = dst->n_clip; + glitz_texture_ensure_parameters (gl, texture, ¶m); - gl->disable (GLITZ_GL_SCISSOR_TEST); + glitz_set_operator (gl, GLITZ_OPERATOR_SRC); - glitz_texture_bind (gl, texture); + if (dst->n_clip > 1) + { + glitz_float_t *data; + void *ptr; + int vertices = 0; + glitz_box_t box, *clip = dst->clip; + int n_clip = dst->n_clip; - x_src += src->x; - y_src += src->y; + ptr = malloc (n_clip * 8 * sizeof (glitz_float_t)); + if (!ptr) + { + mask = GLITZ_STATUS_NO_MEMORY_MASK; + glitz_surface_pop_current (dst); + glitz_surface_status_add (dst, mask); + return; + } - while (n_clip--) - { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds.x1 > box.x1) - box.x1 = bounds.x1; - if (bounds.y1 > box.y1) - box.y1 = bounds.y1; - if (bounds.x2 < box.x2) - box.x2 = bounds.x2; - if (bounds.y2 < box.y2) - box.y2 = bounds.y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - glitz_texture_copy_drawable (gl, - texture, - src->attached, - x_src + (box.x1 - x_dst), - y_src + (box.y1 - y_dst), - box.x2 - box.x1, - box.y2 - box.y1, - box.x1, - box.y1); + data = (glitz_float_t *) ptr; - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_DRAWABLE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - - clip++; - } - - glitz_texture_unbind (gl, texture); - - gl->enable (GLITZ_GL_SCISSOR_TEST); - - status = GLITZ_STATUS_SUCCESS; - } - } - glitz_surface_pop_current (src); + while (n_clip--) + { + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds.x1 > box.x1) + box.x1 = bounds.x1; + if (bounds.y1 > box.y1) + box.y1 = bounds.y1; + if (bounds.x2 < box.x2) + box.x2 = bounds.x2; + if (bounds.y2 < box.y2) + box.y2 = bounds.y2; + + if (box.x1 < box.x2 && box.y1 < box.y2) + { + *data++ = (glitz_float_t) box.x1; + *data++ = (glitz_float_t) box.y1; + *data++ = (glitz_float_t) box.x2; + *data++ = (glitz_float_t) box.y1; + *data++ = (glitz_float_t) box.x2; + *data++ = (glitz_float_t) box.y2; + *data++ = (glitz_float_t) box.x1; + *data++ = (glitz_float_t) box.y2; + + vertices += 4; + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + clip++; + } + + if (vertices) + { + gl->scissor (bounds.x1 + dst->x, + (target_height - dst->y) - bounds.y2, + bounds.x2 - bounds.x1, + bounds.y2 - bounds.y1); + + gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, ptr); + gl->draw_arrays (GLITZ_GL_QUADS, 0, vertices); + } + + free (ptr); + } + else + { + glitz_geometry_enable_none (gl, dst, &bounds); + glitz_geometry_draw_arrays (gl, dst, + GLITZ_GEOMETRY_TYPE_NONE, + &bounds, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + glitz_texture_unbind (gl, texture); + } + } + + status = GLITZ_STATUS_SUCCESS; + } + + glitz_surface_pop_current (dst); } if (status) - glitz_surface_status_add (dst, glitz_status_to_status_mask (status)); + { + if (glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT)) + { + glitz_texture_t *texture; + + gl->read_buffer (src->buffer); + + texture = glitz_surface_get_texture (dst, 1); + if (texture) + { + glitz_box_t box, *clip = dst->clip; + int n_clip = dst->n_clip; + + gl->disable (GLITZ_GL_SCISSOR_TEST); + + glitz_texture_bind (gl, texture); + + x_src += src->x; + y_src += src->y; + + while (n_clip--) + { + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds.x1 > box.x1) + box.x1 = bounds.x1; + if (bounds.y1 > box.y1) + box.y1 = bounds.y1; + if (bounds.x2 < box.x2) + box.x2 = bounds.x2; + if (bounds.y2 < box.y2) + box.y2 = bounds.y2; + + if (box.x1 < box.x2 && box.y1 < box.y2) + { + glitz_texture_copy_drawable (gl, + texture, + src->attached, + x_src + (box.x1 - x_dst), + y_src + (box.y1 - y_dst), + box.x2 - box.x1, + box.y2 - box.y1, + box.x1, + box.y1); + + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_DRAWABLE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + clip++; + } + + glitz_texture_unbind (gl, texture); + + gl->enable (GLITZ_GL_SCISSOR_TEST); + + status = GLITZ_STATUS_SUCCESS; + } + } + glitz_surface_pop_current (src); + } + + if (status) + glitz_surface_status_add (dst, glitz_status_to_status_mask (status)); } diff --git a/gfx/cairo/glitz/src/glitz.h b/gfx/cairo/glitz/src/glitz.h index 53dbceccb96..f07d5d13d3e 100644 --- a/gfx/cairo/glitz/src/glitz.h +++ b/gfx/cairo/glitz/src/glitz.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -37,8 +37,8 @@ #endif #define GLITZ_MAJOR 0 -#define GLITZ_MINOR 4 -#define GLITZ_REVISION 4 +#define GLITZ_MINOR 5 +#define GLITZ_REVISION 0 #if defined(__cplusplus) || defined(c_plusplus) extern "C" { @@ -51,6 +51,9 @@ typedef float glitz_float_t; typedef double glitz_double_t; typedef int glitz_fixed16_16_t; +typedef struct _glitz_drawable glitz_drawable_t; +typedef struct _glitz_surface glitz_surface_t; + typedef struct _glitz_rectangle_t { short x, y; unsigned short width, height; @@ -78,7 +81,7 @@ typedef struct _glitz_trapezoid_t { typedef struct _glitz_span_fixed_t { glitz_fixed16_16_t left, right, y; } glitz_span_fixed_t; - + typedef struct _glitz_trap_t { glitz_span_fixed_t top, bottom; } glitz_trap_t; @@ -93,7 +96,7 @@ typedef struct { unsigned short blue; unsigned short alpha; } glitz_color_t; - + typedef enum { GLITZ_FILTER_NEAREST, GLITZ_FILTER_BILINEAR, @@ -137,13 +140,16 @@ typedef enum { #define GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK (1L << 15) #define GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK (1L << 16) + +/* glitz_format.c */ + typedef enum { GLITZ_STANDARD_ARGB32, GLITZ_STANDARD_RGB24, GLITZ_STANDARD_A8, GLITZ_STANDARD_A1 } glitz_format_name_t; - + #define GLITZ_FORMAT_ID_MASK (1L << 0) #define GLITZ_FORMAT_RED_SIZE_MASK (1L << 1) #define GLITZ_FORMAT_GREEN_SIZE_MASK (1L << 2) @@ -159,9 +165,57 @@ typedef struct _glitz_color_format_t { unsigned short alpha_size; } glitz_color_format_t; - +#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5) +#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6) +#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7) +#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8) + +typedef struct _glitz_drawable_format_t { + glitz_format_id_t id; + glitz_color_format_t color; + unsigned short depth_size; + unsigned short stencil_size; + unsigned short samples; + glitz_bool_t doublebuffer; +} glitz_drawable_format_t; + +#define GLITZ_FORMAT_TYPE_MASK (1L << 5) + +typedef enum { + GLITZ_FORMAT_TYPE_COLOR +} glitz_format_type_t; + +typedef struct _glitz_format_t { + glitz_format_id_t id; + glitz_format_type_t type; + glitz_color_format_t color; +} glitz_format_t; + +glitz_format_t * +glitz_find_standard_format (glitz_drawable_t *drawable, + glitz_format_name_t format_name); + +glitz_format_t * +glitz_find_format (glitz_drawable_t *drawable, + unsigned long mask, + const glitz_format_t *templ, + int count); + +glitz_drawable_format_t * +glitz_find_drawable_format (glitz_drawable_t *other, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + +glitz_drawable_format_t * +glitz_find_pbuffer_format (glitz_drawable_t *other, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + + /* glitz_status.c */ - + typedef enum { GLITZ_STATUS_SUCCESS = 0, GLITZ_STATUS_NO_MEMORY, @@ -176,46 +230,22 @@ glitz_status_string (glitz_status_t status); /* glitz_drawable.c */ -typedef struct _glitz_drawable glitz_drawable_t; - typedef enum { GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, GLITZ_DRAWABLE_BUFFER_BACK_COLOR } glitz_drawable_buffer_t; - -#define GLITZ_FORMAT_DEPTH_SIZE_MASK (1L << 5) -#define GLITZ_FORMAT_STENCIL_SIZE_MASK (1L << 6) -#define GLITZ_FORMAT_DOUBLEBUFFER_MASK (1L << 7) -#define GLITZ_FORMAT_SAMPLES_MASK (1L << 8) -#define GLITZ_FORMAT_WINDOW_MASK (1L << 9) -#define GLITZ_FORMAT_PBUFFER_MASK (1L << 10) - -typedef struct _glitz_drawable_types_t { - glitz_bool_t window; - glitz_bool_t pbuffer; -} glitz_drawable_types_t; -typedef struct _glitz_drawable_format_t { - glitz_format_id_t id; - glitz_color_format_t color; - unsigned short depth_size; - unsigned short stencil_size; - unsigned short samples; - glitz_bool_t doublebuffer; - glitz_drawable_types_t types; -} glitz_drawable_format_t; +glitz_drawable_t * +glitz_create_drawable (glitz_drawable_t *other, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); -glitz_drawable_format_t * -glitz_find_similar_drawable_format (glitz_drawable_t *other, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count); - glitz_drawable_t * glitz_create_pbuffer_drawable (glitz_drawable_t *other, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); void glitz_drawable_destroy (glitz_drawable_t *drawable); @@ -225,8 +255,8 @@ glitz_drawable_reference (glitz_drawable_t *drawable); void glitz_drawable_update_size (glitz_drawable_t *drawable, - unsigned int width, - unsigned int height); + unsigned int width, + unsigned int height); unsigned int glitz_drawable_get_width (glitz_drawable_t *drawable); @@ -234,6 +264,13 @@ glitz_drawable_get_width (glitz_drawable_t *drawable); unsigned int glitz_drawable_get_height (glitz_drawable_t *drawable); +void +glitz_drawable_swap_buffer_region (glitz_drawable_t *drawable, + int x_origin, + int y_origin, + glitz_box_t *box, + int n_box); + void glitz_drawable_swap_buffers (glitz_drawable_t *drawable); @@ -249,49 +286,22 @@ glitz_drawable_get_features (glitz_drawable_t *drawable); glitz_drawable_format_t * glitz_drawable_get_format (glitz_drawable_t *drawable); - -/* glitz_format.c */ - -#define GLITZ_FORMAT_TYPE_MASK (1L << 5) - -typedef enum { - GLITZ_FORMAT_TYPE_COLOR -} glitz_format_type_t; - -typedef struct _glitz_format_t { - glitz_format_id_t id; - glitz_format_type_t type; - glitz_color_format_t color; -} glitz_format_t; - -glitz_format_t * -glitz_find_standard_format (glitz_drawable_t *drawable, - glitz_format_name_t format_name); - -glitz_format_t * -glitz_find_format (glitz_drawable_t *drawable, - unsigned long mask, - const glitz_format_t *templ, - int count); - /* glitz_surface.c */ -typedef struct _glitz_surface glitz_surface_t; - #define GLITZ_SURFACE_UNNORMALIZED_MASK (1L << 0) typedef struct _glitz_surface_attributes_t { glitz_bool_t unnormalized; } glitz_surface_attributes_t; - + glitz_surface_t * glitz_surface_create (glitz_drawable_t *drawable, - glitz_format_t *format, - unsigned int width, - unsigned int height, - unsigned long mask, - glitz_surface_attributes_t *attributes); + glitz_format_t *format, + unsigned int width, + unsigned int height, + unsigned long mask, + glitz_surface_attributes_t *attributes); void glitz_surface_destroy (glitz_surface_t *surface); @@ -301,10 +311,8 @@ glitz_surface_reference (glitz_surface_t *surface); void glitz_surface_attach (glitz_surface_t *surface, - glitz_drawable_t *drawable, - glitz_drawable_buffer_t buffer, - int x, - int y); + glitz_drawable_t *drawable, + glitz_drawable_buffer_t buffer); void glitz_surface_detach (glitz_surface_t *surface); @@ -320,7 +328,7 @@ glitz_surface_get_attached_drawable (glitz_surface_t *surface); void glitz_surface_set_transform (glitz_surface_t *surface, - glitz_transform_t *transform); + glitz_transform_t *transform); typedef enum { GLITZ_FILL_TRANSPARENT, @@ -331,21 +339,21 @@ typedef enum { void glitz_surface_set_fill (glitz_surface_t *surface, - glitz_fill_t fill); + glitz_fill_t fill); void glitz_surface_set_component_alpha (glitz_surface_t *surface, - glitz_bool_t component_alpha); + glitz_bool_t component_alpha); void glitz_surface_set_filter (glitz_surface_t *surface, - glitz_filter_t filter, - glitz_fixed16_16_t *params, - int n_params); + glitz_filter_t filter, + glitz_fixed16_16_t *params, + int n_params); void glitz_surface_set_dither (glitz_surface_t *surface, - glitz_bool_t dither); + glitz_bool_t dither); unsigned int glitz_surface_get_width (glitz_surface_t *surface); @@ -361,27 +369,87 @@ glitz_surface_get_format (glitz_surface_t *surface); void glitz_surface_translate_point (glitz_surface_t *surface, - glitz_point_fixed_t *src, - glitz_point_fixed_t *dst); + glitz_point_fixed_t *src, + glitz_point_fixed_t *dst); void glitz_surface_set_clip_region (glitz_surface_t *surface, - int x_origin, - int y_origin, - glitz_box_t *box, - int n_box); + int x_origin, + int y_origin, + glitz_box_t *box, + int n_box); glitz_bool_t glitz_surface_valid_target (glitz_surface_t *surface); +/* glitz_texture.c */ + +typedef struct _glitz_texture_object glitz_texture_object_t; + +glitz_texture_object_t * +glitz_texture_object_create (glitz_surface_t *surface); + +void +glitz_texture_object_destroy (glitz_texture_object_t *texture); + +void +glitz_texture_object_reference (glitz_texture_object_t *texture); + +typedef enum { + GLITZ_TEXTURE_FILTER_TYPE_MAG = 0, + GLITZ_TEXTURE_FILTER_TYPE_MIN = 1 +} glitz_texture_filter_type_t; + +typedef enum { + GLITZ_TEXTURE_FILTER_NEAREST = 0, + GLITZ_TEXTURE_FILTER_LINEAR = 1 +} glitz_texture_filter_t; + +void +glitz_texture_object_set_filter (glitz_texture_object_t *texture, + glitz_texture_filter_type_t type, + glitz_texture_filter_t filter); + +typedef enum { + GLITZ_TEXTURE_WRAP_TYPE_S = 0, + GLITZ_TEXTURE_WRAP_TYPE_T = 1 +} glitz_texture_wrap_type_t; + +typedef enum { + GLITZ_TEXTURE_WRAP_CLAMP = 0, + GLITZ_TEXTURE_WRAP_CLAMP_TO_EDGE = 1, + GLITZ_TEXTURE_WRAP_CLAMP_TO_BORDER = 2, + GLITZ_TEXTURE_WRAP_REPEAT = 3, + GLITZ_TEXTURE_WRAP_MIRRORED_REPEAT = 4 +} glitz_texture_wrap_t; + +void +glitz_texture_object_set_wrap (glitz_texture_object_t *texture, + glitz_texture_wrap_type_t type, + glitz_texture_wrap_t wrap); + +void +glitz_texture_object_set_border_color (glitz_texture_object_t *texture, + glitz_color_t *color); + +typedef enum { + GLITZ_TEXTURE_TARGET_2D = 0, + GLITZ_TEXTURE_TARGET_RECT = 1 +} glitz_texture_target_t; + +glitz_texture_target_t +glitz_texture_object_get_target (glitz_texture_object_t *texture); + + /* glitz_context.c */ typedef struct _glitz_context glitz_context_t; glitz_context_t * glitz_context_create (glitz_drawable_t *drawable, - glitz_drawable_format_t *format); + glitz_drawable_format_t *format); + void glitz_context_destroy (glitz_context_t *context); @@ -390,51 +458,52 @@ glitz_context_reference (glitz_context_t *context); void glitz_context_copy (glitz_context_t *src, - glitz_context_t *dst, - unsigned long mask); + glitz_context_t *dst, + unsigned long mask); typedef void (*glitz_lose_current_function_t) (void *closure); void glitz_context_set_user_data (glitz_context_t *context, - void *closure, - glitz_lose_current_function_t lose_current); + void *closure, + glitz_lose_current_function_t lose_current); typedef void (*glitz_function_pointer_t) (void); glitz_function_pointer_t glitz_context_get_proc_address (glitz_context_t *context, - const char *name); + const char *name); void -glitz_context_make_current (glitz_context_t *context); +glitz_context_make_current (glitz_context_t *context, + glitz_drawable_t *drawable); void -glitz_context_bind_texture (glitz_context_t *context, - glitz_surface_t *surface); +glitz_context_bind_texture (glitz_context_t *context, + glitz_texture_object_t *texture); /* glitz_rect.c */ void glitz_set_rectangle (glitz_surface_t *dst, - const glitz_color_t *color, - int x, - int y, - unsigned int width, - unsigned int height); - + const glitz_color_t *color, + int x, + int y, + unsigned int width, + unsigned int height); + void glitz_set_rectangles (glitz_surface_t *dst, - const glitz_color_t *color, - const glitz_rectangle_t *rects, - int n_rects); + const glitz_color_t *color, + const glitz_rectangle_t *rects, + int n_rects); /* glitz_buffer.c */ typedef struct _glitz_buffer glitz_buffer_t; - + typedef enum { GLITZ_BUFFER_HINT_STREAM_DRAW, GLITZ_BUFFER_HINT_STREAM_READ, @@ -455,19 +524,19 @@ typedef enum { glitz_buffer_t * glitz_vertex_buffer_create (glitz_drawable_t *drawable, - void *data, - unsigned int size, - glitz_buffer_hint_t hint); + void *data, + unsigned int size, + glitz_buffer_hint_t hint); glitz_buffer_t * glitz_pixel_buffer_create (glitz_drawable_t *drawable, - void *data, - unsigned int size, - glitz_buffer_hint_t hint); + void *data, + unsigned int size, + glitz_buffer_hint_t hint); glitz_buffer_t * glitz_buffer_create_for_data (void *data); - + void glitz_buffer_destroy (glitz_buffer_t *buffer); @@ -476,26 +545,26 @@ glitz_buffer_reference (glitz_buffer_t *buffer); void glitz_buffer_set_data (glitz_buffer_t *buffer, - int offset, - unsigned int size, - const void *data); + int offset, + unsigned int size, + const void *data); void glitz_buffer_get_data (glitz_buffer_t *buffer, - int offset, - unsigned int size, - void *data); - + int offset, + unsigned int size, + void *data); + void * glitz_buffer_map (glitz_buffer_t *buffer, - glitz_buffer_access_t access); - + glitz_buffer_access_t access); + glitz_status_t glitz_buffer_unmap (glitz_buffer_t *buffer); - + /* glitz_pixel.c */ - + typedef enum { GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN, GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP @@ -519,23 +588,23 @@ typedef struct _glitz_pixel_format { void glitz_set_pixels (glitz_surface_t *dst, - int x_dst, - int y_dst, - int width, - int height, - glitz_pixel_format_t *format, - glitz_buffer_t *buffer); + int x_dst, + int y_dst, + int width, + int height, + glitz_pixel_format_t *format, + glitz_buffer_t *buffer); void glitz_get_pixels (glitz_surface_t *src, - int x_src, - int y_src, - int width, - int height, - glitz_pixel_format_t *format, - glitz_buffer_t *buffer); - - + int x_src, + int y_src, + int width, + int height, + glitz_pixel_format_t *format, + glitz_buffer_t *buffer); + + /* glitz_geometry.c */ typedef enum { @@ -562,7 +631,7 @@ typedef enum { GLITZ_COORDINATE_SIZE_X, GLITZ_COORDINATE_SIZE_XY } glitz_coordinate_size_t; - + typedef struct _glitz_coordinate_attribute { glitz_data_type_t type; glitz_coordinate_size_t size; @@ -600,17 +669,17 @@ typedef union _glitz_geometry_format { void glitz_set_geometry (glitz_surface_t *dst, - glitz_geometry_type_t type, - glitz_geometry_format_t *format, - glitz_buffer_t *buffer); + glitz_geometry_type_t type, + glitz_geometry_format_t *format, + glitz_buffer_t *buffer); void glitz_set_array (glitz_surface_t *dst, - int first, - int size, - unsigned int count, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off); + int first, + int size, + unsigned int count, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off); typedef struct _glitz_multi_array glitz_multi_array_t; @@ -625,71 +694,71 @@ glitz_multi_array_reference (glitz_multi_array_t *array); void glitz_multi_array_add (glitz_multi_array_t *array, - int first, - int size, - unsigned int count, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off); + int first, + int size, + unsigned int count, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off); void glitz_multi_array_reset (glitz_multi_array_t *array); void glitz_set_multi_array (glitz_surface_t *dst, - glitz_multi_array_t *array, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off); + glitz_multi_array_t *array, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off); /* glitz_trap.c */ int glitz_add_trapezoids (glitz_buffer_t *buffer, - int offset, - unsigned int size, - glitz_data_type_t type, - glitz_surface_t *mask, - glitz_trapezoid_t *traps, - int n_traps, - int *n_added); + int offset, + unsigned int size, + glitz_data_type_t type, + glitz_surface_t *mask, + glitz_trapezoid_t *traps, + int n_traps, + int *n_added); int glitz_add_traps (glitz_buffer_t *buffer, - int offset, - unsigned int size, - glitz_data_type_t type, - glitz_surface_t *mask, - glitz_trap_t *traps, - int n_traps, - int *n_added); + int offset, + unsigned int size, + glitz_data_type_t type, + glitz_surface_t *mask, + glitz_trap_t *traps, + int n_traps, + int *n_added); /* glitz.c */ void glitz_composite (glitz_operator_t op, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst, - int x_src, - int y_src, - int x_mask, - int y_mask, - int x_dst, - int y_dst, - int width, - int height); + glitz_surface_t *src, + glitz_surface_t *mask, + glitz_surface_t *dst, + int x_src, + int y_src, + int x_mask, + int y_mask, + int x_dst, + int y_dst, + int width, + int height); void glitz_copy_area (glitz_surface_t *src, - glitz_surface_t *dst, - int x_src, - int y_src, - int width, - int height, - int x_dst, - int y_dst); - + glitz_surface_t *dst, + int x_src, + int y_src, + int width, + int height, + int x_dst, + int y_dst); + #if defined(__cplusplus) || defined(c_plusplus) } #endif diff --git a/gfx/cairo/glitz/src/glitz_buffer.c b/gfx/cairo/glitz/src/glitz_buffer.c index df0561b9837..bc47310c458 100644 --- a/gfx/cairo/glitz/src/glitz_buffer.c +++ b/gfx/cairo/glitz/src/glitz_buffer.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,334 +31,335 @@ static glitz_status_t _glitz_buffer_init (glitz_buffer_t *buffer, - glitz_drawable_t *drawable, - void *data, - unsigned int size, - glitz_buffer_hint_t hint) + glitz_drawable_t *drawable, + void *data, + unsigned int size, + glitz_buffer_hint_t hint) { glitz_gl_enum_t usage; - + buffer->ref_count = 1; buffer->name = 0; if (drawable) { - GLITZ_GL_DRAWABLE (drawable); - - switch (hint) { - case GLITZ_BUFFER_HINT_STREAM_DRAW: - usage = GLITZ_GL_STREAM_DRAW; - break; - case GLITZ_BUFFER_HINT_STREAM_READ: - usage = GLITZ_GL_STREAM_READ; - break; - case GLITZ_BUFFER_HINT_STREAM_COPY: - usage = GLITZ_GL_STREAM_COPY; - break; - case GLITZ_BUFFER_HINT_STATIC_DRAW: - usage = GLITZ_GL_STATIC_DRAW; - break; - case GLITZ_BUFFER_HINT_STATIC_READ: - usage = GLITZ_GL_STATIC_READ; - break; - case GLITZ_BUFFER_HINT_STATIC_COPY: - usage = GLITZ_GL_STATIC_COPY; - break; - case GLITZ_BUFFER_HINT_DYNAMIC_DRAW: - usage = GLITZ_GL_DYNAMIC_DRAW; - break; - case GLITZ_BUFFER_HINT_DYNAMIC_READ: - usage = GLITZ_GL_DYNAMIC_READ; - break; - default: - usage = GLITZ_GL_DYNAMIC_COPY; - break; - } + GLITZ_GL_DRAWABLE (drawable); - buffer->owns_data = 1; - buffer->drawable = drawable; - glitz_drawable_reference (drawable); - - drawable->backend->push_current (drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); - - gl->gen_buffers (1, &buffer->name); - if (buffer->name) { - gl->bind_buffer (buffer->target, buffer->name); - gl->buffer_data (buffer->target, size, data, usage); - gl->bind_buffer (buffer->target, 0); - } - - drawable->backend->pop_current (drawable); + switch (hint) { + case GLITZ_BUFFER_HINT_STREAM_DRAW: + usage = GLITZ_GL_STREAM_DRAW; + break; + case GLITZ_BUFFER_HINT_STREAM_READ: + usage = GLITZ_GL_STREAM_READ; + break; + case GLITZ_BUFFER_HINT_STREAM_COPY: + usage = GLITZ_GL_STREAM_COPY; + break; + case GLITZ_BUFFER_HINT_STATIC_DRAW: + usage = GLITZ_GL_STATIC_DRAW; + break; + case GLITZ_BUFFER_HINT_STATIC_READ: + usage = GLITZ_GL_STATIC_READ; + break; + case GLITZ_BUFFER_HINT_STATIC_COPY: + usage = GLITZ_GL_STATIC_COPY; + break; + case GLITZ_BUFFER_HINT_DYNAMIC_DRAW: + usage = GLITZ_GL_DYNAMIC_DRAW; + break; + case GLITZ_BUFFER_HINT_DYNAMIC_READ: + usage = GLITZ_GL_DYNAMIC_READ; + break; + default: + usage = GLITZ_GL_DYNAMIC_COPY; + break; + } + + buffer->owns_data = 1; + buffer->drawable = drawable; + glitz_drawable_reference (drawable); + + drawable->backend->push_current (drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + + gl->gen_buffers (1, &buffer->name); + if (buffer->name) { + gl->bind_buffer (buffer->target, buffer->name); + gl->buffer_data (buffer->target, size, data, usage); + gl->bind_buffer (buffer->target, 0); + } + + drawable->backend->pop_current (drawable); } else { - buffer->drawable = NULL; - usage = GLITZ_GL_DYNAMIC_COPY; + buffer->drawable = NULL; + usage = GLITZ_GL_DYNAMIC_COPY; } - + if (size > 0 && buffer->name == 0) { - buffer->data = malloc (size); - if (buffer->data == NULL) - return GLITZ_STATUS_NO_MEMORY; - - if (data) - memcpy (buffer->data, data, size); - - buffer->owns_data = 1; + buffer->data = malloc (size); + if (buffer->data == NULL) + return GLITZ_STATUS_NO_MEMORY; + + if (data) + memcpy (buffer->data, data, size); + + buffer->owns_data = 1; } else { - buffer->owns_data = 0; - buffer->data = data; + buffer->owns_data = 0; + buffer->data = data; } - + return GLITZ_STATUS_SUCCESS; } glitz_buffer_t * glitz_vertex_buffer_create (glitz_drawable_t *drawable, - void *data, - unsigned int size, - glitz_buffer_hint_t hint) + void *data, + unsigned int size, + glitz_buffer_hint_t hint) { - glitz_buffer_t *buffer; - glitz_status_t status; + glitz_buffer_t *buffer; + glitz_status_t status; - if (size == 0) - return NULL; + if (size == 0) + return NULL; - buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); - if (buffer == NULL) - return NULL; - - buffer->target = GLITZ_GL_ARRAY_BUFFER; - - if (drawable->backend->feature_mask & - GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK) - status = _glitz_buffer_init (buffer, drawable, data, size, hint); - else - status = _glitz_buffer_init (buffer, NULL, data, size, hint); - - if (status != GLITZ_STATUS_SUCCESS) { - free (buffer); - return NULL; - } - - return buffer; + buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); + if (buffer == NULL) + return NULL; + + buffer->target = GLITZ_GL_ARRAY_BUFFER; + + if (drawable->backend->feature_mask & + GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK) + status = _glitz_buffer_init (buffer, drawable, data, size, hint); + else + status = _glitz_buffer_init (buffer, NULL, data, size, hint); + + if (status != GLITZ_STATUS_SUCCESS) { + free (buffer); + return NULL; + } + + return buffer; } glitz_buffer_t * glitz_pixel_buffer_create (glitz_drawable_t *drawable, - void *data, - unsigned int size, - glitz_buffer_hint_t hint) + void *data, + unsigned int size, + glitz_buffer_hint_t hint) { - glitz_buffer_t *buffer; - glitz_status_t status; + glitz_buffer_t *buffer; + glitz_status_t status; - if (size == 0) - return NULL; - - buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); - if (buffer == NULL) - return NULL; - - switch (hint) { - case GLITZ_BUFFER_HINT_STREAM_READ: - case GLITZ_BUFFER_HINT_STATIC_READ: - case GLITZ_BUFFER_HINT_DYNAMIC_READ: - buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER; - break; - default: - buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; - break; - } + if (size == 0) + return NULL; - if (drawable->backend->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) - status = _glitz_buffer_init (buffer, drawable, data, size, hint); - else - status = _glitz_buffer_init (buffer, NULL, data, size, hint); + buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); + if (buffer == NULL) + return NULL; - if (status != GLITZ_STATUS_SUCCESS) { - free (buffer); - return NULL; - } - - return buffer; + switch (hint) { + case GLITZ_BUFFER_HINT_STREAM_READ: + case GLITZ_BUFFER_HINT_STATIC_READ: + case GLITZ_BUFFER_HINT_DYNAMIC_READ: + buffer->target = GLITZ_GL_PIXEL_PACK_BUFFER; + break; + default: + buffer->target = GLITZ_GL_PIXEL_UNPACK_BUFFER; + break; + } + + if (drawable->backend->feature_mask & + GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK) + status = _glitz_buffer_init (buffer, drawable, data, size, hint); + else + status = _glitz_buffer_init (buffer, NULL, data, size, hint); + + if (status != GLITZ_STATUS_SUCCESS) { + free (buffer); + return NULL; + } + + return buffer; } glitz_buffer_t * glitz_buffer_create_for_data (void *data) { - glitz_buffer_t *buffer; - - buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); - if (buffer == NULL) - return NULL; + glitz_buffer_t *buffer; - if (_glitz_buffer_init (buffer, NULL, data, 0, 0)) { - free (buffer); - return NULL; - } - - return buffer; + buffer = (glitz_buffer_t *) malloc (sizeof (glitz_buffer_t)); + if (buffer == NULL) + return NULL; + + if (_glitz_buffer_init (buffer, NULL, data, 0, 0)) { + free (buffer); + return NULL; + } + + return buffer; } void glitz_buffer_destroy (glitz_buffer_t *buffer) { - if (!buffer) - return; + if (!buffer) + return; - buffer->ref_count--; - if (buffer->ref_count) - return; - - if (buffer->drawable) { - buffer->drawable->backend->push_current (buffer->drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); - buffer->drawable->backend->gl.delete_buffers (1, &buffer->name); - buffer->drawable->backend->pop_current (buffer->drawable); - glitz_drawable_destroy (buffer->drawable); - } else if (buffer->owns_data) - free (buffer->data); - - free (buffer); + buffer->ref_count--; + if (buffer->ref_count) + return; + + if (buffer->drawable) { + buffer->drawable->backend->push_current (buffer->drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + buffer->drawable->backend->gl->delete_buffers (1, &buffer->name); + buffer->drawable->backend->pop_current (buffer->drawable); + glitz_drawable_destroy (buffer->drawable); + } else if (buffer->owns_data) + free (buffer->data); + + free (buffer); } void glitz_buffer_reference (glitz_buffer_t *buffer) { - if (!buffer) - return; + if (!buffer) + return; - buffer->ref_count++; + buffer->ref_count++; } void glitz_buffer_set_data (glitz_buffer_t *buffer, - int offset, - unsigned int size, - const void *data) + int offset, + unsigned int size, + const void *data) { - if (buffer->drawable) { - GLITZ_GL_DRAWABLE (buffer->drawable); - - buffer->drawable->backend->push_current (buffer->drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); - gl->bind_buffer (buffer->target, buffer->name); - gl->buffer_sub_data (buffer->target, offset, size, data); - gl->bind_buffer (buffer->target, 0); - buffer->drawable->backend->pop_current (buffer->drawable); - } else if (buffer->data) - memcpy ((char *) buffer->data + offset, data, size); + if (buffer->drawable) { + GLITZ_GL_DRAWABLE (buffer->drawable); + + buffer->drawable->backend->push_current (buffer->drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + gl->bind_buffer (buffer->target, buffer->name); + gl->buffer_sub_data (buffer->target, offset, size, data); + gl->bind_buffer (buffer->target, 0); + buffer->drawable->backend->pop_current (buffer->drawable); + } else if (buffer->data) + memcpy ((char *) buffer->data + offset, data, size); } slim_hidden_def(glitz_buffer_set_data); void glitz_buffer_get_data (glitz_buffer_t *buffer, - int offset, - unsigned int size, - void *data) + int offset, + unsigned int size, + void *data) { - if (buffer->drawable) { - GLITZ_GL_DRAWABLE (buffer->drawable); - - buffer->drawable->backend->push_current (buffer->drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); - - gl->bind_buffer (buffer->target, buffer->name); - gl->get_buffer_sub_data (buffer->target, offset, size, data); - gl->bind_buffer (buffer->target, 0); + if (buffer->drawable) { + GLITZ_GL_DRAWABLE (buffer->drawable); - buffer->drawable->backend->pop_current (buffer->drawable); - } else if (buffer->data) - memcpy (data, (char *) buffer->data + offset, size); + buffer->drawable->backend->push_current (buffer->drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + + gl->bind_buffer (buffer->target, buffer->name); + gl->get_buffer_sub_data (buffer->target, offset, size, data); + gl->bind_buffer (buffer->target, 0); + + buffer->drawable->backend->pop_current (buffer->drawable); + } else if (buffer->data) + memcpy (data, (char *) buffer->data + offset, size); } slim_hidden_def(glitz_buffer_get_data); void * glitz_buffer_map (glitz_buffer_t *buffer, - glitz_buffer_access_t access) + glitz_buffer_access_t access) { - void *pointer = NULL; - - if (buffer->drawable) { - glitz_gl_enum_t buffer_access; + void *pointer = NULL; - GLITZ_GL_DRAWABLE (buffer->drawable); + if (buffer->drawable) { + glitz_gl_enum_t buffer_access; - buffer->drawable->backend->push_current (buffer->drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); - - switch (access) { - case GLITZ_BUFFER_ACCESS_READ_ONLY: - buffer_access = GLITZ_GL_READ_ONLY; - break; - case GLITZ_BUFFER_ACCESS_WRITE_ONLY: - buffer_access = GLITZ_GL_WRITE_ONLY; - break; - default: - buffer_access = GLITZ_GL_READ_WRITE; - break; + GLITZ_GL_DRAWABLE (buffer->drawable); + + buffer->drawable->backend->push_current (buffer->drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + + switch (access) { + case GLITZ_BUFFER_ACCESS_READ_ONLY: + buffer_access = GLITZ_GL_READ_ONLY; + break; + case GLITZ_BUFFER_ACCESS_WRITE_ONLY: + buffer_access = GLITZ_GL_WRITE_ONLY; + break; + default: + buffer_access = GLITZ_GL_READ_WRITE; + break; + } + + gl->bind_buffer (buffer->target, buffer->name); + pointer = gl->map_buffer (buffer->target, buffer_access); + gl->bind_buffer (buffer->target, 0); + + buffer->drawable->backend->pop_current (buffer->drawable); } - gl->bind_buffer (buffer->target, buffer->name); - pointer = gl->map_buffer (buffer->target, buffer_access); - gl->bind_buffer (buffer->target, 0); - - buffer->drawable->backend->pop_current (buffer->drawable); - } - - if (pointer == NULL) - pointer = buffer->data; - - return pointer; + if (pointer == NULL) + pointer = buffer->data; + + return pointer; } glitz_status_t glitz_buffer_unmap (glitz_buffer_t *buffer) { - glitz_status_t status = GLITZ_STATUS_SUCCESS; - - if (buffer->drawable) { - GLITZ_GL_DRAWABLE (buffer->drawable); - - buffer->drawable->backend->push_current (buffer->drawable, NULL, - GLITZ_ANY_CONTEXT_CURRENT); + glitz_status_t status = GLITZ_STATUS_SUCCESS; - gl->bind_buffer (buffer->target, buffer->name); - - if (gl->unmap_buffer (buffer->target) == GLITZ_GL_FALSE) - status = GLITZ_STATUS_CONTENT_DESTROYED; - - gl->bind_buffer (buffer->target, 0); + if (buffer->drawable) { + GLITZ_GL_DRAWABLE (buffer->drawable); - buffer->drawable->backend->pop_current (buffer->drawable); - } + buffer->drawable->backend->push_current (buffer->drawable, NULL, + GLITZ_ANY_CONTEXT_CURRENT); - return status; + gl->bind_buffer (buffer->target, buffer->name); + + if (gl->unmap_buffer (buffer->target) == GLITZ_GL_FALSE) + status = GLITZ_STATUS_CONTENT_DESTROYED; + + gl->bind_buffer (buffer->target, 0); + + buffer->drawable->backend->pop_current (buffer->drawable); + } + + return status; } void * glitz_buffer_bind (glitz_buffer_t *buffer, - glitz_gl_enum_t target) + glitz_gl_enum_t target) { - if (buffer->drawable) { - buffer->drawable->backend->gl.bind_buffer (target, buffer->name); - buffer->target = target; - - return NULL; - } - - return buffer->data; + if (buffer->drawable) { + buffer->drawable->backend->gl->bind_buffer (target, buffer->name); + buffer->target = target; + + return NULL; + } + + return buffer->data; } void glitz_buffer_unbind (glitz_buffer_t *buffer) { - if (buffer->drawable) - buffer->drawable->backend->gl.bind_buffer (buffer->target, 0); + if (buffer->drawable) + buffer->drawable->backend->gl->bind_buffer (buffer->target, 0); } diff --git a/gfx/cairo/glitz/src/glitz_compose.c b/gfx/cairo/glitz/src/glitz_compose.c index c2cbe8d8a6b..1dcf70fe3e7 100644 --- a/gfx/cairo/glitz/src/glitz_compose.c +++ b/gfx/cairo/glitz/src/glitz_compose.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -32,590 +32,591 @@ static void _glitz_combine_argb_argb (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - - op->gl->active_texture (GLITZ_GL_TEXTURE0); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); - - op->gl->active_texture (GLITZ_GL_TEXTURE1); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_COMBINE); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, - GLITZ_GL_MODULATE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, - GLITZ_GL_TEXTURE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, - GLITZ_GL_PREVIOUS); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, - GLITZ_GL_SRC_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, - GLITZ_GL_SRC_ALPHA); + glitz_set_operator (op->gl, op->render_op); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, - GLITZ_GL_MODULATE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, - GLITZ_GL_TEXTURE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, - GLITZ_GL_PREVIOUS); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, - GLITZ_GL_SRC_ALPHA); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, - GLITZ_GL_SRC_ALPHA); + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_ALPHA); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, + GLITZ_GL_SRC_ALPHA); } static void _glitz_combine_argb_argbc (glitz_composite_op_t *op) { - if (op->count == 0) { - glitz_set_operator (op->gl, op->render_op); - - op->gl->active_texture (GLITZ_GL_TEXTURE0); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_COMBINE); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, - GLITZ_GL_INTERPOLATE); + if (op->count == 0) { + glitz_set_operator (op->gl, op->render_op); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, - GLITZ_GL_TEXTURE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE2_RGB, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, - GLITZ_GL_SRC_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, - GLITZ_GL_SRC_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND2_RGB, - GLITZ_GL_SRC_ALPHA); + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); - /* we don't care about the alpha channel, so lets do something (simple?) */ - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, - GLITZ_GL_REPLACE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, - GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_INTERPOLATE); - - op->gl->active_texture (GLITZ_GL_TEXTURE1); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_COMBINE); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, - GLITZ_GL_DOT3_RGBA); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, - GLITZ_GL_PREVIOUS); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, - GLITZ_GL_SRC_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, - GLITZ_GL_SRC_COLOR); - - op->gl->active_texture (GLITZ_GL_TEXTURE2); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - } - - if (op->alpha_mask.red) { - op->gl->color_4f (1.0f, 0.5f, 0.5f, 0.5f); - } else if (op->alpha_mask.green) { - op->gl->color_4f (0.5f, 1.0f, 0.5f, 0.5f); - } else if (op->alpha_mask.blue) { - op->gl->color_4f (0.5f, 0.5f, 1.0f, 0.5f); - } else { - op->gl->active_texture (GLITZ_GL_TEXTURE0); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); - - op->gl->active_texture (GLITZ_GL_TEXTURE1); - glitz_texture_unbind (op->gl, &op->src->texture); - - op->gl->active_texture (GLITZ_GL_TEXTURE2); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - } + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE2_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND2_RGB, + GLITZ_GL_SRC_ALPHA); + + /* we don't care about the alpha channel */ + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_REPLACE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_DOT3_RGBA); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_PREVIOUS); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + } + + if (op->alpha_mask.red) { + op->gl->color_4f (1.0f, 0.5f, 0.5f, 0.5f); + } else if (op->alpha_mask.green) { + op->gl->color_4f (0.5f, 1.0f, 0.5f, 0.5f); + } else if (op->alpha_mask.blue) { + op->gl->color_4f (0.5f, 0.5f, 1.0f, 0.5f); + } else { + op->gl->active_texture (GLITZ_GL_TEXTURE0); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + + op->gl->active_texture (GLITZ_GL_TEXTURE1); + glitz_texture_unbind (op->gl, &op->src->texture); + + op->gl->active_texture (GLITZ_GL_TEXTURE2); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + } } static void _glitz_combine_argb_argbf (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - glitz_filter_enable (op->mask, op); - - op->gl->color_4us (op->alpha_mask.red, - op->alpha_mask.green, - op->alpha_mask.blue, - op->alpha_mask.alpha); + glitz_set_operator (op->gl, op->render_op); + glitz_filter_enable (op->mask, op); + + op->gl->color_4us (op->alpha_mask.red, + op->alpha_mask.green, + op->alpha_mask.blue, + op->alpha_mask.alpha); } static void _glitz_combine_argb_solid (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - - if (op->alpha_mask.alpha != 0xffff) { - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - op->gl->color_4us (op->alpha_mask.alpha, - op->alpha_mask.alpha, - op->alpha_mask.alpha, - op->alpha_mask.alpha); - } else { - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); - } + glitz_set_operator (op->gl, op->render_op); + + if (op->alpha_mask.alpha != 0xffff) { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + op->gl->color_4us (op->alpha_mask.alpha, + op->alpha_mask.alpha, + op->alpha_mask.alpha, + op->alpha_mask.alpha); + } else { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + } } static void _glitz_combine_argb_solidc (glitz_composite_op_t *op) { - unsigned short alpha; + unsigned short alpha; - if (op->count == 0) - glitz_set_operator (op->gl, op->render_op); - - if (op->alpha_mask.red) - alpha = op->alpha_mask.red; - else if (op->alpha_mask.green) - alpha = op->alpha_mask.green; - else if (op->alpha_mask.blue) - alpha = op->alpha_mask.blue; - else - alpha = op->alpha_mask.alpha; - - if (alpha != 0xffff) { - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - op->gl->color_4us (alpha, alpha, alpha, alpha); - } else { - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); - } + if (op->count == 0) + glitz_set_operator (op->gl, op->render_op); + + if (op->alpha_mask.red) + alpha = op->alpha_mask.red; + else if (op->alpha_mask.green) + alpha = op->alpha_mask.green; + else if (op->alpha_mask.blue) + alpha = op->alpha_mask.blue; + else + alpha = op->alpha_mask.alpha; + + if (alpha != 0xffff) { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + op->gl->color_4us (alpha, alpha, alpha, alpha); + } else { + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + op->gl->color_4us (0x0, 0x0, 0x0, 0xffff); + } } static void _glitz_combine_argbf_solid (glitz_composite_op_t *op) { - if (op->count == 0) { - glitz_set_operator (op->gl, op->render_op); - glitz_filter_enable (op->src, op); - } + if (op->count == 0) { + glitz_set_operator (op->gl, op->render_op); + glitz_filter_enable (op->src, op); + } - op->gl->color_4us (0x0, 0x0, 0x0, op->alpha_mask.alpha); + op->gl->color_4us (0x0, 0x0, 0x0, op->alpha_mask.alpha); } static void _glitz_combine_argbf_argbc (glitz_composite_op_t *op) { - if (op->count == 0) { - glitz_set_operator (op->gl, op->render_op); - glitz_filter_enable (op->src, op); - } - - op->gl->color_4us (op->alpha_mask.red, - op->alpha_mask.green, - op->alpha_mask.blue, - op->alpha_mask.alpha); + if (op->count == 0) { + glitz_set_operator (op->gl, op->render_op); + glitz_filter_enable (op->src, op); + } + + op->gl->color_4us (op->alpha_mask.red, + op->alpha_mask.green, + op->alpha_mask.blue, + op->alpha_mask.alpha); } static void _glitz_combine_argbf_solidc (glitz_composite_op_t *op) { - unsigned short alpha; - - if (op->count == 0) { - glitz_set_operator (op->gl, op->render_op); - glitz_filter_enable (op->src, op); - } - - if (op->alpha_mask.red) - alpha = op->alpha_mask.red; - else if (op->alpha_mask.green) - alpha = op->alpha_mask.green; - else if (op->alpha_mask.blue) - alpha = op->alpha_mask.blue; - else - alpha = op->alpha_mask.alpha; - - op->gl->color_4us (0x0, 0x0, 0x0, alpha); + unsigned short alpha; + + if (op->count == 0) { + glitz_set_operator (op->gl, op->render_op); + glitz_filter_enable (op->src, op); + } + + if (op->alpha_mask.red) + alpha = op->alpha_mask.red; + else if (op->alpha_mask.green) + alpha = op->alpha_mask.green; + else if (op->alpha_mask.blue) + alpha = op->alpha_mask.blue; + else + alpha = op->alpha_mask.alpha; + + op->gl->color_4us (0x0, 0x0, 0x0, alpha); } static void _glitz_combine_solid_solid (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - - op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), - SHORT_MULT (op->solid->green, op->alpha_mask.alpha), - SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), - SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); + glitz_set_operator (op->gl, op->render_op); + + op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), + SHORT_MULT (op->solid->green, op->alpha_mask.alpha), + SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), + SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); } static void _glitz_combine_solid_argb (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_COMBINE); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, - GLITZ_GL_MODULATE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, - GLITZ_GL_TEXTURE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, - GLITZ_GL_SRC_ALPHA); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, - GLITZ_GL_SRC_COLOR); + glitz_set_operator (op->gl, op->render_op); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, - GLITZ_GL_MODULATE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, - GLITZ_GL_TEXTURE); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, - GLITZ_GL_PRIMARY_COLOR); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, - GLITZ_GL_SRC_ALPHA); - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, - GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_COMBINE); - op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), - SHORT_MULT (op->solid->green, op->alpha_mask.alpha), - SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), - SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_RGB, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_RGB, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_RGB, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_RGB, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_RGB, + GLITZ_GL_SRC_COLOR); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_COMBINE_ALPHA, + GLITZ_GL_MODULATE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE0_ALPHA, + GLITZ_GL_TEXTURE); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_SOURCE1_ALPHA, + GLITZ_GL_PRIMARY_COLOR); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND0_ALPHA, + GLITZ_GL_SRC_ALPHA); + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_OPERAND1_ALPHA, + GLITZ_GL_SRC_ALPHA); + + op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), + SHORT_MULT (op->solid->green, op->alpha_mask.alpha), + SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), + SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); } /* This only works with the OVER operator. */ static void _glitz_combine_solid_argbc (glitz_composite_op_t *op) { - glitz_color_t solid; + glitz_color_t solid; - solid.red = SHORT_MULT (op->solid->red, op->alpha_mask.alpha); - solid.green = SHORT_MULT (op->solid->green, op->alpha_mask.alpha); - solid.blue = SHORT_MULT (op->solid->blue, op->alpha_mask.alpha); - solid.alpha = SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha); + solid.red = SHORT_MULT (op->solid->red, op->alpha_mask.alpha); + solid.green = SHORT_MULT (op->solid->green, op->alpha_mask.alpha); + solid.blue = SHORT_MULT (op->solid->blue, op->alpha_mask.alpha); + solid.alpha = SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha); - op->gl->enable (GLITZ_GL_BLEND); - op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); - - if (solid.alpha > 0) - op->gl->blend_color ((glitz_gl_clampf_t) solid.red / solid.alpha, - (glitz_gl_clampf_t) solid.green / solid.alpha, - (glitz_gl_clampf_t) solid.blue / solid.alpha, - 1.0f); - else - op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); - - op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_MODULATE); - op->gl->color_4us (solid.alpha, - solid.alpha, - solid.alpha, - solid.alpha); + op->gl->enable (GLITZ_GL_BLEND); + op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); + + if (solid.alpha > 0) + op->gl->blend_color ((glitz_gl_clampf_t) solid.red / solid.alpha, + (glitz_gl_clampf_t) solid.green / solid.alpha, + (glitz_gl_clampf_t) solid.blue / solid.alpha, + 1.0f); + else + op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); + + op->gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_MODULATE); + op->gl->color_4us (solid.alpha, + solid.alpha, + solid.alpha, + solid.alpha); } static void _glitz_combine_solid_argbf (glitz_composite_op_t *op) { - glitz_set_operator (op->gl, op->render_op); - glitz_filter_enable (op->mask, op); + glitz_set_operator (op->gl, op->render_op); + glitz_filter_enable (op->mask, op); - op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), - SHORT_MULT (op->solid->green, op->alpha_mask.alpha), - SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), - SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); + op->gl->color_4us (SHORT_MULT (op->solid->red, op->alpha_mask.alpha), + SHORT_MULT (op->solid->green, op->alpha_mask.alpha), + SHORT_MULT (op->solid->blue, op->alpha_mask.alpha), + SHORT_MULT (op->solid->alpha, op->alpha_mask.alpha)); } /* This only works with the OVER operator. */ static void _glitz_combine_solid_solidc (glitz_composite_op_t *op) { - op->gl->enable (GLITZ_GL_BLEND); - op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); + op->gl->enable (GLITZ_GL_BLEND); + op->gl->blend_func (GLITZ_GL_CONSTANT_COLOR, GLITZ_GL_ONE_MINUS_SRC_COLOR); - if (op->solid->alpha > 0) - op->gl->blend_color ((glitz_gl_clampf_t) op->solid->red / op->solid->alpha, - (glitz_gl_clampf_t) - op->solid->green / op->solid->alpha, - (glitz_gl_clampf_t) - op->solid->blue / op->solid->alpha, - 1.0f); - else - op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); + if (op->solid->alpha > 0) + op->gl->blend_color ((glitz_gl_clampf_t) + op->solid->red / op->solid->alpha, + (glitz_gl_clampf_t) + op->solid->green / op->solid->alpha, + (glitz_gl_clampf_t) + op->solid->blue / op->solid->alpha, + 1.0f); + else + op->gl->blend_color (1.0f, 1.0f, 1.0f, 1.0f); - op->gl->color_4us (SHORT_MULT (op->alpha_mask.red, op->solid->alpha), - SHORT_MULT (op->alpha_mask.green, op->solid->alpha), - SHORT_MULT (op->alpha_mask.blue, op->solid->alpha), - SHORT_MULT (op->alpha_mask.alpha, op->solid->alpha)); + op->gl->color_4us (SHORT_MULT (op->alpha_mask.red, op->solid->alpha), + SHORT_MULT (op->alpha_mask.green, op->solid->alpha), + SHORT_MULT (op->alpha_mask.blue, op->solid->alpha), + SHORT_MULT (op->alpha_mask.alpha, op->solid->alpha)); } static glitz_combine_t _glitz_combine_map[GLITZ_SURFACE_TYPES][GLITZ_SURFACE_TYPES] = { - { - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 } - }, { - { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, - { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } - }, { - { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, - { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, - { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } - }, { - { GLITZ_COMBINE_TYPE_ARGBF, _glitz_combine_argbf_solid, 1, 1 }, - { GLITZ_COMBINE_TYPE_ARGBF_ARGB, _glitz_combine_argbf_solid, 2, 1 }, - { GLITZ_COMBINE_TYPE_ARGBF_ARGBC, _glitz_combine_argbf_argbc, 2, 1 }, - { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, - { GLITZ_COMBINE_TYPE_ARGBF_SOLID, _glitz_combine_argbf_solid, 1, 1 }, - { GLITZ_COMBINE_TYPE_ARGBF_SOLIDC, _glitz_combine_argbf_solidc, 1, 1 } - }, { - { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, - { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } - }, { - { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, - { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, - { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } - } + { + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 } + }, { + { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, + { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } + }, { + { GLITZ_COMBINE_TYPE_ARGB, _glitz_combine_argb_solid, 1, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGB, _glitz_combine_argb_argb, 2, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGBC, _glitz_combine_argb_argbc, 3, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_ARGBF, _glitz_combine_argb_argbf, 2, 2 }, + { GLITZ_COMBINE_TYPE_ARGB_SOLID, _glitz_combine_argb_solid, 1, 0 }, + { GLITZ_COMBINE_TYPE_ARGB_SOLIDC, _glitz_combine_argb_solidc, 1, 0 } + }, { + { GLITZ_COMBINE_TYPE_ARGBF, _glitz_combine_argbf_solid, 1, 1 }, + { GLITZ_COMBINE_TYPE_ARGBF_ARGB, _glitz_combine_argbf_solid, 2, 1 }, + { GLITZ_COMBINE_TYPE_ARGBF_ARGBC, _glitz_combine_argbf_argbc, 2, 1 }, + { GLITZ_COMBINE_TYPE_NA, NULL, 0, 0 }, + { GLITZ_COMBINE_TYPE_ARGBF_SOLID, _glitz_combine_argbf_solid, 1, 1 }, + { GLITZ_COMBINE_TYPE_ARGBF_SOLIDC, _glitz_combine_argbf_solidc, 1, 1 } + }, { + { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, + { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } + }, { + { GLITZ_COMBINE_TYPE_SOLID, _glitz_combine_solid_solid, 0, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGB, _glitz_combine_solid_argb, 1, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGBC, _glitz_combine_solid_argbc, 1, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_ARGBF, _glitz_combine_solid_argbf, 1, 2 }, + { GLITZ_COMBINE_TYPE_SOLID_SOLID, _glitz_combine_solid_solid, 0, 0 }, + { GLITZ_COMBINE_TYPE_SOLID_SOLIDC, _glitz_combine_solid_solidc, 1, 0 } + } }; -#define SURFACE_WRAP(surface, feature_mask) \ - (SURFACE_REPEAT (surface)? \ - (TEXTURE_REPEATABLE (&(surface)->texture) && \ - ( \ - (!SURFACE_MIRRORED (surface)) || \ - ((feature_mask) & GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK) \ - ) \ - ) \ - : \ - ((SURFACE_PAD (surface))? \ - (TEXTURE_PADABLE (&(surface)->texture)) \ - : \ - ( \ - (!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \ - ((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \ - ) \ - ) \ - ) - +#define SURFACE_WRAP(surface, feature_mask) \ + (SURFACE_REPEAT (surface)? \ + (TEXTURE_REPEATABLE (&(surface)->texture) && \ + ( \ + (!SURFACE_MIRRORED (surface)) || \ + ((feature_mask) & GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK) \ + ) \ + ) \ + : \ + ((SURFACE_PAD (surface))? \ + (TEXTURE_PADABLE (&(surface)->texture)) \ + : \ + ( \ + (!SURFACE_PROJECTIVE_TRANSFORM (surface)) || \ + ((feature_mask) & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) \ + ) \ + ) \ + ) + static glitz_surface_type_t _glitz_get_surface_type (glitz_surface_t *surface, - unsigned long feature_mask) + unsigned long feature_mask) { - if (surface == NULL) - return GLITZ_SURFACE_TYPE_NULL; + if (surface == NULL) + return GLITZ_SURFACE_TYPE_NULL; - if (SURFACE_SOLID (surface) && - (SURFACE_REPEAT (surface) || SURFACE_PAD (surface))) { - if (SURFACE_COMPONENT_ALPHA (surface)) - return GLITZ_SURFACE_TYPE_SOLIDC; - else - return GLITZ_SURFACE_TYPE_SOLID; - } + if (SURFACE_SOLID (surface) && + (SURFACE_REPEAT (surface) || SURFACE_PAD (surface))) { + if (SURFACE_COMPONENT_ALPHA (surface)) + return GLITZ_SURFACE_TYPE_SOLIDC; + else + return GLITZ_SURFACE_TYPE_SOLID; + } - if (SURFACE_WRAP (surface, feature_mask)) { - if (SURFACE_FRAGMENT_FILTER (surface)) { - if (SURFACE_COMPONENT_ALPHA (surface)) - return GLITZ_SURFACE_TYPE_NA; + if (SURFACE_WRAP (surface, feature_mask)) { + if (SURFACE_FRAGMENT_FILTER (surface)) { + if (SURFACE_COMPONENT_ALPHA (surface)) + return GLITZ_SURFACE_TYPE_NA; - if (feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) - return GLITZ_SURFACE_TYPE_ARGBF; - - } else if (SURFACE_COMPONENT_ALPHA (surface)) { - return GLITZ_SURFACE_TYPE_ARGBC; - } else - return GLITZ_SURFACE_TYPE_ARGB; - } - - return GLITZ_SURFACE_TYPE_NA; + if (feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) + return GLITZ_SURFACE_TYPE_ARGBF; + + } else if (SURFACE_COMPONENT_ALPHA (surface)) { + return GLITZ_SURFACE_TYPE_ARGBC; + } else + return GLITZ_SURFACE_TYPE_ARGB; + } + + return GLITZ_SURFACE_TYPE_NA; } static glitz_color_t _default_alpha_mask = { - 0xffff, 0xffff, 0xffff, 0xffff + 0xffff, 0xffff, 0xffff, 0xffff }; void glitz_composite_op_init (glitz_composite_op_t *op, - glitz_operator_t render_op, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst) + glitz_operator_t render_op, + glitz_surface_t *src, + glitz_surface_t *mask, + glitz_surface_t *dst) { - glitz_surface_type_t src_type; - glitz_surface_type_t mask_type; - glitz_combine_t *combine; - unsigned long feature_mask; + glitz_surface_type_t src_type; + glitz_surface_type_t mask_type; + glitz_combine_t *combine; + unsigned long feature_mask; - op->render_op = render_op; - op->type = GLITZ_COMBINE_TYPE_NA; - op->combine = NULL; - op->alpha_mask = _default_alpha_mask; - op->src = src; - op->mask = mask; - op->dst = dst; - op->count = 0; - op->solid = NULL; - op->per_component = 0; - op->fp = 0; - - if (dst->attached) - { - op->gl = &dst->attached->backend->gl; - feature_mask = dst->attached->backend->feature_mask; - } - else - { - op->gl = &dst->drawable->backend->gl; - feature_mask = dst->drawable->backend->feature_mask; - } - - src_type = _glitz_get_surface_type (src, feature_mask); - if (src_type < 1) - return; - - mask_type = _glitz_get_surface_type (mask, feature_mask); - if (mask_type < 0) - return; - - if (src_type == GLITZ_SURFACE_TYPE_SOLIDC) - src_type = GLITZ_SURFACE_TYPE_SOLID; - - /* We can't do solid IN argbc OP dest, unless OP is OVER. - But we can do argb IN argbc OP dest, so lets just not use the - source as a solid color if this is the case. I need to figure out - a better way to handle special cases like this. */ - if (src_type == GLITZ_SURFACE_TYPE_SOLID && - (mask_type == GLITZ_SURFACE_TYPE_SOLIDC || - mask_type == GLITZ_SURFACE_TYPE_ARGBC) && - render_op != GLITZ_OPERATOR_OVER) - src_type = GLITZ_SURFACE_TYPE_ARGB; - - combine = &_glitz_combine_map[src_type][mask_type]; - if (!combine->type) - return; - - if (dst->geometry.type == GLITZ_GEOMETRY_TYPE_BITMAP) - { - /* We can't do anything but solid colors with bitmaps yet. */ - if (src_type != GLITZ_SURFACE_TYPE_SOLID || - (mask_type != GLITZ_SURFACE_TYPE_NULL && - mask_type != GLITZ_SURFACE_TYPE_SOLID)) - return; - } - - if (src_type == GLITZ_SURFACE_TYPE_SOLID) { - if (SURFACE_SOLID_DAMAGE (src)) { - glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); - glitz_surface_sync_solid (src); - glitz_surface_pop_current (dst); - } - op->solid = &src->solid; - op->src = NULL; - } - - if (mask_type == GLITZ_SURFACE_TYPE_SOLID) { - if (SURFACE_SOLID_DAMAGE (mask)) { - glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); - glitz_surface_sync_solid (mask); - glitz_surface_pop_current (dst); - } - op->alpha_mask = mask->solid; - op->mask = NULL; - op->combine = combine; - } else if (mask_type == GLITZ_SURFACE_TYPE_SOLIDC) { - if (SURFACE_SOLID_DAMAGE (mask)) { - glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); - glitz_surface_sync_solid (mask); - glitz_surface_pop_current (dst); - } - op->alpha_mask = mask->solid; - op->mask = NULL; - - if (op->src) { - op->per_component = 4; - op->combine = combine; - } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) - op->combine = combine; - - } else if (mask_type != GLITZ_SURFACE_TYPE_NULL) { - if (mask_type == GLITZ_SURFACE_TYPE_ARGBC) { - if (op->src) { - /* we can't do component alpha with alpha only surfaces */ - if (op->src->format->color.red_size) { - op->per_component = 4; - if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) - op->combine = combine; - } - } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) - op->combine = combine; - } else if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) - op->combine = combine; - } else - op->combine = combine; - - if (!(feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK)) { - if (op->src && op->mask) - op->combine = NULL; - } - - if (op->per_component && - (!(feature_mask & GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK))) + op->render_op = render_op; + op->type = GLITZ_COMBINE_TYPE_NA; op->combine = NULL; - - if (op->combine == combine) { - op->type = combine->type; - if (combine->source_shader) { - if (combine->source_shader == 1) - op->fp = glitz_filter_get_fragment_program (src, op); - else - op->fp = glitz_filter_get_fragment_program (mask, op); - if (op->fp == 0) - op->type = GLITZ_COMBINE_TYPE_NA; + op->alpha_mask = _default_alpha_mask; + op->src = src; + op->mask = mask; + op->dst = dst; + op->count = 0; + op->solid = NULL; + op->per_component = 0; + op->fp = 0; + + if (dst->attached) + { + op->gl = dst->attached->backend->gl; + feature_mask = dst->attached->backend->feature_mask; + } + else + { + op->gl = dst->drawable->backend->gl; + feature_mask = dst->drawable->backend->feature_mask; + } + + src_type = _glitz_get_surface_type (src, feature_mask); + if (src_type < 1) + return; + + mask_type = _glitz_get_surface_type (mask, feature_mask); + if (mask_type < 0) + return; + + if (src_type == GLITZ_SURFACE_TYPE_SOLIDC) + src_type = GLITZ_SURFACE_TYPE_SOLID; + + /* We can't do solid IN argbc OP dest, unless OP is OVER. + But we can do argb IN argbc OP dest, so lets just not use the + source as a solid color if this is the case. I need to figure out + a better way to handle special cases like this. */ + if (src_type == GLITZ_SURFACE_TYPE_SOLID && + (mask_type == GLITZ_SURFACE_TYPE_SOLIDC || + mask_type == GLITZ_SURFACE_TYPE_ARGBC) && + render_op != GLITZ_OPERATOR_OVER) + src_type = GLITZ_SURFACE_TYPE_ARGB; + + combine = &_glitz_combine_map[src_type][mask_type]; + if (!combine->type) + return; + + if (dst->geometry.type == GLITZ_GEOMETRY_TYPE_BITMAP) + { + /* We can't do anything but solid colors with bitmaps yet. */ + if (src_type != GLITZ_SURFACE_TYPE_SOLID || + (mask_type != GLITZ_SURFACE_TYPE_NULL && + mask_type != GLITZ_SURFACE_TYPE_SOLID)) + return; + } + + if (src_type == GLITZ_SURFACE_TYPE_SOLID) { + if (SURFACE_SOLID_DAMAGE (src)) { + glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); + glitz_surface_sync_solid (src); + glitz_surface_pop_current (dst); + } + op->solid = &src->solid; + op->src = NULL; + } + + if (mask_type == GLITZ_SURFACE_TYPE_SOLID) { + if (SURFACE_SOLID_DAMAGE (mask)) { + glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); + glitz_surface_sync_solid (mask); + glitz_surface_pop_current (dst); + } + op->alpha_mask = mask->solid; + op->mask = NULL; + op->combine = combine; + } else if (mask_type == GLITZ_SURFACE_TYPE_SOLIDC) { + if (SURFACE_SOLID_DAMAGE (mask)) { + glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); + glitz_surface_sync_solid (mask); + glitz_surface_pop_current (dst); + } + op->alpha_mask = mask->solid; + op->mask = NULL; + + if (op->src) { + op->per_component = 4; + op->combine = combine; + } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) + op->combine = combine; + + } else if (mask_type != GLITZ_SURFACE_TYPE_NULL) { + if (mask_type == GLITZ_SURFACE_TYPE_ARGBC) { + if (op->src) { + /* we can't do component alpha with alpha only surfaces */ + if (op->src->format->color.red_size) { + op->per_component = 4; + if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) + op->combine = combine; + } + } else if (feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) + op->combine = combine; + } else if (feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) + op->combine = combine; + } else + op->combine = combine; + + if (!(feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK)) { + if (op->src && op->mask) + op->combine = NULL; + } + + if (op->per_component && + (!(feature_mask & GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK))) + op->combine = NULL; + + if (op->combine == combine) { + op->type = combine->type; + if (combine->source_shader) { + if (combine->source_shader == 1) + op->fp = glitz_filter_get_fragment_program (src, op); + else + op->fp = glitz_filter_get_fragment_program (mask, op); + if (op->fp == 0) + op->type = GLITZ_COMBINE_TYPE_NA; + } } - } } void glitz_composite_enable (glitz_composite_op_t *op) { - op->combine->enable (op); - op->count++; + op->combine->enable (op); + op->count++; } void glitz_composite_disable (glitz_composite_op_t *op) { - if (op->fp) { - op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); - op->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM); - } + if (op->fp) { + op->gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); + op->gl->disable (GLITZ_GL_FRAGMENT_PROGRAM); + } } diff --git a/gfx/cairo/glitz/src/glitz_context.c b/gfx/cairo/glitz/src/glitz_context.c index 0f11cf64d46..f0977cb0bc4 100644 --- a/gfx/cairo/glitz/src/glitz_context.c +++ b/gfx/cairo/glitz/src/glitz_context.c @@ -1,6 +1,6 @@ /* * Copyright © 2005 Novell, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,10 +31,10 @@ void _glitz_context_init (glitz_context_t *context, - glitz_drawable_t *drawable) + glitz_drawable_t *drawable) { glitz_drawable_reference (drawable); - + context->ref_count = 1; context->drawable = drawable; context->closure = NULL; @@ -49,7 +49,7 @@ _glitz_context_fini (glitz_context_t *context) glitz_context_t * glitz_context_create (glitz_drawable_t *drawable, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { return drawable->backend->create_context (drawable, format); } @@ -59,11 +59,11 @@ void glitz_context_destroy (glitz_context_t *context) { if (!context) - return; + return; context->ref_count--; if (context->ref_count) - return; + return; context->drawable->backend->destroy_context (context); } @@ -73,16 +73,16 @@ void glitz_context_reference (glitz_context_t *context) { if (!context) - return; - + return; + context->ref_count++; } slim_hidden_def(glitz_context_reference); void glitz_context_copy (glitz_context_t *src, - glitz_context_t *dst, - unsigned long mask) + glitz_context_t *dst, + unsigned long mask) { src->drawable->backend->copy_context (src, dst, mask); } @@ -90,8 +90,8 @@ slim_hidden_def(glitz_context_copy); void glitz_context_set_user_data (glitz_context_t *context, - void *closure, - glitz_lose_current_function_t lose_current) + void *closure, + glitz_lose_current_function_t lose_current) { context->closure = closure; context->lose_current = lose_current; @@ -100,28 +100,82 @@ slim_hidden_def(glitz_context_set_user_data); glitz_function_pointer_t glitz_context_get_proc_address (glitz_context_t *context, - const char *name) + const char *name) { return context->drawable->backend->get_proc_address (context, name); } slim_hidden_def(glitz_context_get_proc_address); void -glitz_context_make_current (glitz_context_t *context) +glitz_context_make_current (glitz_context_t *context, + glitz_drawable_t *drawable) { - context->drawable->backend->make_current (context, context->drawable); + if (drawable != context->drawable) + { + glitz_drawable_reference (drawable); + glitz_drawable_destroy (context->drawable); + context->drawable = drawable; + } + + if (drawable->front) + { + if (REGION_NOTEMPTY (&drawable->front->drawable_damage)) + { + glitz_surface_push_current (drawable->front, + GLITZ_DRAWABLE_CURRENT); + glitz_surface_pop_current (drawable->front); + } + + glitz_surface_damage (drawable->front, NULL, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + if (drawable->back) + { + if (REGION_NOTEMPTY (&drawable->back->drawable_damage)) + { + glitz_surface_push_current (drawable->back, + GLITZ_DRAWABLE_CURRENT); + glitz_surface_pop_current (drawable->back); + } + + glitz_surface_damage (drawable->back, NULL, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + drawable->backend->make_current (drawable, context); } slim_hidden_def(glitz_context_make_current); void -glitz_context_bind_texture (glitz_context_t *context, - glitz_surface_t *surface) +glitz_context_bind_texture (glitz_context_t *context, + glitz_texture_object_t *texture) { - glitz_gl_proc_address_list_t *gl = &context->drawable->backend->gl; - - if (!surface->texture.name) - gl->gen_textures (1, &surface->texture.name); - - gl->bind_texture (surface->texture.target, surface->texture.name); + glitz_gl_proc_address_list_t *gl = context->drawable->backend->gl; + + if (REGION_NOTEMPTY (&texture->surface->texture_damage)) + { + glitz_lose_current_function_t lose_current; + + lose_current = context->lose_current; + context->lose_current = 0; + + glitz_surface_push_current (texture->surface, GLITZ_CONTEXT_CURRENT); + _glitz_surface_sync_texture (texture->surface); + glitz_surface_pop_current (texture->surface); + + context->lose_current = lose_current; + + glitz_context_make_current (context, context->drawable); + } + + gl->bind_texture (texture->surface->texture.target, + texture->surface->texture.name); + + glitz_texture_ensure_parameters (gl, + &texture->surface->texture, + &texture->param); } slim_hidden_def(glitz_context_bind_texture); diff --git a/gfx/cairo/glitz/src/glitz_drawable.c b/gfx/cairo/glitz/src/glitz_drawable.c index f8431e42249..9b0e77f6b22 100644 --- a/gfx/cairo/glitz/src/glitz_drawable.c +++ b/gfx/cairo/glitz/src/glitz_drawable.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -29,119 +29,312 @@ #include "glitzint.h" -glitz_drawable_format_t * -glitz_find_similar_drawable_format (glitz_drawable_t *other, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count) +void +_glitz_drawable_init (glitz_drawable_t *drawable, + glitz_int_drawable_format_t *format, + glitz_backend_t *backend, + int width, + int height) { - return glitz_drawable_format_find (other->backend->drawable_formats, - other->backend->n_drawable_formats, - mask, templ, count); + drawable->ref_count = 1; + + drawable->format = format; + drawable->backend = backend; + + drawable->width = width; + drawable->height = height; + + drawable->front = NULL; + drawable->back = NULL; + + drawable->viewport.x = -32767; + drawable->viewport.y = -32767; + drawable->viewport.width = 65535; + drawable->viewport.height = 65535; + + drawable->update_all = 1; } -slim_hidden_def(glitz_find_similar_drawable_format); - + +static glitz_bool_t +_glitz_drawable_size_check (glitz_drawable_t *other, + unsigned int width, + unsigned int height) +{ + if (width == 0 || height == 0) + return 0; + + if (width > other->backend->max_viewport_dims[0] || + height > other->backend->max_viewport_dims[1]) + return 0; + + return 1; +} + +glitz_drawable_t * +glitz_create_drawable (glitz_drawable_t *other, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) +{ + glitz_int_drawable_format_t *iformat; + + if (!_glitz_drawable_size_check (other, width, height)) + return NULL; + + if (format->id >= other->backend->n_drawable_formats) + return NULL; + + iformat = &other->backend->drawable_formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_FBO_MASK)) + return NULL; + + return _glitz_fbo_drawable_create (other, iformat, width, height); +} +slim_hidden_def(glitz_create_drawable); + glitz_drawable_t * glitz_create_pbuffer_drawable (glitz_drawable_t *other, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - if (!format->types.pbuffer) - return NULL; - - return other->backend->create_pbuffer (other, format, width, height); + glitz_int_drawable_format_t *iformat; + + if (!_glitz_drawable_size_check (other, width, height)) + return NULL; + + if (format->id >= other->backend->n_drawable_formats) + return NULL; + + iformat = &other->backend->drawable_formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)) + return NULL; + + return other->backend->create_pbuffer (other, format, width, height); } slim_hidden_def(glitz_create_pbuffer_drawable); void glitz_drawable_destroy (glitz_drawable_t *drawable) { - if (!drawable) - return; + if (!drawable) + return; - drawable->ref_count--; - if (drawable->ref_count) - return; - - drawable->backend->destroy (drawable); + drawable->ref_count--; + if (drawable->ref_count) + return; + + drawable->backend->destroy (drawable); } void glitz_drawable_reference (glitz_drawable_t *drawable) { - if (!drawable) - return; + if (!drawable) + return; - drawable->ref_count++; + drawable->ref_count++; } void glitz_drawable_update_size (glitz_drawable_t *drawable, - unsigned int width, - unsigned int height) + unsigned int width, + unsigned int height) { - drawable->width = (int) width; - drawable->height = (int) height; + drawable->width = (int) width; + drawable->height = (int) height; - drawable->viewport.x = -32767; - drawable->viewport.y = -32767; - drawable->viewport.width = 65535; - drawable->viewport.height = 65535; + drawable->viewport.x = -32767; + drawable->viewport.y = -32767; + drawable->viewport.width = 65535; + drawable->viewport.height = 65535; - drawable->update_all = 1; + drawable->update_all = 1; } unsigned int glitz_drawable_get_width (glitz_drawable_t *drawable) { - return (unsigned int) drawable->width; + return (unsigned int) drawable->width; } slim_hidden_def(glitz_drawable_get_width); unsigned int glitz_drawable_get_height (glitz_drawable_t *drawable) { - return (unsigned int) drawable->height; + return (unsigned int) drawable->height; } slim_hidden_def(glitz_drawable_get_height); +void +glitz_drawable_swap_buffer_region (glitz_drawable_t *drawable, + int x_origin, + int y_origin, + glitz_box_t *box, + int n_box) +{ + if (drawable->format->d.doublebuffer && n_box) + { + glitz_box_t rect; + glitz_surface_t *surface = NULL; + int x_pos, y_pos; + int x, y, w, h; + + GLITZ_GL_DRAWABLE (drawable); + + if (n_box == 1) + { + rect.x1 = x_origin + box->x1; + rect.y1 = y_origin + box->y1; + rect.x2 = x_origin + box->x2; + rect.y2 = y_origin + box->y2; + + if (rect.x1 <= 0 && + rect.y1 <= 0 && + rect.x2 >= drawable->width && + rect.x2 >= drawable->height) + { + if (drawable->backend->swap_buffers (drawable)) + { + if (drawable->front) + { + REGION_EMPTY (&drawable->front->drawable_damage); + glitz_surface_damage (drawable->front, NULL, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + return; + } + } + } + + if (drawable->front) + { + if (glitz_surface_push_current (drawable->front, + GLITZ_DRAWABLE_CURRENT)) + surface = drawable->front; + } + + if (!surface) + { + if (drawable->backend->push_current (drawable, NULL, + GLITZ_DRAWABLE_CURRENT)) + { + drawable->update_all = 1; + + gl->viewport (0, 0, drawable->width, drawable->height); + gl->matrix_mode (GLITZ_GL_PROJECTION); + gl->load_identity (); + gl->ortho (0.0, drawable->width, 0.0, + drawable->height, -1.0, 1.0); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + gl->load_identity (); + gl->scale_f (1.0f, -1.0f, 1.0f); + gl->translate_f (0.0f, -drawable->height, 0.0f); + } + else + { + drawable->backend->pop_current (drawable); + return; + } + } + + gl->disable (GLITZ_GL_DITHER); + + gl->read_buffer (GLITZ_GL_BACK); + gl->draw_buffer (GLITZ_GL_FRONT); + + glitz_set_operator (gl, GLITZ_OPERATOR_SRC); + + x_pos = 0; + y_pos = 0; + + glitz_set_raster_pos (gl, x_pos, y_pos); + + while (n_box--) + { + rect.x1 = x_origin + box->x1; + rect.y1 = y_origin + box->y1; + rect.x2 = x_origin + box->x2; + rect.y2 = y_origin + box->y2; + + if (rect.x1 < rect.x2 && rect.y1 < rect.y2) + { + x = rect.x1; + y = drawable->height - rect.y2; + w = rect.x2 - rect.x1; + h = rect.y2 - rect.y1; + + if (x != x_pos || y != y_pos) + { + gl->bitmap (0, 0, 0, 0, x - x_pos, y - y_pos, NULL); + + x_pos = x; + y_pos = y; + } + + gl->scissor (x, y, w, h); + gl->copy_pixels (x, y, w, h, GLITZ_GL_COLOR); + + if (surface) + glitz_surface_damage (surface, &rect, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + + box++; + } + } + drawable->backend->gl->finish (); + + if (surface) + glitz_surface_pop_current (surface); + else + drawable->backend->pop_current (drawable); + } +} + void glitz_drawable_swap_buffers (glitz_drawable_t *drawable) { - if (drawable->format->doublebuffer) - drawable->backend->swap_buffers (drawable); + glitz_box_t box; + + box.x1 = 0; + box.y1 = 0; + box.x2 = drawable->width; + box.y2 = drawable->height; + + glitz_drawable_swap_buffer_region (drawable, 0, 0, &box, 1); } slim_hidden_def(glitz_drawable_swap_buffers); void glitz_drawable_flush (glitz_drawable_t *drawable) { - drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT); - drawable->backend->gl.flush (); - drawable->backend->pop_current (drawable); + drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT); + drawable->backend->gl->flush (); + drawable->backend->pop_current (drawable); } slim_hidden_def(glitz_drawable_flush); void glitz_drawable_finish (glitz_drawable_t *drawable) { - drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT); - drawable->backend->gl.finish (); - drawable->backend->pop_current (drawable); + drawable->backend->push_current (drawable, NULL, GLITZ_DRAWABLE_CURRENT); + drawable->backend->gl->finish (); + drawable->backend->pop_current (drawable); } slim_hidden_def(glitz_drawable_finish); unsigned long glitz_drawable_get_features (glitz_drawable_t *drawable) { - return drawable->backend->feature_mask; + return drawable->backend->feature_mask; } slim_hidden_def(glitz_drawable_get_features); glitz_drawable_format_t * glitz_drawable_get_format (glitz_drawable_t *drawable) { - return drawable->format; + return &drawable->format->d; } slim_hidden_def(glitz_drawable_get_format); diff --git a/gfx/cairo/glitz/src/glitz_filter.c b/gfx/cairo/glitz/src/glitz_filter.c index 4ec4444099d..cfe939d43c3 100644 --- a/gfx/cairo/glitz/src/glitz_filter.c +++ b/gfx/cairo/glitz/src/glitz_filter.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -30,396 +30,408 @@ #include "glitzint.h" struct _glitz_filter_params_t { - int fp_type; - int id; - glitz_vec4_t *vectors; - int n_vectors; + int fp_type; + int id; + glitz_vec4_t *vectors; + int n_vectors; }; static glitz_status_t _glitz_filter_params_ensure (glitz_surface_t *surface, - int vectors) + int vectors) { int size; - - size = sizeof (glitz_filter_params_t) + vectors * sizeof (glitz_vec4_t); - - if (!surface->filter_params || - surface->filter_params->n_vectors != vectors) - { - if (surface->filter_params) - free (surface->filter_params); - - surface->filter_params = malloc (size); - if (surface->filter_params == NULL) - return GLITZ_STATUS_NO_MEMORY; - surface->filter_params->fp_type = 0; - surface->filter_params->id = 0; - surface->filter_params->vectors = - (glitz_vec4_t *) (surface->filter_params + 1); - surface->filter_params->n_vectors = vectors; + size = sizeof (glitz_filter_params_t) + vectors * sizeof (glitz_vec4_t); + + if (!surface->filter_params || + surface->filter_params->n_vectors != vectors) + { + if (surface->filter_params) + free (surface->filter_params); + + surface->filter_params = malloc (size); + if (surface->filter_params == NULL) + return GLITZ_STATUS_NO_MEMORY; + + surface->filter_params->fp_type = 0; + surface->filter_params->id = 0; + surface->filter_params->vectors = + (glitz_vec4_t *) (surface->filter_params + 1); + surface->filter_params->n_vectors = vectors; } - + return GLITZ_STATUS_SUCCESS; } static void _glitz_filter_params_set (glitz_float_t *value, - const glitz_float_t default_value, - glitz_fixed16_16_t **params, - int *n_params) + const glitz_float_t default_value, + glitz_fixed16_16_t **params, + int *n_params) { - if (*n_params > 0) { - *value = FIXED_TO_FLOAT (**params); - (*params)++; - (*n_params)--; - } else - *value = default_value; + if (*n_params > 0) { + *value = FIXED_TO_FLOAT (**params); + (*params)++; + (*n_params)--; + } else + *value = default_value; } static int _glitz_color_stop_compare (const void *elem1, const void *elem2) { - return - (((glitz_vec4_t *) elem1)->v[2] == ((glitz_vec4_t *) elem2)->v[2]) ? - /* equal offsets, sort on id */ - ((((glitz_vec4_t *) elem1)->v[3] < - ((glitz_vec4_t *) elem2)->v[3]) ? -1 : 1) : - /* sort on offset */ - ((((glitz_vec4_t *) elem1)->v[2] < - ((glitz_vec4_t *) elem2)->v[2]) ? -1 : 1); + return + (((glitz_vec4_t *) elem1)->v[2] == ((glitz_vec4_t *) elem2)->v[2]) ? + /* equal offsets, sort on id */ + ((((glitz_vec4_t *) elem1)->v[3] < + ((glitz_vec4_t *) elem2)->v[3]) ? -1 : 1) : + /* sort on offset */ + ((((glitz_vec4_t *) elem1)->v[2] < + ((glitz_vec4_t *) elem2)->v[2]) ? -1 : 1); } glitz_status_t glitz_filter_set_params (glitz_surface_t *surface, - glitz_filter_t filter, - glitz_fixed16_16_t *params, - int n_params) + glitz_filter_t filter, + glitz_fixed16_16_t *params, + int n_params) { - glitz_vec4_t *vecs; - int i, size = 0; - - switch (filter) { - case GLITZ_FILTER_CONVOLUTION: { - glitz_float_t dm, dn; - int cx, cy, m, n, j; - - _glitz_filter_params_set (&dm, 3.0f, ¶ms, &n_params); - _glitz_filter_params_set (&dn, 3.0f, ¶ms, &n_params); - m = dm; - n = dn; + glitz_vec4_t *vecs; + int i, size = 0; - size = m * n; - if (_glitz_filter_params_ensure (surface, size)) - return GLITZ_STATUS_NO_MEMORY; + switch (filter) { + case GLITZ_FILTER_CONVOLUTION: { + glitz_float_t dm, dn; + int cx, cy, m, n, j; - vecs = surface->filter_params->vectors; - - surface->filter_params->id = 0; - - /* center point is rounded down in case dimensions are not even */ - cx = m / 2; - cy = n / 2; + _glitz_filter_params_set (&dm, 3.0f, ¶ms, &n_params); + _glitz_filter_params_set (&dn, 3.0f, ¶ms, &n_params); + m = dm; + n = dn; - for (i = 0; i < m; i++) { - glitz_vec4_t *vec; - glitz_float_t weight; - - for (j = 0; j < n; j++) { - _glitz_filter_params_set (&weight, 0.0f, ¶ms, &n_params); - if (weight != 0.0f) { - vec = &vecs[surface->filter_params->id++]; - vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit; - vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit; - vec->v[2] = weight; - vec->v[3] = 0.0f; - } - } - } - } break; - case GLITZ_FILTER_GAUSSIAN: { - glitz_float_t radius, sigma, alpha, scale, xy_scale, sum; - int half_size, x, y; - - _glitz_filter_params_set (&radius, 1.0f, ¶ms, &n_params); - glitz_clamp_value (&radius, 0.0f, 1024.0f); + size = m * n; + if (_glitz_filter_params_ensure (surface, size)) + return GLITZ_STATUS_NO_MEMORY; - _glitz_filter_params_set (&sigma, radius / 2.0f, ¶ms, &n_params); - glitz_clamp_value (&sigma, 0.0f, 1024.0f); - - _glitz_filter_params_set (&alpha, radius, ¶ms, &n_params); - glitz_clamp_value (&alpha, 0.0f, 1024.0f); + vecs = surface->filter_params->vectors; - scale = 1.0f / (2.0f * GLITZ_PI * sigma * sigma); - half_size = alpha + 0.5f; + surface->filter_params->id = 0; - if (half_size == 0) - half_size = 1; - - size = half_size * 2 + 1; - xy_scale = 2.0f * radius / size; + /* center point is rounded down in case dimensions are not even */ + cx = m / 2; + cy = n / 2; - if (_glitz_filter_params_ensure (surface, size * size)) - return GLITZ_STATUS_NO_MEMORY; + for (i = 0; i < m; i++) { + glitz_vec4_t *vec; + glitz_float_t weight; - vecs = surface->filter_params->vectors; + for (j = 0; j < n; j++) { + _glitz_filter_params_set (&weight, 0.0f, ¶ms, &n_params); + if (weight != 0.0f) { + vec = &vecs[surface->filter_params->id++]; + vec->v[0] = (i - cx) * surface->texture.texcoord_width_unit; + vec->v[1] = (cy - j) * surface->texture.texcoord_height_unit; + vec->v[2] = weight; + vec->v[3] = 0.0f; + } + } + } + } break; + case GLITZ_FILTER_GAUSSIAN: { + glitz_float_t radius, sigma, alpha, scale, xy_scale, sum; + int half_size, x, y; - surface->filter_params->id = 0; + _glitz_filter_params_set (&radius, 1.0f, ¶ms, &n_params); + glitz_clamp_value (&radius, 0.0f, 1024.0f); - sum = 0.0f; - for (x = 0; x < size; x++) { - glitz_vec4_t *vec; - glitz_float_t fx, fy, amp; - - fx = xy_scale * (x - half_size); - - for (y = 0; y < size; y++) { - fy = xy_scale * (y - half_size); + _glitz_filter_params_set (&sigma, radius / 2.0f, ¶ms, &n_params); + glitz_clamp_value (&sigma, 0.0f, 1024.0f); - amp = scale * exp ((-1.0f * (fx * fx + fy * fy)) / - (2.0f * sigma * sigma)); + _glitz_filter_params_set (&alpha, radius, ¶ms, &n_params); + glitz_clamp_value (&alpha, 0.0f, 1024.0f); - if (amp > 0.0f) { - vec = &vecs[surface->filter_params->id++]; - vec->v[0] = fx * surface->texture.texcoord_width_unit; - vec->v[1] = fy * surface->texture.texcoord_height_unit; - vec->v[2] = amp; - vec->v[3] = 0.0f; - sum += amp; - } - } + scale = 1.0f / (2.0f * GLITZ_PI * sigma * sigma); + half_size = alpha + 0.5f; + + if (half_size == 0) + half_size = 1; + + size = half_size * 2 + 1; + xy_scale = 2.0f * radius / size; + + if (_glitz_filter_params_ensure (surface, size * size)) + return GLITZ_STATUS_NO_MEMORY; + + vecs = surface->filter_params->vectors; + + surface->filter_params->id = 0; + + sum = 0.0f; + for (x = 0; x < size; x++) { + glitz_vec4_t *vec; + glitz_float_t fx, fy, amp; + + fx = xy_scale * (x - half_size); + + for (y = 0; y < size; y++) { + fy = xy_scale * (y - half_size); + + amp = scale * exp ((-1.0f * (fx * fx + fy * fy)) / + (2.0f * sigma * sigma)); + + if (amp > 0.0f) { + vec = &vecs[surface->filter_params->id++]; + vec->v[0] = fx * surface->texture.texcoord_width_unit; + vec->v[1] = fy * surface->texture.texcoord_height_unit; + vec->v[2] = amp; + vec->v[3] = 0.0f; + sum += amp; + } + } + } + + /* normalize */ + if (sum != 0.0f) + sum = 1.0f / sum; + + for (i = 0; i < surface->filter_params->id; i++) + vecs[i].v[2] *= sum; + } break; + case GLITZ_FILTER_LINEAR_GRADIENT: + case GLITZ_FILTER_RADIAL_GRADIENT: + if (n_params <= 4) { + if (surface->box.x2 == 1) + size = surface->box.y2; + else if (surface->box.y2 == 1) + size = surface->box.x2; + } else + size = (n_params - 2) / 3; + + if (size < 2) + size = 2; + + if (_glitz_filter_params_ensure (surface, size + 1)) + return GLITZ_STATUS_NO_MEMORY; + + vecs = surface->filter_params->vectors; + + if (filter == GLITZ_FILTER_LINEAR_GRADIENT) { + glitz_float_t length, angle, dh, dv; + glitz_float_t start_x, start_y, stop_x, stop_y; + + _glitz_filter_params_set (&start_x, 0.0f, ¶ms, &n_params); + _glitz_filter_params_set (&start_y, 0.0f, ¶ms, &n_params); + _glitz_filter_params_set (&stop_x, 1.0f, ¶ms, &n_params); + _glitz_filter_params_set (&stop_y, 0.0f, ¶ms, &n_params); + + dh = stop_x - start_x; + dv = stop_y - start_y; + + length = sqrtf (dh * dh + dv * dv); + + angle = -atan2f (dv, dh); + + vecs->v[2] = cosf (angle); + vecs->v[3] = -sinf (angle); + + vecs->v[0] = vecs->v[2] * start_x; + vecs->v[0] += vecs->v[3] * start_y; + + vecs->v[1] = (length)? 1.0f / length: 2147483647.0f; + } else { + glitz_float_t r0, r1; + + _glitz_filter_params_set (&vecs->v[0], 0.5f, ¶ms, &n_params); + _glitz_filter_params_set (&vecs->v[1], 0.5f, ¶ms, &n_params); + _glitz_filter_params_set (&r0, 0.0f, ¶ms, &n_params); + _glitz_filter_params_set (&r1, 0.5f, ¶ms, &n_params); + + glitz_clamp_value (&r0, 0.0f, r1); + + vecs->v[2] = r0; + if (r1 != r0) + vecs->v[3] = 1.0f / (r1 - r0); + else + vecs->v[3] = 2147483647.0f; + } + + vecs++; + surface->filter_params->id = size; + + for (i = 0; i < size; i++) { + glitz_float_t x_default, y_default, o_default; + + o_default = i / (glitz_float_t) (size - 1); + x_default = (surface->box.x2 * i) / (glitz_float_t) size; + y_default = (surface->box.y2 * i) / (glitz_float_t) size; + + _glitz_filter_params_set (&vecs[i].v[2], o_default, ¶ms, + &n_params); + _glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms, + &n_params); + _glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms, + &n_params); + + glitz_clamp_value (&vecs[i].v[2], 0.0f, 1.0f); + glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f); + glitz_clamp_value (&vecs[i].v[1], 0.0f, surface->box.y2 - 1.0f); + + vecs[i].v[0] += 0.5f; + vecs[i].v[1] += 0.5f; + + vecs[i].v[0] += surface->texture.box.x1; + vecs[i].v[1] = surface->texture.box.y2 - vecs[i].v[1]; + + vecs[i].v[0] *= surface->texture.texcoord_width_unit; + vecs[i].v[1] *= surface->texture.texcoord_height_unit; + + vecs[i].v[3] = i; + } + + /* sort color stops in ascending order */ + qsort (vecs, surface->filter_params->id, sizeof (glitz_vec4_t), + _glitz_color_stop_compare); + + for (i = 0; i < size; i++) { + glitz_float_t diff; + + if ((i + 1) == size) + diff = 1.0f - vecs[i].v[2]; + else + diff = vecs[i + 1].v[2] - vecs[i].v[2]; + + if (diff != 0.0f) + vecs[i].v[3] = 1.0f / diff; + else + vecs[i].v[3] = 2147483647.0f; + } + break; + case GLITZ_FILTER_BILINEAR: + case GLITZ_FILTER_NEAREST: + if (surface->filter_params) + free (surface->filter_params); + + surface->filter_params = NULL; + break; } - /* normalize */ - if (sum != 0.0f) - sum = 1.0f / sum; - - for (i = 0; i < surface->filter_params->id; i++) - vecs[i].v[2] *= sum; - } break; - case GLITZ_FILTER_LINEAR_GRADIENT: - case GLITZ_FILTER_RADIAL_GRADIENT: - if (n_params <= 4) { - if (surface->box.x2 == 1) - size = surface->box.y2; - else if (surface->box.y2 == 1) - size = surface->box.x2; - } else - size = (n_params - 2) / 3; - - if (size < 2) - size = 2; + glitz_filter_set_type (surface, filter); - if (_glitz_filter_params_ensure (surface, size + 1)) - return GLITZ_STATUS_NO_MEMORY; - - vecs = surface->filter_params->vectors; - - if (filter == GLITZ_FILTER_LINEAR_GRADIENT) { - glitz_float_t length, angle, dh, dv; - glitz_float_t start_x, start_y, stop_x, stop_y; - - _glitz_filter_params_set (&start_x, 0.0f, ¶ms, &n_params); - _glitz_filter_params_set (&start_y, 0.0f, ¶ms, &n_params); - _glitz_filter_params_set (&stop_x, 1.0f, ¶ms, &n_params); - _glitz_filter_params_set (&stop_y, 0.0f, ¶ms, &n_params); - - dh = stop_x - start_x; - dv = stop_y - start_y; - - length = sqrtf (dh * dh + dv * dv); - - angle = -atan2f (dv, dh); - - vecs->v[2] = cosf (angle); - vecs->v[3] = -sinf (angle); - - vecs->v[0] = vecs->v[2] * start_x; - vecs->v[0] += vecs->v[3] * start_y; - - vecs->v[1] = (length)? 1.0f / length: 2147483647.0f; - } else { - glitz_float_t r0, r1; - - _glitz_filter_params_set (&vecs->v[0], 0.5f, ¶ms, &n_params); - _glitz_filter_params_set (&vecs->v[1], 0.5f, ¶ms, &n_params); - _glitz_filter_params_set (&r0, 0.0f, ¶ms, &n_params); - _glitz_filter_params_set (&r1, 0.5f, ¶ms, &n_params); - - glitz_clamp_value (&r0, 0.0f, r1); - - vecs->v[2] = r0; - if (r1 != r0) - vecs->v[3] = 1.0f / (r1 - r0); - else - vecs->v[3] = 2147483647.0f; - } - - vecs++; - surface->filter_params->id = size; - - for (i = 0; i < size; i++) { - glitz_float_t x_default, y_default, o_default; - - o_default = i / (glitz_float_t) (size - 1); - x_default = (surface->box.x2 * i) / (glitz_float_t) size; - y_default = (surface->box.y2 * i) / (glitz_float_t) size; - - _glitz_filter_params_set (&vecs[i].v[2], o_default, ¶ms, &n_params); - _glitz_filter_params_set (&vecs[i].v[0], x_default, ¶ms, &n_params); - _glitz_filter_params_set (&vecs[i].v[1], y_default, ¶ms, &n_params); - - glitz_clamp_value (&vecs[i].v[2], 0.0f, 1.0f); - glitz_clamp_value (&vecs[i].v[0], 0.0f, surface->box.x2 - 1.0f); - glitz_clamp_value (&vecs[i].v[1], 0.0f, surface->box.y2 - 1.0f); - - vecs[i].v[0] += 0.5f; - vecs[i].v[1] += 0.5f; - - vecs[i].v[0] += surface->texture.box.x1; - vecs[i].v[1] = surface->texture.box.y2 - vecs[i].v[1]; - - vecs[i].v[0] *= surface->texture.texcoord_width_unit; - vecs[i].v[1] *= surface->texture.texcoord_height_unit; - - vecs[i].v[3] = i; - } - - /* sort color stops in ascending order */ - qsort (vecs, surface->filter_params->id, sizeof (glitz_vec4_t), - _glitz_color_stop_compare); - - for (i = 0; i < size; i++) { - glitz_float_t diff; - - if ((i + 1) == size) - diff = 1.0f - vecs[i].v[2]; - else - diff = vecs[i + 1].v[2] - vecs[i].v[2]; - - if (diff != 0.0f) - vecs[i].v[3] = 1.0f / diff; - else - vecs[i].v[3] = 2147483647.0f; /* should be FLT_MAX, but this will do */ - } - break; - case GLITZ_FILTER_BILINEAR: - case GLITZ_FILTER_NEAREST: - if (surface->filter_params) - free (surface->filter_params); - - surface->filter_params = NULL; - break; - } - - glitz_filter_set_type (surface, filter); - - return GLITZ_STATUS_SUCCESS; + return GLITZ_STATUS_SUCCESS; } glitz_gl_uint_t glitz_filter_get_fragment_program (glitz_surface_t *surface, - glitz_composite_op_t *op) + glitz_composite_op_t *op) { - return glitz_get_fragment_program (op, - surface->filter_params->fp_type, - surface->filter_params->id); + return glitz_get_fragment_program (op, + surface->filter_params->fp_type, + surface->filter_params->id); } void glitz_filter_set_type (glitz_surface_t *surface, - glitz_filter_t filter) + glitz_filter_t filter) { - switch (filter) { - case GLITZ_FILTER_CONVOLUTION: - case GLITZ_FILTER_GAUSSIAN: - surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION; - break; - case GLITZ_FILTER_LINEAR_GRADIENT: - if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) { - if (SURFACE_MIRRORED (surface)) - surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_REFLECT; - else - surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_REPEAT; - } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) { - surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_NEAREST; - } else - surface->filter_params->fp_type = GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT; - break; - case GLITZ_FILTER_RADIAL_GRADIENT: - if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) { - if (SURFACE_MIRRORED (surface)) - surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_REFLECT; - else - surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_REPEAT; - } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) { - surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_NEAREST; - } else - surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT; - break; - case GLITZ_FILTER_BILINEAR: - case GLITZ_FILTER_NEAREST: - break; - } + switch (filter) { + case GLITZ_FILTER_CONVOLUTION: + case GLITZ_FILTER_GAUSSIAN: + surface->filter_params->fp_type = GLITZ_FP_CONVOLUTION; + break; + case GLITZ_FILTER_LINEAR_GRADIENT: + if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) { + if (SURFACE_MIRRORED (surface)) + surface->filter_params->fp_type = + GLITZ_FP_LINEAR_GRADIENT_REFLECT; + else + surface->filter_params->fp_type = + GLITZ_FP_LINEAR_GRADIENT_REPEAT; + } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) { + surface->filter_params->fp_type = + GLITZ_FP_LINEAR_GRADIENT_NEAREST; + } else + surface->filter_params->fp_type = + GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT; + break; + case GLITZ_FILTER_RADIAL_GRADIENT: + if (surface->flags & GLITZ_SURFACE_FLAG_REPEAT_MASK) { + if (SURFACE_MIRRORED (surface)) + surface->filter_params->fp_type = + GLITZ_FP_RADIAL_GRADIENT_REFLECT; + else + surface->filter_params->fp_type = + GLITZ_FP_RADIAL_GRADIENT_REPEAT; + } else if (surface->flags & GLITZ_SURFACE_FLAG_PAD_MASK) { + surface->filter_params->fp_type = GLITZ_FP_RADIAL_GRADIENT_NEAREST; + } else + surface->filter_params->fp_type = + GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT; + break; + case GLITZ_FILTER_BILINEAR: + case GLITZ_FILTER_NEAREST: + break; + } } void glitz_filter_enable (glitz_surface_t *surface, - glitz_composite_op_t *op) + glitz_composite_op_t *op) { - glitz_gl_proc_address_list_t *gl = op->gl; - int i; + glitz_gl_proc_address_list_t *gl = op->gl; + int i; - gl->enable (GLITZ_GL_FRAGMENT_PROGRAM); - gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, op->fp); + gl->enable (GLITZ_GL_FRAGMENT_PROGRAM); + gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, op->fp); - switch (surface->filter) { - case GLITZ_FILTER_GAUSSIAN: - case GLITZ_FILTER_CONVOLUTION: - for (i = 0; i < surface->filter_params->id; i++) - gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i, - surface->filter_params->vectors[i].v); - break; - case GLITZ_FILTER_LINEAR_GRADIENT: - case GLITZ_FILTER_RADIAL_GRADIENT: { - int j, fp_type = surface->filter_params->fp_type; - glitz_vec4_t *vec; + switch (surface->filter) { + case GLITZ_FILTER_GAUSSIAN: + case GLITZ_FILTER_CONVOLUTION: + for (i = 0; i < surface->filter_params->id; i++) + gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i, + surface->filter_params->vectors[i].v); + break; + case GLITZ_FILTER_LINEAR_GRADIENT: + case GLITZ_FILTER_RADIAL_GRADIENT: { + int j, fp_type = surface->filter_params->fp_type; + glitz_vec4_t *vec; - vec = surface->filter_params->vectors; - - gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0, vec->v); + vec = surface->filter_params->vectors; - vec++; + gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 0, vec->v); - if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT || - fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) { - glitz_vec4_t v; + vec++; - v.v[0] = v.v[1] = -1.0f; - v.v[2] = 0.0f; - v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f; - - gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v); - j = 2; - } else - j = 1; - - for (i = 0; i < surface->filter_params->id; i++, vec++) - gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i + j, vec->v); - - if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT || - fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) { - glitz_vec4_t v; + if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT || + fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) { + glitz_vec4_t v; - v.v[0] = v.v[1] = -1.0f; - v.v[2] = v.v[3] = 1.0f; - - gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, i + j, v.v); - } - } break; - case GLITZ_FILTER_BILINEAR: - case GLITZ_FILTER_NEAREST: - break; - } + v.v[0] = v.v[1] = -1.0f; + v.v[2] = 0.0f; + v.v[3] = (vec->v[3])? 1.0f / vec->v[3]: 1.0f; + + gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, 1, v.v); + j = 2; + } else + j = 1; + + for (i = 0; i < surface->filter_params->id; i++, vec++) + gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, + i + j, vec->v); + + if (fp_type == GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT || + fp_type == GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT) { + glitz_vec4_t v; + + v.v[0] = v.v[1] = -1.0f; + v.v[2] = v.v[3] = 1.0f; + + gl->program_local_param_4fv (GLITZ_GL_FRAGMENT_PROGRAM, + i + j, v.v); + } + } break; + case GLITZ_FILTER_BILINEAR: + case GLITZ_FILTER_NEAREST: + break; + } } diff --git a/gfx/cairo/glitz/src/glitz_format.c b/gfx/cairo/glitz/src/glitz_format.c index d3596904477..8e93e3a23f8 100644 --- a/gfx/cairo/glitz/src/glitz_format.c +++ b/gfx/cairo/glitz/src/glitz_format.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -32,254 +32,387 @@ #include struct _texture_format { - glitz_gl_int_t texture_format; - glitz_format_t format; + glitz_gl_int_t texture_format; + glitz_format_t format; } _texture_formats[] = { - { GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } }, - { GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } }, - { GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } }, - { GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } }, - { GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } }, - { GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } }, - { GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } }, - { GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } }, - { GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } }, - { GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } }, - { GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } }, - { GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } }, - { GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } }, - { GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } }, - { GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } }, - { GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } }, - { GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } }, - { GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } } + { GLITZ_GL_ALPHA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 4 } } }, + { GLITZ_GL_ALPHA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 8 } } }, + { GLITZ_GL_ALPHA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 12 } } }, + { GLITZ_GL_ALPHA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 0, 0, 0, 16 } } }, + { GLITZ_GL_R3_G3_B2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 3, 3, 2, 0 } } }, + { GLITZ_GL_RGB4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 0 } } }, + { GLITZ_GL_RGB5, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 6, 5, 0 } } }, + { GLITZ_GL_RGB8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 0 } } }, + { GLITZ_GL_RGB10, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 0 } } }, + { GLITZ_GL_RGB12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 0 } } }, + { GLITZ_GL_RGB16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 0 } } }, + { GLITZ_GL_RGBA2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 2, 2, 2, 2 } } }, + { GLITZ_GL_RGB5_A1, { 0, GLITZ_FORMAT_TYPE_COLOR, { 5, 5, 5, 1 } } }, + { GLITZ_GL_RGBA4, { 0, GLITZ_FORMAT_TYPE_COLOR, { 4, 4, 4, 4 } } }, + { GLITZ_GL_RGBA8, { 0, GLITZ_FORMAT_TYPE_COLOR, { 8, 8, 8, 8 } } }, + { GLITZ_GL_RGB10_A2, { 0, GLITZ_FORMAT_TYPE_COLOR, { 10, 10, 10, 2 } } }, + { GLITZ_GL_RGBA12, { 0, GLITZ_FORMAT_TYPE_COLOR, { 12, 12, 12, 12 } } }, + { GLITZ_GL_RGBA16, { 0, GLITZ_FORMAT_TYPE_COLOR, { 16, 16, 16, 16 } } } }; static void _glitz_add_texture_format (glitz_format_t **formats, - glitz_gl_int_t **texture_formats, - int *n_formats, - glitz_gl_int_t texture_format, - glitz_format_t *format) + glitz_gl_int_t **texture_formats, + int *n_formats, + glitz_gl_int_t texture_format, + glitz_format_t *format) { - *formats = realloc (*formats, sizeof (glitz_format_t) * (*n_formats + 1)); - *texture_formats = realloc (*texture_formats, - sizeof (glitz_gl_enum_t) * (*n_formats + 1)); + *formats = realloc (*formats, sizeof (glitz_format_t) * (*n_formats + 1)); + *texture_formats = realloc (*texture_formats, + sizeof (glitz_gl_enum_t) * (*n_formats + 1)); - if (*formats && *texture_formats) { - (*texture_formats)[*n_formats] = texture_format; - (*formats)[*n_formats] = *format; - (*formats)[*n_formats].id = *n_formats; - (*n_formats)++; - } else - *n_formats = 0; + if (*formats && *texture_formats) { + (*texture_formats)[*n_formats] = texture_format; + (*formats)[*n_formats] = *format; + (*formats)[*n_formats].id = *n_formats; + (*n_formats)++; + } else + *n_formats = 0; } void glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl, - glitz_format_t **formats, - glitz_gl_int_t **texture_formats, - int *n_formats) + glitz_format_t **formats, + glitz_gl_int_t **texture_formats, + int *n_formats) { - glitz_gl_int_t value; - int i, n_texture_formats; - - n_texture_formats = - sizeof (_texture_formats) / sizeof (struct _texture_format); - - for (i = 0; i < n_texture_formats; i++) { - gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0, - _texture_formats[i].texture_format, 1, 1, 0, - GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL); + glitz_gl_int_t value; + int i, n_texture_formats; - switch (_texture_formats[i].format.type) { - case GLITZ_FORMAT_TYPE_COLOR: - if (_texture_formats[i].format.color.red_size) { - gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, - GLITZ_GL_TEXTURE_RED_SIZE, &value); - if (value != _texture_formats[i].format.color.red_size) - continue; - } - - if (_texture_formats[i].format.color.green_size) { - gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, - GLITZ_GL_TEXTURE_GREEN_SIZE, &value); - if (value != _texture_formats[i].format.color.green_size) - continue; - } + n_texture_formats = + sizeof (_texture_formats) / sizeof (struct _texture_format); - if (_texture_formats[i].format.color.blue_size) { - gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, - GLITZ_GL_TEXTURE_BLUE_SIZE, &value); - if (value != _texture_formats[i].format.color.blue_size) - continue; - } + for (i = 0; i < n_texture_formats; i++) { + gl->tex_image_2d (GLITZ_GL_PROXY_TEXTURE_2D, 0, + _texture_formats[i].texture_format, 1, 1, 0, + GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL); - if (_texture_formats[i].format.color.alpha_size) { - gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, - GLITZ_GL_TEXTURE_ALPHA_SIZE, &value); - if (value != _texture_formats[i].format.color.alpha_size) - continue; - } - break; - default: - continue; + switch (_texture_formats[i].format.type) { + case GLITZ_FORMAT_TYPE_COLOR: + if (_texture_formats[i].format.color.red_size) { + gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, + GLITZ_GL_TEXTURE_RED_SIZE, + &value); + if (value != _texture_formats[i].format.color.red_size) + continue; + } + + if (_texture_formats[i].format.color.green_size) { + gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, + GLITZ_GL_TEXTURE_GREEN_SIZE, + &value); + if (value != _texture_formats[i].format.color.green_size) + continue; + } + + if (_texture_formats[i].format.color.blue_size) { + gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, + GLITZ_GL_TEXTURE_BLUE_SIZE, + &value); + if (value != _texture_formats[i].format.color.blue_size) + continue; + } + + if (_texture_formats[i].format.color.alpha_size) { + gl->get_tex_level_parameter_iv (GLITZ_GL_PROXY_TEXTURE_2D, 0, + GLITZ_GL_TEXTURE_ALPHA_SIZE, + &value); + if (value != _texture_formats[i].format.color.alpha_size) + continue; + } + break; + default: + continue; + } + + _glitz_add_texture_format (formats, + texture_formats, + n_formats, + _texture_formats[i].texture_format, + &_texture_formats[i].format); } - - _glitz_add_texture_format (formats, - texture_formats, - n_formats, - _texture_formats[i].texture_format, - &_texture_formats[i].format); - } +} + +static void +_glitz_add_drawable_format (glitz_int_drawable_format_t *format, + glitz_int_drawable_format_t **formats, + int *n_formats) +{ + void *ptr; + + ptr = realloc (*formats, + sizeof (glitz_int_drawable_format_t) * (*n_formats + 1)); + if (ptr) + { + *formats = ptr; + (*formats)[*n_formats] = *format; + (*n_formats)++; + } +} + +/* TODO: Available drawable formats needs to be validated is a similar way + as surface formats. */ +void +_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl, + unsigned long feature_mask, + glitz_int_drawable_format_t **formats, + int *n_formats) +{ + if (feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) + { + glitz_int_drawable_format_t format; + glitz_drawable_format_t d[] = { + { 0, { 8, 8, 8, 0 }, 0, 0, 1, 0 }, + { 0, { 8, 8, 8, 8 }, 0, 0, 1, 0 }, + { 0, { 8, 8, 8, 0 }, 24, 8, 1, 1 }, + { 0, { 8, 8, 8, 8 }, 24, 8, 1, 1 } + }; + int i; + + format.types = GLITZ_DRAWABLE_TYPE_FBO_MASK; + format.caveat = 0; + format.u.val = 0; + + for (i = 0; i < sizeof (d) / sizeof (d[0]); i++) + { + format.d = d[i]; + format.d.id = *n_formats; + + _glitz_add_drawable_format (&format, formats, n_formats); + } + } +} + +void +glitz_drawable_format_copy (const glitz_drawable_format_t *src, + glitz_drawable_format_t *dst, + unsigned long mask) +{ + if (mask & GLITZ_FORMAT_ID_MASK) + dst->id = src->id; + + if (mask & GLITZ_FORMAT_RED_SIZE_MASK) + dst->color.red_size = src->color.red_size; + + if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) + dst->color.green_size = src->color.green_size; + + if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) + dst->color.blue_size = src->color.blue_size; + + if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) + dst->color.alpha_size = src->color.alpha_size; + + if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK) + dst->depth_size = src->depth_size; + + if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK) + dst->stencil_size = src->stencil_size; + + if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK) + dst->doublebuffer = src->doublebuffer; + + if (mask & GLITZ_FORMAT_SAMPLES_MASK) + dst->samples = src->samples; } glitz_drawable_format_t * -glitz_drawable_format_find (glitz_drawable_format_t *formats, - int n_formats, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count) +glitz_drawable_format_find (glitz_int_drawable_format_t *formats, + int n_formats, + unsigned long mask, + const glitz_int_drawable_format_t *templ, + int count) { - for (; n_formats; n_formats--, formats++) { - if (mask & GLITZ_FORMAT_ID_MASK) - if (templ->id != formats->id) - continue; + for (; n_formats; n_formats--, formats++) + { + if (mask & GLITZ_FORMAT_ID_MASK) + if (templ->d.id != formats->d.id) + continue; - if (mask & GLITZ_FORMAT_RED_SIZE_MASK) - if (templ->color.red_size != formats->color.red_size) - continue; + if (mask & GLITZ_FORMAT_RED_SIZE_MASK) + if (templ->d.color.red_size != formats->d.color.red_size) + continue; - if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) - if (templ->color.green_size != formats->color.green_size) - continue; + if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) + if (templ->d.color.green_size != formats->d.color.green_size) + continue; - if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) - if (templ->color.blue_size != formats->color.blue_size) - continue; + if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) + if (templ->d.color.blue_size != formats->d.color.blue_size) + continue; - if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) - if (templ->color.alpha_size != formats->color.alpha_size) - continue; + if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) + if (templ->d.color.alpha_size != formats->d.color.alpha_size) + continue; - if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK) - if (templ->depth_size != formats->depth_size) - continue; + if (mask & GLITZ_FORMAT_DEPTH_SIZE_MASK) + if (templ->d.depth_size != formats->d.depth_size) + continue; - if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK) - if (templ->stencil_size != formats->stencil_size) - continue; + if (mask & GLITZ_FORMAT_STENCIL_SIZE_MASK) + if (templ->d.stencil_size != formats->d.stencil_size) + continue; - if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK) - if (templ->doublebuffer != formats->doublebuffer) - continue; + if (mask & GLITZ_FORMAT_DOUBLEBUFFER_MASK) + if (templ->d.doublebuffer != formats->d.doublebuffer) + continue; - if (mask & GLITZ_FORMAT_SAMPLES_MASK) - if (templ->samples != formats->samples) - continue; + if (mask & GLITZ_FORMAT_SAMPLES_MASK) + if (templ->d.samples != formats->d.samples) + continue; - if (mask & GLITZ_FORMAT_WINDOW_MASK) - if (templ->types.window != formats->types.window) - continue; + if (mask & GLITZ_INT_FORMAT_WINDOW_MASK) + if ((templ->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK) != + (formats->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)) + continue; - if (mask & GLITZ_FORMAT_PBUFFER_MASK) - if (templ->types.pbuffer != formats->types.pbuffer) - continue; - - if (count-- == 0) - return formats; - } + if (mask & GLITZ_INT_FORMAT_PBUFFER_MASK) + if ((templ->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK) != + (formats->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)) + continue; - return NULL; + if (mask & GLITZ_INT_FORMAT_FBO_MASK) + if ((templ->types & GLITZ_DRAWABLE_TYPE_FBO_MASK) != + (formats->types & GLITZ_DRAWABLE_TYPE_FBO_MASK)) + continue; + + if (count-- == 0) + return &formats->d; + } + + return NULL; } static glitz_format_t * _glitz_format_find (glitz_format_t *formats, - int n_formats, - unsigned long mask, - const glitz_format_t *templ, - int count) + int n_formats, + unsigned long mask, + const glitz_format_t *templ, + int count) { - for (; n_formats; n_formats--, formats++) { - if (mask & GLITZ_FORMAT_ID_MASK) - if (templ->id != formats->id) - continue; + for (; n_formats; n_formats--, formats++) { + if (mask & GLITZ_FORMAT_ID_MASK) + if (templ->id != formats->id) + continue; - if (mask & GLITZ_FORMAT_TYPE_MASK) - if (templ->type != formats->type) - continue; + if (mask & GLITZ_FORMAT_TYPE_MASK) + if (templ->type != formats->type) + continue; - if (mask & GLITZ_FORMAT_RED_SIZE_MASK) - if (templ->color.red_size != formats->color.red_size) - continue; + if (mask & GLITZ_FORMAT_RED_SIZE_MASK) + if (templ->color.red_size != formats->color.red_size) + continue; - if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) - if (templ->color.green_size != formats->color.green_size) - continue; + if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) + if (templ->color.green_size != formats->color.green_size) + continue; - if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) - if (templ->color.blue_size != formats->color.blue_size) - continue; + if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) + if (templ->color.blue_size != formats->color.blue_size) + continue; - if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) - if (templ->color.alpha_size != formats->color.alpha_size) - continue; + if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) + if (templ->color.alpha_size != formats->color.alpha_size) + continue; - if (count-- == 0) - return formats; - } + if (count-- == 0) + return formats; + } - return NULL; + return NULL; } glitz_format_t * glitz_find_format (glitz_drawable_t *drawable, - unsigned long mask, - const glitz_format_t *templ, - int count) + unsigned long mask, + const glitz_format_t *templ, + int count) { - return _glitz_format_find (drawable->backend->formats, - drawable->backend->n_formats, - mask, templ, count); + return _glitz_format_find (drawable->backend->formats, + drawable->backend->n_formats, + mask, templ, count); } glitz_format_t * glitz_find_standard_format (glitz_drawable_t *drawable, - glitz_format_name_t format_name) + glitz_format_name_t format_name) { - glitz_format_t templ; - unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK | - GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK | - GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK; + glitz_format_t templ; + unsigned long mask = GLITZ_FORMAT_RED_SIZE_MASK | + GLITZ_FORMAT_GREEN_SIZE_MASK | GLITZ_FORMAT_BLUE_SIZE_MASK | + GLITZ_FORMAT_ALPHA_SIZE_MASK | GLITZ_FORMAT_TYPE_MASK; - templ.type = GLITZ_FORMAT_TYPE_COLOR; + templ.type = GLITZ_FORMAT_TYPE_COLOR; - switch (format_name) { - case GLITZ_STANDARD_ARGB32: - templ.color.red_size = 8; - templ.color.green_size = 8; - templ.color.blue_size = 8; - templ.color.alpha_size = 8; - break; - case GLITZ_STANDARD_RGB24: - templ.color.red_size = 8; - templ.color.green_size = 8; - templ.color.blue_size = 8; - templ.color.alpha_size = 0; - break; - case GLITZ_STANDARD_A8: - templ.color.red_size = 0; - templ.color.green_size = 0; - templ.color.blue_size = 0; - templ.color.alpha_size = 8; - break; - case GLITZ_STANDARD_A1: - templ.color.red_size = 0; - templ.color.green_size = 0; - templ.color.blue_size = 0; - templ.color.alpha_size = 1; - break; - } + switch (format_name) { + case GLITZ_STANDARD_ARGB32: + templ.color.red_size = 8; + templ.color.green_size = 8; + templ.color.blue_size = 8; + templ.color.alpha_size = 8; + break; + case GLITZ_STANDARD_RGB24: + templ.color.red_size = 8; + templ.color.green_size = 8; + templ.color.blue_size = 8; + templ.color.alpha_size = 0; + break; + case GLITZ_STANDARD_A8: + templ.color.red_size = 0; + templ.color.green_size = 0; + templ.color.blue_size = 0; + templ.color.alpha_size = 8; + break; + case GLITZ_STANDARD_A1: + templ.color.red_size = 0; + templ.color.green_size = 0; + templ.color.blue_size = 0; + templ.color.alpha_size = 1; + break; + } - return glitz_find_format (drawable, mask, &templ, 0); + return glitz_find_format (drawable, mask, &templ, 0); } + +glitz_drawable_format_t * +glitz_find_drawable_format (glitz_drawable_t *other, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) +{ + glitz_int_drawable_format_t itempl; + + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_FBO_MASK; + mask |= GLITZ_INT_FORMAT_FBO_MASK; + + return glitz_drawable_format_find (other->backend->drawable_formats, + other->backend->n_drawable_formats, + mask, &itempl, count); +} +slim_hidden_def(glitz_find_drawable_format); + +glitz_drawable_format_t * +glitz_find_pbuffer_format (glitz_drawable_t *other, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) +{ + glitz_int_drawable_format_t itempl; + + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + mask |= GLITZ_INT_FORMAT_PBUFFER_MASK; + + return glitz_drawable_format_find (other->backend->drawable_formats, + other->backend->n_drawable_formats, + mask, &itempl, count); +} +slim_hidden_def(glitz_find_pbuffer_format); diff --git a/gfx/cairo/glitz/src/glitz_framebuffer.c b/gfx/cairo/glitz/src/glitz_framebuffer.c index 87edbe4bd8b..69e73819ad3 100644 --- a/gfx/cairo/glitz/src/glitz_framebuffer.c +++ b/gfx/cairo/glitz/src/glitz_framebuffer.c @@ -1,6 +1,6 @@ /* * Copyright © 2005 Novell, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -29,48 +29,375 @@ #include "glitzint.h" -void -glitz_framebuffer_init (glitz_framebuffer_t *framebuffer) -{ - framebuffer->name = 0; -} +typedef struct _glitz_fbo_drawable { + glitz_drawable_t base; + glitz_drawable_t *other; + int width; + int height; + glitz_gl_uint_t fb; + glitz_gl_uint_t front; + glitz_gl_uint_t back; + glitz_gl_uint_t depth; + glitz_gl_uint_t stencil; + glitz_gl_uint_t front_texture; + glitz_gl_uint_t back_texture; + glitz_gl_enum_t internal_format; +} glitz_fbo_drawable_t; -void -glitz_framebuffer_fini (glitz_gl_proc_address_list_t *gl, - glitz_framebuffer_t *framebuffer) +static glitz_bool_t +_glitz_fbo_bind (glitz_fbo_drawable_t *drawable) { - if (framebuffer->name) - gl->delete_framebuffers (1, &framebuffer->name); -} + glitz_bool_t update = 0; + glitz_gl_enum_t status; -void -glitz_framebuffer_unbind (glitz_gl_proc_address_list_t *gl) -{ - gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0); -} + GLITZ_GL_DRAWABLE (drawable->other); -glitz_bool_t -glitz_framebuffer_complete (glitz_gl_proc_address_list_t *gl, - glitz_framebuffer_t *framebuffer, - glitz_texture_t *texture) -{ - if (!framebuffer->name) + if (!drawable->fb) { - if (!TEXTURE_ALLOCATED (texture)) - glitz_texture_allocate (gl, texture); - - gl->gen_framebuffers (1, &framebuffer->name); + gl->gen_framebuffers (1, &drawable->fb); - gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, framebuffer->name); - - gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER, - GLITZ_GL_COLOR_ATTACHMENT0, - GLITZ_GL_TEXTURE_2D, texture->name, - 0); + drawable->width = drawable->base.width; + drawable->height = drawable->base.height; + update = 1; + } + else if (drawable->width != drawable->base.width || + drawable->height != drawable->base.height) + { + drawable->width = drawable->base.width; + drawable->height = drawable->base.height; + update = 1; } - else - gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, framebuffer->name); - return (gl->check_framebuffer_status (GLITZ_GL_FRAMEBUFFER) == - GLITZ_GL_FRAMEBUFFER_COMPLETE); + gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, drawable->fb); + + if (drawable->base.front && + drawable->front_texture != drawable->base.front->texture.name) + { + gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT0, + drawable->base.front->texture.target, + drawable->base.front->texture.name, + 0); + + drawable->front_texture = drawable->base.front->texture.name; + + if (drawable->front) + { + gl->delete_renderbuffers (1, &drawable->front); + drawable->front = 0; + } + } + + if (!drawable->front_texture && !drawable->front) + { + gl->gen_renderbuffers (1, &drawable->front); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, drawable->front); + gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER, + drawable->internal_format, + drawable->base.width, + drawable->base.height); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0); + gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT0, + GLITZ_GL_RENDERBUFFER, + drawable->front); + } + + if (drawable->base.format->d.doublebuffer) + { + if (drawable->base.back && + drawable->back_texture != drawable->base.back->texture.name) + { + gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT1, + drawable->base.back->texture.target, + drawable->base.back->texture.name, + 0); + + drawable->back_texture = drawable->base.back->texture.name; + + if (drawable->back) + { + gl->delete_renderbuffers (1, &drawable->back); + drawable->back = 0; + } + } + + if (!drawable->back_texture && !drawable->back) + { + gl->gen_renderbuffers (1, &drawable->back); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, + drawable->back); + gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER, + drawable->internal_format, + drawable->base.width, + drawable->base.height); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0); + gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT1, + GLITZ_GL_RENDERBUFFER, + drawable->back); + } + } + + if (update) + { + if (drawable->base.format->d.depth_size) + { + if (!drawable->depth) + gl->gen_renderbuffers (1, &drawable->depth); + + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, drawable->depth); + gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER, + GLITZ_GL_DEPTH_COMPONENT, + drawable->base.width, + drawable->base.height); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0); + + gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_DEPTH_ATTACHMENT, + GLITZ_GL_RENDERBUFFER, + drawable->depth); + } + + if (drawable->base.format->d.stencil_size) + { + if (!drawable->stencil) + gl->gen_renderbuffers (1, &drawable->stencil); + + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, + drawable->stencil); + gl->renderbuffer_storage (GLITZ_GL_RENDERBUFFER, + GLITZ_GL_STENCIL_INDEX, + drawable->base.width, + drawable->base.height); + gl->bind_renderbuffer (GLITZ_GL_RENDERBUFFER, 0); + + gl->framebuffer_renderbuffer (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_STENCIL_ATTACHMENT, + GLITZ_GL_RENDERBUFFER, + drawable->stencil); + } + } + + status = gl->check_framebuffer_status (GLITZ_GL_FRAMEBUFFER); + if (status == GLITZ_GL_FRAMEBUFFER_COMPLETE) + return 1; + + return 0; +} + +static void +_glitz_fbo_attach_notify (void *abstract_drawable, + glitz_surface_t *surface) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + glitz_texture_t *texture; + + GLITZ_GL_DRAWABLE (drawable->other); + + texture = &surface->texture; + if (!TEXTURE_ALLOCATED (texture)) + { + drawable->other->backend->push_current (drawable->other, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + glitz_texture_allocate (gl, texture); + drawable->other->backend->pop_current (drawable->other); + + if (!TEXTURE_ALLOCATED (texture)) + return; + } + + REGION_EMPTY (&surface->drawable_damage); +} + +static void +_glitz_fbo_detach_notify (void *abstract_drawable, + glitz_surface_t *surface) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + if (surface->texture.name == drawable->front_texture || + surface->texture.name == drawable->back_texture) + { + GLITZ_GL_DRAWABLE (drawable->other); + + drawable->other->backend->push_current (drawable->other, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + + gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, drawable->fb); + + if (surface->texture.name == drawable->front_texture) + { + gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT0, + surface->texture.target, + 0, 0); + drawable->front_texture = 0; + } + + if (surface->texture.name == drawable->back_texture) + { + gl->framebuffer_texture_2d (GLITZ_GL_FRAMEBUFFER, + GLITZ_GL_COLOR_ATTACHMENT1, + surface->texture.target, + 0, 0); + drawable->back_texture = 0; + } + + gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0); + + surface->fb = 0; + + drawable->other->backend->pop_current (drawable->other); + } +} + +static glitz_bool_t +_glitz_fbo_push_current (void *abstract_drawable, + glitz_surface_t *surface, + glitz_constraint_t constraint) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + drawable->other->backend->push_current (drawable->other, surface, + constraint); + + if (constraint == GLITZ_DRAWABLE_CURRENT) + { + if (_glitz_fbo_bind (drawable)) + { + drawable->base.update_all = drawable->other->update_all = 1; + surface->fb = drawable->fb; + return 1; + } + } + + return 0; +} + +static glitz_surface_t * +_glitz_fbo_pop_current (void *abstract_drawable) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + GLITZ_GL_DRAWABLE (drawable->other); + + gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0); + + return drawable->other->backend->pop_current (drawable->other); +} + +static void +_glitz_fbo_make_current (void *abstract_drawable, + void *abstract_context) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + drawable->other->backend->make_current (drawable->other, abstract_context); + + _glitz_fbo_bind (drawable); +} + +static glitz_bool_t +_glitz_fbo_swap_buffers (void *abstract_drawable) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + if (!drawable->fb) + return 1; + + return 0; +} + +static void +_glitz_fbo_destroy (void *abstract_drawable) +{ + glitz_fbo_drawable_t *drawable = (glitz_fbo_drawable_t *) + abstract_drawable; + + if (drawable->fb) + { + GLITZ_GL_DRAWABLE (drawable->other); + + drawable->other->backend->push_current (drawable->other, NULL, + GLITZ_ANY_CONTEXT_CURRENT); + + gl->delete_framebuffers (1, &drawable->fb); + + if (drawable->front) + gl->delete_renderbuffers (1, &drawable->front); + + if (drawable->back) + gl->delete_renderbuffers (1, &drawable->back); + + if (drawable->depth) + gl->delete_renderbuffers (1, &drawable->depth); + + if (drawable->stencil) + gl->delete_renderbuffers (1, &drawable->stencil); + + drawable->other->backend->pop_current (drawable->other); + } + + glitz_drawable_destroy (drawable->other); + + free (drawable); +} + +glitz_drawable_t * +_glitz_fbo_drawable_create (glitz_drawable_t *other, + glitz_int_drawable_format_t *format, + int width, + int height) +{ + glitz_fbo_drawable_t *drawable; + glitz_backend_t *backend; + + drawable = malloc (sizeof (glitz_fbo_drawable_t) + + sizeof (glitz_backend_t)); + if (!drawable) + return NULL; + + glitz_drawable_reference (other); + drawable->other = other; + backend = (glitz_backend_t *) (drawable + 1); + *backend = *other->backend; + + backend->destroy = _glitz_fbo_destroy; + backend->push_current = _glitz_fbo_push_current; + backend->pop_current = _glitz_fbo_pop_current; + backend->attach_notify = _glitz_fbo_attach_notify; + backend->detach_notify = _glitz_fbo_detach_notify; + backend->swap_buffers = _glitz_fbo_swap_buffers; + backend->make_current = _glitz_fbo_make_current; + + drawable->fb = 0; + + drawable->width = 0; + drawable->height = 0; + + drawable->front = 0; + drawable->back = 0; + drawable->depth = 0; + drawable->stencil = 0; + + drawable->front_texture = 0; + drawable->back_texture = 0; + + /* XXX: temporary solution until we have proper format validation */ + if (format->d.color.alpha_size) + drawable->internal_format = GLITZ_GL_RGBA; + else + drawable->internal_format = GLITZ_GL_RGB; + + _glitz_drawable_init (&drawable->base, format, backend, width, height); + + return &drawable->base; } diff --git a/gfx/cairo/glitz/src/glitz_geometry.c b/gfx/cairo/glitz/src/glitz_geometry.c index 9c16aa930af..4a5cbdf3342 100644 --- a/gfx/cairo/glitz/src/glitz_geometry.c +++ b/gfx/cairo/glitz/src/glitz_geometry.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -35,151 +35,151 @@ _glitz_data_type (glitz_data_type_t type) { switch (type) { case GLITZ_DATA_TYPE_SHORT: - return GLITZ_GL_SHORT; + return GLITZ_GL_SHORT; case GLITZ_DATA_TYPE_INT: - return GLITZ_GL_INT; + return GLITZ_GL_INT; case GLITZ_DATA_TYPE_DOUBLE: - return GLITZ_GL_DOUBLE; + return GLITZ_GL_DOUBLE; default: - return GLITZ_GL_FLOAT; + return GLITZ_GL_FLOAT; } } void glitz_set_geometry (glitz_surface_t *dst, - glitz_geometry_type_t type, - glitz_geometry_format_t *format, - glitz_buffer_t *buffer) + glitz_geometry_type_t type, + glitz_geometry_format_t *format, + glitz_buffer_t *buffer) { switch (type) { case GLITZ_GEOMETRY_TYPE_VERTEX: { - glitz_buffer_reference (buffer); - if (dst->geometry.buffer) - glitz_buffer_destroy (dst->geometry.buffer); - dst->geometry.buffer = buffer; - - dst->geometry.type = GLITZ_GEOMETRY_TYPE_VERTEX; - - switch (format->vertex.primitive) { - case GLITZ_PRIMITIVE_POINTS: - dst->geometry.u.v.prim = GLITZ_GL_POINTS; - break; - case GLITZ_PRIMITIVE_LINES: - dst->geometry.u.v.prim = GLITZ_GL_LINES; - break; - case GLITZ_PRIMITIVE_LINE_STRIP: - dst->geometry.u.v.prim = GLITZ_GL_LINE_STRIP; - break; - case GLITZ_PRIMITIVE_LINE_LOOP: - dst->geometry.u.v.prim = GLITZ_GL_LINE_LOOP; - break; - case GLITZ_PRIMITIVE_TRIANGLES: - dst->geometry.u.v.prim = GLITZ_GL_TRIANGLES; - break; - case GLITZ_PRIMITIVE_TRIANGLE_STRIP: - dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_STRIP; - break; - case GLITZ_PRIMITIVE_TRIANGLE_FAN: - dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_FAN; - break; - case GLITZ_PRIMITIVE_QUADS: - dst->geometry.u.v.prim = GLITZ_GL_QUADS; - break; - case GLITZ_PRIMITIVE_QUAD_STRIP: - dst->geometry.u.v.prim = GLITZ_GL_QUAD_STRIP; - break; - default: - dst->geometry.u.v.prim = GLITZ_GL_POLYGON; - break; - } - - dst->geometry.u.v.type = _glitz_data_type (format->vertex.type); - dst->geometry.stride = format->vertex.bytes_per_vertex; - dst->geometry.attributes = format->vertex.attributes; + glitz_buffer_reference (buffer); + if (dst->geometry.buffer) + glitz_buffer_destroy (dst->geometry.buffer); + dst->geometry.buffer = buffer; - if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) - { - dst->geometry.u.v.src.type = - _glitz_data_type (format->vertex.src.type); - dst->geometry.u.v.src.offset = format->vertex.src.offset; - - if (format->vertex.src.size == GLITZ_COORDINATE_SIZE_XY) - dst->geometry.u.v.src.size = 2; - else - dst->geometry.u.v.src.size = 1; - } - - if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) - { - dst->geometry.u.v.mask.type = - _glitz_data_type (format->vertex.mask.type); - dst->geometry.u.v.mask.offset = format->vertex.mask.offset; - - if (format->vertex.mask.size == GLITZ_COORDINATE_SIZE_XY) - dst->geometry.u.v.mask.size = 2; - else - dst->geometry.u.v.mask.size = 1; - } + dst->geometry.type = GLITZ_GEOMETRY_TYPE_VERTEX; + + switch (format->vertex.primitive) { + case GLITZ_PRIMITIVE_POINTS: + dst->geometry.u.v.prim = GLITZ_GL_POINTS; + break; + case GLITZ_PRIMITIVE_LINES: + dst->geometry.u.v.prim = GLITZ_GL_LINES; + break; + case GLITZ_PRIMITIVE_LINE_STRIP: + dst->geometry.u.v.prim = GLITZ_GL_LINE_STRIP; + break; + case GLITZ_PRIMITIVE_LINE_LOOP: + dst->geometry.u.v.prim = GLITZ_GL_LINE_LOOP; + break; + case GLITZ_PRIMITIVE_TRIANGLES: + dst->geometry.u.v.prim = GLITZ_GL_TRIANGLES; + break; + case GLITZ_PRIMITIVE_TRIANGLE_STRIP: + dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_STRIP; + break; + case GLITZ_PRIMITIVE_TRIANGLE_FAN: + dst->geometry.u.v.prim = GLITZ_GL_TRIANGLE_FAN; + break; + case GLITZ_PRIMITIVE_QUADS: + dst->geometry.u.v.prim = GLITZ_GL_QUADS; + break; + case GLITZ_PRIMITIVE_QUAD_STRIP: + dst->geometry.u.v.prim = GLITZ_GL_QUAD_STRIP; + break; + default: + dst->geometry.u.v.prim = GLITZ_GL_POLYGON; + break; + } + + dst->geometry.u.v.type = _glitz_data_type (format->vertex.type); + dst->geometry.stride = format->vertex.bytes_per_vertex; + dst->geometry.attributes = format->vertex.attributes; + + if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_SRC_COORD_MASK) + { + dst->geometry.u.v.src.type = + _glitz_data_type (format->vertex.src.type); + dst->geometry.u.v.src.offset = format->vertex.src.offset; + + if (format->vertex.src.size == GLITZ_COORDINATE_SIZE_XY) + dst->geometry.u.v.src.size = 2; + else + dst->geometry.u.v.src.size = 1; + } + + if (format->vertex.attributes & GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK) + { + dst->geometry.u.v.mask.type = + _glitz_data_type (format->vertex.mask.type); + dst->geometry.u.v.mask.offset = format->vertex.mask.offset; + + if (format->vertex.mask.size == GLITZ_COORDINATE_SIZE_XY) + dst->geometry.u.v.mask.size = 2; + else + dst->geometry.u.v.mask.size = 1; + } } break; case GLITZ_GEOMETRY_TYPE_BITMAP: - glitz_buffer_reference (buffer); - if (dst->geometry.buffer) - glitz_buffer_destroy (dst->geometry.buffer); - dst->geometry.buffer = buffer; - - dst->geometry.type = GLITZ_GEOMETRY_TYPE_BITMAP; + glitz_buffer_reference (buffer); + if (dst->geometry.buffer) + glitz_buffer_destroy (dst->geometry.buffer); + dst->geometry.buffer = buffer; - if (format->bitmap.scanline_order == - GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) - dst->geometry.u.b.top_down = 1; - else - dst->geometry.u.b.top_down = 0; + dst->geometry.type = GLITZ_GEOMETRY_TYPE_BITMAP; - switch (format->bitmap.pad) { - case 2: - dst->geometry.u.b.pad = 2; - break; - case 4: - dst->geometry.u.b.pad = 4; - break; - case 8: - dst->geometry.u.b.pad = 8; - break; - default: - dst->geometry.u.b.pad = 1; - break; - } - - dst->geometry.stride = format->bitmap.bytes_per_line; - dst->geometry.attributes = 0; - break; + if (format->bitmap.scanline_order == + GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) + dst->geometry.u.b.top_down = 1; + else + dst->geometry.u.b.top_down = 0; + + switch (format->bitmap.pad) { + case 2: + dst->geometry.u.b.pad = 2; + break; + case 4: + dst->geometry.u.b.pad = 4; + break; + case 8: + dst->geometry.u.b.pad = 8; + break; + default: + dst->geometry.u.b.pad = 1; + break; + } + + dst->geometry.stride = format->bitmap.bytes_per_line; + dst->geometry.attributes = 0; + break; default: - dst->geometry.type = GLITZ_GEOMETRY_TYPE_NONE; - if (dst->geometry.buffer) - glitz_buffer_destroy (dst->geometry.buffer); + dst->geometry.type = GLITZ_GEOMETRY_TYPE_NONE; + if (dst->geometry.buffer) + glitz_buffer_destroy (dst->geometry.buffer); - dst->geometry.buffer = NULL; - dst->geometry.attributes = 0; - break; + dst->geometry.buffer = NULL; + dst->geometry.attributes = 0; + break; } } slim_hidden_def(glitz_set_geometry); void glitz_set_array (glitz_surface_t *dst, - int first, - int size, - unsigned int count, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off) + int first, + int size, + unsigned int count, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off) { if (dst->geometry.array) { - glitz_multi_array_destroy (dst->geometry.array); - dst->geometry.array = NULL; + glitz_multi_array_destroy (dst->geometry.array); + dst->geometry.array = NULL; } - + dst->geometry.first = first; dst->geometry.size = size; dst->geometry.count = count; @@ -191,33 +191,33 @@ slim_hidden_def(glitz_set_array); glitz_multi_array_t * glitz_multi_array_create (unsigned int size) { - glitz_multi_array_t *array; - int alloc_size; + glitz_multi_array_t *array; + int alloc_size; - if (!size) - return NULL; + if (!size) + return NULL; - alloc_size = sizeof (glitz_multi_array_t) + (sizeof (int) + - sizeof (int) + - sizeof (unsigned int) + - sizeof (glitz_vec2_t) + - sizeof (int)) * (size); - - array = (glitz_multi_array_t *) malloc (alloc_size); - if (array == NULL) - return NULL; + alloc_size = sizeof (glitz_multi_array_t) + (sizeof (int) + + sizeof (int) + + sizeof (unsigned int) + + sizeof (glitz_vec2_t) + + sizeof (int)) * (size); - array->ref_count = 1; - array->size = size; - array->first = (int *) (array + 1); - array->sizes = (int *) (array->first + size); - array->count = (int *) (array->sizes + size); - array->off = (glitz_vec2_t *) (array->count + size); - array->span = (int *) (array->off + size); + array = (glitz_multi_array_t *) malloc (alloc_size); + if (array == NULL) + return NULL; - array->n_arrays = 0; - - return array; + array->ref_count = 1; + array->size = size; + array->first = (int *) (array + 1); + array->sizes = (int *) (array->first + size); + array->count = (int *) (array->sizes + size); + array->off = (glitz_vec2_t *) (array->count + size); + array->span = (int *) (array->off + size); + + array->n_arrays = 0; + + return array; } slim_hidden_def(glitz_multi_array_create); @@ -225,12 +225,12 @@ void glitz_multi_array_destroy (glitz_multi_array_t *array) { if (!array) - return; - + return; + array->ref_count--; if (array->ref_count) - return; - + return; + free (array); } @@ -238,23 +238,23 @@ void glitz_multi_array_reference (glitz_multi_array_t *array) { if (array == NULL) - return; - + return; + array->ref_count++; } void glitz_multi_array_add (glitz_multi_array_t *array, - int first, - int size, - unsigned int count, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off) + int first, + int size, + unsigned int count, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off) { int i; if (array->size == array->n_arrays) - return; + return; i = array->n_arrays++; @@ -262,14 +262,14 @@ glitz_multi_array_add (glitz_multi_array_t *array, array->sizes[i] = size; array->count[i] = count; array->span[i] = 0; - + if (i == 0 || x_off || y_off) { - array->off[i].v[0] = FIXED_TO_FLOAT (x_off); - array->off[i].v[1] = FIXED_TO_FLOAT (y_off); - array->current_span = &array->span[i]; + array->off[i].v[0] = FIXED_TO_FLOAT (x_off); + array->off[i].v[1] = FIXED_TO_FLOAT (y_off); + array->current_span = &array->span[i]; } - + (*array->current_span)++; } slim_hidden_def(glitz_multi_array_add); @@ -283,14 +283,14 @@ slim_hidden_def(glitz_multi_array_reset); void glitz_set_multi_array (glitz_surface_t *dst, - glitz_multi_array_t *array, - glitz_fixed16_16_t x_off, - glitz_fixed16_16_t y_off) + glitz_multi_array_t *array, + glitz_fixed16_16_t x_off, + glitz_fixed16_16_t y_off) { glitz_multi_array_reference (array); - + if (dst->geometry.array) - glitz_multi_array_destroy (dst->geometry.array); + glitz_multi_array_destroy (dst->geometry.array); dst->geometry.array = array; dst->geometry.count = array->n_arrays; @@ -301,49 +301,49 @@ slim_hidden_def(glitz_set_multi_array); void glitz_geometry_enable_none (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *box) + glitz_surface_t *dst, + glitz_box_t *box) { - dst->geometry.data[0] = (glitz_float_t) box->x1; - dst->geometry.data[1] = (glitz_float_t) box->y1; - dst->geometry.data[2] = (glitz_float_t) box->x2; - dst->geometry.data[3] = (glitz_float_t) box->y1; - dst->geometry.data[4] = (glitz_float_t) box->x2; - dst->geometry.data[5] = (glitz_float_t) box->y2; - dst->geometry.data[6] = (glitz_float_t) box->x1; - dst->geometry.data[7] = (glitz_float_t) box->y2; - - gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, dst->geometry.data); + dst->geometry.data[0] = (glitz_float_t) box->x1; + dst->geometry.data[1] = (glitz_float_t) box->y1; + dst->geometry.data[2] = (glitz_float_t) box->x2; + dst->geometry.data[3] = (glitz_float_t) box->y1; + dst->geometry.data[4] = (glitz_float_t) box->x2; + dst->geometry.data[5] = (glitz_float_t) box->y2; + dst->geometry.data[6] = (glitz_float_t) box->x1; + dst->geometry.data[7] = (glitz_float_t) box->y2; + + gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, dst->geometry.data); } void glitz_geometry_enable (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *box) + glitz_surface_t *dst, + glitz_box_t *box) { switch (dst->geometry.type) { case GLITZ_GEOMETRY_TYPE_VERTEX: - gl->vertex_pointer (2, dst->geometry.u.v.type, dst->geometry.stride, - glitz_buffer_bind (dst->geometry.buffer, - GLITZ_GL_ARRAY_BUFFER)); - break; + gl->vertex_pointer (2, dst->geometry.u.v.type, dst->geometry.stride, + glitz_buffer_bind (dst->geometry.buffer, + GLITZ_GL_ARRAY_BUFFER)); + break; case GLITZ_GEOMETRY_TYPE_BITMAP: - dst->geometry.u.b.base = - glitz_buffer_bind (dst->geometry.buffer, - GLITZ_GL_PIXEL_UNPACK_BUFFER); + dst->geometry.u.b.base = + glitz_buffer_bind (dst->geometry.buffer, + GLITZ_GL_PIXEL_UNPACK_BUFFER); - gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0); - gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0); #if BITMAP_BIT_ORDER == MSBFirst - gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_FALSE); + gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_FALSE); #else - gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_TRUE); + gl->pixel_store_i (GLITZ_GL_UNPACK_LSB_FIRST, GLITZ_GL_TRUE); #endif - - break; + + break; case GLITZ_GEOMETRY_TYPE_NONE: - glitz_geometry_enable_none (gl, dst, box); + glitz_geometry_enable_none (gl, dst, box); } } @@ -351,132 +351,130 @@ void glitz_geometry_disable (glitz_surface_t *dst) { if (dst->geometry.buffer) - glitz_buffer_unbind (dst->geometry.buffer); + glitz_buffer_unbind (dst->geometry.buffer); } static void _glitz_draw_rectangle (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *bounds, - int damage) + glitz_surface_t *dst, + glitz_box_t *bounds, + int damage) { glitz_box_t *clip = dst->clip; int n_clip = dst->n_clip; glitz_box_t box; - int target_height = SURFACE_DRAWABLE_HEIGHT (dst); - + while (n_clip--) { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds->x1 > box.x1) - box.x1 = bounds->x1; - if (bounds->y1 > box.y1) - box.y1 = bounds->y1; - if (bounds->x2 < box.x2) - box.x2 = bounds->x2; - if (bounds->y2 < box.y2) - box.y2 = bounds->y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - gl->scissor (box.x1 + dst->x, - target_height - dst->y - box.y2, - box.x2 - box.x1, box.y2 - box.y1); + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds->x1 > box.x1) + box.x1 = bounds->x1; + if (bounds->y1 > box.y1) + box.y1 = bounds->y1; + if (bounds->x2 < box.x2) + box.x2 = bounds->x2; + if (bounds->y2 < box.y2) + box.y2 = bounds->y2; - gl->draw_arrays (GLITZ_GL_QUADS, 0, 4); - - if (damage) - glitz_surface_damage (dst, &box, damage); - } - - clip++; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + gl->scissor (box.x1 + dst->x, + dst->attached->height - dst->y - box.y2, + box.x2 - box.x1, box.y2 - box.y1); + + gl->draw_arrays (GLITZ_GL_QUADS, 0, 4); + + if (damage) + glitz_surface_damage (dst, &box, damage); + } + + clip++; } } -#define MULTI_DRAW_ARRAYS(surface) \ - ((surface)->drawable->backend->feature_mask & \ +#define MULTI_DRAW_ARRAYS(surface) \ + ((surface)->drawable->backend->feature_mask & \ GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) static void _glitz_draw_vertex_arrays (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *bounds, - int damage) + glitz_surface_t *dst, + glitz_box_t *bounds, + int damage) { glitz_multi_array_t *array = dst->geometry.array; glitz_box_t *clip = dst->clip; int i, n_clip = dst->n_clip; glitz_box_t box; - int target_height = SURFACE_DRAWABLE_HEIGHT (dst); - + while (n_clip--) { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds->x1 > box.x1) - box.x1 = bounds->x1; - if (bounds->y1 > box.y1) - box.y1 = bounds->y1; - if (bounds->x2 < box.x2) - box.x2 = bounds->x2; - if (bounds->y2 < box.y2) - box.y2 = bounds->y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - gl->scissor (box.x1 + dst->x, - target_height - dst->y - box.y2, - box.x2 - box.x1, box.y2 - box.y1); + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds->x1 > box.x1) + box.x1 = bounds->x1; + if (bounds->y1 > box.y1) + box.y1 = bounds->y1; + if (bounds->x2 < box.x2) + box.x2 = bounds->x2; + if (bounds->y2 < box.y2) + box.y2 = bounds->y2; - gl->push_matrix (); - - if (dst->geometry.off.v[0] || dst->geometry.off.v[1]) - gl->translate_f (dst->geometry.off.v[0], - dst->geometry.off.v[1], 0.0f); - - if (array) - { - for (i = 0; i < array->n_arrays;) - { - gl->translate_f (array->off[i].v[0], - array->off[i].v[1], 0.0f); - - if (MULTI_DRAW_ARRAYS (dst)) - { - gl->multi_draw_arrays (dst->geometry.u.v.prim, - &array->first[i], - &array->count[i], - array->span[i]); - i += array->span[i]; - } - else - { - do { - if (array->count[i]) - gl->draw_arrays (dst->geometry.u.v.prim, - array->first[i], - array->count[i]); - - } while (array->span[++i] == 0); - } - } - } else - gl->draw_arrays (dst->geometry.u.v.prim, - dst->geometry.first, - dst->geometry.count); - - gl->pop_matrix (); - - if (damage) - glitz_surface_damage (dst, &box, damage); - } - - clip++; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + gl->scissor (box.x1 + dst->x, + dst->attached->height - dst->y - box.y2, + box.x2 - box.x1, box.y2 - box.y1); + + gl->push_matrix (); + + if (dst->geometry.off.v[0] || dst->geometry.off.v[1]) + gl->translate_f (dst->geometry.off.v[0], + dst->geometry.off.v[1], 0.0f); + + if (array) + { + for (i = 0; i < array->n_arrays;) + { + gl->translate_f (array->off[i].v[0], + array->off[i].v[1], 0.0f); + + if (MULTI_DRAW_ARRAYS (dst)) + { + gl->multi_draw_arrays (dst->geometry.u.v.prim, + &array->first[i], + &array->count[i], + array->span[i]); + i += array->span[i]; + } + else + { + do { + if (array->count[i]) + gl->draw_arrays (dst->geometry.u.v.prim, + array->first[i], + array->count[i]); + + } while (array->span[++i] == 0); + } + } + } else + gl->draw_arrays (dst->geometry.u.v.prim, + dst->geometry.first, + dst->geometry.count); + + gl->pop_matrix (); + + if (damage) + glitz_surface_damage (dst, &box, damage); + } + + clip++; } } @@ -486,43 +484,43 @@ _glitz_draw_vertex_arrays (glitz_gl_proc_address_list_t *gl, #define BITMAP_STRIDE(x, w, a) \ (((((x) & 3) + (w) + (((a) << 3) - 1)) / ((a) << 3)) * (a)) -#define BITMAP_SETUP(dst, first, size, count, _w, _h, _b_off, _p_off) \ - (_w) = (size); \ - (_h) = (count); \ - (_b_off) = (first) >> 3; \ - if ((_p_off) != ((first) & 3)) \ - { \ - (_p_off) = (first) & 3; \ - gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, _p_off); \ - } \ - if ((dst)->geometry.u.b.top_down) \ - { \ - dst_stride = BITMAP_STRIDE ((first), _w, BITMAP_PAD); \ - if ((dst)->geometry.stride) \ - src_stride = (dst)->geometry.stride; \ - else \ - src_stride = BITMAP_STRIDE ((first), _w, \ - (dst)->geometry.u.b.pad); \ - min_stride = MIN (src_stride, dst_stride); \ - base = (dst)->geometry.u.b.base + (_b_off); \ - y = (_h); \ - while (y--) \ - memcpy (bitmap + ((_h) - 1 - y) * dst_stride, \ - base + y * src_stride, \ - min_stride); \ - (_b_off) = 0; \ +#define BITMAP_SETUP(dst, first, size, count, _w, _h, _b_off, _p_off) \ + (_w) = (size); \ + (_h) = (count); \ + (_b_off) = (first) >> 3; \ + if ((_p_off) != ((first) & 3)) \ + { \ + (_p_off) = (first) & 3; \ + gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, _p_off); \ + } \ + if ((dst)->geometry.u.b.top_down) \ + { \ + dst_stride = BITMAP_STRIDE ((first), _w, BITMAP_PAD); \ + if ((dst)->geometry.stride) \ + src_stride = (dst)->geometry.stride; \ + else \ + src_stride = BITMAP_STRIDE ((first), _w, \ + (dst)->geometry.u.b.pad); \ + min_stride = MIN (src_stride, dst_stride); \ + base = (dst)->geometry.u.b.base + (_b_off); \ + y = (_h); \ + while (y--) \ + memcpy (bitmap + ((_h) - 1 - y) * dst_stride, \ + base + y * src_stride, \ + min_stride); \ + (_b_off) = 0; \ } /* TODO: clipping could be done without glScissor, that might be faster. Other then solid colors can be used if bitmap fits into a stipple pattern. Maybe we should add a repeat parameter to glitz_bitmap_format_t as 2, 4, 8, 16 and 32 sized bitmaps can be tiled. - */ +*/ static void _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *bounds, - int damage) + glitz_surface_t *dst, + glitz_box_t *bounds, + int damage) { glitz_multi_array_t *array = dst->geometry.array; glitz_box_t *clip = dst->clip; @@ -534,148 +532,149 @@ _glitz_draw_bitmap_arrays (glitz_gl_proc_address_list_t *gl, int byte_offset, pixel_offset = 0; glitz_float_t x_off, y_off; glitz_box_t box; - int target_height = SURFACE_DRAWABLE_HEIGHT (dst); - + if (dst->geometry.u.b.top_down) { - int max_size = 0; - - if (array) - { - int size; - - for (i = 0, n = array->n_arrays; n--; i++) - { - x = array->first[i]; - w = array->sizes[i]; - size = BITMAP_STRIDE (x, w, BITMAP_PAD) * array->count[i]; - if (size > max_size) - max_size = size; - } - } - else - { - x = dst->geometry.first; - w = dst->geometry.size; - max_size = BITMAP_STRIDE (x, w, BITMAP_PAD) * dst->geometry.count; - } + int max_size = 0; - if (max_size > N_STACK_BITMAP) - { - heap_bitmap = malloc (max_size); - if (!heap_bitmap) - { - glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); - return; - } - bitmap = heap_bitmap; - } else - bitmap = stack_bitmap; + if (array) + { + int size; - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, BITMAP_PAD); - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); + for (i = 0, n = array->n_arrays; n--; i++) + { + x = array->first[i]; + w = array->sizes[i]; + size = BITMAP_STRIDE (x, w, BITMAP_PAD) * array->count[i]; + if (size > max_size) + max_size = size; + } + } + else + { + x = dst->geometry.first; + w = dst->geometry.size; + max_size = BITMAP_STRIDE (x, w, BITMAP_PAD) * dst->geometry.count; + } + + if (max_size > N_STACK_BITMAP) + { + heap_bitmap = malloc (max_size); + if (!heap_bitmap) + { + glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); + return; + } + bitmap = heap_bitmap; + } else + bitmap = stack_bitmap; + + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, BITMAP_PAD); + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); } else { - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, dst->geometry.u.b.pad); - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, - dst->geometry.stride * 8); + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, dst->geometry.u.b.pad); + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, + dst->geometry.stride * 8); } - + while (n_clip--) { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (bounds->x1 > box.x1) - box.x1 = bounds->x1; - if (bounds->y1 > box.y1) - box.y1 = bounds->y1; - if (bounds->x2 < box.x2) - box.x2 = bounds->x2; - if (bounds->y2 < box.y2) - box.y2 = bounds->y2; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - gl->scissor (box.x1 + dst->x, - target_height - dst->y - box.y2, - box.x2 - box.x1, box.y2 - box.y1); + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (bounds->x1 > box.x1) + box.x1 = bounds->x1; + if (bounds->y1 > box.y1) + box.y1 = bounds->y1; + if (bounds->x2 < box.x2) + box.x2 = bounds->x2; + if (bounds->y2 < box.y2) + box.y2 = bounds->y2; - x_off = dst->x + dst->geometry.off.v[0]; - y_off = dst->y + dst->geometry.off.v[1]; - - if (array) - { - x_off += array->off->v[0]; - y_off += array->off->v[1]; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + gl->scissor (box.x1 + dst->x, + dst->attached->height - dst->y - box.y2, + box.x2 - box.x1, box.y2 - box.y1); - glitz_set_raster_pos (gl, x_off, target_height - y_off); + x_off = dst->x + dst->geometry.off.v[0]; + y_off = dst->y + dst->geometry.off.v[1]; - for (i = 0, n = array->n_arrays; n--; i++) - { - if (n) - { - x_off = array->off[i + 1].v[0]; - y_off = array->off[i + 1].v[1]; - } + if (array) + { + x_off += array->off->v[0]; + y_off += array->off->v[1]; - BITMAP_SETUP (dst, - array->first[i], - array->sizes[i], - array->count[i], - w, h, byte_offset, pixel_offset); - - gl->bitmap (w, h, - 0.0f, (glitz_gl_float_t) array->count[i], - x_off, -y_off, - bitmap + byte_offset); - } - } - else - { - glitz_set_raster_pos (gl, x_off, target_height - y_off); - - BITMAP_SETUP (dst, - dst->geometry.first, - dst->geometry.size, - dst->geometry.count, - w, h, byte_offset, pixel_offset); - - gl->bitmap (w, h, - 0.0f, (glitz_gl_float_t) dst->geometry.count, - 0.0f, 0.0f, - bitmap + byte_offset); - } + glitz_set_raster_pos (gl, x_off, + dst->attached->height - y_off); - if (damage) - glitz_surface_damage (dst, &box, damage); - } - - clip++; + for (i = 0, n = array->n_arrays; n--; i++) + { + if (n) + { + x_off = array->off[i + 1].v[0]; + y_off = array->off[i + 1].v[1]; + } + + BITMAP_SETUP (dst, + array->first[i], + array->sizes[i], + array->count[i], + w, h, byte_offset, pixel_offset); + + gl->bitmap (w, h, + 0.0f, (glitz_gl_float_t) array->count[i], + x_off, -y_off, + bitmap + byte_offset); + } + } + else + { + glitz_set_raster_pos (gl, x_off, + dst->attached->height - y_off); + + BITMAP_SETUP (dst, + dst->geometry.first, + dst->geometry.size, + dst->geometry.count, + w, h, byte_offset, pixel_offset); + + gl->bitmap (w, h, + 0.0f, (glitz_gl_float_t) dst->geometry.count, + 0.0f, 0.0f, + bitmap + byte_offset); + } + + if (damage) + glitz_surface_damage (dst, &box, damage); + } + + clip++; } if (heap_bitmap) - free (heap_bitmap); + free (heap_bitmap); } void glitz_geometry_draw_arrays (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_geometry_type_t type, - glitz_box_t *bounds, - int damage) + glitz_surface_t *dst, + glitz_geometry_type_t type, + glitz_box_t *bounds, + int damage) { switch (type) { case GLITZ_GEOMETRY_TYPE_VERTEX: - _glitz_draw_vertex_arrays (gl, dst, bounds, damage); - break; + _glitz_draw_vertex_arrays (gl, dst, bounds, damage); + break; case GLITZ_GEOMETRY_TYPE_BITMAP: - _glitz_draw_bitmap_arrays (gl, dst, bounds, damage); - break; + _glitz_draw_bitmap_arrays (gl, dst, bounds, damage); + break; case GLITZ_GEOMETRY_TYPE_NONE: - _glitz_draw_rectangle (gl, dst, bounds, damage); - break; + _glitz_draw_rectangle (gl, dst, bounds, damage); + break; } } diff --git a/gfx/cairo/glitz/src/glitz_gl.h b/gfx/cairo/glitz/src/glitz_gl.h index fca15772e4c..7b76a31e13d 100644 --- a/gfx/cairo/glitz/src/glitz_gl.h +++ b/gfx/cairo/glitz/src/glitz_gl.h @@ -112,8 +112,9 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t; #define GLITZ_GL_MAX_TEXTURE_SIZE 0x0D33 #define GLITZ_GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GLITZ_GL_TEXTURE_WIDTH 0x1000 -#define GLITZ_GL_TEXTURE_HEIGHT 0x1001 +#define GLITZ_GL_TEXTURE_WIDTH 0x1000 +#define GLITZ_GL_TEXTURE_HEIGHT 0x1001 +#define GLITZ_GL_TEXTURE_BORDER_COLOR 0x1004 #define GLITZ_GL_TEXTURE_ENV 0x2300 #define GLITZ_GL_TEXTURE_ENV_MODE 0x2200 @@ -135,6 +136,7 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t; #define GLITZ_GL_MODULATE 0x2100 #define GLITZ_GL_NEAREST 0x2600 #define GLITZ_GL_LINEAR 0x2601 +#define GLITZ_GL_CLAMP 0x2900 #define GLITZ_GL_REPEAT 0x2901 #define GLITZ_GL_CLAMP_TO_EDGE 0x812F #define GLITZ_GL_CLAMP_TO_BORDER 0x812D @@ -188,6 +190,9 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t; #define GLITZ_GL_TRANSFORM_BIT 0x00001000 #define GLITZ_GL_COLOR_BUFFER_BIT 0x00004000 +#define GLITZ_GL_STENCIL_INDEX 0x1901 +#define GLITZ_GL_DEPTH_COMPONENT 0x1902 + #define GLITZ_GL_ALPHA 0x1906 #define GLITZ_GL_RGB 0x1907 #define GLITZ_GL_LUMINANCE 0x1909 @@ -309,8 +314,14 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t; #define GLITZ_GL_WRITE_ONLY 0x88B9 #define GLITZ_GL_READ_WRITE 0x88BA -#define GLITZ_GL_FRAMEBUFFER 0x8D40 -#define GLITZ_GL_COLOR_ATTACHMENT0 0x8CE0 +#define GLITZ_GL_FRAMEBUFFER 0x8D40 +#define GLITZ_GL_RENDERBUFFER 0x8D41 + +#define GLITZ_GL_COLOR_ATTACHMENT0 0x8CE0 +#define GLITZ_GL_COLOR_ATTACHMENT1 0x8CE1 +#define GLITZ_GL_DEPTH_ATTACHMENT 0x8D00 +#define GLITZ_GL_STENCIL_ATTACHMENT 0x8D20 + #define GLITZ_GL_FRAMEBUFFER_COMPLETE 0x8CD5 #define GLITZ_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 #define GLITZ_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 @@ -322,6 +333,13 @@ typedef ptrdiff_t glitz_gl_sizeiptr_t; #define GLITZ_GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD #define GLITZ_GL_FRAMEBUFFER_STATUS_ERROR 0x8CDE +#define GLITZ_GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GLITZ_GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GLITZ_GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GLITZ_GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GLITZ_GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GLITZ_GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_enable_t) (glitz_gl_enum_t cap); typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_disable_t) @@ -470,6 +488,9 @@ typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_image_2d_t) const glitz_gl_void_t *pixels); typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_parameter_i_t) (glitz_gl_enum_t target, glitz_gl_enum_t pname, glitz_gl_int_t param); +typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_tex_parameter_fv_t) + (glitz_gl_enum_t target, glitz_gl_enum_t pname, + const glitz_gl_float_t *parama); typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_get_tex_level_parameter_iv_t) (glitz_gl_enum_t target, glitz_gl_int_t level, glitz_gl_enum_t pname, glitz_gl_int_t *param); @@ -524,10 +545,23 @@ typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_delete_framebuffers_t) (glitz_gl_sizei_t, const glitz_gl_uint_t *); typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_bind_framebuffer_t) (glitz_gl_enum_t, glitz_gl_uint_t); -typedef glitz_gl_enum_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_check_framebuffer_status_t) - (glitz_gl_enum_t); +typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_framebuffer_renderbuffer_t) + (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_enum_t, + glitz_gl_uint_t); typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_framebuffer_texture_2d_t) (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_uint_t, glitz_gl_int_t); +typedef glitz_gl_enum_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_check_framebuffer_status_t) + (glitz_gl_enum_t); +typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_gen_renderbuffers_t) + (glitz_gl_sizei_t, glitz_gl_uint_t *); +typedef void (GLITZ_GL_API_ATTRIBUTE * glitz_gl_delete_renderbuffers_t) + (glitz_gl_sizei_t, const glitz_gl_uint_t *); +typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_bind_renderbuffer_t) + (glitz_gl_enum_t, glitz_gl_uint_t); +typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_renderbuffer_storage_t) + (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_sizei_t, glitz_gl_sizei_t); +typedef glitz_gl_void_t (GLITZ_GL_API_ATTRIBUTE * glitz_gl_get_renderbuffer_parameter_iv_t) + (glitz_gl_enum_t, glitz_gl_enum_t, glitz_gl_int_t *); #endif /* GLITZ_GL_H_INCLUDED */ diff --git a/gfx/cairo/glitz/src/glitz_operator.c b/gfx/cairo/glitz/src/glitz_operator.c index b19186bfa18..194b508620a 100644 --- a/gfx/cairo/glitz/src/glitz_operator.c +++ b/gfx/cairo/glitz/src/glitz_operator.c @@ -32,59 +32,61 @@ #include "glitzint.h" void -glitz_set_operator (glitz_gl_proc_address_list_t *gl, glitz_operator_t op) { - switch (op) { - case GLITZ_OPERATOR_CLEAR: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ZERO); - break; - case GLITZ_OPERATOR_SRC: - gl->disable (GLITZ_GL_BLEND); - break; - case GLITZ_OPERATOR_DST: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE); - break; - case GLITZ_OPERATOR_OVER: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE_MINUS_SRC_ALPHA); - break; - case GLITZ_OPERATOR_OVER_REVERSE: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ONE); - break; - case GLITZ_OPERATOR_IN: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ZERO); - break; - case GLITZ_OPERATOR_IN_REVERSE: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_SRC_ALPHA); - break; - case GLITZ_OPERATOR_OUT: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ZERO); - break; - case GLITZ_OPERATOR_OUT_REVERSE: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE_MINUS_SRC_ALPHA); - break; - case GLITZ_OPERATOR_ATOP: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ONE_MINUS_SRC_ALPHA); - break; - case GLITZ_OPERATOR_ATOP_REVERSE: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_SRC_ALPHA); - break; - case GLITZ_OPERATOR_XOR: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, - GLITZ_GL_ONE_MINUS_SRC_ALPHA); - break; - case GLITZ_OPERATOR_ADD: - gl->enable (GLITZ_GL_BLEND); - gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE); - break; - } +glitz_set_operator (glitz_gl_proc_address_list_t *gl, + glitz_operator_t op) +{ + switch (op) { + case GLITZ_OPERATOR_CLEAR: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ZERO); + break; + case GLITZ_OPERATOR_SRC: + gl->disable (GLITZ_GL_BLEND); + break; + case GLITZ_OPERATOR_DST: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE); + break; + case GLITZ_OPERATOR_OVER: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE_MINUS_SRC_ALPHA); + break; + case GLITZ_OPERATOR_OVER_REVERSE: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ONE); + break; + case GLITZ_OPERATOR_IN: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ZERO); + break; + case GLITZ_OPERATOR_IN_REVERSE: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_SRC_ALPHA); + break; + case GLITZ_OPERATOR_OUT: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_ZERO); + break; + case GLITZ_OPERATOR_OUT_REVERSE: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ZERO, GLITZ_GL_ONE_MINUS_SRC_ALPHA); + break; + case GLITZ_OPERATOR_ATOP: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_DST_ALPHA, GLITZ_GL_ONE_MINUS_SRC_ALPHA); + break; + case GLITZ_OPERATOR_ATOP_REVERSE: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, GLITZ_GL_SRC_ALPHA); + break; + case GLITZ_OPERATOR_XOR: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE_MINUS_DST_ALPHA, + GLITZ_GL_ONE_MINUS_SRC_ALPHA); + break; + case GLITZ_OPERATOR_ADD: + gl->enable (GLITZ_GL_BLEND); + gl->blend_func (GLITZ_GL_ONE, GLITZ_GL_ONE); + break; + } } diff --git a/gfx/cairo/glitz/src/glitz_pixel.c b/gfx/cairo/glitz/src/glitz_pixel.c index 56f16c1b8a5..95c3d758740 100644 --- a/gfx/cairo/glitz/src/glitz_pixel.c +++ b/gfx/cairo/glitz/src/glitz_pixel.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -32,71 +32,71 @@ #include typedef struct _glitz_gl_pixel_format { - glitz_pixel_format_t pixel; - glitz_gl_enum_t format; - glitz_gl_enum_t type; + glitz_pixel_format_t pixel; + glitz_gl_enum_t format; + glitz_gl_enum_t type; } glitz_gl_pixel_format_t; - + static glitz_gl_pixel_format_t _gl_pixel_formats[] = { - { { - { - 8, - 0x000000ff, - 0x00000000, - 0x00000000, - 0x00000000 - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, - GLITZ_GL_ALPHA, - GLITZ_GL_UNSIGNED_BYTE - }, { - { - { - 32, - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, - GLITZ_GL_BGRA, - -#if IMAGE_BYTE_ORDER == MSBFirst - GLITZ_GL_UNSIGNED_INT_8_8_8_8_REV + { + { + 8, + 0x000000ff, + 0x00000000, + 0x00000000, + 0x00000000 + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, + GLITZ_GL_ALPHA, + GLITZ_GL_UNSIGNED_BYTE + }, { + { + { + 32, + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, + GLITZ_GL_BGRA, + +#if IMAGE_BYTE_ORDER == MSBFirst + GLITZ_GL_UNSIGNED_INT_8_8_8_8_REV #else - GLITZ_GL_UNSIGNED_BYTE + GLITZ_GL_UNSIGNED_BYTE #endif - - } + + } }; static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = { - { { - { - 16, - 0x00000000, - 0x0000f800, - 0x000007e0, - 0x0000001f - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, - GLITZ_GL_BGR, - -#if IMAGE_BYTE_ORDER == MSBFirst - GLITZ_GL_UNSIGNED_SHORT_5_6_5_REV + { + { + 16, + 0x00000000, + 0x0000f800, + 0x000007e0, + 0x0000001f + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, + GLITZ_GL_BGR, + +#if IMAGE_BYTE_ORDER == MSBFirst + GLITZ_GL_UNSIGNED_SHORT_5_6_5_REV #else - GLITZ_GL_UNSIGNED_SHORT_5_6_5 + GLITZ_GL_UNSIGNED_SHORT_5_6_5 #endif - - } + + } }; #define SOLID_ALPHA 0 @@ -105,148 +105,148 @@ static glitz_gl_pixel_format_t _gl_packed_pixel_formats[] = { #define SOLID_BLUE 3 static glitz_pixel_format_t _solid_format[] = { - { { - 16, - 0x0000ffff, - 0x00000000, - 0x00000000, - 0x00000000 - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, { - { - 16, - 0x00000000, - 0x0000ffff, - 0x00000000, - 0x00000000 - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, { - { - 16, - 0x00000000, - 0x00000000, - 0x0000ffff, - 0x00000000 - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }, { - { - 16, - 0x00000000, - 0x00000000, - 0x00000000, - 0x0000ffff - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - } + { + 16, + 0x0000ffff, + 0x00000000, + 0x00000000, + 0x00000000 + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, { + { + 16, + 0x00000000, + 0x0000ffff, + 0x00000000, + 0x00000000 + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, { + { + 16, + 0x00000000, + 0x00000000, + 0x0000ffff, + 0x00000000 + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }, { + { + 16, + 0x00000000, + 0x00000000, + 0x00000000, + 0x0000ffff + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + } }; typedef struct _glitz_pixel_color { - uint32_t r, g, b, a; + uint32_t r, g, b, a; } glitz_pixel_color_t; typedef struct _glitz_pixel_transform_op { - char *line; - int offset; - glitz_pixel_format_t *format; - glitz_pixel_color_t *color; + char *line; + int offset; + glitz_pixel_format_t *format; + glitz_pixel_color_t *color; } glitz_pixel_transform_op_t; -#define FETCH(p, mask) ((mask)? \ - ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * 0xffffffff) / \ - ((uint64_t) (mask)))): 0x0) +#define FETCH(p, mask) \ + ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \ + 0xffffffff) / ((uint64_t) (mask)))): 0x0) -#define FETCH_A(p, mask) ((mask)? \ - ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * 0xffffffff) / \ - ((uint64_t) (mask)))): 0xffffffff) +#define FETCH_A(p, mask) \ + ((mask) ? ((uint32_t) ((((uint64_t) (((uint32_t) (p)) & (mask))) * \ + 0xffffffff) /((uint64_t) (mask)))): 0xffffffff) typedef void (*glitz_pixel_fetch_function_t) (glitz_pixel_transform_op_t *op); static void _fetch_1 (glitz_pixel_transform_op_t *op) { - uint8_t p = (uint8_t) op->line[op->offset / 8]; + uint8_t p = (uint8_t) op->line[op->offset / 8]; #if BITMAP_BIT_ORDER == MSBFirst - p = (p >> (7 - (op->offset % 8))) & 0x1; + p = (p >> (7 - (op->offset % 8))) & 0x1; #else - p = (p >> (op->offset % 8)) & 0x1; + p = (p >> (op->offset % 8)) & 0x1; #endif - - op->color->a = FETCH_A (p, op->format->masks.alpha_mask); - op->color->r = FETCH (p, op->format->masks.red_mask); - op->color->g = FETCH (p, op->format->masks.green_mask); - op->color->b = FETCH (p, op->format->masks.blue_mask); + + op->color->a = FETCH_A (p, op->format->masks.alpha_mask); + op->color->r = FETCH (p, op->format->masks.red_mask); + op->color->g = FETCH (p, op->format->masks.green_mask); + op->color->b = FETCH (p, op->format->masks.blue_mask); } static void _fetch_8 (glitz_pixel_transform_op_t *op) { - uint8_t p = op->line[op->offset]; - - op->color->a = FETCH_A (p, op->format->masks.alpha_mask); - op->color->r = FETCH (p, op->format->masks.red_mask); - op->color->g = FETCH (p, op->format->masks.green_mask); - op->color->b = FETCH (p, op->format->masks.blue_mask); + uint8_t p = op->line[op->offset]; + + op->color->a = FETCH_A (p, op->format->masks.alpha_mask); + op->color->r = FETCH (p, op->format->masks.red_mask); + op->color->g = FETCH (p, op->format->masks.green_mask); + op->color->b = FETCH (p, op->format->masks.blue_mask); } static void _fetch_16 (glitz_pixel_transform_op_t *op) { - uint16_t p = ((uint16_t *) op->line)[op->offset]; - - op->color->a = FETCH_A (p, op->format->masks.alpha_mask); - op->color->r = FETCH (p, op->format->masks.red_mask); - op->color->g = FETCH (p, op->format->masks.green_mask); - op->color->b = FETCH (p, op->format->masks.blue_mask); + uint16_t p = ((uint16_t *) op->line)[op->offset]; + + op->color->a = FETCH_A (p, op->format->masks.alpha_mask); + op->color->r = FETCH (p, op->format->masks.red_mask); + op->color->g = FETCH (p, op->format->masks.green_mask); + op->color->b = FETCH (p, op->format->masks.blue_mask); } static void _fetch_24 (glitz_pixel_transform_op_t *op) { - uint8_t *l = (uint8_t *) &op->line[op->offset * 3]; - uint32_t p; - + uint8_t *l = (uint8_t *) &op->line[op->offset * 3]; + uint32_t p; + #if IMAGE_BYTE_ORDER == MSBFirst - p = 0xff000000 | (l[2] << 16) | (l[1] << 8) | (l[0]); + p = 0xff000000 | (l[2] << 16) | (l[1] << 8) | (l[0]); #else - p = 0xff000000 | (l[0] << 16) | (l[1] << 8) | (l[2]); + p = 0xff000000 | (l[0] << 16) | (l[1] << 8) | (l[2]); #endif - op->color->a = FETCH_A (p, op->format->masks.alpha_mask); - op->color->r = FETCH (p, op->format->masks.red_mask); - op->color->g = FETCH (p, op->format->masks.green_mask); - op->color->b = FETCH (p, op->format->masks.blue_mask); + op->color->a = FETCH_A (p, op->format->masks.alpha_mask); + op->color->r = FETCH (p, op->format->masks.red_mask); + op->color->g = FETCH (p, op->format->masks.green_mask); + op->color->b = FETCH (p, op->format->masks.blue_mask); } static void _fetch_32 (glitz_pixel_transform_op_t *op) { - uint32_t p = ((uint32_t *) op->line)[op->offset]; - - op->color->a = FETCH_A (p, op->format->masks.alpha_mask); - op->color->r = FETCH (p, op->format->masks.red_mask); - op->color->g = FETCH (p, op->format->masks.green_mask); - op->color->b = FETCH (p, op->format->masks.blue_mask); + uint32_t p = ((uint32_t *) op->line)[op->offset]; + + op->color->a = FETCH_A (p, op->format->masks.alpha_mask); + op->color->r = FETCH (p, op->format->masks.red_mask); + op->color->g = FETCH (p, op->format->masks.green_mask); + op->color->b = FETCH (p, op->format->masks.blue_mask); } typedef void (*glitz_pixel_store_function_t) (glitz_pixel_transform_op_t *op); -#define STORE(v, mask) \ - (((uint32_t) (((v) * (uint64_t) (mask)) / 0xffffffff)) & (mask)) +#define STORE(v, mask) \ + (((uint32_t) (((v) * (uint64_t) (mask)) / 0xffffffff)) & (mask)) static void _store_1 (glitz_pixel_transform_op_t *op) { - uint8_t *p = (uint8_t *) &op->line[op->offset / 8]; - uint32_t offset; + uint8_t *p = (uint8_t *) &op->line[op->offset / 8]; + uint32_t offset; #if BITMAP_BIT_ORDER == MSBFirst offset = 7 - (op->offset % 8); @@ -254,70 +254,70 @@ _store_1 (glitz_pixel_transform_op_t *op) offset = op->offset % 8; #endif - *p |= - ((STORE (op->color->a, op->format->masks.alpha_mask) | - STORE (op->color->r, op->format->masks.red_mask) | - STORE (op->color->g, op->format->masks.green_mask) | - STORE (op->color->b, op->format->masks.blue_mask)) & 0x1) << offset; + *p |= + ((STORE (op->color->a, op->format->masks.alpha_mask) | + STORE (op->color->r, op->format->masks.red_mask) | + STORE (op->color->g, op->format->masks.green_mask) | + STORE (op->color->b, op->format->masks.blue_mask)) & 0x1) << offset; } static void _store_8 (glitz_pixel_transform_op_t *op) { - uint8_t *p = (uint8_t *) &op->line[op->offset]; - - *p = (uint8_t) - STORE (op->color->a, op->format->masks.alpha_mask) | - STORE (op->color->r, op->format->masks.red_mask) | - STORE (op->color->g, op->format->masks.green_mask) | - STORE (op->color->b, op->format->masks.blue_mask); + uint8_t *p = (uint8_t *) &op->line[op->offset]; + + *p = (uint8_t) + STORE (op->color->a, op->format->masks.alpha_mask) | + STORE (op->color->r, op->format->masks.red_mask) | + STORE (op->color->g, op->format->masks.green_mask) | + STORE (op->color->b, op->format->masks.blue_mask); } static void _store_16 (glitz_pixel_transform_op_t *op) { - uint16_t *p = &((uint16_t *) op->line)[op->offset]; + uint16_t *p = &((uint16_t *) op->line)[op->offset]; - *p = (uint16_t) - STORE (op->color->a, op->format->masks.alpha_mask) | - STORE (op->color->r, op->format->masks.red_mask) | - STORE (op->color->g, op->format->masks.green_mask) | - STORE (op->color->b, op->format->masks.blue_mask); + *p = (uint16_t) + STORE (op->color->a, op->format->masks.alpha_mask) | + STORE (op->color->r, op->format->masks.red_mask) | + STORE (op->color->g, op->format->masks.green_mask) | + STORE (op->color->b, op->format->masks.blue_mask); } static void _store_24 (glitz_pixel_transform_op_t *op) { - uint8_t *l = (uint8_t *) &op->line[op->offset * 3]; - - uint32_t p = - STORE (op->color->a, op->format->masks.alpha_mask) | - STORE (op->color->r, op->format->masks.red_mask) | - STORE (op->color->g, op->format->masks.green_mask) | - STORE (op->color->b, op->format->masks.blue_mask); - + uint8_t *l = (uint8_t *) &op->line[op->offset * 3]; + + uint32_t p = + STORE (op->color->a, op->format->masks.alpha_mask) | + STORE (op->color->r, op->format->masks.red_mask) | + STORE (op->color->g, op->format->masks.green_mask) | + STORE (op->color->b, op->format->masks.blue_mask); + #if IMAGE_BYTE_ORDER == MSBFirst - l[2] = p >> 16; - l[1] = p >> 8; - l[0] = p; + l[2] = p >> 16; + l[1] = p >> 8; + l[0] = p; #else - l[0] = p >> 16; - l[1] = p >> 8; - l[2] = p; + l[0] = p >> 16; + l[1] = p >> 8; + l[2] = p; #endif - + } static void _store_32 (glitz_pixel_transform_op_t *op) { - uint32_t *p = &((uint32_t *) op->line)[op->offset]; - - *p = - STORE (op->color->a, op->format->masks.alpha_mask) | - STORE (op->color->r, op->format->masks.red_mask) | - STORE (op->color->g, op->format->masks.green_mask) | - STORE (op->color->b, op->format->masks.blue_mask); + uint32_t *p = &((uint32_t *) op->line)[op->offset]; + + *p = + STORE (op->color->a, op->format->masks.alpha_mask) | + STORE (op->color->r, op->format->masks.red_mask) | + STORE (op->color->g, op->format->masks.green_mask) | + STORE (op->color->b, op->format->masks.blue_mask); } #define GLITZ_TRANSFORM_PIXELS_MASK (1L << 0) @@ -325,270 +325,284 @@ _store_32 (glitz_pixel_transform_op_t *op) #define GLITZ_TRANSFORM_COPY_BOX_MASK (1L << 2) typedef struct _glitz_image { - char *data; - glitz_pixel_format_t *format; - int width; - int height; + char *data; + glitz_pixel_format_t *format; + int width; + int height; } glitz_image_t; static void _glitz_pixel_transform (unsigned long transform, - glitz_image_t *src, - glitz_image_t *dst, - int x_src, - int y_src, - int x_dst, - int y_dst, - int width, - int height) + glitz_image_t *src, + glitz_image_t *dst, + int x_src, + int y_src, + int x_dst, + int y_dst, + int width, + int height) { - int src_stride, dst_stride; - int x, y, bytes_per_pixel = 0; - glitz_pixel_fetch_function_t fetch; - glitz_pixel_store_function_t store; - glitz_pixel_color_t color; - glitz_pixel_transform_op_t src_op, dst_op; + int src_stride, dst_stride; + int x, y, bytes_per_pixel = 0; + glitz_pixel_fetch_function_t fetch; + glitz_pixel_store_function_t store; + glitz_pixel_color_t color; + glitz_pixel_transform_op_t src_op, dst_op; - switch (src->format->masks.bpp) { - case 1: - fetch = _fetch_1; - break; - case 8: - fetch = _fetch_8; - break; - case 16: - fetch = _fetch_16; - break; - case 24: - fetch = _fetch_24; - break; - case 32: - default: - fetch = _fetch_32; - break; - } - - switch (dst->format->masks.bpp) { - case 1: - store = _store_1; - break; - case 8: - store = _store_8; - break; - case 16: - store = _store_16; - break; - case 24: - store = _store_24; - break; - case 32: - default: - store = _store_32; - break; - } - - src_stride = (src->format->bytes_per_line)? src->format->bytes_per_line: - (((src->width * src->format->masks.bpp) / 8) + 3) & -4; - if (src_stride == 0) - src_stride = 1; - src_op.format = src->format; - src_op.color = &color; - - dst_stride = (dst->format->bytes_per_line)? dst->format->bytes_per_line: - (((dst->width * dst->format->masks.bpp) / 8) + 3) & -4; - if (dst_stride == 0) - dst_stride = 1; - dst_op.format = dst->format; - dst_op.color = &color; - - for (y = 0; y < height; y++) { - if (src->format->scanline_order != dst->format->scanline_order) - src_op.line = &src->data[(src->height - (y + y_src) - 1) * src_stride]; - else - src_op.line = &src->data[(y + y_src) * src_stride]; - - dst_op.line = &dst->data[(y + y_dst) * dst_stride]; - - if (transform & GLITZ_TRANSFORM_PIXELS_MASK) { - for (x = 0; x < width; x++) { - src_op.offset = x_src + x; - dst_op.offset = x_dst + x; - - fetch (&src_op); - store (&dst_op); - } - } else { - /* This only works for bpp >= 8, but it shouldn't be a problem as - it will never be used for bitmaps */ - if (bytes_per_pixel == 0) - bytes_per_pixel = src->format->masks.bpp / 8; - - memcpy (&dst_op.line[x_dst * bytes_per_pixel], - &src_op.line[x_src * bytes_per_pixel], - width * bytes_per_pixel); + switch (src->format->masks.bpp) { + case 1: + fetch = _fetch_1; + break; + case 8: + fetch = _fetch_8; + break; + case 16: + fetch = _fetch_16; + break; + case 24: + fetch = _fetch_24; + break; + case 32: + default: + fetch = _fetch_32; + break; + } + + switch (dst->format->masks.bpp) { + case 1: + store = _store_1; + break; + case 8: + store = _store_8; + break; + case 16: + store = _store_16; + break; + case 24: + store = _store_24; + break; + case 32: + default: + store = _store_32; + break; + } + + src_stride = (src->format->bytes_per_line)? src->format->bytes_per_line: + (((src->width * src->format->masks.bpp) / 8) + 3) & -4; + if (src_stride == 0) + src_stride = 1; + src_op.format = src->format; + src_op.color = &color; + + dst_stride = (dst->format->bytes_per_line)? dst->format->bytes_per_line: + (((dst->width * dst->format->masks.bpp) / 8) + 3) & -4; + if (dst_stride == 0) + dst_stride = 1; + dst_op.format = dst->format; + dst_op.color = &color; + + for (y = 0; y < height; y++) { + if (src->format->scanline_order != dst->format->scanline_order) + src_op.line = &src->data[(src->height - (y + y_src) - 1) * + src_stride]; + else + src_op.line = &src->data[(y + y_src) * src_stride]; + + dst_op.line = &dst->data[(y + y_dst) * dst_stride]; + + if (transform & GLITZ_TRANSFORM_PIXELS_MASK) + { + for (x = 0; x < width; x++) + { + src_op.offset = x_src + x; + dst_op.offset = x_dst + x; + + fetch (&src_op); + store (&dst_op); + } + } + else + { + /* This only works for bpp >= 8, but it shouldn't be a problem as + it will never be used for bitmaps */ + if (bytes_per_pixel == 0) + bytes_per_pixel = src->format->masks.bpp / 8; + + memcpy (&dst_op.line[x_dst * bytes_per_pixel], + &src_op.line[x_src * bytes_per_pixel], + width * bytes_per_pixel); + } } - } } static glitz_bool_t -_glitz_format_match (glitz_pixel_masks_t *masks1, - glitz_pixel_masks_t *masks2, - glitz_color_format_t *internal_color) +_glitz_format_match (glitz_pixel_masks_t *masks1, + glitz_pixel_masks_t *masks2, + unsigned long mask) { - if (masks1->bpp != masks2->bpp) - return 0; - - if (internal_color->red_size) - if (masks1->red_mask != masks2->red_mask) - return 0; + if (masks1->bpp != masks2->bpp) + return 0; - if (internal_color->green_size) - if (masks1->green_mask != masks2->green_mask) - return 0; + if (mask & GLITZ_FORMAT_RED_SIZE_MASK) + if (masks1->red_mask != masks2->red_mask) + return 0; - if (internal_color->blue_size) - if (masks1->blue_mask != masks2->blue_mask) - return 0; - - if (internal_color->alpha_size) - if (masks1->alpha_mask != masks2->alpha_mask) - return 0; - - return 1; + if (mask & GLITZ_FORMAT_GREEN_SIZE_MASK) + if (masks1->green_mask != masks2->green_mask) + return 0; + + if (mask & GLITZ_FORMAT_BLUE_SIZE_MASK) + if (masks1->blue_mask != masks2->blue_mask) + return 0; + + if (mask & GLITZ_FORMAT_ALPHA_SIZE_MASK) + if (masks1->alpha_mask != masks2->alpha_mask) + return 0; + + return 1; } static glitz_gl_pixel_format_t * _glitz_find_gl_pixel_format (glitz_pixel_format_t *format, - glitz_color_format_t *internal_color, - unsigned long feature_mask) + unsigned long color_mask, + unsigned long feature_mask) { - int i, n_formats; + int i, n_formats; - n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t); - for (i = 0; i < n_formats; i++) { - if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks, &format->masks, - internal_color)) - return &_gl_pixel_formats[i]; - } - - if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) { - n_formats = sizeof (_gl_packed_pixel_formats) / - sizeof (glitz_gl_pixel_format_t); - - for (i = 0; i < n_formats; i++) { - if (_glitz_format_match (&_gl_packed_pixel_formats[i].pixel.masks, - &format->masks, - internal_color)) - return &_gl_packed_pixel_formats[i]; + n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t); + for (i = 0; i < n_formats; i++) + { + if (_glitz_format_match (&_gl_pixel_formats[i].pixel.masks, + &format->masks, color_mask)) + return &_gl_pixel_formats[i]; } - } - - return NULL; + + if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) + { + n_formats = sizeof (_gl_packed_pixel_formats) / + sizeof (glitz_gl_pixel_format_t); + + for (i = 0; i < n_formats; i++) + { + if (_glitz_format_match (&_gl_packed_pixel_formats[i].pixel.masks, + &format->masks, color_mask)) + return &_gl_packed_pixel_formats[i]; + } + } + + return NULL; } static int _component_size (unsigned long mask) { - unsigned long y; - - /* HACKMEM 169 */ - y = (mask >> 1) & 033333333333; - y = mask - y - ((y >> 1) & 033333333333); - return (((y + (y >> 3)) & 030707070707) % 077); + unsigned long y; + + /* HACKMEM 169 */ + y = (mask >> 1) & 033333333333; + y = mask - y - ((y >> 1) & 033333333333); + return (((y + (y >> 3)) & 030707070707) % 077); } static glitz_bool_t _glitz_format_diff (glitz_pixel_masks_t *masks, - glitz_color_format_t *pixel_color, - glitz_color_format_t *internal_color, - int *diff) + glitz_color_format_t *pixel_color, + glitz_color_format_t *internal_color, + int *diff) { - int size; - - *diff = 0; + int size; - size = _component_size (masks->red_mask); - if (size < pixel_color->red_size && size < internal_color->red_size) - return 0; - - *diff += abs (size - internal_color->red_size); + *diff = 0; - size = _component_size (masks->green_mask); - if (size < pixel_color->green_size && size < internal_color->green_size) - return 0; - - *diff += abs (size - internal_color->green_size); + size = _component_size (masks->red_mask); + if (size < pixel_color->red_size && size < internal_color->red_size) + return 0; - size = _component_size (masks->blue_mask); - if (size < pixel_color->blue_size && size < internal_color->blue_size) - return 0; - - *diff += abs (size - internal_color->blue_size); + *diff += abs (size - internal_color->red_size); - size = _component_size (masks->alpha_mask); - if (size < pixel_color->alpha_size && size < internal_color->alpha_size) - return 0; - - *diff += abs (size - internal_color->alpha_size); - - return 1; + size = _component_size (masks->green_mask); + if (size < pixel_color->green_size && size < internal_color->green_size) + return 0; + + *diff += abs (size - internal_color->green_size); + + size = _component_size (masks->blue_mask); + if (size < pixel_color->blue_size && size < internal_color->blue_size) + return 0; + + *diff += abs (size - internal_color->blue_size); + + size = _component_size (masks->alpha_mask); + if (size < pixel_color->alpha_size && size < internal_color->alpha_size) + return 0; + + *diff += abs (size - internal_color->alpha_size); + + return 1; } static glitz_gl_pixel_format_t * _glitz_find_best_gl_pixel_format (glitz_pixel_format_t *format, - glitz_color_format_t *internal_color, - unsigned long feature_mask) + glitz_color_format_t *internal_color, + unsigned long feature_mask) { - glitz_gl_pixel_format_t *best = NULL; - glitz_color_format_t color; - int i, n_formats, diff, best_diff = MAXSHORT; + glitz_gl_pixel_format_t *best = NULL; + glitz_color_format_t color; + int i, n_formats, diff, best_diff = MAXSHORT; - color.red_size = _component_size (format->masks.red_mask); - color.green_size = _component_size (format->masks.green_mask); - color.blue_size = _component_size (format->masks.blue_mask); - color.alpha_size = _component_size (format->masks.alpha_mask); + color.red_size = _component_size (format->masks.red_mask); + color.green_size = _component_size (format->masks.green_mask); + color.blue_size = _component_size (format->masks.blue_mask); + color.alpha_size = _component_size (format->masks.alpha_mask); - n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t); - for (i = 0; best_diff > 0 && i < n_formats; i++) { - if (_glitz_format_diff (&_gl_pixel_formats[i].pixel.masks, - &color, - internal_color, - &diff)) { - if (diff < best_diff) { - best = &_gl_pixel_formats[i]; - best_diff = diff; - } + n_formats = sizeof (_gl_pixel_formats) / sizeof (glitz_gl_pixel_format_t); + for (i = 0; best_diff > 0 && i < n_formats; i++) + { + if (_glitz_format_diff (&_gl_pixel_formats[i].pixel.masks, + &color, + internal_color, + &diff)) + { + if (diff < best_diff) + { + best = &_gl_pixel_formats[i]; + best_diff = diff; + } + } } - } - - if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) { - n_formats = sizeof (_gl_packed_pixel_formats) / - sizeof (glitz_gl_pixel_format_t); - - for (i = 0; best_diff > 0 && i < n_formats; i++) { - if (_glitz_format_diff (&_gl_packed_pixel_formats[i].pixel.masks, - &color, - internal_color, - &diff)) { - if (diff < best_diff) { - best = &_gl_packed_pixel_formats[i]; - best_diff = diff; - } - } - } - } - return best; + if (feature_mask & GLITZ_FEATURE_PACKED_PIXELS_MASK) + { + n_formats = sizeof (_gl_packed_pixel_formats) / + sizeof (glitz_gl_pixel_format_t); + + for (i = 0; best_diff > 0 && i < n_formats; i++) + { + if (_glitz_format_diff (&_gl_packed_pixel_formats[i].pixel.masks, + &color, + internal_color, + &diff)) + { + if (diff < best_diff) + { + best = &_gl_packed_pixel_formats[i]; + best_diff = diff; + } + } + } + } + + return best; } void glitz_set_pixels (glitz_surface_t *dst, - int x_dst, - int y_dst, - int width, - int height, - glitz_pixel_format_t *format, - glitz_buffer_t *buffer) + int x_dst, + int y_dst, + int width, + int height, + glitz_pixel_format_t *format, + glitz_buffer_t *buffer) { glitz_box_t *clip = dst->clip; int n_clip = dst->n_clip; @@ -601,142 +615,155 @@ glitz_set_pixels (glitz_surface_t *dst, glitz_bool_t bound = 0; int bytes_per_line = 0, bytes_per_pixel = 0; glitz_image_t src_image, dst_image; + unsigned long color_mask; glitz_box_t box; - + GLITZ_GL_SURFACE (dst); - + if (x_dst < 0 || x_dst > (dst->box.x2 - width) || - y_dst < 0 || y_dst > (dst->box.y2 - height)) { - glitz_surface_status_add (dst, GLITZ_STATUS_BAD_COORDINATE_MASK); - return; + y_dst < 0 || y_dst > (dst->box.y2 - height)) + { + glitz_surface_status_add (dst, GLITZ_STATUS_BAD_COORDINATE_MASK); + return; } if (SURFACE_SOLID (dst)) { - glitz_color_t old = dst->solid; + glitz_color_t old = dst->solid; - while (n_clip--) - { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (x_dst > box.x1) - box.x1 = x_dst; - if (y_dst > box.y1) - box.y1 = y_dst; - if (x_dst + width < box.x2) - box.x2 = x_dst + width; - if (y_dst + height < box.y2) - box.y2 = y_dst + height; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - dst_image.width = dst_image.height = 1; + while (n_clip--) + { + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (x_dst > box.x1) + box.x1 = x_dst; + if (y_dst > box.y1) + box.y1 = y_dst; + if (x_dst + width < box.x2) + box.x2 = x_dst + width; + if (y_dst + height < box.y2) + box.y2 = y_dst + height; - src_image.data = - glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY); - src_image.data += format->skip_lines * format->bytes_per_line; - src_image.format = format; - src_image.width = src_image.height = 1; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + dst_image.width = dst_image.height = 1; - if (format->masks.alpha_mask && dst->format->color.alpha_size) - { - dst_image.data = (void *) &dst->solid.alpha; - dst_image.format = &_solid_format[SOLID_ALPHA]; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - format->xoffset, 0, 0, 0, 1, 1); - } else - dst->solid.alpha = 0xffff; - - if (format->masks.red_mask && dst->format->color.red_size) - { - dst_image.data = (void *) &dst->solid.red; - dst_image.format = &_solid_format[SOLID_RED]; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - format->xoffset, 0, 0, 0, 1, 1); - } else - dst->solid.red = 0; - - if (format->masks.green_mask && dst->format->color.green_size) - { - dst_image.data = (void *) &dst->solid.green; - dst_image.format = &_solid_format[SOLID_GREEN]; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - format->xoffset, 0, 0, 0, 1, 1); - } else - dst->solid.green = 0; + src_image.data = + glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_READ_ONLY); + src_image.data += format->skip_lines * format->bytes_per_line; + src_image.format = format; + src_image.width = src_image.height = 1; - if (format->masks.blue_mask && dst->format->color.blue_size) - { - dst_image.data = (void *) &dst->solid.blue; - dst_image.format = &_solid_format[SOLID_BLUE]; + if (format->masks.alpha_mask && dst->format->color.alpha_size) + { + dst_image.data = (void *) &dst->solid.alpha; + dst_image.format = &_solid_format[SOLID_ALPHA]; - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - format->xoffset, 0, 0, 0, 1, 1); - } else - dst->solid.blue = 0; - - glitz_buffer_unmap (buffer); + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + format->xoffset, 0, 0, 0, 1, 1); + } else + dst->solid.alpha = 0xffff; - if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK) - { - dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_DRAWABLE_MASK); - } - else - { - if (dst->solid.red != old.red || - dst->solid.green != old.green || - dst->solid.blue != old.blue || - dst->solid.alpha != old.alpha) - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_DRAWABLE_MASK); - } - break; - } - } - return; + if (format->masks.red_mask && dst->format->color.red_size) + { + dst_image.data = (void *) &dst->solid.red; + dst_image.format = &_solid_format[SOLID_RED]; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + format->xoffset, 0, 0, 0, 1, 1); + } else + dst->solid.red = 0; + + if (format->masks.green_mask && dst->format->color.green_size) + { + dst_image.data = (void *) &dst->solid.green; + dst_image.format = &_solid_format[SOLID_GREEN]; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + format->xoffset, 0, 0, 0, 1, 1); + } else + dst->solid.green = 0; + + if (format->masks.blue_mask && dst->format->color.blue_size) + { + dst_image.data = (void *) &dst->solid.blue; + dst_image.format = &_solid_format[SOLID_BLUE]; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + format->xoffset, 0, 0, 0, 1, 1); + } else + dst->solid.blue = 0; + + glitz_buffer_unmap (buffer); + + if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK) + { + dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_DRAWABLE_MASK); + } + else + { + if (dst->solid.red != old.red || + dst->solid.green != old.green || + dst->solid.blue != old.blue || + dst->solid.alpha != old.alpha) + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_DRAWABLE_MASK); + } + break; + } + clip++; + } + return; } - + + color_mask = 0; + if (dst->format->color.red_size) + color_mask |= GLITZ_FORMAT_RED_SIZE_MASK; + if (dst->format->color.green_size) + color_mask |= GLITZ_FORMAT_GREEN_SIZE_MASK; + if (dst->format->color.blue_size) + color_mask |= GLITZ_FORMAT_BLUE_SIZE_MASK; + if (dst->format->color.alpha_size) + color_mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK; + /* find direct format */ gl_format = - _glitz_find_gl_pixel_format (format, - &dst->format->color, - dst->drawable->backend->feature_mask); + _glitz_find_gl_pixel_format (format, + color_mask, + dst->drawable->backend->feature_mask); if (gl_format == NULL) { - unsigned long feature_mask; + unsigned long feature_mask; - feature_mask = dst->drawable->backend->feature_mask; - transform |= GLITZ_TRANSFORM_PIXELS_MASK; - gl_format = - _glitz_find_best_gl_pixel_format (format, - &dst->format->color, - feature_mask); + feature_mask = dst->drawable->backend->feature_mask; + transform |= GLITZ_TRANSFORM_PIXELS_MASK; + gl_format = + _glitz_find_best_gl_pixel_format (format, + &dst->format->color, + feature_mask); } glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); texture = glitz_surface_get_texture (dst, 1); if (!texture) { - glitz_surface_pop_current (dst); - return; + glitz_surface_pop_current (dst); + return; } if (height > 1) { - if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) - transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; + if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) + transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; } glitz_texture_bind (gl, texture); @@ -746,367 +773,483 @@ glitz_set_pixels (glitz_surface_t *dst, while (n_clip--) { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - if (x_dst > box.x1) - box.x1 = x_dst; - if (y_dst > box.y1) - box.y1 = y_dst; - if (x_dst + width < box.x2) - box.x2 = x_dst + width; - if (y_dst + height < box.y2) - box.y2 = y_dst + height; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - if (transform) - { - if (!data) - { - int stride, bpp; + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; + if (x_dst > box.x1) + box.x1 = x_dst; + if (y_dst > box.y1) + box.y1 = y_dst; + if (x_dst + width < box.x2) + box.x2 = x_dst + width; + if (y_dst + height < box.y2) + box.y2 = y_dst + height; - bpp = gl_format->pixel.masks.bpp; - stride = (((width * bpp) / 8) + 3) & -4; - data = malloc (stride * height); - if (!data) - { - glitz_surface_status_add (dst, - GLITZ_STATUS_NO_MEMORY_MASK); - goto BAIL; - } - - dst_image.data = pixels = data; - dst_image.format = &gl_format->pixel; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + if (transform) + { + if (!data) + { + int stride, bpp; - ptr = - glitz_buffer_map (buffer, - GLITZ_BUFFER_ACCESS_READ_ONLY); - src_image.format = format; + bpp = gl_format->pixel.masks.bpp; + stride = (((width * bpp) / 8) + 3) & -4; + data = malloc (stride * height); + if (!data) + { + glitz_surface_status_add (dst, + GLITZ_STATUS_NO_MEMORY_MASK); + goto BAIL; + } - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4); - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); - } - - dst_image.width = box.x2 - box.x1; - dst_image.height = box.y2 - box.y1; + dst_image.data = pixels = data; + dst_image.format = &gl_format->pixel; - src_image.width = box.x2 - box.x1; - src_image.height = box.y2 - box.y1; + ptr = + glitz_buffer_map (buffer, + GLITZ_BUFFER_ACCESS_READ_ONLY); + src_image.format = format; - src_image.data = ptr + (format->skip_lines + box.y1 - y_dst) * - format->bytes_per_line; + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4); + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); + } - _glitz_pixel_transform (transform, - &src_image, - &dst_image, - format->xoffset + box.x1 - x_dst, 0, - 0, 0, - box.x2 - box.x1, box.y2 - box.y1); - } - else - { - if (!bound) - { - ptr = glitz_buffer_bind (buffer, - GLITZ_GL_PIXEL_UNPACK_BUFFER); - - bytes_per_line = format->bytes_per_line; - bytes_per_pixel = format->masks.bpp / 8; - if (bytes_per_line) - { - if ((bytes_per_line % 4) == 0) - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4); - else if ((bytes_per_line % 2) == 0) - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2); - else - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); - - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, - bytes_per_line / bytes_per_pixel); - } - else - { - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, width); - bytes_per_line = width * bytes_per_pixel; - } - bound = 1; - } - - pixels = ptr + - (format->skip_lines + y_dst + height - box.y2) * - bytes_per_line + - (format->xoffset + box.x1 - x_dst) * bytes_per_pixel; - } + dst_image.width = box.x2 - box.x1; + dst_image.height = box.y2 - box.y1; - gl->tex_sub_image_2d (texture->target, 0, - texture->box.x1 + box.x1, - texture->box.y2 - box.y2, - box.x2 - box.x1, box.y2 - box.y1, - gl_format->format, gl_format->type, - pixels); + src_image.width = box.x2 - box.x1; + src_image.height = box.y2 - box.y1; - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_DRAWABLE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - clip++; + src_image.data = ptr + (format->skip_lines + box.y1 - y_dst) * + format->bytes_per_line; + + _glitz_pixel_transform (transform, + &src_image, + &dst_image, + format->xoffset + box.x1 - x_dst, 0, + 0, 0, + box.x2 - box.x1, box.y2 - box.y1); + } + else + { + if (!bound) + { + ptr = glitz_buffer_bind (buffer, + GLITZ_GL_PIXEL_UNPACK_BUFFER); + + bytes_per_line = format->bytes_per_line; + bytes_per_pixel = format->masks.bpp / 8; + if (bytes_per_line) + { + if ((bytes_per_line % 4) == 0) + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 4); + else if ((bytes_per_line % 2) == 0) + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 2); + else + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); + + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, + bytes_per_line / bytes_per_pixel); + } + else + { + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, width); + bytes_per_line = width * bytes_per_pixel; + } + bound = 1; + } + + pixels = ptr + + (format->skip_lines + y_dst + height - box.y2) * + bytes_per_line + + (format->xoffset + box.x1 - x_dst) * bytes_per_pixel; + } + + gl->tex_sub_image_2d (texture->target, 0, + texture->box.x1 + box.x1, + texture->box.y2 - box.y2, + box.x2 - box.x1, box.y2 - box.y1, + gl_format->format, gl_format->type, + pixels); + + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_DRAWABLE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + clip++; } if (transform) { - free (data); - glitz_buffer_unmap (buffer); + free (data); + glitz_buffer_unmap (buffer); } else - glitz_buffer_unbind (buffer); + glitz_buffer_unbind (buffer); - BAIL: +BAIL: glitz_texture_unbind (gl, texture); glitz_surface_pop_current (dst); } void glitz_get_pixels (glitz_surface_t *src, - int x_src, - int y_src, - int width, - int height, - glitz_pixel_format_t *format, - glitz_buffer_t *buffer) + int x_src, + int y_src, + int width, + int height, + glitz_pixel_format_t *format, + glitz_buffer_t *buffer) { - glitz_bool_t from_drawable; - glitz_texture_t *texture = NULL; - char *pixels, *data = NULL; - glitz_gl_pixel_format_t *gl_format = NULL; - unsigned long transform = 0; - int src_x = 0, src_y = 0, src_w = width, src_h = height; - int xoffset, bytes_per_line, bpp; - glitz_color_format_t *color; + glitz_box_t *clip = src->clip; + int n_clip = src->n_clip; + glitz_bool_t from_drawable; + glitz_texture_t *texture = NULL; + char *pixels, *data = NULL; + glitz_gl_pixel_format_t *gl_format = NULL; + unsigned long transform = 0; + int src_x = 0, src_y = 0; + int src_w = width, src_h = height; + int bytes_per_line, bytes_per_pixel; + glitz_color_format_t *color; + unsigned long color_mask; + glitz_box_t box; - GLITZ_GL_SURFACE (src); - - if (x_src < 0 || x_src > (src->box.x2 - width) || - y_src < 0 || y_src > (src->box.y2 - height)) { - glitz_surface_status_add (src, GLITZ_STATUS_BAD_COORDINATE_MASK); - return; - } + GLITZ_GL_SURFACE (src); - if (SURFACE_SOLID (src)) { - glitz_image_t src_image, dst_image; - glitz_pixel_format_t dst_format; - - if (SURFACE_SOLID_DAMAGE (src)) { - glitz_surface_push_current (src, GLITZ_ANY_CONTEXT_CURRENT); - glitz_surface_sync_solid (src); - glitz_surface_pop_current (src); + if (x_src < 0 || x_src > (src->box.x2 - width) || + y_src < 0 || y_src > (src->box.y2 - height)) + { + glitz_surface_status_add (src, GLITZ_STATUS_BAD_COORDINATE_MASK); + return; } - src_image.width = src_image.height = 1; + if (SURFACE_SOLID (src)) + { + glitz_image_t src_image, dst_image; + glitz_pixel_format_t dst_format; - dst_format = *format; + while (n_clip--) + { + box.x1 = clip->x1 + src->x_clip; + box.y1 = clip->y1 + src->y_clip; + box.x2 = clip->x2 + src->x_clip; + box.y2 = clip->y2 + src->y_clip; + if (x_src > box.x1) + box.x1 = x_src; + if (y_src > box.y1) + box.y1 = y_src; + if (x_src + width < box.x2) + box.x2 = x_src + width; + if (y_src + height < box.y2) + box.y2 = y_src + height; - dst_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - dst_image.data += format->skip_lines * format->bytes_per_line; - dst_image.format = &dst_format; - dst_image.width = dst_image.height = 1; + if (box.x1 < box.x2 && box.y1 < box.y2) + { + if (SURFACE_SOLID_DAMAGE (src)) + { + glitz_surface_push_current (src, + GLITZ_ANY_CONTEXT_CURRENT); + glitz_surface_sync_solid (src); + glitz_surface_pop_current (src); + } - if (format->masks.alpha_mask) { - src_image.data = (void *) &src->solid.alpha; - src_image.format = &_solid_format[SOLID_ALPHA]; + src_image.width = src_image.height = 1; - dst_format.masks.alpha_mask = format->masks.alpha_mask; - dst_format.masks.red_mask = 0; - dst_format.masks.green_mask = 0; - dst_format.masks.blue_mask = 0; + dst_format = *format; - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - 0, 0, format->xoffset, 0, 1, 1); + dst_image.data = + glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); + dst_image.data += format->skip_lines * format->bytes_per_line; + dst_image.format = &dst_format; + dst_image.width = dst_image.height = 1; + + if (format->masks.alpha_mask) + { + src_image.data = (void *) &src->solid.alpha; + src_image.format = &_solid_format[SOLID_ALPHA]; + + dst_format.masks.alpha_mask = format->masks.alpha_mask; + dst_format.masks.red_mask = 0; + dst_format.masks.green_mask = 0; + dst_format.masks.blue_mask = 0; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + 0, 0, format->xoffset, 0, 1, 1); + } + + if (format->masks.red_mask) + { + src_image.data = (void *) &src->solid.red; + src_image.format = &_solid_format[SOLID_RED]; + + dst_format.masks.alpha_mask = 0; + dst_format.masks.red_mask = format->masks.red_mask; + dst_format.masks.green_mask = 0; + dst_format.masks.blue_mask = 0; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + 0, 0, format->xoffset, 0, 1, 1); + } + + if (format->masks.green_mask) + { + src_image.data = (void *) &src->solid.green; + src_image.format = &_solid_format[SOLID_GREEN]; + + dst_format.masks.alpha_mask = 0; + dst_format.masks.red_mask = 0; + dst_format.masks.green_mask = format->masks.green_mask; + dst_format.masks.blue_mask = 0; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + 0, 0, format->xoffset, 0, 1, 1); + } + + if (format->masks.blue_mask) + { + src_image.data = (void *) &src->solid.blue; + src_image.format = &_solid_format[SOLID_BLUE]; + + dst_format.masks.alpha_mask = 0; + dst_format.masks.red_mask = 0; + dst_format.masks.green_mask = 0; + dst_format.masks.blue_mask = format->masks.blue_mask; + + _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, + &src_image, &dst_image, + 0, 0, format->xoffset, 0, 1, 1); + } + + glitz_buffer_unmap (buffer); + + break; + } + clip++; + } + + return; } - if (format->masks.red_mask) { - src_image.data = (void *) &src->solid.red; - src_image.format = &_solid_format[SOLID_RED]; - - dst_format.masks.alpha_mask = 0; - dst_format.masks.red_mask = format->masks.red_mask; - dst_format.masks.green_mask = 0; - dst_format.masks.blue_mask = 0; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - 0, 0, format->xoffset, 0, 1, 1); + color = &src->format->color; + from_drawable = glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT); + if (from_drawable) + { + if (src->attached) + color = &src->attached->format->d.color; } - - if (format->masks.green_mask) { - src_image.data = (void *) &src->solid.green; - src_image.format = &_solid_format[SOLID_GREEN]; - - dst_format.masks.alpha_mask = 0; - dst_format.masks.red_mask = 0; - dst_format.masks.green_mask = format->masks.green_mask; - dst_format.masks.blue_mask = 0; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - 0, 0, format->xoffset, 0, 1, 1); - } - - if (format->masks.blue_mask) { - src_image.data = (void *) &src->solid.blue; - src_image.format = &_solid_format[SOLID_BLUE]; - - dst_format.masks.alpha_mask = 0; - dst_format.masks.red_mask = 0; - dst_format.masks.green_mask = 0; - dst_format.masks.blue_mask = format->masks.blue_mask; - - _glitz_pixel_transform (GLITZ_TRANSFORM_PIXELS_MASK, - &src_image, &dst_image, - 0, 0, format->xoffset, 0, 1, 1); - } - - glitz_buffer_unmap (buffer); - - return; - } - - color = &src->format->color; - from_drawable = glitz_surface_push_current (src, GLITZ_DRAWABLE_CURRENT); - if (from_drawable) { - if (src->attached) - color = &src->attached->format->color; - } else { - texture = glitz_surface_get_texture (src, 0); - if (!texture) { - glitz_surface_pop_current (src); - return; - } - - if (texture->width > width || texture->height > height) - transform |= GLITZ_TRANSFORM_COPY_BOX_MASK; - } - - if (transform || height > 1) { - if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) - transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; - } - - /* find direct format */ - gl_format = - _glitz_find_gl_pixel_format (format, color, - src->drawable->backend->feature_mask); - if (gl_format == NULL) { - transform |= GLITZ_TRANSFORM_PIXELS_MASK; - - gl_format = - _glitz_find_best_gl_pixel_format (format, color, - src->drawable->backend->feature_mask); - } - - /* should not happen */ - if (gl_format == NULL) { - glitz_surface_pop_current (src); - return; - } - - if (transform) { - int stride; - - if (transform & GLITZ_TRANSFORM_COPY_BOX_MASK) { - src_w = texture->width; - src_h = texture->height; - src_x = x_src + src->texture.box.x1; - src_y = y_src + src->texture.box.y1; - } - - stride = (((src_w * gl_format->pixel.masks.bpp) / 8) + 3) & -4; - - data = malloc (stride * src_h); - if (!data) { - glitz_surface_status_add (src, GLITZ_STATUS_NO_MEMORY_MASK); - return; - } - pixels = data; - xoffset = 0; - bytes_per_line = stride; - bpp = gl_format->pixel.masks.bpp; - } else { - xoffset = format->xoffset; - bytes_per_line = format->bytes_per_line; - bpp = format->masks.bpp; - pixels = glitz_buffer_bind (buffer, GLITZ_GL_PIXEL_PACK_BUFFER); - pixels += format->skip_lines * bytes_per_line; - } - - gl->pixel_store_i (GLITZ_GL_PACK_SKIP_ROWS, 0); - gl->pixel_store_i (GLITZ_GL_PACK_SKIP_PIXELS, xoffset); - - if (bytes_per_line) { - if ((bytes_per_line % 4) == 0) - gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 4); - else if ((bytes_per_line % 2) == 0) - gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 2); else - gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 1); - - gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, bytes_per_line / (bpp / 8)); - } else { - gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 1); - gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, 0); - } + { + texture = glitz_surface_get_texture (src, 0); + if (!texture) + { + glitz_surface_pop_current (src); + return; + } - if (from_drawable) { - gl->read_buffer (src->buffer); - - gl->disable (GLITZ_GL_SCISSOR_TEST); + if (texture->width > width || texture->height > height) + transform |= GLITZ_TRANSFORM_COPY_BOX_MASK; - gl->read_pixels (x_src + src->x, - SURFACE_DRAWABLE_HEIGHT (src) - (y_src + src->y) - height, - width, height, - gl_format->format, gl_format->type, - pixels); - - gl->enable (GLITZ_GL_SCISSOR_TEST); - } else { - glitz_texture_bind (gl, texture); - gl->get_tex_image (texture->target, 0, - gl_format->format, gl_format->type, - pixels); - glitz_texture_unbind (gl, texture); - } + if (src->n_clip > 1 || + clip->x1 + src->x_clip > x_src || + clip->y1 + src->y_clip > y_src || + clip->x2 + src->x_clip < x_src + width || + clip->y2 + src->y_clip < y_src + height) + transform |= GLITZ_TRANSFORM_COPY_BOX_MASK; + } - if (transform) { - glitz_image_t src_image, dst_image; + if (transform || height > 1) + { + if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN) + transform |= GLITZ_TRANSFORM_SCANLINE_ORDER_MASK; + } - src_image.data = data; - src_image.format = &gl_format->pixel; - src_image.width = src_w; - src_image.height = src_h; + color_mask = 0; + if (format->masks.red_mask) + color_mask |= GLITZ_FORMAT_RED_SIZE_MASK; + if (format->masks.green_mask) + color_mask |= GLITZ_FORMAT_GREEN_SIZE_MASK; + if (format->masks.blue_mask) + color_mask |= GLITZ_FORMAT_BLUE_SIZE_MASK; + if (format->masks.alpha_mask) + color_mask |= GLITZ_FORMAT_ALPHA_SIZE_MASK; - dst_image.data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - dst_image.format = format; - dst_image.width = width; - dst_image.height = height; + /* find direct format */ + gl_format = + _glitz_find_gl_pixel_format (format, color_mask, + src->drawable->backend->feature_mask); + if (gl_format == NULL) + { + unsigned int features; - if (format->scanline_order == GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP) - src_y = src_h - src_y - height; + transform |= GLITZ_TRANSFORM_PIXELS_MASK; + features = src->drawable->backend->feature_mask; - _glitz_pixel_transform (transform, - &src_image, - &dst_image, - src_x, src_y, - format->xoffset, format->skip_lines, - width, height); + gl_format = _glitz_find_best_gl_pixel_format (format, color, features); + } - glitz_buffer_unmap (buffer); - } else - glitz_buffer_unbind (buffer); + /* should not happen */ + if (gl_format == NULL) + { + glitz_surface_pop_current (src); + return; + } - glitz_surface_pop_current (src); + if (transform) + { + int stride; - if (data) - free (data); + if (transform & GLITZ_TRANSFORM_COPY_BOX_MASK) + { + if (texture) + { + src_w = texture->width; + src_h = texture->height; + src_x = src->texture.box.x1; + src_y = src->texture.box.y1; + } + } + + stride = (((src_w * gl_format->pixel.masks.bpp) / 8) + 3) & -4; + + data = malloc (stride * src_h); + if (!data) + { + glitz_surface_status_add (src, GLITZ_STATUS_NO_MEMORY_MASK); + return; + } + + pixels = data; + bytes_per_pixel = gl_format->pixel.masks.bpp / 8; + bytes_per_line = stride; + } + else + { + bytes_per_pixel = format->masks.bpp / 8; + bytes_per_line = format->bytes_per_line; + if (!bytes_per_line) + bytes_per_line = width * bytes_per_pixel; + + pixels = glitz_buffer_bind (buffer, GLITZ_GL_PIXEL_PACK_BUFFER); + pixels += format->skip_lines * bytes_per_line; + pixels += format->xoffset * bytes_per_pixel; + } + + gl->pixel_store_i (GLITZ_GL_PACK_SKIP_ROWS, 0); + gl->pixel_store_i (GLITZ_GL_PACK_SKIP_PIXELS, 0); + + if ((bytes_per_line % 4) == 0) + gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 4); + else if ((bytes_per_line % 2) == 0) + gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 2); + else + gl->pixel_store_i (GLITZ_GL_PACK_ALIGNMENT, 1); + + gl->pixel_store_i (GLITZ_GL_PACK_ROW_LENGTH, + bytes_per_line / bytes_per_pixel); + + if (from_drawable) + { + gl->read_buffer (src->buffer); + + gl->disable (GLITZ_GL_SCISSOR_TEST); + + while (n_clip--) + { + box.x1 = clip->x1 + src->x_clip; + box.y1 = clip->y1 + src->y_clip; + box.x2 = clip->x2 + src->x_clip; + box.y2 = clip->y2 + src->y_clip; + if (x_src > box.x1) + box.x1 = x_src; + if (y_src > box.y1) + box.y1 = y_src; + if (x_src + width < box.x2) + box.x2 = x_src + width; + if (y_src + height < box.y2) + box.y2 = y_src + height; + + if (box.x1 < box.x2 && box.y1 < box.y2) + { + gl->read_pixels (box.x1 + src->x, + src->attached->height - (box.y2 + src->y), + box.x2 - box.x1, box.y2 - box.y1, + gl_format->format, gl_format->type, + pixels + + (y_src + height - box.y2) * bytes_per_line + + (box.x1 - x_src) * bytes_per_pixel); + } + clip++; + } + + gl->enable (GLITZ_GL_SCISSOR_TEST); + } + else + { + glitz_texture_bind (gl, texture); + gl->get_tex_image (texture->target, 0, + gl_format->format, gl_format->type, + pixels); + glitz_texture_unbind (gl, texture); + } + + if (transform) + { + glitz_image_t src_image, dst_image; + + src_image.data = data; + src_image.format = &gl_format->pixel; + src_image.width = src_w; + src_image.height = src_h; + + dst_image.data = glitz_buffer_map (buffer, + GLITZ_BUFFER_ACCESS_WRITE_ONLY); + dst_image.format = format; + dst_image.width = width; + dst_image.height = height; + + clip = src->clip; + n_clip = src->n_clip; + + while (n_clip--) + { + box.x1 = clip->x1 + src->x_clip; + box.y1 = clip->y1 + src->y_clip; + box.x2 = clip->x2 + src->x_clip; + box.y2 = clip->y2 + src->y_clip; + if (x_src > box.x1) + box.x1 = x_src; + if (y_src > box.y1) + box.y1 = y_src; + if (x_src + width < box.x2) + box.x2 = x_src + width; + if (y_src + height < box.y2) + box.y2 = y_src + height; + + if (box.x1 < box.x2 && box.y1 < box.y2) + { + _glitz_pixel_transform (transform, + &src_image, + &dst_image, + box.x1 - x_src, box.y1 - y_src, + format->xoffset + box.x1 - x_src, + format->skip_lines + box.y1 - y_src, + box.x2 - box.x1, box.y2 - box.y1); + } + clip++; + } + + glitz_buffer_unmap (buffer); + } else + glitz_buffer_unbind (buffer); + + glitz_surface_pop_current (src); + + if (data) + free (data); } diff --git a/gfx/cairo/glitz/src/glitz_program.c b/gfx/cairo/glitz/src/glitz_program.c index b5d02399a14..7caebc10822 100644 --- a/gfx/cairo/glitz/src/glitz_program.c +++ b/gfx/cairo/glitz/src/glitz_program.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -36,36 +36,36 @@ #define EXPAND_RECT "RECT" #define EXPAND_NA "NA" -#define EXPAND_X_IN_SOLID_OP \ - { "", "", "MUL result.color, color, fragment.color.a;" } +#define EXPAND_X_IN_SOLID_OP \ + { "", "", "MUL result.color, color, fragment.color.a;" } + +#define EXPAND_SOLID_IN_X_OP \ + { "", "", "MUL result.color, fragment.color, color.a;" } -#define EXPAND_SOLID_IN_X_OP \ - { "", "", "MUL result.color, fragment.color, color.a;" } - #define EXPAND_SRC_DECL "TEMP src;" -#define EXPAND_SRC_2D_IN_OP \ - { "TXP src, fragment.texcoord[1], texture[1], 2D;", \ - "DP4 color.a, color, fragment.color;", \ - "MUL result.color, src, color.a;" } - -#define EXPAND_SRC_RECT_IN_OP \ - { "TXP src, fragment.texcoord[1], texture[1], RECT;", \ - "DP4 color.a, color, fragment.color;", \ - "MUL result.color, src, color.a;" } +#define EXPAND_SRC_2D_IN_OP \ + { "TXP src, fragment.texcoord[1], texture[1], 2D;", \ + "DP4 color.a, color, fragment.color;", \ + "MUL result.color, src, color.a;" } + +#define EXPAND_SRC_RECT_IN_OP \ + { "TXP src, fragment.texcoord[1], texture[1], RECT;", \ + "DP4 color.a, color, fragment.color;", \ + "MUL result.color, src, color.a;" } #define EXPAND_MASK_DECL "TEMP mask;" -#define EXPAND_MASK_2D_IN_OP \ - { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \ - "DP4 mask.a, mask, fragment.color;", \ - "MUL result.color, color, mask.a;" } +#define EXPAND_MASK_2D_IN_OP \ + { "TXP mask, fragment.texcoord[0], texture[0], 2D;", \ + "DP4 mask.a, mask, fragment.color;", \ + "MUL result.color, color, mask.a;" } -#define EXPAND_MASK_RECT_IN_OP \ - { "TXP mask, fragment.texcoord[0], texture[0], RECT;", \ - "DP4 mask.a, mask, fragment.color;", \ - "MUL result.color, color, mask.a;" } +#define EXPAND_MASK_RECT_IN_OP \ + { "TXP mask, fragment.texcoord[0], texture[0], RECT;", \ + "DP4 mask.a, mask, fragment.color;", \ + "MUL result.color, color, mask.a;" } -#define EXPAND_IN_NA \ - { "NA", "NA", "NA" } +#define EXPAND_IN_NA \ + { "NA", "NA", "NA" } typedef struct _glitz_program_expand_t glitz_program_expand_t; @@ -76,98 +76,98 @@ typedef struct _glitz_inop { } glitz_in_op_t; static const struct _glitz_program_expand_t { - char *texture; - char *declarations; - glitz_in_op_t in; + char *texture; + char *declarations; + glitz_in_op_t in; } _program_expand_map[GLITZ_TEXTURE_LAST][GLITZ_TEXTURE_LAST][2] = { - { - /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_NONE] */ { - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } - }, - - /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_2D] */ - { - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, - { EXPAND_2D, EXPAND_NONE, EXPAND_SOLID_IN_X_OP } - }, - - /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_RECT] */ - { - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, - { EXPAND_RECT, EXPAND_NONE, EXPAND_SOLID_IN_X_OP } + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_NONE] */ + { + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } + }, + + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_2D] */ + { + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, + { EXPAND_2D, EXPAND_NONE, EXPAND_SOLID_IN_X_OP } + }, + + /* [GLITZ_TEXTURE_NONE][GLITZ_TEXTURE_RECT] */ + { + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA }, + { EXPAND_RECT, EXPAND_NONE, EXPAND_SOLID_IN_X_OP } + } + }, { + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_NONE] */ + { + { EXPAND_2D, EXPAND_NONE, EXPAND_X_IN_SOLID_OP }, + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } + }, + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_2D] */ + { + { EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP }, + { EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } + }, + + /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_RECT] */ + { + { EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP }, + { EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } + } + }, { + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_NONE] */ + { + { EXPAND_RECT, EXPAND_NONE, EXPAND_X_IN_SOLID_OP }, + { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } + }, + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_2D] */ + { + { EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP }, + { EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } + }, + + /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_RECT] */ + { + { EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP }, + { EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_RECT_IN_OP } + } } - }, { - - /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_NONE] */ - { - { EXPAND_2D, EXPAND_NONE, EXPAND_X_IN_SOLID_OP }, - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } - }, - - /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_2D] */ - { - { EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP }, - { EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } - }, - - /* [GLITZ_TEXTURE_2D][GLITZ_TEXTURE_RECT] */ - { - { EXPAND_2D, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP }, - { EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } - } - }, { - - /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_NONE] */ - { - { EXPAND_RECT, EXPAND_NONE, EXPAND_X_IN_SOLID_OP }, - { EXPAND_NA, EXPAND_NA, EXPAND_IN_NA } - }, - - /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_2D] */ - { - { EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_2D_IN_OP }, - { EXPAND_2D, EXPAND_SRC_DECL, EXPAND_SRC_2D_IN_OP } - }, - - /* [GLITZ_TEXTURE_RECT][GLITZ_TEXTURE_RECT] */ - { - { EXPAND_RECT, EXPAND_MASK_DECL, EXPAND_MASK_RECT_IN_OP }, - { EXPAND_RECT, EXPAND_SRC_DECL, EXPAND_SRC_RECT_IN_OP } - } - } }; /* * general convolution filter. */ static const char *_convolution_header[] = { - "PARAM p[%d] = { program.local[0..%d] };", - "ATTRIB pos = fragment.texcoord[%s];", - "TEMP color, in, coord, position;", + "PARAM p[%d] = { program.local[0..%d] };", + "ATTRIB pos = fragment.texcoord[%s];", + "TEMP color, in, coord, position;", - /* extra declarations */ - "%s" - - /* perspective divide */ - "RCP position.w, pos.w;", - "MUL position, pos, position.w;", NULL + /* extra declarations */ + "%s" + + /* perspective divide */ + "RCP position.w, pos.w;", + "MUL position, pos, position.w;", NULL }; static const char *_convolution_sample_first[] = { - "MOV coord, 0.0;", - "ADD coord.x, position.x, p[0].x;", - "ADD coord.y, position.y, p[0].y;", - "TEX in, coord, texture[%s], %s;", - "MUL color, in, p[0].z;", NULL + "MOV coord, 0.0;", + "ADD coord.x, position.x, p[0].x;", + "ADD coord.y, position.y, p[0].y;", + "TEX in, coord, texture[%s], %s;", + "MUL color, in, p[0].z;", NULL }; static const char *_convolution_sample[] = { - "ADD coord.x, position.x, p[%d].x;", - "ADD coord.y, position.y, p[%d].y;", - "TEX in, coord, texture[%s], %s;", - "MAD color, in, p[%d].z, color;", NULL + "ADD coord.x, position.x, p[%d].x;", + "ADD coord.y, position.y, p[%d].y;", + "TEX in, coord, texture[%s], %s;", + "MAD color, in, p[%d].z, color;", NULL }; @@ -175,17 +175,17 @@ static const char *_convolution_sample[] = { * gradient filters. */ static const char *_gradient_header[] = { - "PARAM gradient = program.local[0];", - "PARAM stops[%d] = { program.local[1..%d] };", - "ATTRIB pos = fragment.texcoord[%s];", - "TEMP color, second_color, stop0, stop1, position;", + "PARAM gradient = program.local[0];", + "PARAM stops[%d] = { program.local[1..%d] };", + "ATTRIB pos = fragment.texcoord[%s];", + "TEMP color, second_color, stop0, stop1, position;", - /* extra declarations */ - "%s", + /* extra declarations */ + "%s", - /* perspective divide */ - "RCP position.w, pos.w;", - "MUL position, pos, position.w;", NULL + /* perspective divide */ + "RCP position.w, pos.w;", + "MUL position, pos, position.w;", NULL }; /* @@ -197,10 +197,10 @@ static const char *_gradient_header[] = { * gradient.w = -sin (angle) */ static const char *_linear_gradient_calculations[] = { - "MUL position.x, gradient.z, position.x;", - "MAD position.x, gradient.w, position.y, position.x;", - "SUB position.z, position.x, gradient.x;", - "MUL position.z, position.z, gradient.y;", NULL + "MUL position.x, gradient.z, position.x;", + "MAD position.x, gradient.w, position.y, position.x;", + "SUB position.z, position.x, gradient.x;", + "MUL position.z, position.z, gradient.y;", NULL }; /* @@ -212,171 +212,172 @@ static const char *_linear_gradient_calculations[] = { * gradient.w = 1 / (radius1 - radius0) */ static const char *_radial_gradient_calculations[] = { - "SUB position, position, gradient;", - "MUL position.x, position.x, position.x;", - "MAD position.x, position.y, position.y, position.x;", - "RSQ position.y, position.x;", - "RCP position.x, position.y;", - "MUL position.x, position.x, position.x;", - "MUL position.x, position.x, position.y;", - "SUB position.x, position.x, gradient.z;", - "MUL position.z, position.x, gradient.w;", NULL + "SUB position, position, gradient;", + "MUL position.x, position.x, position.x;", + "MAD position.x, position.y, position.y, position.x;", + "RSQ position.y, position.x;", + "RCP position.x, position.y;", + "MUL position.x, position.x, position.x;", + "MUL position.x, position.x, position.y;", + "SUB position.x, position.x, gradient.z;", + "MUL position.z, position.x, gradient.w;", NULL }; static const char *_gradient_fill_repeat[] = { - "FRC position.z, position.z;", NULL + "FRC position.z, position.z;", NULL }; static const char *_gradient_fill_reflect[] = { - "FLR position.w, position.z;", - "MUL position.w, position.w, 0.5;", - "FLR position.w, position.w;", - "MUL position.y, position.w, 2.0;", - "FLR position.x, position.z;", - "SUB position.y, position.x, position.y;", - "FRC position.x, position.z;", - "SUB position.x, position.x, position.y;", - "ABS position.z, position.x;", NULL + "FLR position.w, position.z;", + "MUL position.w, position.w, 0.5;", + "FLR position.w, position.w;", + "MUL position.y, position.w, 2.0;", + "FLR position.x, position.z;", + "SUB position.y, position.x, position.y;", + "FRC position.x, position.z;", + "SUB position.x, position.x, position.y;", + "ABS position.z, position.x;", NULL }; static const char *_gradient_init_stops[] = { - "MOV stop0, stops[0];", - "MOV stop1, stops[%d];", NULL + "MOV stop0, stops[0];", + "MOV stop1, stops[%d];", NULL }; static const char *_gradient_lower_stop[] = { - "SLT position.x, stops[%d].z, position.z;", - "CMP stop0, -position.x, stops[%d], stop0;", NULL + "SLT position.x, stops[%d].z, position.z;", + "CMP stop0, -position.x, stops[%d], stop0;", NULL }; static const char *_gradient_higher_stop[] = { - "SLT position.x, position.z, stops[%d].z;", - "CMP stop1, -position.x, stops[%d], stop1;", NULL + "SLT position.x, position.z, stops[%d].z;", + "CMP stop1, -position.x, stops[%d], stop1;", NULL }; static const char *_gradient_fetch_and_interpolate[] = { - "TEX color, stop0, texture[%s], %s;", - "TEX second_color, stop1, texture[%s], %s;", + "TEX color, stop0, texture[%s], %s;", + "TEX second_color, stop1, texture[%s], %s;", - /* normalize gradient offset to color stop span */ - "SUB position.z, position.z, stop0.z;", - "MUL_SAT position.z, position.z, stop0.w;", + /* normalize gradient offset to color stop span */ + "SUB position.z, position.z, stop0.z;", + "MUL_SAT position.z, position.z, stop0.w;", - /* linear interpolation */ - "LRP color, position.z, second_color, color;", NULL + /* linear interpolation */ + "LRP color, position.z, second_color, color;", NULL }; static struct _glitz_program_query { - glitz_gl_enum_t query; - glitz_gl_enum_t max_query; - glitz_gl_int_t min; + glitz_gl_enum_t query; + glitz_gl_enum_t max_query; + glitz_gl_int_t min; } _program_limits[] = { - { GLITZ_GL_PROGRAM_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_INSTRUCTIONS, 1 }, - { GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 }, - { GLITZ_GL_PROGRAM_PARAMETERS, - GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 }, - { GLITZ_GL_PROGRAM_NATIVE_PARAMETERS, - GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 }, - { GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 }, - { GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_TEX_INSTRUCTIONS, 1 }, - { GLITZ_GL_PROGRAM_TEX_INDIRECTIONS, - GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, 0 }, - { GLITZ_GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS, 0 }, - { GLITZ_GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS, - GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS, 0 }, - { GLITZ_GL_PROGRAM_NATIVE_TEX_INDIRECTIONS, - GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS, 0 }, + { GLITZ_GL_PROGRAM_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_INSTRUCTIONS, 1 }, + { GLITZ_GL_PROGRAM_NATIVE_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS, 1 }, + { GLITZ_GL_PROGRAM_PARAMETERS, + GLITZ_GL_MAX_PROGRAM_PARAMETERS, 1 }, + { GLITZ_GL_PROGRAM_NATIVE_PARAMETERS, + GLITZ_GL_MAX_PROGRAM_NATIVE_PARAMETERS, 1 }, + { GLITZ_GL_PROGRAM_ALU_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_ALU_INSTRUCTIONS, 0 }, + { GLITZ_GL_PROGRAM_TEX_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_TEX_INSTRUCTIONS, 1 }, + { GLITZ_GL_PROGRAM_TEX_INDIRECTIONS, + GLITZ_GL_MAX_PROGRAM_TEX_INDIRECTIONS, 0 }, + { GLITZ_GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS, 0 }, + { GLITZ_GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS, + GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS, 0 }, + { GLITZ_GL_PROGRAM_NATIVE_TEX_INDIRECTIONS, + GLITZ_GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS, 0 }, }; static glitz_bool_t _glitz_program_under_limits (glitz_gl_proc_address_list_t *gl) { - int i, n_limits; + int i, n_limits; - n_limits = sizeof (_program_limits) / (sizeof (struct _glitz_program_query)); + n_limits = sizeof (_program_limits) / + (sizeof (struct _glitz_program_query)); - for (i = 0; i < n_limits; i++) { - glitz_gl_int_t value, max; + for (i = 0; i < n_limits; i++) { + glitz_gl_int_t value, max; - gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, - _program_limits[i].query, &value); - gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, - _program_limits[i].max_query, &max); + gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, + _program_limits[i].query, &value); + gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, + _program_limits[i].max_query, &max); - if (value < _program_limits[i].min) - return 0; - - if (value >= max) - return 0; - } + if (value < _program_limits[i].min) + return 0; - return 1; + if (value >= max) + return 0; + } + + return 1; } static glitz_gl_int_t _glitz_compile_arb_fragment_program (glitz_gl_proc_address_list_t *gl, - char *program_string, - int n_parameters) + char *program_string, + int n_parameters) { - glitz_gl_int_t error, pid = -1; - glitz_gl_uint_t program; + glitz_gl_int_t error, pid = -1; + glitz_gl_uint_t program; - /* clear error flags */ - while (gl->get_error () != GLITZ_GL_NO_ERROR); + /* clear error flags */ + while (gl->get_error () != GLITZ_GL_NO_ERROR); - gl->gen_programs (1, &program); - gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program); - gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM, - GLITZ_GL_PROGRAM_FORMAT_ASCII, - strlen (program_string), - program_string); - if (gl->get_error () == GLITZ_GL_NO_ERROR) { - gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error); - - if (error == -1) { - glitz_gl_int_t value; - - gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, - GLITZ_GL_PROGRAM_UNDER_NATIVE_LIMITS, - &value); - - if (value == GLITZ_GL_TRUE) { - gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, - GLITZ_GL_MAX_PROGRAM_LOCAL_PARAMETERS, - &value); - - if (value >= n_parameters) { - if (_glitz_program_under_limits (gl)) - pid = program; - } - } + gl->gen_programs (1, &program); + gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, program); + gl->program_string (GLITZ_GL_FRAGMENT_PROGRAM, + GLITZ_GL_PROGRAM_FORMAT_ASCII, + strlen (program_string), + program_string); + if (gl->get_error () == GLITZ_GL_NO_ERROR) { + gl->get_integer_v (GLITZ_GL_PROGRAM_ERROR_POSITION, &error); + + if (error == -1) { + glitz_gl_int_t value; + + gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, + GLITZ_GL_PROGRAM_UNDER_NATIVE_LIMITS, + &value); + + if (value == GLITZ_GL_TRUE) { + gl->get_program_iv (GLITZ_GL_FRAGMENT_PROGRAM, + GLITZ_GL_MAX_PROGRAM_LOCAL_PARAMETERS, + &value); + + if (value >= n_parameters) { + if (_glitz_program_under_limits (gl)) + pid = program; + } + } + } } - } - - if (pid == -1) { - gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); - gl->delete_programs (1, &program); - } - - return pid; + + if (pid == -1) { + gl->bind_program (GLITZ_GL_FRAGMENT_PROGRAM, 0); + gl->delete_programs (1, &program); + } + + return pid; } static void _string_array_to_char_array (char *dst, const char *src[]) { - int i, n; - - for (i = 0; src[i]; i++) { - n = strlen (src[i]); - memcpy (dst, src[i], n); - dst += n; - } - *dst = '\0'; + int i, n; + + for (i = 0; src[i]; i++) { + n = strlen (src[i]); + memcpy (dst, src[i], n); + dst += n; + } + *dst = '\0'; } /* these should be more than enough */ @@ -388,231 +389,234 @@ _string_array_to_char_array (char *dst, const char *src[]) static glitz_gl_uint_t _glitz_create_fragment_program (glitz_composite_op_t *op, - int fp_type, - int id, - const glitz_program_expand_t *expand) + int fp_type, + int id, + const glitz_program_expand_t *expand) { - char buffer[1024], *program = NULL, *tex, *p = NULL; - char *texture_type, *extra_declarations; - const glitz_in_op_t *in; - glitz_gl_uint_t fp; - int i; + char buffer[1024], *program = NULL, *tex, *p = NULL; + char *texture_type, *extra_declarations; + const glitz_in_op_t *in; + glitz_gl_uint_t fp; + int i; - switch (op->type) { - case GLITZ_COMBINE_TYPE_ARGBF: - case GLITZ_COMBINE_TYPE_ARGBF_SOLID: - case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC: - i = 0; - tex = "0"; - break; - case GLITZ_COMBINE_TYPE_ARGB_ARGBF: - case GLITZ_COMBINE_TYPE_SOLID_ARGBF: - i = 1; - tex = "0"; - break; - case GLITZ_COMBINE_TYPE_ARGBF_ARGB: - case GLITZ_COMBINE_TYPE_ARGBF_ARGBC: - i = 0; - tex = "1"; - break; - default: - return 0; - } + switch (op->type) { + case GLITZ_COMBINE_TYPE_ARGBF: + case GLITZ_COMBINE_TYPE_ARGBF_SOLID: + case GLITZ_COMBINE_TYPE_ARGBF_SOLIDC: + i = 0; + tex = "0"; + break; + case GLITZ_COMBINE_TYPE_ARGB_ARGBF: + case GLITZ_COMBINE_TYPE_SOLID_ARGBF: + i = 1; + tex = "0"; + break; + case GLITZ_COMBINE_TYPE_ARGBF_ARGB: + case GLITZ_COMBINE_TYPE_ARGBF_ARGBC: + i = 0; + tex = "1"; + break; + default: + return 0; + } - texture_type = expand[i].texture; - extra_declarations = expand[i].declarations; - in = &expand[i].in; + texture_type = expand[i].texture; + extra_declarations = expand[i].declarations; + in = &expand[i].in; - switch (fp_type) { - case GLITZ_FP_CONVOLUTION: - program = malloc (CONVOLUTION_BASE_SIZE + CONVOLUTION_SAMPLE_SIZE * id); - if (program == NULL) - return 0; - - p = program; - - p += sprintf (p, "!!ARBfp1.0"); - - _string_array_to_char_array (buffer, _convolution_header); - p += sprintf (p, buffer, id, id - 1, tex, extra_declarations); - - _string_array_to_char_array (buffer, _convolution_sample_first); - p += sprintf (p, buffer, tex, texture_type); - - _string_array_to_char_array (buffer, _convolution_sample); - for (i = 1; i < id; i++) - p += sprintf (p, buffer, i, i, tex, texture_type, i); - - break; - case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT: - case GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT: - id += 2; - /* fall-through */ - case GLITZ_FP_LINEAR_GRADIENT_NEAREST: - case GLITZ_FP_LINEAR_GRADIENT_REPEAT: - case GLITZ_FP_LINEAR_GRADIENT_REFLECT: - case GLITZ_FP_RADIAL_GRADIENT_NEAREST: - case GLITZ_FP_RADIAL_GRADIENT_REPEAT: - case GLITZ_FP_RADIAL_GRADIENT_REFLECT: - program = malloc (GRADIENT_BASE_SIZE + GRADIENT_STOP_SIZE * id); - if (program == NULL) - return 0; - - p = program; - - p += sprintf (p, "!!ARBfp1.0"); - - _string_array_to_char_array (buffer, _gradient_header); - p += sprintf (p, buffer, id, id, tex, extra_declarations); - switch (fp_type) { + case GLITZ_FP_CONVOLUTION: + program = malloc (CONVOLUTION_BASE_SIZE + + CONVOLUTION_SAMPLE_SIZE * id); + if (program == NULL) + return 0; + + p = program; + + p += sprintf (p, "!!ARBfp1.0"); + + _string_array_to_char_array (buffer, _convolution_header); + p += sprintf (p, buffer, id, id - 1, tex, extra_declarations); + + _string_array_to_char_array (buffer, _convolution_sample_first); + p += sprintf (p, buffer, tex, texture_type); + + _string_array_to_char_array (buffer, _convolution_sample); + for (i = 1; i < id; i++) + p += sprintf (p, buffer, i, i, tex, texture_type, i); + + break; case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT: + case GLITZ_FP_RADIAL_GRADIENT_TRANSPARENT: + id += 2; + /* fall-through */ case GLITZ_FP_LINEAR_GRADIENT_NEAREST: case GLITZ_FP_LINEAR_GRADIENT_REPEAT: case GLITZ_FP_LINEAR_GRADIENT_REFLECT: - _string_array_to_char_array (buffer, _linear_gradient_calculations); - break; - default: - _string_array_to_char_array (buffer, _radial_gradient_calculations); - break; - } - - p += sprintf (p, buffer); - - switch (fp_type) { - case GLITZ_FP_LINEAR_GRADIENT_REPEAT: + case GLITZ_FP_RADIAL_GRADIENT_NEAREST: case GLITZ_FP_RADIAL_GRADIENT_REPEAT: - _string_array_to_char_array (buffer, _gradient_fill_repeat); - p += sprintf (p, buffer); - break; - case GLITZ_FP_LINEAR_GRADIENT_REFLECT: case GLITZ_FP_RADIAL_GRADIENT_REFLECT: - _string_array_to_char_array (buffer, _gradient_fill_reflect); - p += sprintf (p, buffer); - break; + program = malloc (GRADIENT_BASE_SIZE + GRADIENT_STOP_SIZE * id); + if (program == NULL) + return 0; + + p = program; + + p += sprintf (p, "!!ARBfp1.0"); + + _string_array_to_char_array (buffer, _gradient_header); + p += sprintf (p, buffer, id, id, tex, extra_declarations); + + switch (fp_type) { + case GLITZ_FP_LINEAR_GRADIENT_TRANSPARENT: + case GLITZ_FP_LINEAR_GRADIENT_NEAREST: + case GLITZ_FP_LINEAR_GRADIENT_REPEAT: + case GLITZ_FP_LINEAR_GRADIENT_REFLECT: + _string_array_to_char_array (buffer, + _linear_gradient_calculations); + break; + default: + _string_array_to_char_array (buffer, + _radial_gradient_calculations); + break; + } + + p += sprintf (p, buffer); + + switch (fp_type) { + case GLITZ_FP_LINEAR_GRADIENT_REPEAT: + case GLITZ_FP_RADIAL_GRADIENT_REPEAT: + _string_array_to_char_array (buffer, _gradient_fill_repeat); + p += sprintf (p, buffer); + break; + case GLITZ_FP_LINEAR_GRADIENT_REFLECT: + case GLITZ_FP_RADIAL_GRADIENT_REFLECT: + _string_array_to_char_array (buffer, _gradient_fill_reflect); + p += sprintf (p, buffer); + break; + default: + break; + } + + _string_array_to_char_array (buffer, _gradient_init_stops); + p += sprintf (p, buffer, id - 1); + + _string_array_to_char_array (buffer, _gradient_lower_stop); + for (i = 1; i < (id - 1); i++) + p += sprintf (p, buffer, i, i); + + _string_array_to_char_array (buffer, _gradient_higher_stop); + for (i = 1; i < (id - 1); i++) + p += sprintf (p, buffer, id - i - 1, id - i - 1); + + _string_array_to_char_array (buffer, _gradient_fetch_and_interpolate); + p += sprintf (p, buffer, tex, texture_type, tex, texture_type); + + id++; + break; default: - break; + return 0; } - - _string_array_to_char_array (buffer, _gradient_init_stops); - p += sprintf (p, buffer, id - 1); - _string_array_to_char_array (buffer, _gradient_lower_stop); - for (i = 1; i < (id - 1); i++) - p += sprintf (p, buffer, i, i); - - _string_array_to_char_array (buffer, _gradient_higher_stop); - for (i = 1; i < (id - 1); i++) - p += sprintf (p, buffer, id - i - 1, id - i - 1); - - _string_array_to_char_array (buffer, _gradient_fetch_and_interpolate); - p += sprintf (p, buffer, tex, texture_type, tex, texture_type); - - id++; - break; - default: - return 0; - } + if (program == NULL) + return 0; - if (program == NULL) - return 0; - - p += sprintf (p, "%s", in->fetch); - if (op->per_component) - p += sprintf (p, "%s", in->dot_product); - p += sprintf (p, "%s", in->mult); - sprintf (p, "END"); + p += sprintf (p, "%s", in->fetch); + if (op->per_component) + p += sprintf (p, "%s", in->dot_product); + p += sprintf (p, "%s", in->mult); + sprintf (p, "END"); - fp = _glitz_compile_arb_fragment_program (op->gl, program, id); - - free (program); + fp = _glitz_compile_arb_fragment_program (op->gl, program, id); - return fp; + free (program); + + return fp; } - + void glitz_program_map_init (glitz_program_map_t *map) { - memset (map, 0, sizeof (glitz_program_map_t)); + memset (map, 0, sizeof (glitz_program_map_t)); } void glitz_program_map_fini (glitz_gl_proc_address_list_t *gl, - glitz_program_map_t *map) + glitz_program_map_t *map) { - glitz_gl_uint_t program; - int i, j, k, x, y; - - for (i = 0; i < GLITZ_COMBINE_TYPES; i++) { - for (j = 0; j < GLITZ_FP_TYPES; j++) { - for (x = 0; x < GLITZ_TEXTURE_LAST; x++) { - for (y = 0; y < GLITZ_TEXTURE_LAST; y++) { - glitz_program_t *p = &map->filters[i][j].fp[x][y]; - - if (p->name) { - for (k = 0; k < p->size; k++) - if (p->name[k] > 0) { - program = p->name[k]; - gl->delete_programs (1, &program); - } - - free (p->name); - } - } - } + glitz_gl_uint_t program; + int i, j, k, x, y; + + for (i = 0; i < GLITZ_COMBINE_TYPES; i++) { + for (j = 0; j < GLITZ_FP_TYPES; j++) { + for (x = 0; x < GLITZ_TEXTURE_LAST; x++) { + for (y = 0; y < GLITZ_TEXTURE_LAST; y++) { + glitz_program_t *p = &map->filters[i][j].fp[x][y]; + + if (p->name) { + for (k = 0; k < p->size; k++) + if (p->name[k] > 0) { + program = p->name[k]; + gl->delete_programs (1, &program); + } + + free (p->name); + } + } + } + } } - } } -#define TEXTURE_INDEX(surface) \ - ((surface)? \ - (((surface)->texture.target == GLITZ_GL_TEXTURE_2D)? \ - GLITZ_TEXTURE_2D: \ - GLITZ_TEXTURE_RECT \ - ) : \ - GLITZ_TEXTURE_NONE \ - ) +#define TEXTURE_INDEX(surface) \ + ((surface)? \ + (((surface)->texture.target == GLITZ_GL_TEXTURE_2D)? \ + GLITZ_TEXTURE_2D: \ + GLITZ_TEXTURE_RECT \ + ) : \ + GLITZ_TEXTURE_NONE \ + ) glitz_gl_uint_t glitz_get_fragment_program (glitz_composite_op_t *op, - int fp_type, - int id) + int fp_type, + int id) { - glitz_program_map_t *map; - glitz_program_t *program; - int t0 = TEXTURE_INDEX (op->src); - int t1 = TEXTURE_INDEX (op->mask); + glitz_program_map_t *map; + glitz_program_t *program; + int t0 = TEXTURE_INDEX (op->src); + int t1 = TEXTURE_INDEX (op->mask); - map = op->dst->drawable->backend->program_map; - program = &map->filters[op->type][fp_type].fp[t0][t1]; - - if (program->size < id) { - int old_size; - - program->name = realloc (program->name, - id * sizeof (glitz_gl_uint_t)); - if (program->name == NULL) { - glitz_surface_status_add (op->dst, GLITZ_STATUS_NO_MEMORY_MASK); - return 0; + map = op->dst->drawable->backend->program_map; + program = &map->filters[op->type][fp_type].fp[t0][t1]; + + if (program->size < id) { + int old_size; + + program->name = realloc (program->name, + id * sizeof (glitz_gl_uint_t)); + if (program->name == NULL) { + glitz_surface_status_add (op->dst, GLITZ_STATUS_NO_MEMORY_MASK); + return 0; + } + old_size = program->size; + program->size = id; + memset (program->name + old_size, 0, + (program->size - old_size) * sizeof (glitz_gl_uint_t)); } - old_size = program->size; - program->size = id; - memset (program->name + old_size, 0, - (program->size - old_size) * sizeof (glitz_gl_uint_t)); - } - - if (program->name[id - 1] == 0) { - glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT); - - program->name[id - 1] = - _glitz_create_fragment_program (op, fp_type, id, - _program_expand_map[t0][t1]); - - glitz_surface_pop_current (op->dst); - } - if (program->name[id - 1] > 0) - return program->name[id - 1]; - else - return 0; + if (program->name[id - 1] == 0) { + glitz_surface_push_current (op->dst, GLITZ_CONTEXT_CURRENT); + + program->name[id - 1] = + _glitz_create_fragment_program (op, fp_type, id, + _program_expand_map[t0][t1]); + + glitz_surface_pop_current (op->dst); + } + + if (program->name[id - 1] > 0) + return program->name[id - 1]; + else + return 0; } diff --git a/gfx/cairo/glitz/src/glitz_rect.c b/gfx/cairo/glitz/src/glitz_rect.c index 360c63538d3..d9f5c0447ae 100644 --- a/gfx/cairo/glitz/src/glitz_rect.c +++ b/gfx/cairo/glitz/src/glitz_rect.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -29,260 +29,259 @@ #include "glitzint.h" -#define STORE_16(dst, size, src) \ - dst = ((size) ? \ - ((((((1L << (size)) - 1L) * (src)) / 0xffff) * 0xffff) / \ - ((1L << (size)) - 1L)) : \ - dst) +#define STORE_16(dst, size, src) \ + dst = ((size) ? \ + ((((((1L << (size)) - 1L) * (src)) / 0xffff) * 0xffff) / \ + ((1L << (size)) - 1L)) : \ + dst) static glitz_buffer_t * _glitz_minimum_buffer (glitz_surface_t *surface, - const glitz_rectangle_t *rects, - int n_rects, - unsigned int *pixel) + const glitz_rectangle_t *rects, + int n_rects, + unsigned int *pixel) { glitz_buffer_t *buffer; int i, size = 0; unsigned int *data; - + while (n_rects--) { - i = rects->width * rects->height; - if (i > size) - size = i; - - rects++; + i = rects->width * rects->height; + if (i > size) + size = i; + + rects++; } if (size <= 1) - return glitz_buffer_create_for_data (pixel); - + return glitz_buffer_create_for_data (pixel); + buffer = glitz_pixel_buffer_create (surface->drawable, NULL, - size * sizeof (unsigned int), - GLITZ_BUFFER_HINT_STATIC_DRAW); + size * sizeof (unsigned int), + GLITZ_BUFFER_HINT_STATIC_DRAW); if (!buffer) - return NULL; - + return NULL; + data = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); - + while (size--) - *data++ = *pixel; + *data++ = *pixel; glitz_buffer_unmap (buffer); - + return buffer; } void glitz_set_rectangles (glitz_surface_t *dst, - const glitz_color_t *color, - const glitz_rectangle_t *rects, - int n_rects) + const glitz_color_t *color, + const glitz_rectangle_t *rects, + int n_rects) { GLITZ_GL_SURFACE (dst); if (n_rects < 1) - return; + return; if (SURFACE_SOLID (dst)) { - glitz_color_t old = dst->solid; - glitz_box_t *clip = dst->clip; - int n_clip = dst->n_clip; + glitz_color_t old = dst->solid; + glitz_box_t *clip = dst->clip; + int n_clip = dst->n_clip; - for (; n_clip; clip++, n_clip--) - { - if (clip->x1 > 0 || - clip->y1 > 0 || - clip->x2 < 1 || - clip->y2 < 1) - continue; - - for (; n_rects; rects++, n_rects--) - { - if (rects->x > 0 || - rects->y > 0 || - (rects->x + rects->width) < 1 || - (rects->y + rects->height) < 1) - continue; - - STORE_16 (dst->solid.red, - dst->format->color.red_size, - color->red); - STORE_16 (dst->solid.green, - dst->format->color.green_size, - color->green); - STORE_16 (dst->solid.blue, - dst->format->color.blue_size, - color->blue); - STORE_16 (dst->solid.alpha, - dst->format->color.alpha_size, - color->alpha); - - if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK) - { - dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; - glitz_surface_damage (dst, &dst->box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_DRAWABLE_MASK); - } - else - { - if (dst->solid.red != old.red || - dst->solid.green != old.green || - dst->solid.blue != old.blue || - dst->solid.alpha != old.alpha) - glitz_surface_damage (dst, &dst->box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_DRAWABLE_MASK); - } - break; - } - break; - } + for (; n_clip; clip++, n_clip--) + { + if (clip->x1 > 0 || + clip->y1 > 0 || + clip->x2 < 1 || + clip->y2 < 1) + continue; + + for (; n_rects; rects++, n_rects--) + { + if (rects->x > 0 || + rects->y > 0 || + (rects->x + rects->width) < 1 || + (rects->y + rects->height) < 1) + continue; + + STORE_16 (dst->solid.red, + dst->format->color.red_size, + color->red); + STORE_16 (dst->solid.green, + dst->format->color.green_size, + color->green); + STORE_16 (dst->solid.blue, + dst->format->color.blue_size, + color->blue); + STORE_16 (dst->solid.alpha, + dst->format->color.alpha_size, + color->alpha); + + if (dst->flags & GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK) + { + dst->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; + glitz_surface_damage (dst, &dst->box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_DRAWABLE_MASK); + } + else + { + if (dst->solid.red != old.red || + dst->solid.green != old.green || + dst->solid.blue != old.blue || + dst->solid.alpha != old.alpha) + glitz_surface_damage (dst, &dst->box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_DRAWABLE_MASK); + } + break; + } + break; + } } else { - static glitz_pixel_format_t pf = { - { - 32, - 0xff000000, - 0x00ff0000, - 0x0000ff00, - 0x000000ff - }, - 0, 0, 0, - GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP - }; - glitz_buffer_t *buffer = NULL; - glitz_box_t box; - glitz_bool_t drawable = 0; + static glitz_pixel_format_t pf = { + { + 32, + 0xff000000, + 0x00ff0000, + 0x0000ff00, + 0x000000ff + }, + 0, 0, 0, + GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP + }; + glitz_buffer_t *buffer = NULL; + glitz_box_t box; + glitz_bool_t drawable = 0; - if (n_rects == 1 && rects->width <= 1 && rects->height <= 1) - { - glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); - } - else - { - drawable = glitz_surface_push_current (dst, - GLITZ_DRAWABLE_CURRENT); - } + if (n_rects == 1 && rects->width <= 1 && rects->height <= 1) + { + glitz_surface_push_current (dst, GLITZ_ANY_CONTEXT_CURRENT); + } + else + { + drawable = glitz_surface_push_current (dst, + GLITZ_DRAWABLE_CURRENT); + } - if (drawable) - { - glitz_box_t *clip; - int n_clip; - int target_height = SURFACE_DRAWABLE_HEIGHT (dst); - - gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff, - color->green / (glitz_gl_clampf_t) 0xffff, - color->blue / (glitz_gl_clampf_t) 0xffff, - color->alpha / (glitz_gl_clampf_t) 0xffff); + if (drawable) + { + glitz_box_t *clip; + int n_clip; - while (n_rects--) - { - clip = dst->clip; - n_clip = dst->n_clip; - while (n_clip--) - { - box.x1 = clip->x1 + dst->x_clip; - box.y1 = clip->y1 + dst->y_clip; - box.x2 = clip->x2 + dst->x_clip; - box.y2 = clip->y2 + dst->y_clip; - - if (dst->box.x1 > box.x1) - box.x1 = dst->box.x1; - if (dst->box.y1 > box.y1) - box.y1 = dst->box.y1; - if (dst->box.x2 < box.x2) - box.x2 = dst->box.x2; - if (dst->box.y2 < box.y2) - box.y2 = dst->box.y2; - - if (rects->x > box.x1) - box.x1 = rects->x; - if (rects->y > box.y1) - box.y1 = rects->y; - if (rects->x + rects->width < box.x2) - box.x2 = rects->x + rects->width; - if (rects->y + rects->height < box.y2) - box.y2 = rects->y + rects->height; - - if (box.x1 < box.x2 && box.y1 < box.y2) - { - gl->scissor (box.x1, - target_height - dst->y - box.y2, - box.x2 - box.x1, - box.y2 - box.y1); - - gl->clear (GLITZ_GL_COLOR_BUFFER_BIT); - - glitz_surface_damage (dst, &box, - GLITZ_DAMAGE_TEXTURE_MASK | - GLITZ_DAMAGE_SOLID_MASK); - } - - clip++; - } - rects++; - } - } - else - { - unsigned int pixel = - ((((unsigned int) color->alpha * 0xff) / 0xffff) << 24) | - ((((unsigned int) color->red * 0xff) / 0xffff) << 16) | - ((((unsigned int) color->green * 0xff) / 0xffff) << 8) | - ((((unsigned int) color->blue * 0xff) / 0xffff)); - int x1, y1, x2, y2; + gl->clear_color (color->red / (glitz_gl_clampf_t) 0xffff, + color->green / (glitz_gl_clampf_t) 0xffff, + color->blue / (glitz_gl_clampf_t) 0xffff, + color->alpha / (glitz_gl_clampf_t) 0xffff); - buffer = _glitz_minimum_buffer (dst, rects, n_rects, &pixel); - if (!buffer) - { - glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); - return; - } + while (n_rects--) + { + clip = dst->clip; + n_clip = dst->n_clip; + while (n_clip--) + { + box.x1 = clip->x1 + dst->x_clip; + box.y1 = clip->y1 + dst->y_clip; + box.x2 = clip->x2 + dst->x_clip; + box.y2 = clip->y2 + dst->y_clip; - while (n_rects--) - { - x1 = rects->x; - y1 = rects->y; - x2 = x1 + rects->width; - y2 = y1 + rects->height; - - if (x1 < 0) - x1 = 0; - if (y1 < 0) - y1 = 0; - if (x2 > dst->box.x2) - x2 = dst->box.x2; - if (y2 > dst->box.y2) - y2 = dst->box.y2; + if (dst->box.x1 > box.x1) + box.x1 = dst->box.x1; + if (dst->box.y1 > box.y1) + box.y1 = dst->box.y1; + if (dst->box.x2 < box.x2) + box.x2 = dst->box.x2; + if (dst->box.y2 < box.y2) + box.y2 = dst->box.y2; - if (x1 < x2 && y1 < y2) - glitz_set_pixels (dst, - x1, y1, - x2 - x1, y2 - y1, - &pf, buffer); + if (rects->x > box.x1) + box.x1 = rects->x; + if (rects->y > box.y1) + box.y1 = rects->y; + if (rects->x + rects->width < box.x2) + box.x2 = rects->x + rects->width; + if (rects->y + rects->height < box.y2) + box.y2 = rects->y + rects->height; - rects++; - } - - if (buffer) - glitz_buffer_destroy (buffer); - } - glitz_surface_pop_current (dst); + if (box.x1 < box.x2 && box.y1 < box.y2) + { + gl->scissor (box.x1, + dst->attached->height - dst->y - box.y2, + box.x2 - box.x1, + box.y2 - box.y1); + + gl->clear (GLITZ_GL_COLOR_BUFFER_BIT); + + glitz_surface_damage (dst, &box, + GLITZ_DAMAGE_TEXTURE_MASK | + GLITZ_DAMAGE_SOLID_MASK); + } + + clip++; + } + rects++; + } + } + else + { + unsigned int pixel = + ((((unsigned int) color->alpha * 0xff) / 0xffff) << 24) | + ((((unsigned int) color->red * 0xff) / 0xffff) << 16) | + ((((unsigned int) color->green * 0xff) / 0xffff) << 8) | + ((((unsigned int) color->blue * 0xff) / 0xffff)); + int x1, y1, x2, y2; + + buffer = _glitz_minimum_buffer (dst, rects, n_rects, &pixel); + if (!buffer) + { + glitz_surface_status_add (dst, GLITZ_STATUS_NO_MEMORY_MASK); + return; + } + + while (n_rects--) + { + x1 = rects->x; + y1 = rects->y; + x2 = x1 + rects->width; + y2 = y1 + rects->height; + + if (x1 < 0) + x1 = 0; + if (y1 < 0) + y1 = 0; + if (x2 > dst->box.x2) + x2 = dst->box.x2; + if (y2 > dst->box.y2) + y2 = dst->box.y2; + + if (x1 < x2 && y1 < y2) + glitz_set_pixels (dst, + x1, y1, + x2 - x1, y2 - y1, + &pf, buffer); + + rects++; + } + + if (buffer) + glitz_buffer_destroy (buffer); + } + glitz_surface_pop_current (dst); } } slim_hidden_def(glitz_set_rectangles); void glitz_set_rectangle (glitz_surface_t *dst, - const glitz_color_t *color, - int x, - int y, - unsigned int width, - unsigned int height) + const glitz_color_t *color, + int x, + int y, + unsigned int width, + unsigned int height) { glitz_rectangle_t rect; diff --git a/gfx/cairo/glitz/src/glitz_region.c b/gfx/cairo/glitz/src/glitz_region.c index 88e7884ddeb..f853ef92b81 100644 --- a/gfx/cairo/glitz/src/glitz_region.c +++ b/gfx/cairo/glitz/src/glitz_region.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,41 +31,41 @@ #define REGION_ALLOC_CHUNK 16 -#define BOX_SUBSUMS_BOX(b1, b2) \ - ((b2)->x1 >= (b1)->x1 && \ - (b2)->x2 <= (b1)->x2 && \ - (b2)->y1 >= (b1)->y1 && \ - (b2)->y2 <= (b1)->y2) +#define BOX_SUBSUMS_BOX(b1, b2) \ + ((b2)->x1 >= (b1)->x1 && \ + (b2)->x2 <= (b1)->x2 && \ + (b2)->y1 >= (b1)->y1 && \ + (b2)->y2 <= (b1)->y2) -#define BOX_INTERSECTS_BOX(b1, b2) \ - ((b1)->x1 < (b2)->x2 && \ - (b1)->x2 > (b2)->x1 && \ - (b1)->y1 < (b2)->y2 && \ - (b1)->y2 > (b2)->y1) +#define BOX_INTERSECTS_BOX(b1, b2) \ + ((b1)->x1 < (b2)->x2 && \ + (b1)->x2 > (b2)->x1 && \ + (b1)->y1 < (b2)->y2 && \ + (b1)->y2 > (b2)->y1) -#define BOX_CLOSE_TO_BOX(b1, b2) \ - ((b1)->x1 < ((b2)->x2 + 1) && \ - (b1)->x2 > ((b2)->x1 - 1) && \ - (b1)->y1 < ((b2)->y2 + 1) && \ - (b1)->y2 > ((b2)->y1 - 1)) +#define BOX_CLOSE_TO_BOX(b1, b2) \ + ((b1)->x1 < ((b2)->x2 + 1) && \ + (b1)->x2 > ((b2)->x1 - 1) && \ + (b1)->y1 < ((b2)->y2 + 1) && \ + (b1)->y2 > ((b2)->y1 - 1)) -#define BOX_NEXT_TO_BOX(b1, b2) \ - ((((b1)->x1 == (b2)->x2 || \ - (b1)->x2 == (b2)->x1) && \ - (b1)->y1 == (b2)->y1 && \ - (b1)->y2 == (b2)->y2) || \ - (((b1)->y1 == (b2)->y2 || \ - (b1)->y2 == (b2)->y1) && \ - (b1)->x1 == (b2)->x1 && \ - (b1)->x2 == (b2)->x2)) +#define BOX_NEXT_TO_BOX(b1, b2) \ + ((((b1)->x1 == (b2)->x2 || \ + (b1)->x2 == (b2)->x1) && \ + (b1)->y1 == (b2)->y1 && \ + (b1)->y2 == (b2)->y2) || \ + (((b1)->y1 == (b2)->y2 || \ + (b1)->y2 == (b2)->y1) && \ + (b1)->x1 == (b2)->x1 && \ + (b1)->x2 == (b2)->x2)) -#define MERGE_BOXES(d, b1, b2) \ - { \ - (d)->x1 = MIN ((b1)->x1, (b2)->x1); \ - (d)->y1 = MIN ((b1)->y1, (b2)->y1); \ - (d)->x2 = MAX ((b1)->x2, (b2)->x2); \ - (d)->y2 = MAX ((b1)->y2, (b2)->y2); \ - } +#define MERGE_BOXES(d, b1, b2) \ + { \ + (d)->x1 = MIN ((b1)->x1, (b2)->x1); \ + (d)->y1 = MIN ((b1)->y1, (b2)->y1); \ + (d)->x2 = MAX ((b1)->x2, (b2)->x2); \ + (d)->y2 = MAX ((b1)->y2, (b2)->y2); \ + } /* * No real union, boxes that intersect are just joined into bigger boxes. @@ -74,93 +74,94 @@ */ glitz_status_t glitz_region_union (glitz_region_t *region, - glitz_box_t *ubox) -{ - if (region->n_box == 0) { - region->extents = *ubox; - region->box = ®ion->extents; - region->n_box = 1; + glitz_box_t *ubox) +{ + if (region->n_box == 0) { + region->extents = *ubox; + region->box = ®ion->extents; + region->n_box = 1; + + return GLITZ_STATUS_SUCCESS; + } + + if (BOX_CLOSE_TO_BOX (ubox, ®ion->extents)) { + glitz_box_t *box, *new_box, *dst_box; + int n_box; + + box = region->box; + n_box = region->n_box; + + while (n_box--) { + if (BOX_SUBSUMS_BOX (box, ubox)) + return GLITZ_STATUS_SUCCESS; + + box++; + } + + box = region->box; + n_box = region->n_box; + + new_box = ubox; + dst_box = NULL; + while (n_box--) { + + if (BOX_INTERSECTS_BOX (box, new_box) || + BOX_NEXT_TO_BOX (box, new_box)) { + + if (dst_box) { + /* + * Remove box from region + */ + region->n_box--; + if (region->n_box == 1) { + MERGE_BOXES (®ion->extents, box, new_box); + region->box = ®ion->extents; + + return GLITZ_STATUS_SUCCESS; + } else { + MERGE_BOXES (dst_box, box, new_box); + if (n_box) + memmove (box, box + 1, + n_box * sizeof (glitz_box_t)); + } + continue; + } else { + dst_box = box; + MERGE_BOXES (dst_box, box, new_box); + new_box = dst_box; + } + } + box++; + } + + if (dst_box) { + if (region->n_box > 1) + MERGE_BOXES (®ion->extents, ®ion->extents, ubox); + + return GLITZ_STATUS_SUCCESS; + } + } + + /* + * Add box to region + */ + if (region->size < (region->n_box + 1)) { + region->size += REGION_ALLOC_CHUNK; + region->data = (void *) realloc (region->data, + sizeof (glitz_box_t) * region->size); + if (!region->data) + return GLITZ_STATUS_NO_MEMORY; + } + + region->box = (glitz_box_t *) region->data; + + region->box[region->n_box] = *ubox; + if (region->n_box == 1) + region->box[0] = region->extents; + + region->n_box++; + + MERGE_BOXES (®ion->extents, ®ion->extents, ubox); return GLITZ_STATUS_SUCCESS; - } - - if (BOX_CLOSE_TO_BOX (ubox, ®ion->extents)) { - glitz_box_t *box, *new_box, *dst_box; - int n_box; - - box = region->box; - n_box = region->n_box; - - while (n_box--) { - if (BOX_SUBSUMS_BOX (box, ubox)) - return GLITZ_STATUS_SUCCESS; - - box++; - } - - box = region->box; - n_box = region->n_box; - - new_box = ubox; - dst_box = NULL; - while (n_box--) { - - if (BOX_INTERSECTS_BOX (box, new_box) || - BOX_NEXT_TO_BOX (box, new_box)) { - - if (dst_box) { - /* - * Remove box from region - */ - region->n_box--; - if (region->n_box == 1) { - MERGE_BOXES (®ion->extents, box, new_box); - region->box = ®ion->extents; - - return GLITZ_STATUS_SUCCESS; - } else { - MERGE_BOXES (dst_box, box, new_box); - if (n_box) - memmove (box, box + 1, n_box * sizeof (glitz_box_t)); - } - continue; - } else { - dst_box = box; - MERGE_BOXES (dst_box, box, new_box); - new_box = dst_box; - } - } - box++; - } - - if (dst_box) { - if (region->n_box > 1) - MERGE_BOXES (®ion->extents, ®ion->extents, ubox); - - return GLITZ_STATUS_SUCCESS; - } - } - - /* - * Add box to region - */ - if (region->size < (region->n_box + 1)) { - region->size += REGION_ALLOC_CHUNK; - region->data = (void *) realloc (region->data, - sizeof (glitz_box_t) * region->size); - if (!region->data) - return GLITZ_STATUS_NO_MEMORY; - } - - region->box = (glitz_box_t *) region->data; - - region->box[region->n_box] = *ubox; - if (region->n_box == 1) - region->box[0] = region->extents; - - region->n_box++; - - MERGE_BOXES (®ion->extents, ®ion->extents, ubox); - - return GLITZ_STATUS_SUCCESS; } diff --git a/gfx/cairo/glitz/src/glitz_status.c b/gfx/cairo/glitz/src/glitz_status.c index 2edcb08271f..8aa06cce686 100644 --- a/gfx/cairo/glitz/src/glitz_status.c +++ b/gfx/cairo/glitz/src/glitz_status.c @@ -34,57 +34,57 @@ unsigned long glitz_status_to_status_mask (glitz_status_t status) { - switch (status) { - case GLITZ_STATUS_NO_MEMORY: - return GLITZ_STATUS_NO_MEMORY_MASK; - case GLITZ_STATUS_BAD_COORDINATE: - return GLITZ_STATUS_BAD_COORDINATE_MASK; - case GLITZ_STATUS_NOT_SUPPORTED: - return GLITZ_STATUS_NOT_SUPPORTED_MASK; - case GLITZ_STATUS_CONTENT_DESTROYED: - return GLITZ_STATUS_CONTENT_DESTROYED_MASK; - case GLITZ_STATUS_SUCCESS: - break; - } - - return 0; + switch (status) { + case GLITZ_STATUS_NO_MEMORY: + return GLITZ_STATUS_NO_MEMORY_MASK; + case GLITZ_STATUS_BAD_COORDINATE: + return GLITZ_STATUS_BAD_COORDINATE_MASK; + case GLITZ_STATUS_NOT_SUPPORTED: + return GLITZ_STATUS_NOT_SUPPORTED_MASK; + case GLITZ_STATUS_CONTENT_DESTROYED: + return GLITZ_STATUS_CONTENT_DESTROYED_MASK; + case GLITZ_STATUS_SUCCESS: + break; + } + + return 0; } glitz_status_t glitz_status_pop_from_mask (unsigned long *mask) { - if (*mask & GLITZ_STATUS_NO_MEMORY_MASK) { - *mask &= ~GLITZ_STATUS_NO_MEMORY_MASK; - return GLITZ_STATUS_NO_MEMORY; - } else if (*mask & GLITZ_STATUS_BAD_COORDINATE_MASK) { - *mask &= ~GLITZ_STATUS_BAD_COORDINATE_MASK; - return GLITZ_STATUS_BAD_COORDINATE; - } else if (*mask & GLITZ_STATUS_NOT_SUPPORTED_MASK) { - *mask &= ~GLITZ_STATUS_NOT_SUPPORTED_MASK; - return GLITZ_STATUS_NOT_SUPPORTED; - } else if (*mask & GLITZ_STATUS_CONTENT_DESTROYED_MASK) { - *mask &= ~GLITZ_STATUS_CONTENT_DESTROYED_MASK; - return GLITZ_STATUS_CONTENT_DESTROYED; - } - - return GLITZ_STATUS_SUCCESS; + if (*mask & GLITZ_STATUS_NO_MEMORY_MASK) { + *mask &= ~GLITZ_STATUS_NO_MEMORY_MASK; + return GLITZ_STATUS_NO_MEMORY; + } else if (*mask & GLITZ_STATUS_BAD_COORDINATE_MASK) { + *mask &= ~GLITZ_STATUS_BAD_COORDINATE_MASK; + return GLITZ_STATUS_BAD_COORDINATE; + } else if (*mask & GLITZ_STATUS_NOT_SUPPORTED_MASK) { + *mask &= ~GLITZ_STATUS_NOT_SUPPORTED_MASK; + return GLITZ_STATUS_NOT_SUPPORTED; + } else if (*mask & GLITZ_STATUS_CONTENT_DESTROYED_MASK) { + *mask &= ~GLITZ_STATUS_CONTENT_DESTROYED_MASK; + return GLITZ_STATUS_CONTENT_DESTROYED; + } + + return GLITZ_STATUS_SUCCESS; } const char * glitz_status_string (glitz_status_t status) { - switch (status) { - case GLITZ_STATUS_SUCCESS: - return "success"; - case GLITZ_STATUS_NO_MEMORY: - return "out of memory"; - case GLITZ_STATUS_BAD_COORDINATE: - return "bad coordinate"; - case GLITZ_STATUS_NOT_SUPPORTED: - return "not supported"; - case GLITZ_STATUS_CONTENT_DESTROYED: - return "content destroyed"; - } + switch (status) { + case GLITZ_STATUS_SUCCESS: + return "success"; + case GLITZ_STATUS_NO_MEMORY: + return "out of memory"; + case GLITZ_STATUS_BAD_COORDINATE: + return "bad coordinate"; + case GLITZ_STATUS_NOT_SUPPORTED: + return "not supported"; + case GLITZ_STATUS_CONTENT_DESTROYED: + return "content destroyed"; + } - return ""; + return ""; } diff --git a/gfx/cairo/glitz/src/glitz_surface.c b/gfx/cairo/glitz/src/glitz_surface.c index eff07babb6b..23d30bbcc8e 100644 --- a/gfx/cairo/glitz/src/glitz_surface.c +++ b/gfx/cairo/glitz/src/glitz_surface.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -34,39 +34,39 @@ glitz_surface_t * glitz_surface_create (glitz_drawable_t *drawable, - glitz_format_t *format, - unsigned int width, - unsigned int height, - unsigned long mask, - glitz_surface_attributes_t *attributes) + glitz_format_t *format, + unsigned int width, + unsigned int height, + unsigned long mask, + glitz_surface_attributes_t *attributes) { glitz_surface_t *surface; glitz_bool_t unnormalized = 0; unsigned long feature_mask = drawable->backend->feature_mask; if (!width || !height) - return NULL; + return NULL; if (mask & GLITZ_SURFACE_UNNORMALIZED_MASK) { - if (attributes->unnormalized) - { - if (!(feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)) - return NULL; + if (attributes->unnormalized) + { + if (!(feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK)) + return NULL; - unnormalized = 1; - } + unnormalized = 1; + } } surface = (glitz_surface_t *) calloc (1, sizeof (glitz_surface_t)); if (surface == NULL) - return NULL; + return NULL; surface->drawable = drawable; glitz_drawable_reference (drawable); - + surface->ref_count = 1; - surface->filter = GLITZ_FILTER_NEAREST; + surface->filter = GLITZ_FILTER_NEAREST; surface->format = format; surface->box.x2 = (short) width; surface->box.y2 = (short) height; @@ -76,250 +76,256 @@ glitz_surface_create (glitz_drawable_t *drawable, if (width == 1 && height == 1) { - surface->flags |= GLITZ_SURFACE_FLAG_SOLID_MASK; - surface->solid.alpha = 0xffff; - - REGION_INIT (&surface->texture_damage, &surface->box); - REGION_INIT (&surface->drawable_damage, &surface->box); + surface->flags |= GLITZ_SURFACE_FLAG_SOLID_MASK; + surface->solid.alpha = 0xffff; + + REGION_INIT (&surface->texture_damage, &surface->box); + REGION_INIT (&surface->drawable_damage, &surface->box); } else { - REGION_INIT (&surface->texture_damage, NULL_BOX); - REGION_INIT (&surface->drawable_damage, NULL_BOX); + REGION_INIT (&surface->texture_damage, NULL_BOX); + REGION_INIT (&surface->drawable_damage, NULL_BOX); } - - glitz_texture_init (&surface->texture, width, height, - drawable->backend->texture_formats[format->id], - feature_mask, unnormalized); - glitz_framebuffer_init (&surface->framebuffer); - + glitz_texture_init (&surface->texture, width, height, + drawable->backend->texture_formats[format->id], + feature_mask, unnormalized); + if (width > 64 || height > 64) { - glitz_surface_push_current (surface, GLITZ_CONTEXT_CURRENT); - glitz_texture_size_check (&drawable->backend->gl, &surface->texture, - drawable->backend->max_texture_2d_size, - drawable->backend->max_texture_rect_size); - glitz_surface_pop_current (surface); - - if (TEXTURE_INVALID_SIZE (&surface->texture)) - { - glitz_surface_destroy (surface); - return NULL; - } + glitz_surface_push_current (surface, GLITZ_CONTEXT_CURRENT); + glitz_texture_size_check (drawable->backend->gl, &surface->texture, + drawable->backend->max_texture_2d_size, + drawable->backend->max_texture_rect_size); + glitz_surface_pop_current (surface); + + if (TEXTURE_INVALID_SIZE (&surface->texture)) + { + glitz_surface_destroy (surface); + return NULL; + } } - + return surface; } void glitz_surface_destroy (glitz_surface_t *surface) { - if (!surface) - return; + if (!surface) + return; - surface->ref_count--; - if (surface->ref_count) - return; + surface->ref_count--; + if (surface->ref_count) + return; - if (surface->texture.name) { - glitz_surface_push_current (surface, GLITZ_ANY_CONTEXT_CURRENT); + if (surface->attached) + { + surface->attached->backend->detach_notify (surface->attached, surface); + if (surface->attached->front == surface) + surface->attached->front = NULL; + else if (surface->attached->back == surface) + surface->attached->back = NULL; - glitz_framebuffer_fini (&surface->drawable->backend->gl, - &surface->framebuffer); - glitz_texture_fini (&surface->drawable->backend->gl, &surface->texture); - - glitz_surface_pop_current (surface); - } + glitz_drawable_destroy (surface->attached); + surface->attached = NULL; + } - REGION_UNINIT (&surface->texture_damage); - REGION_UNINIT (&surface->drawable_damage); - - if (surface->geometry.buffer) - glitz_buffer_destroy (surface->geometry.buffer); - - if (surface->geometry.array) - glitz_multi_array_destroy (surface->geometry.array); - - if (surface->transform) - free (surface->transform); - - if (surface->filter_params) - free (surface->filter_params); + if (surface->texture.name) { + glitz_surface_push_current (surface, GLITZ_ANY_CONTEXT_CURRENT); + glitz_texture_fini (surface->drawable->backend->gl, &surface->texture); + glitz_surface_pop_current (surface); + } - if (surface->attached) - glitz_drawable_destroy (surface->attached); - - glitz_drawable_destroy (surface->drawable); + REGION_UNINIT (&surface->texture_damage); + REGION_UNINIT (&surface->drawable_damage); - free (surface); + if (surface->geometry.buffer) + glitz_buffer_destroy (surface->geometry.buffer); + + if (surface->geometry.array) + glitz_multi_array_destroy (surface->geometry.array); + + if (surface->transform) + free (surface->transform); + + if (surface->filter_params) + free (surface->filter_params); + + glitz_drawable_destroy (surface->drawable); + + free (surface); } void glitz_surface_reference (glitz_surface_t *surface) { - if (surface == NULL) - return; + if (surface == NULL) + return; - surface->ref_count++; + surface->ref_count++; } -static void +void _glitz_surface_sync_texture (glitz_surface_t *surface) { if (REGION_NOTEMPTY (&surface->texture_damage)) { - glitz_box_t *box; - int n_box; - - GLITZ_GL_SURFACE (surface); - - if (!(TEXTURE_ALLOCATED (&surface->texture))) - glitz_texture_allocate (gl, &surface->texture); + glitz_box_t *box; + int n_box; - if (SURFACE_SOLID (surface) && (!SURFACE_SOLID_DAMAGE (surface))) - { - glitz_gl_float_t color[4]; - - if (TEXTURE_ALLOCATED (&surface->texture)) - { - color[0] = surface->solid.red / 65535.0f; - color[1] = surface->solid.green / 65535.0f; - color[2] = surface->solid.blue / 65535.0f; - color[3] = surface->solid.alpha / 65535.0f; - - glitz_texture_bind (gl, &surface->texture); - gl->tex_sub_image_2d (surface->texture.target, 0, - surface->texture.box.x1, - surface->texture.box.y1, - 1, 1, GLITZ_GL_RGBA, - GLITZ_GL_FLOAT, color); - glitz_texture_unbind (gl, &surface->texture); - } - REGION_EMPTY (&surface->texture_damage); - return; - } + GLITZ_GL_SURFACE (surface); - glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); - - gl->read_buffer (surface->buffer); - - gl->disable (GLITZ_GL_SCISSOR_TEST); - - glitz_texture_bind (gl, &surface->texture); - - box = REGION_RECTS (&surface->texture_damage); - n_box = REGION_NUM_RECTS (&surface->texture_damage); - - while (n_box--) - { - glitz_texture_copy_drawable (gl, - &surface->texture, - surface->attached, - box->x1 + surface->x, - box->y1 + surface->y, - box->x2 - box->x1, - box->y2 - box->y1, - box->x1, - box->y1); - - box++; - } + if (!(TEXTURE_ALLOCATED (&surface->texture))) + glitz_texture_allocate (gl, &surface->texture); - REGION_EMPTY (&surface->texture_damage); - - glitz_texture_unbind (gl, &surface->texture); - - gl->enable (GLITZ_GL_SCISSOR_TEST); - - glitz_surface_pop_current (surface); + if (SURFACE_SOLID (surface) && (!SURFACE_SOLID_DAMAGE (surface))) + { + glitz_gl_float_t color[4]; + + if (TEXTURE_ALLOCATED (&surface->texture)) + { + color[0] = surface->solid.red / 65535.0f; + color[1] = surface->solid.green / 65535.0f; + color[2] = surface->solid.blue / 65535.0f; + color[3] = surface->solid.alpha / 65535.0f; + + glitz_texture_bind (gl, &surface->texture); + gl->tex_sub_image_2d (surface->texture.target, 0, + surface->texture.box.x1, + surface->texture.box.y1, + 1, 1, GLITZ_GL_RGBA, + GLITZ_GL_FLOAT, color); + glitz_texture_unbind (gl, &surface->texture); + } + REGION_EMPTY (&surface->texture_damage); + return; + } + + glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); + + gl->read_buffer (surface->buffer); + + gl->disable (GLITZ_GL_SCISSOR_TEST); + + glitz_texture_bind (gl, &surface->texture); + + box = REGION_RECTS (&surface->texture_damage); + n_box = REGION_NUM_RECTS (&surface->texture_damage); + + while (n_box--) + { + glitz_texture_copy_drawable (gl, + &surface->texture, + surface->attached, + box->x1 + surface->x, + box->y1 + surface->y, + box->x2 - box->x1, + box->y2 - box->y1, + box->x1, + box->y1); + + box++; + } + + REGION_EMPTY (&surface->texture_damage); + + glitz_texture_unbind (gl, &surface->texture); + + gl->enable (GLITZ_GL_SCISSOR_TEST); + + glitz_surface_pop_current (surface); } } void glitz_surface_sync_drawable (glitz_surface_t *surface) -{ +{ if (REGION_NOTEMPTY (&surface->drawable_damage)) { - glitz_texture_t *texture; - glitz_box_t *box, *ext; - int n_box; - - GLITZ_GL_SURFACE (surface); - - texture = glitz_surface_get_texture (surface, 0); - if (!texture) - return; - - box = REGION_RECTS (&surface->drawable_damage); - ext = REGION_EXTENTS (&surface->drawable_damage); - n_box = REGION_NUM_RECTS (&surface->drawable_damage); - - glitz_texture_bind (gl, texture); - - glitz_texture_set_tex_gen (gl, texture, NULL, - 0, 0, - GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK, - NULL); - - gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, - GLITZ_GL_REPLACE); - gl->color_4us (0x0, 0x0, 0x0, 0xffff); - - glitz_texture_ensure_wrap (gl, texture, GLITZ_GL_CLAMP_TO_EDGE); - glitz_texture_ensure_filter (gl, texture, GLITZ_GL_NEAREST); - - glitz_set_operator (gl, GLITZ_OPERATOR_SRC); - - gl->scissor (surface->x + ext->x1, - surface->attached->height - surface->y - ext->y2, - ext->x2 - ext->x1, - ext->y2 - ext->y1); + glitz_texture_t *texture; + glitz_texture_parameters_t param; + glitz_box_t *box, *ext; + int n_box; - if (n_box > 1) - { - glitz_float_t *data; - void *ptr; - int vertices; - - ptr = malloc (n_box * 8 * sizeof (glitz_float_t)); - if (!ptr) { - glitz_surface_status_add (surface, - GLITZ_STATUS_NO_MEMORY_MASK); - return; - } - - data = (glitz_float_t *) ptr; - vertices = n_box << 2; - - while (n_box--) - { - *data++ = (glitz_float_t) box->x1; - *data++ = (glitz_float_t) box->y1; - *data++ = (glitz_float_t) box->x2; - *data++ = (glitz_float_t) box->y1; - *data++ = (glitz_float_t) box->x2; - *data++ = (glitz_float_t) box->y2; - *data++ = (glitz_float_t) box->x1; - *data++ = (glitz_float_t) box->y2; - - box++; - } + GLITZ_GL_SURFACE (surface); - gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, ptr); - gl->draw_arrays (GLITZ_GL_QUADS, 0, vertices); - - free (ptr); - } - else - { - glitz_geometry_enable_none (gl, surface, ext); - gl->draw_arrays (GLITZ_GL_QUADS, 0, 4); - } + texture = glitz_surface_get_texture (surface, 0); + if (!texture) + return; - glitz_texture_unbind (gl, texture); - - REGION_EMPTY (&surface->drawable_damage); + box = REGION_RECTS (&surface->drawable_damage); + ext = REGION_EXTENTS (&surface->drawable_damage); + n_box = REGION_NUM_RECTS (&surface->drawable_damage); + + glitz_texture_bind (gl, texture); + + glitz_texture_set_tex_gen (gl, texture, NULL, + 0, 0, + GLITZ_SURFACE_FLAGS_GEN_COORDS_MASK, + NULL); + + gl->tex_env_f (GLITZ_GL_TEXTURE_ENV, GLITZ_GL_TEXTURE_ENV_MODE, + GLITZ_GL_REPLACE); + gl->color_4us (0x0, 0x0, 0x0, 0xffff); + + param.filter[0] = param.filter[1] = GLITZ_GL_CLAMP_TO_EDGE; + param.wrap[0] = param.wrap[1] = GLITZ_GL_NEAREST; + + glitz_texture_ensure_parameters (gl, texture, ¶m); + + glitz_set_operator (gl, GLITZ_OPERATOR_SRC); + + gl->scissor (surface->x + ext->x1, + surface->attached->height - surface->y - ext->y2, + ext->x2 - ext->x1, + ext->y2 - ext->y1); + + if (n_box > 1) + { + glitz_float_t *data; + void *ptr; + int vertices; + + ptr = malloc (n_box * 8 * sizeof (glitz_float_t)); + if (!ptr) { + glitz_surface_status_add (surface, + GLITZ_STATUS_NO_MEMORY_MASK); + return; + } + + data = (glitz_float_t *) ptr; + vertices = n_box << 2; + + while (n_box--) + { + *data++ = (glitz_float_t) box->x1; + *data++ = (glitz_float_t) box->y1; + *data++ = (glitz_float_t) box->x2; + *data++ = (glitz_float_t) box->y1; + *data++ = (glitz_float_t) box->x2; + *data++ = (glitz_float_t) box->y2; + *data++ = (glitz_float_t) box->x1; + *data++ = (glitz_float_t) box->y2; + + box++; + } + + gl->vertex_pointer (2, GLITZ_GL_FLOAT, 0, ptr); + gl->draw_arrays (GLITZ_GL_QUADS, 0, vertices); + + free (ptr); + } + else + { + glitz_geometry_enable_none (gl, surface, ext); + gl->draw_arrays (GLITZ_GL_QUADS, 0, 4); + } + + glitz_texture_unbind (gl, texture); + + REGION_EMPTY (&surface->drawable_damage); } } @@ -328,93 +334,96 @@ glitz_surface_sync_solid (glitz_surface_t *surface) { if (SURFACE_SOLID_DAMAGE (surface)) { - glitz_gl_float_t *c, color[64]; - glitz_texture_t *texture; - - GLITZ_GL_SURFACE (surface); - - texture = glitz_surface_get_texture (surface, 0); - - c = &color[(texture->box.y1 * texture->width + texture->box.x1) * 4]; - if (texture) - { - glitz_texture_bind (gl, texture); - gl->get_tex_image (texture->target, 0, - GLITZ_GL_RGBA, GLITZ_GL_FLOAT, color); - glitz_texture_unbind (gl, texture); - } - else - { - c[0] = c[1] = c[2] = 0.0f; - c[3] = 1.0f; - } - - surface->solid.red = c[0] * 65535.0f; - surface->solid.green = c[1] * 65535.0f; - surface->solid.blue = c[2] * 65535.0f; - surface->solid.alpha = c[3] * 65535.0f; + glitz_gl_float_t *c, color[64]; + glitz_texture_t *texture; - surface->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; + GLITZ_GL_SURFACE (surface); + + texture = glitz_surface_get_texture (surface, 0); + + c = &color[(texture->box.y1 * texture->width + texture->box.x1) * 4]; + if (texture) + { + glitz_texture_bind (gl, texture); + gl->get_tex_image (texture->target, 0, + GLITZ_GL_RGBA, GLITZ_GL_FLOAT, color); + glitz_texture_unbind (gl, texture); + } + else + { + c[0] = c[1] = c[2] = 0.0f; + c[3] = 1.0f; + } + + surface->solid.red = c[0] * 65535.0f; + surface->solid.green = c[1] * 65535.0f; + surface->solid.blue = c[2] * 65535.0f; + surface->solid.alpha = c[3] * 65535.0f; + + surface->flags &= ~GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; } } glitz_texture_t * glitz_surface_get_texture (glitz_surface_t *surface, - glitz_bool_t allocate) + glitz_bool_t allocate) { GLITZ_GL_SURFACE (surface); if (REGION_NOTEMPTY (&surface->texture_damage)) { - _glitz_surface_sync_texture (surface); + _glitz_surface_sync_texture (surface); } else if (allocate) { - if (!(TEXTURE_ALLOCATED (&surface->texture))) - glitz_texture_allocate (gl, &surface->texture); + if (!(TEXTURE_ALLOCATED (&surface->texture))) + glitz_texture_allocate (gl, &surface->texture); } - + if (TEXTURE_ALLOCATED (&surface->texture)) - return &surface->texture; - + return &surface->texture; + return NULL; } void glitz_surface_damage (glitz_surface_t *surface, - glitz_box_t *box, - int what) + glitz_box_t *box, + int what) { - if (box) + if (surface->attached && !DRAWABLE_IS_FBO (surface->attached)) { - if (what & GLITZ_DAMAGE_DRAWABLE_MASK) - REGION_UNION (&surface->drawable_damage, box); + if (box) + { + if (what & GLITZ_DAMAGE_DRAWABLE_MASK) + REGION_UNION (&surface->drawable_damage, box); - if (surface->attached && (what & GLITZ_DAMAGE_TEXTURE_MASK)) - REGION_UNION (&surface->texture_damage, box); + if (surface->attached && (what & GLITZ_DAMAGE_TEXTURE_MASK)) + REGION_UNION (&surface->texture_damage, box); + } + else + { + if (what & GLITZ_DAMAGE_DRAWABLE_MASK) + { + REGION_EMPTY (&surface->drawable_damage); + REGION_INIT (&surface->drawable_damage, &surface->box); + } + + if (surface->attached && (what & GLITZ_DAMAGE_TEXTURE_MASK)) + { + REGION_EMPTY (&surface->texture_damage); + REGION_INIT (&surface->texture_damage, &surface->box); + } + } } - else - { - if (what & GLITZ_DAMAGE_DRAWABLE_MASK) - { - REGION_EMPTY (&surface->drawable_damage); - REGION_INIT (&surface->drawable_damage, &surface->box); - } - - if (surface->attached && (what & GLITZ_DAMAGE_TEXTURE_MASK)) - { - REGION_EMPTY (&surface->texture_damage); - REGION_INIT (&surface->texture_damage, &surface->box); - } - } - + if (what & GLITZ_DAMAGE_SOLID_MASK) - surface->flags |= GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_SOLID_DAMAGE_MASK; } void glitz_surface_status_add (glitz_surface_t *surface, - int flags) + int flags) { surface->status_mask |= flags; } @@ -424,108 +433,142 @@ _glitz_surface_update_state (glitz_surface_t *surface) { glitz_drawable_t *drawable; int width, height; - + GLITZ_GL_SURFACE (surface); - if (surface->attached) - { - drawable = surface->attached; - width = drawable->width; - height = drawable->height; - } - else - { - drawable = surface->drawable; - width = surface->texture.width; - height = surface->texture.height; - } - + drawable = surface->attached; + width = drawable->width; + height = drawable->height; + if (drawable->update_all || - drawable->viewport.x != surface->x || - drawable->viewport.y != surface->y || - drawable->viewport.width != surface->box.x2 || - drawable->viewport.height != surface->box.y2) + drawable->viewport.x != surface->x || + drawable->viewport.y != surface->y || + drawable->viewport.width != surface->box.x2 || + drawable->viewport.height != surface->box.y2) { - gl->viewport (surface->x, - height - surface->y - surface->box.y2, - surface->box.x2, - surface->box.y2); - gl->matrix_mode (GLITZ_GL_PROJECTION); - gl->load_identity (); - gl->ortho (0.0, - surface->box.x2, - height - surface->box.y2, - height, - -1.0, 1.0); - gl->matrix_mode (GLITZ_GL_MODELVIEW); - gl->load_identity (); - gl->scale_f (1.0f, -1.0f, 1.0f); - gl->translate_f (0.0f, -height, 0.0f); - - drawable->viewport.x = surface->x; - drawable->viewport.y = surface->y; - drawable->viewport.width = surface->box.x2; - drawable->viewport.height = surface->box.y2; - - drawable->update_all = 0; + gl->viewport (surface->x, + height - surface->y - surface->box.y2, + surface->box.x2, + surface->box.y2); + gl->matrix_mode (GLITZ_GL_PROJECTION); + gl->load_identity (); + gl->ortho (0.0, + surface->box.x2, + height - surface->box.y2, + height, + -1.0, 1.0); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + gl->load_identity (); + gl->scale_f (1.0f, -1.0f, 1.0f); + gl->translate_f (0.0f, -height, 0.0f); + + drawable->viewport.x = surface->x; + drawable->viewport.y = surface->y; + drawable->viewport.width = surface->box.x2; + drawable->viewport.height = surface->box.y2; + + drawable->update_all = 0; } - + gl->draw_buffer (surface->buffer); if (SURFACE_DITHER (surface)) - gl->enable (GLITZ_GL_DITHER); + gl->enable (GLITZ_GL_DITHER); else - gl->disable (GLITZ_GL_DITHER); + gl->disable (GLITZ_GL_DITHER); } void glitz_surface_attach (glitz_surface_t *surface, - glitz_drawable_t *drawable, - glitz_drawable_buffer_t buffer, - int x, - int y) + glitz_drawable_t *drawable, + glitz_drawable_buffer_t buffer) { - glitz_drawable_reference (drawable); + if (drawable) + { + if (buffer == GLITZ_DRAWABLE_BUFFER_FRONT_COLOR) + { + if (surface == drawable->front) + return; - if (surface->attached) - glitz_drawable_destroy (surface->attached); - - surface->attached = drawable; - surface->x = x; - surface->y = y; + if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR) + drawable = NULL; - switch (buffer) { - case GLITZ_DRAWABLE_BUFFER_FRONT_COLOR: - surface->buffer = GLITZ_GL_FRONT; - break; - case GLITZ_DRAWABLE_BUFFER_BACK_COLOR: - surface->buffer = GLITZ_GL_BACK; - break; + if (drawable) + { + glitz_drawable_reference (drawable); + if (drawable->front) + glitz_surface_detach (drawable->front); + + drawable->front = surface; + } + + surface->buffer = GLITZ_GL_FRONT; + } + else if ((buffer == GLITZ_DRAWABLE_BUFFER_BACK_COLOR) && + drawable->format->d.doublebuffer) + { + if (surface == drawable->back) + return; + + if (surface->format->type != GLITZ_FORMAT_TYPE_COLOR) + drawable = NULL; + + if (drawable) + { + glitz_drawable_reference (drawable); + if (drawable->back) + glitz_surface_detach (drawable->back); + + drawable->back = surface; + } + + surface->buffer = GLITZ_GL_BACK; + } + else + drawable = NULL; } - if ((!SURFACE_SOLID (surface)) || SURFACE_SOLID_DAMAGE (surface)) - REGION_EMPTY (&surface->texture_damage); + if (surface->attached) + glitz_surface_detach (surface); + + surface->attached = drawable; + if (drawable) + { + surface->attached->backend->attach_notify (drawable, surface); + + if (TEXTURE_ALLOCATED (&surface->texture)) + glitz_surface_damage (surface, NULL, GLITZ_DAMAGE_DRAWABLE_MASK); + + if ((!SURFACE_SOLID (surface)) || SURFACE_SOLID_DAMAGE (surface)) + REGION_EMPTY (&surface->texture_damage); + } } void glitz_surface_detach (glitz_surface_t *surface) { if (!surface->attached) - return; + return; if (REGION_NOTEMPTY (&surface->texture_damage)) { - glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); - _glitz_surface_sync_texture (surface); - glitz_surface_pop_current (surface); + glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); + _glitz_surface_sync_texture (surface); + glitz_surface_pop_current (surface); } - - glitz_drawable_destroy (surface->attached); + + surface->attached->backend->detach_notify (surface->attached, surface); + + if (surface == surface->attached->front) + surface->attached->front = NULL; + + if (surface == surface->attached->back) + surface->attached->back = NULL; + + glitz_drawable_destroy (surface->attached); + surface->attached = NULL; - surface->buffer = GLITZ_GL_FRONT; - surface->x = 0; - surface->y = 0; - + REGION_EMPTY (&surface->drawable_damage); REGION_INIT (&surface->drawable_damage, &surface->box); } @@ -546,382 +589,391 @@ slim_hidden_def(glitz_surface_get_attached_drawable); glitz_bool_t glitz_surface_push_current (glitz_surface_t *surface, - glitz_constraint_t constraint) + glitz_constraint_t constraint) { - if (surface->attached) - { - surface->attached->backend->push_current (surface->attached, - surface, - constraint); - if (constraint == GLITZ_DRAWABLE_CURRENT) - { - if (surface->attached->backend->feature_mask & - GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) - glitz_framebuffer_unbind (&surface->attached->backend->gl); - - _glitz_surface_update_state (surface); - glitz_surface_sync_drawable (surface); - } - } - else - { - surface->drawable->backend->push_current (surface->drawable, - surface, - constraint); - if (constraint == GLITZ_DRAWABLE_CURRENT) - { - if (surface->drawable->backend->feature_mask & - GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) - { - if (glitz_framebuffer_complete (&surface->drawable->backend->gl, - &surface->framebuffer, - &surface->texture)) - { - _glitz_surface_update_state (surface); - return 1; - } - } + glitz_drawable_t *drawable; - return 0; - } - } - - return 1; + if (surface->attached) + { + drawable = surface->attached; + if (drawable->backend->push_current (drawable, surface, + constraint)) + { + if (constraint == GLITZ_DRAWABLE_CURRENT) + { + if (drawable->backend->feature_mask & + GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) + { + if (!surface->fb) + { + GLITZ_GL_DRAWABLE (drawable); + + gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, 0); + + _glitz_surface_update_state (surface); + glitz_surface_sync_drawable (surface); + } + else + { + _glitz_surface_update_state (surface); + } + } + else + { + _glitz_surface_update_state (surface); + glitz_surface_sync_drawable (surface); + } + } + + return 1; + } + + return 0; + } + else + { + drawable = surface->drawable; + + if (constraint == GLITZ_DRAWABLE_CURRENT) + { + drawable->backend->push_current (drawable, surface, + GLITZ_ANY_CONTEXT_CURRENT); + } + else + { + return drawable->backend->push_current (drawable, surface, + constraint); + } + } + + return 0; } void glitz_surface_pop_current (glitz_surface_t *surface) { - glitz_surface_t *other; - - if (surface->attached) { - other = surface->attached->backend->pop_current (surface->attached); - } else { - if (surface->framebuffer.name) - glitz_framebuffer_unbind (&surface->drawable->backend->gl); - - other = surface->drawable->backend->pop_current (surface->drawable); - } + glitz_drawable_t *drawable; + glitz_surface_t *other; - if (other) { - if ((!other->attached) && - (other->drawable->backend->feature_mask & - GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK)) + drawable = (surface->attached) ? surface->attached : surface->drawable; + + other = drawable->backend->pop_current (drawable); + if (other) { - glitz_framebuffer_complete (&other->drawable->backend->gl, - &other->framebuffer, - &other->texture); + if (other->fb) + drawable->backend->gl->bind_framebuffer (GLITZ_GL_FRAMEBUFFER, + other->fb); + + _glitz_surface_update_state (other); } - _glitz_surface_update_state (other); - } } void glitz_surface_set_transform (glitz_surface_t *surface, - glitz_transform_t *transform) + glitz_transform_t *transform) { - static glitz_transform_t identity = { - { - { FIXED1, 0x00000, 0x00000 }, - { 0x00000, FIXED1, 0x00000 }, - { 0x00000, 0x00000, FIXED1 } + static glitz_transform_t identity = { + { + { FIXED1, 0x00000, 0x00000 }, + { 0x00000, FIXED1, 0x00000 }, + { 0x00000, 0x00000, FIXED1 } + } + }; + + if (transform && + memcmp (transform, &identity, sizeof (glitz_transform_t)) == 0) + transform = NULL; + + if (transform) { + glitz_gl_float_t height, *m, *t; + + if (!surface->transform) { + surface->transform = malloc (sizeof (glitz_matrix_t)); + if (surface->transform == NULL) { + glitz_surface_status_add (surface, + GLITZ_STATUS_NO_MEMORY_MASK); + return; + } + } + + m = surface->transform->m; + t = surface->transform->t; + + m[0] = FIXED_TO_FLOAT (transform->matrix[0][0]); + m[4] = FIXED_TO_FLOAT (transform->matrix[0][1]); + m[8] = 0.0f; + m[12] = FIXED_TO_FLOAT (transform->matrix[0][2]); + + m[1] = FIXED_TO_FLOAT (transform->matrix[1][0]); + m[5] = FIXED_TO_FLOAT (transform->matrix[1][1]); + m[9] = 0.0f; + m[13] = FIXED_TO_FLOAT (transform->matrix[1][2]); + + m[2] = 0.0f; + m[6] = 0.0f; + m[10] = 1.0f; + m[14] = 0.0f; + + m[3] = FIXED_TO_FLOAT (transform->matrix[2][0]); + m[7] = FIXED_TO_FLOAT (transform->matrix[2][1]); + m[11] = 0.0f; + m[15] = FIXED_TO_FLOAT (transform->matrix[2][2]); + + /* Projective transformation matrix conversion to normalized + texture coordinates seems to be working fine. However, it would be + good if someone could verify that this is actually a correct way for + doing this. + + We need to do this: + + scale (IDENTITY, 0, -1) + translate (IDENTITY, 0, -texture_height) + multiply (TEXTURE_MATRIX, IDENTITY, MATRIX) + scale (TEXTURE_MATRIX, 0, -1) + translate (TEXTURE_MATRIX, 0, -texture_height) + + the following code does it pretty efficiently. */ + + height = surface->texture.texcoord_height_unit * + (surface->texture.box.y2 - surface->texture.box.y1); + + t[0] = m[0]; + t[4] = m[4]; + t[8] = 0.0f; + t[12] = surface->texture.texcoord_width_unit * m[12]; + + t[3] = m[3] / surface->texture.texcoord_width_unit; + t[7] = m[7] / surface->texture.texcoord_height_unit; + t[11] = 0.0f; + t[15] = m[15]; + + t[1] = height * t[3] - m[1]; + t[5] = height * t[7] - m[5]; + t[9] = 0.0f; + t[13] = height * t[15] - surface->texture.texcoord_height_unit * m[13]; + + t[2] = 0.0f; + t[6] = 0.0f; + t[10] = 1.0f; + t[14] = 0.0f; + + /* scale y = -1 */ + t[4] = -t[4]; + t[5] = -t[5]; + t[7] = -t[7]; + + /* translate y = -texture_height */ + t[12] -= t[4] * height; + t[13] -= t[5] * height; + t[15] -= t[7] * height; + + /* Translate coordinates into texture. This only makes a difference + when GL_ARB_texture_border_clamp is missing as box.x1 and box.y1 are + otherwise always zero. This breaks projective transformations so + those wont work without GL_ARB_texture_border_clamp. */ + t[12] += surface->texture.texcoord_width_unit * + surface->texture.box.x1; + t[13] += surface->texture.texcoord_height_unit * + surface->texture.box.y1; + + surface->flags |= GLITZ_SURFACE_FLAG_TRANSFORM_MASK; + if (m[3] != 0.0f || m[7] != 0.0f || (m[15] != 1.0f && m[15] != -1.0f)) + surface->flags |= GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK; + } else { + if (surface->transform) + free (surface->transform); + + surface->transform = NULL; + surface->flags &= ~GLITZ_SURFACE_FLAG_TRANSFORM_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK; } - }; - - if (transform && - memcmp (transform, &identity, sizeof (glitz_transform_t)) == 0) - transform = NULL; - - if (transform) { - glitz_gl_float_t height, *m, *t; - - if (!surface->transform) { - surface->transform = malloc (sizeof (glitz_matrix_t)); - if (surface->transform == NULL) { - glitz_surface_status_add (surface, GLITZ_STATUS_NO_MEMORY_MASK); - return; - } - } - - m = surface->transform->m; - t = surface->transform->t; - - m[0] = FIXED_TO_FLOAT (transform->matrix[0][0]); - m[4] = FIXED_TO_FLOAT (transform->matrix[0][1]); - m[8] = 0.0f; - m[12] = FIXED_TO_FLOAT (transform->matrix[0][2]); - - m[1] = FIXED_TO_FLOAT (transform->matrix[1][0]); - m[5] = FIXED_TO_FLOAT (transform->matrix[1][1]); - m[9] = 0.0f; - m[13] = FIXED_TO_FLOAT (transform->matrix[1][2]); - - m[2] = 0.0f; - m[6] = 0.0f; - m[10] = 1.0f; - m[14] = 0.0f; - - m[3] = FIXED_TO_FLOAT (transform->matrix[2][0]); - m[7] = FIXED_TO_FLOAT (transform->matrix[2][1]); - m[11] = 0.0f; - m[15] = FIXED_TO_FLOAT (transform->matrix[2][2]); - - /* Projective transformation matrix conversion to normalized - texture coordinates seems to be working fine. However, it would be - good if someone could verify that this is actually a correct way for - doing this. - - We need to do this: - - scale (IDENTITY, 0, -1) - translate (IDENTITY, 0, -texture_height) - multiply (TEXTURE_MATRIX, IDENTITY, MATRIX) - scale (TEXTURE_MATRIX, 0, -1) - translate (TEXTURE_MATRIX, 0, -texture_height) - - the following code does it pretty efficiently. */ - - height = surface->texture.texcoord_height_unit * - (surface->texture.box.y2 - surface->texture.box.y1); - - t[0] = m[0]; - t[4] = m[4]; - t[8] = 0.0f; - t[12] = surface->texture.texcoord_width_unit * m[12]; - - t[3] = m[3] / surface->texture.texcoord_width_unit; - t[7] = m[7] / surface->texture.texcoord_height_unit; - t[11] = 0.0f; - t[15] = m[15]; - - t[1] = height * t[3] - m[1]; - t[5] = height * t[7] - m[5]; - t[9] = 0.0f; - t[13] = height * t[15] - surface->texture.texcoord_height_unit * m[13]; - - t[2] = 0.0f; - t[6] = 0.0f; - t[10] = 1.0f; - t[14] = 0.0f; - - /* scale y = -1 */ - t[4] = -t[4]; - t[5] = -t[5]; - t[7] = -t[7]; - - /* translate y = -texture_height */ - t[12] -= t[4] * height; - t[13] -= t[5] * height; - t[15] -= t[7] * height; - - /* Translate coordinates into texture. This only makes a difference when - GL_ARB_texture_border_clamp is missing as box.x1 and box.y1 are - otherwise always zero. This breaks projective transformations so - those wont work without GL_ARB_texture_border_clamp. */ - t[12] += surface->texture.texcoord_width_unit * surface->texture.box.x1; - t[13] += surface->texture.texcoord_height_unit * surface->texture.box.y1; - - surface->flags |= GLITZ_SURFACE_FLAG_TRANSFORM_MASK; - if (m[3] != 0.0f || m[7] != 0.0f || (m[15] != 1.0f && m[15] != -1.0f)) - surface->flags |= GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK; - } else { - if (surface->transform) - free (surface->transform); - - surface->transform = NULL; - surface->flags &= ~GLITZ_SURFACE_FLAG_TRANSFORM_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK; - } } slim_hidden_def(glitz_surface_set_transform); void glitz_surface_set_fill (glitz_surface_t *surface, - glitz_fill_t fill) + glitz_fill_t fill) { - switch (fill) { - case GLITZ_FILL_TRANSPARENT: - surface->flags &= ~GLITZ_SURFACE_FLAG_REPEAT_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; - break; - case GLITZ_FILL_NEAREST: - surface->flags &= ~GLITZ_SURFACE_FLAG_REPEAT_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_PAD_MASK; - break; - case GLITZ_FILL_REPEAT: - surface->flags |= GLITZ_SURFACE_FLAG_REPEAT_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; - break; - case GLITZ_FILL_REFLECT: - surface->flags |= GLITZ_SURFACE_FLAG_REPEAT_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_MIRRORED_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; - break; - } + switch (fill) { + case GLITZ_FILL_TRANSPARENT: + surface->flags &= ~GLITZ_SURFACE_FLAG_REPEAT_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; + break; + case GLITZ_FILL_NEAREST: + surface->flags &= ~GLITZ_SURFACE_FLAG_REPEAT_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_PAD_MASK; + break; + case GLITZ_FILL_REPEAT: + surface->flags |= GLITZ_SURFACE_FLAG_REPEAT_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_MIRRORED_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; + break; + case GLITZ_FILL_REFLECT: + surface->flags |= GLITZ_SURFACE_FLAG_REPEAT_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_MIRRORED_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_PAD_MASK; + break; + } - glitz_filter_set_type (surface, surface->filter); + glitz_filter_set_type (surface, surface->filter); } slim_hidden_def(glitz_surface_set_fill); void glitz_surface_set_component_alpha (glitz_surface_t *surface, - glitz_bool_t component_alpha) + glitz_bool_t component_alpha) { - if (component_alpha && surface->format->color.red_size) - surface->flags |= GLITZ_SURFACE_FLAG_COMPONENT_ALPHA_MASK; - else - surface->flags &= ~GLITZ_SURFACE_FLAG_COMPONENT_ALPHA_MASK; + if (component_alpha && surface->format->color.red_size) + surface->flags |= GLITZ_SURFACE_FLAG_COMPONENT_ALPHA_MASK; + else + surface->flags &= ~GLITZ_SURFACE_FLAG_COMPONENT_ALPHA_MASK; } slim_hidden_def(glitz_surface_set_component_alpha); void glitz_surface_set_filter (glitz_surface_t *surface, - glitz_filter_t filter, - glitz_fixed16_16_t *params, - int n_params) + glitz_filter_t filter, + glitz_fixed16_16_t *params, + int n_params) { - glitz_status_t status; - - status = glitz_filter_set_params (surface, filter, params, n_params); - if (status) { - glitz_surface_status_add (surface, glitz_status_to_status_mask (status)); - } else { - switch (filter) { - case GLITZ_FILTER_NEAREST: - surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; - break; - case GLITZ_FILTER_BILINEAR: - surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; - break; - case GLITZ_FILTER_CONVOLUTION: - case GLITZ_FILTER_GAUSSIAN: - surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; - break; - case GLITZ_FILTER_LINEAR_GRADIENT: - case GLITZ_FILTER_RADIAL_GRADIENT: - surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; - surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; - surface->flags |= GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; - break; + glitz_status_t status; + + status = glitz_filter_set_params (surface, filter, params, n_params); + if (status) { + glitz_surface_status_add (surface, + glitz_status_to_status_mask (status)); + } else { + switch (filter) { + case GLITZ_FILTER_NEAREST: + surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; + break; + case GLITZ_FILTER_BILINEAR: + surface->flags &= ~GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; + break; + case GLITZ_FILTER_CONVOLUTION: + case GLITZ_FILTER_GAUSSIAN: + surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; + break; + case GLITZ_FILTER_LINEAR_GRADIENT: + case GLITZ_FILTER_RADIAL_GRADIENT: + surface->flags |= GLITZ_SURFACE_FLAG_FRAGMENT_FILTER_MASK; + surface->flags &= ~GLITZ_SURFACE_FLAG_LINEAR_TRANSFORM_FILTER_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_IGNORE_WRAP_MASK; + surface->flags |= GLITZ_SURFACE_FLAG_EYE_COORDS_MASK; + break; + } + surface->filter = filter; } - surface->filter = filter; - } } slim_hidden_def(glitz_surface_set_filter); void glitz_surface_set_dither (glitz_surface_t *surface, - glitz_bool_t dither) + glitz_bool_t dither) { - if (dither) - surface->flags |= GLITZ_SURFACE_FLAG_DITHER_MASK; - else - surface->flags &= ~GLITZ_SURFACE_FLAG_DITHER_MASK; + if (dither) + surface->flags |= GLITZ_SURFACE_FLAG_DITHER_MASK; + else + surface->flags &= ~GLITZ_SURFACE_FLAG_DITHER_MASK; } slim_hidden_def(glitz_surface_set_dither); void glitz_surface_flush (glitz_surface_t *surface) { - if (surface->attached && REGION_NOTEMPTY (&surface->drawable_damage)) { - glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); - glitz_surface_pop_current (surface); - } + if (!surface->attached) + return; + + if (!DRAWABLE_IS_FBO (surface->attached)) + { + if (REGION_NOTEMPTY (&surface->drawable_damage)) + { + glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); + glitz_surface_pop_current (surface); + } + } } slim_hidden_def(glitz_surface_flush); unsigned int glitz_surface_get_width (glitz_surface_t *surface) { - return (unsigned int) surface->box.x2; + return (unsigned int) surface->box.x2; } slim_hidden_def(glitz_surface_get_width); unsigned int glitz_surface_get_height (glitz_surface_t *surface) { - return (unsigned int) surface->box.y2; + return (unsigned int) surface->box.y2; } slim_hidden_def(glitz_surface_get_height); glitz_status_t glitz_surface_get_status (glitz_surface_t *surface) { - return glitz_status_pop_from_mask (&surface->status_mask); + return glitz_status_pop_from_mask (&surface->status_mask); } slim_hidden_def(glitz_surface_get_status); glitz_format_t * glitz_surface_get_format (glitz_surface_t *surface) { - return surface->format; + return surface->format; } slim_hidden_def(glitz_surface_get_format); void glitz_surface_translate_point (glitz_surface_t *surface, - glitz_point_fixed_t *src, - glitz_point_fixed_t *dst) + glitz_point_fixed_t *src, + glitz_point_fixed_t *dst) { if (surface->texture.target == GLITZ_GL_TEXTURE_2D) { - dst->x = (INT_TO_FIXED (surface->texture.box.x1) + src->x) / - surface->texture.width; - dst->y = (INT_TO_FIXED (surface->texture.box.y2) - src->y) / - surface->texture.height; + dst->x = (INT_TO_FIXED (surface->texture.box.x1) + src->x) / + surface->texture.width; + dst->y = (INT_TO_FIXED (surface->texture.box.y2) - src->y) / + surface->texture.height; } else { - dst->x = INT_TO_FIXED (surface->texture.box.x1) + src->x; - dst->y = INT_TO_FIXED (surface->texture.box.y2) - src->y; + dst->x = INT_TO_FIXED (surface->texture.box.x1) + src->x; + dst->y = INT_TO_FIXED (surface->texture.box.y2) - src->y; } } slim_hidden_def(glitz_surface_translate_point); void glitz_surface_set_clip_region (glitz_surface_t *surface, - int x_origin, - int y_origin, - glitz_box_t *box, - int n_box) + int x_origin, + int y_origin, + glitz_box_t *box, + int n_box) { if (n_box) { - surface->clip = box; - surface->n_clip = n_box; - surface->x_clip = x_origin; - surface->y_clip = y_origin; + surface->clip = box; + surface->n_clip = n_box; + surface->x_clip = x_origin; + surface->y_clip = y_origin; } else { - surface->clip = &surface->box; - surface->n_clip = 1; - surface->x_clip = surface->y_clip = 0; + surface->clip = &surface->box; + surface->n_clip = 1; + surface->x_clip = surface->y_clip = 0; } } slim_hidden_def(glitz_surface_set_clip_region); - -glitz_bool_t -glitz_surface_valid_target (glitz_surface_t *surface) -{ - glitz_bool_t valid; - - valid = glitz_surface_push_current (surface, GLITZ_DRAWABLE_CURRENT); - glitz_surface_pop_current (surface); - - return valid; -} diff --git a/gfx/cairo/glitz/src/glitz_texture.c b/gfx/cairo/glitz/src/glitz_texture.c index 6f65588c304..53737e3fe43 100644 --- a/gfx/cairo/glitz/src/glitz_texture.c +++ b/gfx/cairo/glitz/src/glitz_texture.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,317 +31,444 @@ void glitz_texture_init (glitz_texture_t *texture, - int width, - int height, - glitz_gl_int_t texture_format, - unsigned long feature_mask, - glitz_bool_t unnormalized) + int width, + int height, + glitz_gl_int_t texture_format, + unsigned long feature_mask, + glitz_bool_t unnormalized) { - texture->filter = 0; - texture->wrap = 0; + texture->param.filter[0] = texture->param.filter[1] = GLITZ_GL_NEAREST; + texture->param.wrap[0] = texture->param.wrap[1] = GLITZ_GL_CLAMP; + texture->param.border_color.red = texture->param.border_color.green = + texture->param.border_color.blue = + texture->param.border_color.alpha = 0; + texture->format = texture_format; texture->name = 0; if (feature_mask & GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK) { - texture->box.x1 = texture->box.y1 = 0; - texture->box.x2 = texture->width = width; - texture->box.y2 = texture->height = height; - texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK | - GLITZ_TEXTURE_FLAG_PADABLE_MASK; + texture->box.x1 = texture->box.y1 = 0; + texture->box.x2 = texture->width = width; + texture->box.y2 = texture->height = height; + texture->flags = GLITZ_TEXTURE_FLAG_REPEATABLE_MASK | + GLITZ_TEXTURE_FLAG_PADABLE_MASK; } else { - texture->box.x1 = texture->box.y1 = 1; - texture->box.x2 = width + 1; - texture->box.y2 = height + 1; - texture->width = width + 2; - texture->height = height + 2; - texture->flags = 0; + texture->box.x1 = texture->box.y1 = 1; + texture->box.x2 = width + 1; + texture->box.y2 = height + 1; + texture->width = width + 2; + texture->height = height + 2; + texture->flags = 0; } - + if (!unnormalized && - ((feature_mask & GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK) || - (POWER_OF_TWO (texture->width) && POWER_OF_TWO (texture->height)))) + ((feature_mask & GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK) || + (POWER_OF_TWO (texture->width) && POWER_OF_TWO (texture->height)))) { - texture->target = GLITZ_GL_TEXTURE_2D; + texture->target = GLITZ_GL_TEXTURE_2D; } else { - texture->flags &= ~GLITZ_TEXTURE_FLAG_REPEATABLE_MASK; - - if (feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK) - { - texture->target = GLITZ_GL_TEXTURE_RECTANGLE; - } - else - { - texture->target = GLITZ_GL_TEXTURE_2D; - texture->flags &= ~GLITZ_TEXTURE_FLAG_PADABLE_MASK; - - if (!POWER_OF_TWO (texture->width)) - texture->width = glitz_uint_to_power_of_two (texture->width); - - if (!POWER_OF_TWO (texture->height)) - texture->height = glitz_uint_to_power_of_two (texture->height); - } + texture->flags &= ~GLITZ_TEXTURE_FLAG_REPEATABLE_MASK; + + if (feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK) + { + texture->target = GLITZ_GL_TEXTURE_RECTANGLE; + } + else + { + texture->target = GLITZ_GL_TEXTURE_2D; + texture->flags &= ~GLITZ_TEXTURE_FLAG_PADABLE_MASK; + + if (!POWER_OF_TWO (texture->width)) + texture->width = glitz_uint_to_power_of_two (texture->width); + + if (!POWER_OF_TWO (texture->height)) + texture->height = glitz_uint_to_power_of_two (texture->height); + } } if (texture->target == GLITZ_GL_TEXTURE_2D) { - texture->texcoord_width_unit = 1.0f / texture->width; - texture->texcoord_height_unit = 1.0f / texture->height; + texture->texcoord_width_unit = 1.0f / texture->width; + texture->texcoord_height_unit = 1.0f / texture->height; } else { - texture->texcoord_width_unit = 1.0f; - texture->texcoord_height_unit = 1.0f; + texture->texcoord_width_unit = 1.0f; + texture->texcoord_height_unit = 1.0f; } } void glitz_texture_size_check (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_int_t max_2d, - glitz_gl_int_t max_rect) { - glitz_gl_enum_t proxy_target; - glitz_gl_int_t value, max; + glitz_texture_t *texture, + glitz_gl_int_t max_2d, + glitz_gl_int_t max_rect) +{ + glitz_gl_enum_t proxy_target; + glitz_gl_int_t value, max; - if (texture->target == GLITZ_GL_TEXTURE_2D) { - max = max_2d; - proxy_target = GLITZ_GL_PROXY_TEXTURE_2D; - } else { - max = max_rect; - proxy_target = GLITZ_GL_PROXY_TEXTURE_RECTANGLE; - } - - if (texture->width > max || texture->height > max) { - texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; - return; - } - - gl->tex_image_2d (proxy_target, 0, - texture->format, texture->width, texture->height, - 0, GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL); - gl->get_tex_level_parameter_iv (proxy_target, 0, - GLITZ_GL_TEXTURE_WIDTH, &value); - if (value != texture->width) { - texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; - return; - } - - gl->get_tex_level_parameter_iv (proxy_target, 0, - GLITZ_GL_TEXTURE_HEIGHT, &value); - if (value != texture->height) - texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; + if (texture->target == GLITZ_GL_TEXTURE_2D) { + max = max_2d; + proxy_target = GLITZ_GL_PROXY_TEXTURE_2D; + } else { + max = max_rect; + proxy_target = GLITZ_GL_PROXY_TEXTURE_RECTANGLE; + } + + if (texture->width > max || texture->height > max) { + texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; + return; + } + + gl->tex_image_2d (proxy_target, 0, + texture->format, texture->width, texture->height, + 0, GLITZ_GL_RGBA, GLITZ_GL_UNSIGNED_BYTE, NULL); + gl->get_tex_level_parameter_iv (proxy_target, 0, + GLITZ_GL_TEXTURE_WIDTH, &value); + if (value != texture->width) { + texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; + return; + } + + gl->get_tex_level_parameter_iv (proxy_target, 0, + GLITZ_GL_TEXTURE_HEIGHT, &value); + if (value != texture->height) + texture->flags |= GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK; } void glitz_texture_allocate (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture) + glitz_texture_t *texture) { - char *data = NULL; - - if (!texture->name) - gl->gen_textures (1, &texture->name); - - texture->flags |= GLITZ_TEXTURE_FLAG_ALLOCATED_MASK; - - glitz_texture_bind (gl, texture); + char *data = NULL; + + if (!texture->name) + gl->gen_textures (1, &texture->name); + + texture->flags |= GLITZ_TEXTURE_FLAG_ALLOCATED_MASK; + + glitz_texture_bind (gl, texture); + + if (texture->box.x2 != texture->width || + texture->box.y2 != texture->height) { + data = malloc (texture->width * texture->height); + if (data) + memset (data, 0, texture->width * texture->height); + + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0); + gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); + } + + gl->tex_image_2d (texture->target, 0, texture->format, + texture->width, texture->height, 0, + GLITZ_GL_ALPHA, GLITZ_GL_UNSIGNED_BYTE, data); + + gl->tex_parameter_i (texture->target, + GLITZ_GL_TEXTURE_MAG_FILTER, + texture->param.filter[0]); + gl->tex_parameter_i (texture->target, + GLITZ_GL_TEXTURE_MIN_FILTER, + texture->param.filter[1]); + + glitz_texture_unbind (gl, texture); - if (texture->box.x2 != texture->width || - texture->box.y2 != texture->height) { - data = malloc (texture->width * texture->height); if (data) - memset (data, 0, texture->width * texture->height); - - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); - gl->pixel_store_i (GLITZ_GL_UNPACK_ROW_LENGTH, 0); - gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_ROWS, 0); - gl->pixel_store_i (GLITZ_GL_UNPACK_SKIP_PIXELS, 0); - gl->pixel_store_i (GLITZ_GL_UNPACK_ALIGNMENT, 1); - } - - gl->tex_image_2d (texture->target, 0, texture->format, - texture->width, texture->height, 0, - GLITZ_GL_ALPHA, GLITZ_GL_UNSIGNED_BYTE, data); - - gl->tex_parameter_i (texture->target, - GLITZ_GL_TEXTURE_MAG_FILTER, - GLITZ_GL_NEAREST); - gl->tex_parameter_i (texture->target, - GLITZ_GL_TEXTURE_MIN_FILTER, - GLITZ_GL_NEAREST); - - texture->filter = GLITZ_GL_NEAREST; - - glitz_texture_unbind (gl, texture); - - if (data) - free (data); + free (data); } -void +void glitz_texture_fini (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture) + glitz_texture_t *texture) { - if (texture->name) - gl->delete_textures (1, &texture->name); -} - -void -glitz_texture_ensure_filter (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_enum_t filter) -{ - if (!texture->name) - return; - - if (texture->filter != filter) { - gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_MAG_FILTER, filter); - gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_MIN_FILTER, filter); - texture->filter = filter; - } -} - -void -glitz_texture_ensure_wrap (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_enum_t wrap) -{ - if (!texture->name) - return; - - if (texture->wrap != wrap) { - gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_WRAP_S, wrap); - gl->tex_parameter_i (texture->target, GLITZ_GL_TEXTURE_WRAP_T, wrap); - texture->wrap = wrap; - } + if (texture->name) + gl->delete_textures (1, &texture->name); } void glitz_texture_bind (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture) -{ - gl->disable (GLITZ_GL_TEXTURE_RECTANGLE); - gl->disable (GLITZ_GL_TEXTURE_2D); + glitz_texture_t *texture) +{ + gl->disable (GLITZ_GL_TEXTURE_RECTANGLE); + gl->disable (GLITZ_GL_TEXTURE_2D); - if (!texture->name) - return; + if (!texture->name) + return; - gl->enable (texture->target); - gl->bind_texture (texture->target, texture->name); + gl->enable (texture->target); + gl->bind_texture (texture->target, texture->name); } void glitz_texture_unbind (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture) + glitz_texture_t *texture) { - gl->bind_texture (texture->target, 0); - gl->disable (texture->target); + gl->bind_texture (texture->target, 0); + gl->disable (texture->target); } void glitz_texture_copy_drawable (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_drawable_t *drawable, - int x_drawable, - int y_drawable, - int width, - int height, - int x_texture, - int y_texture) + glitz_texture_t *texture, + glitz_drawable_t *drawable, + int x_drawable, + int y_drawable, + int width, + int height, + int x_texture, + int y_texture) { - gl->copy_tex_sub_image_2d (texture->target, 0, - texture->box.x1 + x_texture, - texture->box.y2 - y_texture - height, - x_drawable, - drawable->height - y_drawable - height, - width, height); + gl->copy_tex_sub_image_2d (texture->target, 0, + texture->box.x1 + x_texture, + texture->box.y2 - y_texture - height, + x_drawable, + drawable->height - y_drawable - height, + width, height); } void glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_geometry_t *geometry, - int x_src, - int y_src, - unsigned long flags, - glitz_int_coordinate_t *coord) + glitz_texture_t *texture, + glitz_geometry_t *geometry, + int x_src, + int y_src, + unsigned long flags, + glitz_int_coordinate_t *coord) { glitz_vec4_t plane; if (flags & GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK) { - plane.v[1] = plane.v[2] = 0.0f; - - if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK) - { - plane.v[0] = 1.0f; - plane.v[3] = -x_src; - } - else - { - plane.v[0] = texture->texcoord_width_unit; - - if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK) - plane.v[3] = -(x_src) * texture->texcoord_width_unit; - else - plane.v[3] = -(x_src - texture->box.x1) * - texture->texcoord_width_unit; - } - - gl->tex_gen_i (GLITZ_GL_S, GLITZ_GL_TEXTURE_GEN_MODE, - GLITZ_GL_EYE_LINEAR); - gl->tex_gen_fv (GLITZ_GL_S, GLITZ_GL_EYE_PLANE, plane.v); + plane.v[1] = plane.v[2] = 0.0f; - gl->enable (GLITZ_GL_TEXTURE_GEN_S); + if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK) + { + plane.v[0] = 1.0f; + plane.v[3] = -x_src; + } + else + { + plane.v[0] = texture->texcoord_width_unit; + + if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK) + plane.v[3] = -(x_src) * texture->texcoord_width_unit; + else + plane.v[3] = -(x_src - texture->box.x1) * + texture->texcoord_width_unit; + } + + gl->tex_gen_i (GLITZ_GL_S, GLITZ_GL_TEXTURE_GEN_MODE, + GLITZ_GL_EYE_LINEAR); + gl->tex_gen_fv (GLITZ_GL_S, GLITZ_GL_EYE_PLANE, plane.v); + + gl->enable (GLITZ_GL_TEXTURE_GEN_S); } else - gl->disable (GLITZ_GL_TEXTURE_GEN_S); + gl->disable (GLITZ_GL_TEXTURE_GEN_S); if (flags & GLITZ_SURFACE_FLAG_GEN_T_COORDS_MASK) { - plane.v[0] = plane.v[2] = 0.0f; - if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK) - { - plane.v[1] = 1.0f; - plane.v[3] = -y_src; - } - else - { - plane.v[1] = -texture->texcoord_height_unit; - - if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK) - plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) * - texture->texcoord_height_unit; - else - plane.v[3] = (y_src + texture->box.y2) * - texture->texcoord_height_unit; - } - - gl->tex_gen_i (GLITZ_GL_T, GLITZ_GL_TEXTURE_GEN_MODE, - GLITZ_GL_EYE_LINEAR); - gl->tex_gen_fv (GLITZ_GL_T, GLITZ_GL_EYE_PLANE, plane.v); - - gl->enable (GLITZ_GL_TEXTURE_GEN_T); + plane.v[0] = plane.v[2] = 0.0f; + if (flags & GLITZ_SURFACE_FLAG_EYE_COORDS_MASK) + { + plane.v[1] = 1.0f; + plane.v[3] = -y_src; + } + else + { + plane.v[1] = -texture->texcoord_height_unit; + + if (flags & GLITZ_SURFACE_FLAG_TRANSFORM_MASK) + plane.v[3] = (y_src + texture->box.y2 - texture->box.y1) * + texture->texcoord_height_unit; + else + plane.v[3] = (y_src + texture->box.y2) * + texture->texcoord_height_unit; + } + + gl->tex_gen_i (GLITZ_GL_T, GLITZ_GL_TEXTURE_GEN_MODE, + GLITZ_GL_EYE_LINEAR); + gl->tex_gen_fv (GLITZ_GL_T, GLITZ_GL_EYE_PLANE, plane.v); + + gl->enable (GLITZ_GL_TEXTURE_GEN_T); } else - gl->disable (GLITZ_GL_TEXTURE_GEN_T); + gl->disable (GLITZ_GL_TEXTURE_GEN_T); if (!(flags & GLITZ_SURFACE_FLAG_GEN_S_COORDS_MASK)) { - unsigned char *ptr; + unsigned char *ptr; - gl->enable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY); - - ptr = glitz_buffer_bind (geometry->buffer, GLITZ_GL_ARRAY_BUFFER); - ptr += coord->offset; + gl->enable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY); - gl->tex_coord_pointer (coord->size, - coord->type, - geometry->stride, - (void *) ptr); + ptr = glitz_buffer_bind (geometry->buffer, GLITZ_GL_ARRAY_BUFFER); + ptr += coord->offset; + + gl->tex_coord_pointer (coord->size, + coord->type, + geometry->stride, + (void *) ptr); } else - gl->disable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY); + gl->disable_client_state (GLITZ_GL_TEXTURE_COORD_ARRAY); +} + +glitz_texture_object_t * +glitz_texture_object_create (glitz_surface_t *surface) +{ + glitz_texture_object_t *texture; + + GLITZ_GL_SURFACE (surface); + + /* GL_ARB_texture_rectangle is required for sane texture coordinates. + GL_ARB_texture_border_clamp is required right now as glitz will + emulate it when missing, which means a 1 pixel translucent black + border inside textures and that cannot be exposed to clients. */ + if ((!(surface->drawable->backend->feature_mask & + GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK)) || + (!(surface->drawable->backend->feature_mask & + GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK))) + return 0; + + texture = malloc (sizeof (glitz_texture_object_t)); + if (!texture) + return 0; + + texture->ref_count = 1; + + glitz_surface_reference (surface); + texture->surface = surface; + + if (!(TEXTURE_ALLOCATED (&surface->texture))) + glitz_texture_allocate (gl, &surface->texture); + + texture->param = surface->texture.param; + + return texture; +} + +void +glitz_texture_object_destroy (glitz_texture_object_t *texture) +{ + texture->ref_count--; + if (texture->ref_count) + return; + + glitz_surface_destroy (texture->surface); + free (texture); +} + +void +glitz_texture_object_reference (glitz_texture_object_t *texture) +{ + texture->ref_count++; +} + +void +glitz_texture_object_set_filter (glitz_texture_object_t *texture, + glitz_texture_filter_type_t type, + glitz_texture_filter_t filter) +{ + static glitz_gl_enum_t filters[] = { + GLITZ_GL_NEAREST, + GLITZ_GL_LINEAR + }; + + texture->param.filter[type] = filters[filter]; +} + +void +glitz_texture_object_set_wrap (glitz_texture_object_t *texture, + glitz_texture_wrap_type_t type, + glitz_texture_wrap_t wrap) +{ + static glitz_gl_enum_t wraps[] = { + GLITZ_GL_CLAMP, + GLITZ_GL_CLAMP_TO_EDGE, + GLITZ_GL_CLAMP_TO_BORDER, + GLITZ_GL_REPEAT, + GLITZ_GL_MIRRORED_REPEAT + }; + + texture->param.wrap[type] = wraps[wrap]; +} + +void +glitz_texture_object_set_border_color (glitz_texture_object_t *texture, + glitz_color_t *color) +{ + texture->param.border_color = *color; +} + +void +glitz_texture_ensure_parameters (glitz_gl_proc_address_list_t *gl, + glitz_texture_t *texture, + glitz_texture_parameters_t *param) +{ + static const glitz_gl_enum_t filters[] = { + GLITZ_GL_TEXTURE_MAG_FILTER, + GLITZ_GL_TEXTURE_MIN_FILTER + }; + static const glitz_gl_enum_t wraps[] = { + GLITZ_GL_TEXTURE_WRAP_S, + GLITZ_GL_TEXTURE_WRAP_T + }; + int i; + + if (!texture->name) + return; + + for (i = 0; i < 2; i++) + { + if (texture->param.filter[i] != param->filter[i]) + { + texture->param.filter[i] = param->filter[i]; + gl->tex_parameter_i (texture->target, filters[i], + param->filter[i]); + } + + if (texture->param.wrap[i] != param->wrap[i]) + { + texture->param.wrap[i] = param->wrap[i]; + gl->tex_parameter_i (texture->target, wraps[i], param->wrap[i]); + } + } + + if (texture->param.wrap[0] == GLITZ_GL_CLAMP_TO_BORDER || + texture->param.wrap[1] == GLITZ_GL_CLAMP_TO_BORDER || + texture->param.wrap[0] == GLITZ_GL_CLAMP || + texture->param.wrap[1] == GLITZ_GL_CLAMP) + { + if (memcmp (&texture->param.border_color, ¶m->border_color, + sizeof (glitz_color_t))) + { + glitz_vec4_t vec; + + vec.v[0] = (glitz_float_t) param->border_color.red / 0xffff; + vec.v[1] = (glitz_float_t) param->border_color.green / 0xffff; + vec.v[2] = (glitz_float_t) param->border_color.blue / 0xffff; + vec.v[3] = (glitz_float_t) param->border_color.alpha / 0xffff; + + gl->tex_parameter_fv (texture->target, + GLITZ_GL_TEXTURE_BORDER_COLOR, + vec.v); + + texture->param.border_color = param->border_color; + } + } +} + +glitz_texture_target_t +glitz_texture_object_get_target (glitz_texture_object_t *texture) +{ + if (texture->surface->texture.target == GLITZ_GL_TEXTURE_2D) + return GLITZ_TEXTURE_TARGET_2D; + + return GLITZ_TEXTURE_TARGET_RECT; } diff --git a/gfx/cairo/glitz/src/glitz_trap.c b/gfx/cairo/glitz/src/glitz_trap.c index 7cad8a5661c..7a1654db4e9 100644 --- a/gfx/cairo/glitz/src/glitz_trap.c +++ b/gfx/cairo/glitz/src/glitz_trap.c @@ -1,6 +1,6 @@ /* * Copyright © 2005 Novell, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -30,9 +30,9 @@ #include "glitzint.h" /* whether 't' is a well defined not obviously empty trapezoid */ -#define TRAPEZOID_VALID(t) ((t)->left.p1.y != (t)->left.p2.y && \ - (t)->right.p1.y != (t)->right.p2.y && \ - (int) ((t)->bottom - (t)->top) > 0) +#define TRAPEZOID_VALID(t) ((t)->left.p1.y != (t)->left.p2.y && \ + (t)->right.p1.y != (t)->right.p2.y && \ + (int) ((t)->bottom - (t)->top) > 0) /* whether 't' is a well defined not obviously empty trap */ #define TRAP_VALID(t) ((int) ((t)->bottom.y - (t)->top.y) > 0) @@ -46,57 +46,57 @@ typedef struct _glitz_edge { int hyp; } glitz_edge_t; -#define EDGE_INIT(e, p1x, p1y, p2x, p2y) \ - (e)->hyp = 1; \ - (e)->dx = (p2x) - (p1x); \ - (e)->dy = (p2y) - (p1y); \ - if ((e)->dy) \ - (e)->kx = (e)->dx / (e)->dy; \ - else \ - (e)->kx = 0; \ - (e)->x0 = (p1x) - (e)->kx * (p1y); \ - if ((e)->dx) \ - (e)->ky = (e)->dy / (e)->dx; \ - else \ - (e)->ky = 0; \ +#define EDGE_INIT(e, p1x, p1y, p2x, p2y) \ + (e)->hyp = 1; \ + (e)->dx = (p2x) - (p1x); \ + (e)->dy = (p2y) - (p1y); \ + if ((e)->dy) \ + (e)->kx = (e)->dx / (e)->dy; \ + else \ + (e)->kx = 0; \ + (e)->x0 = (p1x) - (e)->kx * (p1y); \ + if ((e)->dx) \ + (e)->ky = (e)->dy / (e)->dx; \ + else \ + (e)->ky = 0; \ (e)->y0 = (p1y) - (e)->ky * (p1x) #define EDGE_X(e, _y) (((e)->kx * (_y)) + (e)->x0) #define EDGE_Y(e, _x) (((e)->ky * (_x)) + (e)->y0) -#define EDGE_INTERSECT_BOX(upper_x, lower_y, left_y, right_y, \ - box_x1, box_x2, box_y1, box_y2, \ - max_x, max_y, \ - _x1, _y1, _x2, _y2) \ - if (upper_x < (box_x1)) \ - { \ - (_x1) = 0.0f; \ - (_y1) = (left_y) - (box_y1); \ - } \ - else if ((upper_x) > (box_x2)) \ - { \ - (_x1) = (max_x); \ - (_y1) = (right_y) - (box_y1); \ - } \ - else \ - { \ - (_x1) = (upper_x) - (box_x1); \ - (_y1) = 0.0f; \ - } \ - if ((lower_x) < (box_x1)) \ - { \ - (_x2) = 0.0f; \ - (_y2) = (left_y) - (box_y1); \ - } \ - else if ((lower_x) > (box_x2)) \ - { \ - (_x2) = (max_x); \ - (_y2) = (right_y) - (box_y1); \ - } \ - else \ - { \ - (_x2) = (lower_x) - (box_x1); \ - (_y2) = (max_y); \ +#define EDGE_INTERSECT_BOX(upper_x, lower_y, left_y, right_y, \ + box_x1, box_x2, box_y1, box_y2, \ + max_x, max_y, \ + _x1, _y1, _x2, _y2) \ + if (upper_x < (box_x1)) \ + { \ + (_x1) = 0.0f; \ + (_y1) = (left_y) - (box_y1); \ + } \ + else if ((upper_x) > (box_x2)) \ + { \ + (_x1) = (max_x); \ + (_y1) = (right_y) - (box_y1); \ + } \ + else \ + { \ + (_x1) = (upper_x) - (box_x1); \ + (_y1) = 0.0f; \ + } \ + if ((lower_x) < (box_x1)) \ + { \ + (_x2) = 0.0f; \ + (_y2) = (left_y) - (box_y1); \ + } \ + else if ((lower_x) > (box_x2)) \ + { \ + (_x2) = (max_x); \ + (_y2) = (right_y) - (box_y1); \ + } \ + else \ + { \ + (_x2) = (lower_x) - (box_x1); \ + (_y2) = (max_y); \ } #define AREA_ABOVE_LEFT(x1, y1, x2, y2, bottom) \ @@ -110,11 +110,11 @@ typedef struct _glitz_edge { */ static glitz_float_t _glitz_pixel_area (glitz_float_t pixel_x, - glitz_float_t pixel_y, - glitz_float_t top, - glitz_float_t bottom, - glitz_edge_t *left, - glitz_edge_t *right) + glitz_float_t pixel_y, + glitz_float_t top, + glitz_float_t bottom, + glitz_edge_t *left, + glitz_edge_t *right) { glitz_float_t area; glitz_float_t upper_x, lower_x; @@ -124,158 +124,158 @@ _glitz_pixel_area (glitz_float_t pixel_x, glitz_float_t x1, x2, y1, y2; if (bottom >= pixel_y_1) - bottom = 1.0f; + bottom = 1.0f; else - bottom = bottom - pixel_y; + bottom = bottom - pixel_y; if (top <= pixel_y) - top = 0.0f; + top = 0.0f; else - top = top - pixel_y; - + top = top - pixel_y; + if (right->ky) { - upper_x = EDGE_X (right, pixel_y); - lower_x = EDGE_X (right, pixel_y_1); + upper_x = EDGE_X (right, pixel_y); + lower_x = EDGE_X (right, pixel_y_1); - left_y = EDGE_Y (right, pixel_x); - right_y = EDGE_Y (right, pixel_x_1); + left_y = EDGE_Y (right, pixel_x); + right_y = EDGE_Y (right, pixel_x_1); - EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y, - pixel_x, pixel_x_1, pixel_y, pixel_y_1, - 1.0f, 1.0f, x1, y1, x2, y2); - - if (bottom <= y1) - { - if (left_y > right_y) - area = bottom; - else - area = 0.0f; - } - else - { - if (bottom < y2) - { - x2 -= right->kx * (y2 - bottom); - y2 = bottom; - } - area = AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom); - } + EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y, + pixel_x, pixel_x_1, pixel_y, pixel_y_1, + 1.0f, 1.0f, x1, y1, x2, y2); - if (top <= y1) - { - if (left_y > right_y) - area -= top; - } - else - { - if (top < y2) - { - x2 -= right->kx * (y2 - top); - y2 = top; - } + if (bottom <= y1) + { + if (left_y > right_y) + area = bottom; + else + area = 0.0f; + } + else + { + if (bottom < y2) + { + x2 -= right->kx * (y2 - bottom); + y2 = bottom; + } + area = AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom); + } - area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, top); - } + if (top <= y1) + { + if (left_y > right_y) + area -= top; + } + else + { + if (top < y2) + { + x2 -= right->kx * (y2 - top); + y2 = top; + } + + area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, top); + } } else { - /* Vertical Edge */ - if (right->x0 < pixel_x_1) - area = (right->x0 - pixel_x) * (bottom - top); - else - area = bottom - top; + /* Vertical Edge */ + if (right->x0 < pixel_x_1) + area = (right->x0 - pixel_x) * (bottom - top); + else + area = bottom - top; } if (left->kx) { - upper_x = EDGE_X (left, pixel_y); - lower_x = EDGE_X (left, pixel_y_1); + upper_x = EDGE_X (left, pixel_y); + lower_x = EDGE_X (left, pixel_y_1); - left_y = EDGE_Y (left, pixel_x); - right_y = EDGE_Y (left, pixel_x_1); + left_y = EDGE_Y (left, pixel_x); + right_y = EDGE_Y (left, pixel_x_1); - EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y, - pixel_x, pixel_x_1, pixel_y, pixel_y_1, - 1.0f, 1.0f, x1, y1, x2, y2); - - if (bottom <= y1) - { - if (left_y > right_y) - area -= bottom; - } - else - { - if (bottom < y2) - { - x2 -= left->kx * (y2 - bottom); - y2 = bottom; - } - area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom); - } + EDGE_INTERSECT_BOX (upper_x, lower_y, left_y, right_y, + pixel_x, pixel_x_1, pixel_y, pixel_y_1, + 1.0f, 1.0f, x1, y1, x2, y2); - if (top <= y1) - { - if (left_y > right_y) - area += top; - } - else - { - if (top < y2) - { - x2 -= left->kx * (y2 - top); - y2 = top; - } - - area += AREA_ABOVE_LEFT (x1, y1, x2, y2, top); - } + if (bottom <= y1) + { + if (left_y > right_y) + area -= bottom; + } + else + { + if (bottom < y2) + { + x2 -= left->kx * (y2 - bottom); + y2 = bottom; + } + area -= AREA_ABOVE_LEFT (x1, y1, x2, y2, bottom); + } + + if (top <= y1) + { + if (left_y > right_y) + area += top; + } + else + { + if (top < y2) + { + x2 -= left->kx * (y2 - top); + y2 = top; + } + + area += AREA_ABOVE_LEFT (x1, y1, x2, y2, top); + } } else { - /* Vertical Edge */ - if (left->x0 > pixel_x) - area -= (left->x0 - pixel_x) * (bottom - top); + /* Vertical Edge */ + if (left->x0 > pixel_x) + area -= (left->x0 - pixel_x) * (bottom - top); } - + return area; } #define TRAPINIT(trap, _top, _bottom, _left, _right) \ if (!TRAPEZOID_VALID (trap)) \ - continue; \ - \ + continue; \ + \ (_top) = FIXED_TO_FLOAT ((trap)->top); \ (_bottom) = FIXED_TO_FLOAT ((trap)->bottom); \ - \ + \ (_left)->tx = FIXED_TO_FLOAT ((trap)->left.p1.x); \ (_left)->bx = FIXED_TO_FLOAT ((trap)->left.p1.y); \ - \ + \ (_right)->tx = FIXED_TO_FLOAT ((trap)->right.p1.x); \ (_right)->bx = FIXED_TO_FLOAT ((trap)->right.p1.y); \ - \ + \ EDGE_INIT (_left, \ - (_left)->tx, (_left)->bx, \ - FIXED_TO_FLOAT ((trap)->left.p2.x), \ - FIXED_TO_FLOAT ((trap)->left.p2.y)); \ - \ + (_left)->tx, (_left)->bx, \ + FIXED_TO_FLOAT ((trap)->left.p2.x), \ + FIXED_TO_FLOAT ((trap)->left.p2.y)); \ + \ EDGE_INIT (_right, \ - (_right)->tx, (_right)->bx, \ - FIXED_TO_FLOAT ((trap)->right.p2.x), \ - FIXED_TO_FLOAT ((trap)->right.p2.y)); \ - \ + (_right)->tx, (_right)->bx, \ + FIXED_TO_FLOAT ((trap)->right.p2.x), \ + FIXED_TO_FLOAT ((trap)->right.p2.y)); \ + \ if ((_left)->dx) \ { \ - (_left)->tx = EDGE_X (_left, _top); \ - (_left)->bx = EDGE_X (_left, _bottom); \ + (_left)->tx = EDGE_X (_left, _top); \ + (_left)->bx = EDGE_X (_left, _bottom); \ } else \ - (_left)->tx = (_left)->bx = (_left)->x0; \ - \ + (_left)->tx = (_left)->bx = (_left)->x0; \ + \ if ((_right)->dx) \ { \ - (_right)->tx = EDGE_X (_right, _top); \ - (_right)->bx = EDGE_X (_right, _bottom); \ + (_right)->tx = EDGE_X (_right, _top); \ + (_right)->bx = EDGE_X (_right, _bottom); \ } else \ - (_right)->tx = (_right)->bx = (_right)->x0 + (_right)->tx = (_right)->bx = (_right)->x0 #define TRAP glitz_trapezoid_t @@ -306,26 +306,26 @@ _glitz_pixel_area (glitz_float_t pixel_x, #undef TRAP #undef TRAPINIT -#define TRAPINIT(trap, _top, _bottom, _left, _right) \ - if (!TRAP_VALID (trap)) \ - continue; \ - \ - (_top) = FIXED_TO_FLOAT ((trap)->top.y); \ - (_bottom) = FIXED_TO_FLOAT ((trap)->bottom.y); \ - \ - (_left)->tx = FIXED_TO_FLOAT ((trap)->top.left); \ - (_left)->bx = FIXED_TO_FLOAT ((trap)->bottom.left); \ - \ - (_right)->tx = FIXED_TO_FLOAT ((trap)->top.right); \ - (_right)->bx = FIXED_TO_FLOAT ((trap)->bottom.right); \ - \ - EDGE_INIT (_left, \ - (_left)->tx, _top, \ - (_left)->bx, _bottom); \ - \ - EDGE_INIT (_right, \ - (_right)->tx, _top, \ - (_right)->bx, _bottom) +#define TRAPINIT(trap, _top, _bottom, _left, _right) \ + if (!TRAP_VALID (trap)) \ + continue; \ + \ + (_top) = FIXED_TO_FLOAT ((trap)->top.y); \ + (_bottom) = FIXED_TO_FLOAT ((trap)->bottom.y); \ + \ + (_left)->tx = FIXED_TO_FLOAT ((trap)->top.left); \ + (_left)->bx = FIXED_TO_FLOAT ((trap)->bottom.left); \ + \ + (_right)->tx = FIXED_TO_FLOAT ((trap)->top.right); \ + (_right)->bx = FIXED_TO_FLOAT ((trap)->bottom.right); \ + \ + EDGE_INIT (_left, \ + (_left)->tx, _top, \ + (_left)->bx, _bottom); \ + \ + EDGE_INIT (_right, \ + (_right)->tx, _top, \ + (_right)->bx, _bottom) #define TRAP glitz_trap_t @@ -358,44 +358,44 @@ _glitz_pixel_area (glitz_float_t pixel_x, int glitz_add_trapezoids (glitz_buffer_t *buffer, - int offset, - unsigned int size, - glitz_data_type_t type, - glitz_surface_t *mask, - glitz_trapezoid_t *traps, - int n_traps, - int *n_added) + int offset, + unsigned int size, + glitz_data_type_t type, + glitz_surface_t *mask, + glitz_trapezoid_t *traps, + int n_traps, + int *n_added) { int count, n = n_traps; uint8_t *ptr; - + *n_added = 0; - + ptr = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); if (!ptr) - return 0; + return 0; ptr += offset; - + switch (type) { case GLITZ_DATA_TYPE_SHORT: - count = _glitz_add_trapezoids_short (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_trapezoids_short (ptr, size, mask, traps, &n_traps); + break; case GLITZ_DATA_TYPE_INT: - count = _glitz_add_trapezoids_int (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_trapezoids_int (ptr, size, mask, traps, &n_traps); + break; case GLITZ_DATA_TYPE_DOUBLE: - count = _glitz_add_trapezoids_double (ptr, size, mask, - traps, &n_traps); - break; + count = _glitz_add_trapezoids_double (ptr, size, mask, + traps, &n_traps); + break; default: - count = _glitz_add_trapezoids_float (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_trapezoids_float (ptr, size, mask, traps, &n_traps); + break; } if (glitz_buffer_unmap (buffer)) - return 0; - + return 0; + *n_added = n - n_traps; return count; @@ -403,42 +403,42 @@ glitz_add_trapezoids (glitz_buffer_t *buffer, int glitz_add_traps (glitz_buffer_t *buffer, - int offset, - unsigned int size, - glitz_data_type_t type, - glitz_surface_t *mask, - glitz_trap_t *traps, - int n_traps, - int *n_added) + int offset, + unsigned int size, + glitz_data_type_t type, + glitz_surface_t *mask, + glitz_trap_t *traps, + int n_traps, + int *n_added) { int count, n = n_traps; uint8_t *ptr; - + *n_added = 0; - + ptr = glitz_buffer_map (buffer, GLITZ_BUFFER_ACCESS_WRITE_ONLY); if (!ptr) return 0; ptr += offset; - + switch (type) { case GLITZ_DATA_TYPE_SHORT: - count = _glitz_add_traps_short (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_traps_short (ptr, size, mask, traps, &n_traps); + break; case GLITZ_DATA_TYPE_INT: - count = _glitz_add_traps_int (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_traps_int (ptr, size, mask, traps, &n_traps); + break; case GLITZ_DATA_TYPE_DOUBLE: - count = _glitz_add_traps_double (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_traps_double (ptr, size, mask, traps, &n_traps); + break; default: - count = _glitz_add_traps_float (ptr, size, mask, traps, &n_traps); - break; + count = _glitz_add_traps_float (ptr, size, mask, traps, &n_traps); + break; } if (glitz_buffer_unmap (buffer)) - return 0; + return 0; *n_added = n - n_traps; diff --git a/gfx/cairo/glitz/src/glitz_trapimp.h b/gfx/cairo/glitz/src/glitz_trapimp.h index 6f25dfdee3a..cdf46fb8714 100644 --- a/gfx/cairo/glitz/src/glitz_trapimp.h +++ b/gfx/cairo/glitz/src/glitz_trapimp.h @@ -1,6 +1,6 @@ /* * Copyright © 2005 Novell, Inc. - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * NOVELL, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL NOVELL, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -25,7 +25,7 @@ /* Define the following before including this file: - + TRAPS name of function for adding trapezoids UNIT type of underlying vertex unit TRAP type of underlying trapezoid structure @@ -38,69 +38,69 @@ #define VSKIP (BYTES_PER_VERTEX / sizeof (UNIT)) #define TSKIP (BYTES_PER_VERTEX / sizeof (glitz_float_t)) -#define ADD_VERTEX(vptr, tptr, texcoord, _x, _y) \ - (vptr)[0] = (UNIT) (_x); \ - (vptr)[1] = (UNIT) (_y); \ - (tptr)[0] = (texcoord); \ - (vptr) += VSKIP; \ +#define ADD_VERTEX(vptr, tptr, texcoord, _x, _y) \ + (vptr)[0] = (UNIT) (_x); \ + (vptr)[1] = (UNIT) (_y); \ + (tptr)[0] = (texcoord); \ + (vptr) += VSKIP; \ (tptr) += TSKIP -#define ADD_QUAD(vptr, tptr, offset, size, \ - t00, t01, t10, t11, x1, y1, x2, y2) \ - if ((offset) == (size)) \ - return (toff); \ - (offset) += BYTES_PER_QUAD; \ - ADD_VERTEX (vptr, tptr, t00, x1, y1); \ - ADD_VERTEX (vptr, tptr, t01, x2, y1); \ - ADD_VERTEX (vptr, tptr, t10, x2, y2); \ +#define ADD_QUAD(vptr, tptr, offset, size, \ + t00, t01, t10, t11, x1, y1, x2, y2) \ + if ((offset) == (size)) \ + return (toff); \ + (offset) += BYTES_PER_QUAD; \ + ADD_VERTEX (vptr, tptr, t00, x1, y1); \ + ADD_VERTEX (vptr, tptr, t01, x2, y1); \ + ADD_VERTEX (vptr, tptr, t10, x2, y2); \ ADD_VERTEX (vptr, tptr, t11, x1, y2) #define ADD_PIXEL(vptr, tptr, offset, size, tmp0, tbase, tsize, \ - x1, y1, x2, y2, alpha) \ + x1, y1, x2, y2, alpha) \ (tmp0) = (tbase) + (alpha - 0.5f) * (tsize); \ ADD_QUAD (vptr, tptr, offset, size, tmp0, tmp0, tmp0, tmp0, \ - x1, y1, x2, y2) + x1, y1, x2, y2) -#define CALC_SPAN(tmp0, tmp1, tbase, tsize, edge, end) \ - (tmp0) = (edge) - (end); \ - (tmp0) = (tbase) - (tmp0) * (tsize); \ +#define CALC_SPAN(tmp0, tmp1, tbase, tsize, edge, end) \ + (tmp0) = (edge) - (end); \ + (tmp0) = (tbase) - (tmp0) * (tsize); \ (tmp1) = (tbase) + (end) * (tsize) #define ADD_LEFT_SPAN(vptr, tptr, offset, size, tmp0, tmp1, tbase, tsize, \ - x1, y1, x2, y2, end) \ + x1, y1, x2, y2, end) \ CALC_SPAN (tmp0, tmp1, tbase, tsize, (x2) - (x1), end); \ ADD_QUAD (vptr, tptr, offset, size, tmp0, tmp1, tmp1, tmp0, \ - x1, y1, x2, y2) + x1, y1, x2, y2) #define ADD_RIGHT_SPAN(vptr, tptr, offset, size, tmp0, tmp1, tbase, tsize, \ - x1, y1, x2, y2, end) \ + x1, y1, x2, y2, end) \ CALC_SPAN (tmp0, tmp1, tbase, tsize, (x2) - (x1), end); \ ADD_QUAD (vptr, tptr, offset, size, tmp1, tmp0, tmp0, tmp1, \ - x1, y1, x2, y2) + x1, y1, x2, y2) #define ADD_TOP_SPAN(vptr, tptr, offset, size, tmp0, tmp1, tbase, tsize, \ - x1, y1, x2, y2, end) \ + x1, y1, x2, y2, end) \ CALC_SPAN (tmp0, tmp1, tbase, tsize, (y2) - (y1), end); \ ADD_QUAD (vptr, tptr, offset, size, tmp0, tmp0, tmp1, tmp1, \ - x1, y1, x2, y2) + x1, y1, x2, y2) #define ADD_BOTTOM_SPAN(vptr, tptr, offset, size, tmp0, tmp1, tbase, tsize, \ - x1, y1, x2, y2, end) \ + x1, y1, x2, y2, end) \ CALC_SPAN (tmp0, tmp1, tbase, tsize, (y2) - (y1), end); \ ADD_QUAD (vptr, tptr, offset, size, tmp1, tmp1, tmp0, tmp0, \ - x1, y1, x2, y2) + x1, y1, x2, y2) -#define CALC_EDGE(tl, tr, bl, br, x1, x2, tsize, edge, tx, bx) \ - if ((edge)->hyp) \ - { \ - (edge)->hypx = (edge)->dy / \ - sqrtf ((edge)->dx * (edge)->dx + (edge)->dy * (edge)->dy); \ - (edge)->hyp = 0; \ - } \ - (tl) = (((tx) - (x1)) * (edge)->hypx) * tsize; \ - (tr) = (((tx) - (x2)) * (edge)->hypx) * tsize; \ - (bl) = (((bx) - (x1)) * (edge)->hypx) * tsize; \ +#define CALC_EDGE(tl, tr, bl, br, x1, x2, tsize, edge, tx, bx) \ + if ((edge)->hyp) \ + { \ + (edge)->hypx = (edge)->dy / \ + sqrtf ((edge)->dx * (edge)->dx + (edge)->dy * (edge)->dy); \ + (edge)->hyp = 0; \ + } \ + (tl) = (((tx) - (x1)) * (edge)->hypx) * tsize; \ + (tr) = (((tx) - (x2)) * (edge)->hypx) * tsize; \ + (bl) = (((bx) - (x1)) * (edge)->hypx) * tsize; \ (br) = (((bx) - (x2)) * (edge)->hypx) * tsize #define CALC_LEFT_EDGE(tl, tr, bl, br, x1, x2, tbase, tsize, edge, tx, bx) \ @@ -118,20 +118,20 @@ (br) = (tbase) + (br) #define ADD_LEFT_EDGE(vptr, tptr, offset, size, \ - tmp0, tmp1, tmp2, tmp3, tbase, tsize, \ - edge, x1, y1, x2, y2, tx, bx) \ + tmp0, tmp1, tmp2, tmp3, tbase, tsize, \ + edge, x1, y1, x2, y2, tx, bx) \ CALC_LEFT_EDGE (tmp0, tmp1, tmp2, tmp3, x1, x2, \ - tbase, tsize, edge, tx, bx); \ + tbase, tsize, edge, tx, bx); \ ADD_QUAD (vptr, tptr, offset, size, tmp0, tmp1, tmp3, tmp2, \ - x1, y1, x2, y2) + x1, y1, x2, y2) #define ADD_RIGHT_EDGE(vptr, tptr, offset, size, \ - tmp0, tmp1, tmp2, tmp3, tbase, tsize, \ - edge, x1, y1, x2, y2, tx, bx) \ + tmp0, tmp1, tmp2, tmp3, tbase, tsize, \ + edge, x1, y1, x2, y2, tx, bx) \ CALC_RIGHT_EDGE (tmp0, tmp1, tmp2, tmp3, x1, x2, \ - tbase, tsize, edge, tx, bx); \ + tbase, tsize, edge, tx, bx); \ ADD_QUAD (vptr, tptr, offset, size, tmp0, tmp1, tmp3, tmp2, \ - x1, y1, x2, y2) + x1, y1, x2, y2) /* An implicit mask surface for a single anti-aliased edge that @@ -157,33 +157,33 @@ mask.type : FLOAT mask.size : COORDINATE_SIZE_X mask.offset : 2 * sizeof (type) - + Trapezoid: top { l, r, y } bottom { l, r, y } - + Bounds: x1 = floor (MIN (top.l, bottom.l)) x2 = ceil (MAX (top.r, bottom.r)) y1 = floor (top.y) y2 = ceil (bottom.y) - + W = x2 - x1; H = y2 - y1; TH = 1 if TOP rectangle exist, else 0 BH = 1 if BOTTOM rectangle exist, else 0 - + TOP rectangle exists if: floor (top.y) != top.y BOTTOM rectangle exists if: ceil (bottom.y) != bottom.y && bottom.y > ceil (top.y) MIDDLE rectangle exists if: (H - TH - BH) > 0 - - W + + W +----------------------------------------------------+ - | | + | | | TOP +---------------------------+ | TH - | / | | + | / | | +---------------/-----------------------------+------+ | / | | | MIDDLE / | | @@ -210,7 +210,7 @@ TRAPS (void *ptr, unsigned int toff = 0, offset = 0; UNIT *vptr = (UNIT *) ptr; glitz_float_t *tptr = (glitz_float_t *) (vptr + 2); - + glitz_edge_t left, right; glitz_float_t top, bottom; @@ -232,499 +232,499 @@ TRAPS (void *ptr, for (; *n_traps; (*n_traps)--, traps++) { - TRAPINIT (traps, top, bottom, &left, &right); - - /* - Top left X greater than top right X or bottom left X greater - than bottom right X. To me, this seems like an invalid trapezoid. - Cairo's current caps generation code, creates a lot of these. The - following adjustments makes them render almost correct. - */ - if (left.tx > right.tx) - { - if (floorf (left.tx) > floorf (right.tx)) - left.tx = right.tx = floorf (left.tx); - } - - if (left.bx > right.bx) - { - if (floorf (left.bx) > floorf (right.bx)) - left.bx = right.bx = floorf (left.bx); - } + TRAPINIT (traps, top, bottom, &left, &right); - x1 = floorf (MIN (left.tx, left.bx)); - x2 = ceilf (MAX (right.tx, right.bx)); + /* + Top left X greater than top right X or bottom left X greater + than bottom right X. To me, this seems like an invalid trapezoid. + Cairo's current caps generation code, creates a lot of these. The + following adjustments makes them render almost correct. + */ + if (left.tx > right.tx) + { + if (floorf (left.tx) > floorf (right.tx)) + left.tx = right.tx = floorf (left.tx); + } - /* - TOP rectangle - W - +---------+---------+------------------+---------+--------+ - | | | | | | - | lE | +------+------------------|------+ | rE | - | |/ | | \| | 1 - | /| lEtE | tE | tErE |\ | - | +-+---------+------------------+---------+-+ | - +-----+---+---------+------------------+---------+--------+ + if (left.bx > right.bx) + { + if (floorf (left.bx) > floorf (right.bx)) + left.bx = right.bx = floorf (left.bx); + } - The following set sub-rectangles might need to be generated - to render the top span of the trapezoid correctly. - - lE = Left Edge - tE = Top Edge - rE = Right Edge - lEtE = Left/Top Edge intersection - tErE = Top/Right Edge intersection - */ - y1 = ceilf (top); - if (y1 != top) - { - y0 = floorf (top); - lx = x1; - rx = x2; - - y1lx = EDGE_X (&left, y1); - y1rx = EDGE_X (&right, y1); + x1 = floorf (MIN (left.tx, left.bx)); + x2 = ceilf (MAX (right.tx, right.bx)); - if (bottom > y1) - { - l = MAX (left.tx, y1lx); - r = MIN (right.tx, y1rx); - } - else - { - l = MAX (left.tx, left.bx); - r = MIN (right.tx, right.bx); - } - - lspan = ceilf (l); - rspan = floorf (r); - - l = floorf (l); - if (l > rspan) - l = rspan; + /* + TOP rectangle + W + +---------+---------+------------------+---------+--------+ + | | | | | | + | lE | +------+------------------|------+ | rE | + | |/ | | \| | 1 + | /| lEtE | tE | tErE |\ | + | +-+---------+------------------+---------+-+ | + +-----+---+---------+------------------+---------+--------+ - r = ceilf (r); - if (r < lspan) - r = lspan; + The following set sub-rectangles might need to be generated + to render the top span of the trapezoid correctly. - /* Left Edge */ - if (l > x1) - { - lx = EDGE_X (&left, y0); - if (left.dx > 0.0f) - { - tmpx = y1lx + (left.tx - lx); - lx = left.tx; - } - else - { - if (bottom < y1) - { - lx += (left.bx - y1lx); - tmpx = left.bx; - } - else - tmpx = y1lx; - } - - ADD_LEFT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &left, - x1, y0, l, y1, - lx, tmpx); - - lx = l; - } + lE = Left Edge + tE = Top Edge + rE = Right Edge + lEtE = Left/Top Edge intersection + tErE = Top/Right Edge intersection + */ + y1 = ceilf (top); + if (y1 != top) + { + y0 = floorf (top); + lx = x1; + rx = x2; - /* Right Edge */ - if (r < x2) - { - rx = EDGE_X (&right, y0); - if (right.dx < 0.0f) - { - tmpx = y1rx - (rx - right.tx); - rx = right.tx; - } - else - { - if (bottom < y1) - { - rx -= (y1rx - right.bx); - tmpx = right.bx; - } - else - tmpx = y1rx; - } - - ADD_RIGHT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &right, - r, y0, x2, y1, - rx, tmpx); - rx = r; - } + y1lx = EDGE_X (&left, y1); + y1rx = EDGE_X (&right, y1); - /* Left/Top Edge intersection */ - if (lx < l) - { - area = _glitz_pixel_area (l++, y0, - top, bottom, - &left, &right); - - ADD_LEFT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - lx, y0, l, y1, - area); - } - - /* Top Edge */ - while (l < r) - { - if (l < lspan || l >= rspan) - { - area = _glitz_pixel_area (l, y0, - top, bottom, - &left, &right); - - tmpx = l++; - - ADD_PIXEL (vptr, tptr, offset, size, - tmp0, - tbase, tsize, - tmpx, y0, l, y1, - area); - } - else - { - area = MIN (bottom, y1) - top; - ADD_TOP_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - lspan, y0, rspan, y1, - area); - l = rspan; - } - } + if (bottom > y1) + { + l = MAX (left.tx, y1lx); + r = MIN (right.tx, y1rx); + } + else + { + l = MAX (left.tx, left.bx); + r = MIN (right.tx, right.bx); + } - /* Top/Right Edge intersection */ - if (rx > r) - { - area = _glitz_pixel_area (r, y0, - top, bottom, - &left, &right); + lspan = ceilf (l); + rspan = floorf (r); - ADD_RIGHT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - r, y0, rx, y1, - area); - } - } - else - { - y1lx = EDGE_X (&left, y1); - y1rx = EDGE_X (&right, y1); - } + l = floorf (l); + if (l > rspan) + l = rspan; - /* - BOTTOM rectangle - W - +--+------+---------+------------------+---------+----+----+ - | \ | | | | / | - | \ | | | |/ | - | \| | | /| | 1 - | |\ lEbE | bE | bErE / | | - | lE | +------+------------------|----+ | rE | - | | | | | | - +---------+---------+------------------+---------+---------+ + r = ceilf (r); + if (r < lspan) + r = lspan; - The following set sub-rectangles might need to be generated - to render the bottom span of the trapezoid correctly. - - lE = Left Edge - bE = Top Edge - rE = Right Edge - lEbE = Left/Bottom Edge intersection - bErE = Bottom/Right Edge intersection - */ + /* Left Edge */ + if (l > x1) + { + lx = EDGE_X (&left, y0); + if (left.dx > 0.0f) + { + tmpx = y1lx + (left.tx - lx); + lx = left.tx; + } + else + { + if (bottom < y1) + { + lx += (left.bx - y1lx); + tmpx = left.bx; + } + else + tmpx = y1lx; + } - y2 = floorf (bottom); - if (y2 != bottom && y2 >= y1) - { - y3 = ceilf (bottom); - lx = x1; - rx = x2; + ADD_LEFT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &left, + x1, y0, l, y1, + lx, tmpx); - if (y2 > y1) - { - y2lx = EDGE_X (&left, y2); - y2rx = EDGE_X (&right, y2); - } - else - { - y2lx = y1lx; - y2rx = y1rx; - } + lx = l; + } - l = MAX (left.bx, y2lx); - r = MIN (right.bx, y2rx); - - lspan = ceilf (l); - rspan = floorf (r); - - l = floorf (l); - if (l > rspan) - l = rspan; - - r = ceilf (r); - if (r < lspan) - r = lspan; + /* Right Edge */ + if (r < x2) + { + rx = EDGE_X (&right, y0); + if (right.dx < 0.0f) + { + tmpx = y1rx - (rx - right.tx); + rx = right.tx; + } + else + { + if (bottom < y1) + { + rx -= (y1rx - right.bx); + tmpx = right.bx; + } + else + tmpx = y1rx; + } - /* Left Edge */ - if (l > x1) - { - lx = EDGE_X (&left, y3); - if (y2lx > left.bx) - { - tmpx = y2lx + (left.bx - lx); - lx = left.bx; - } else - tmpx = y2lx; - - ADD_LEFT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &left, - x1, y2, l, y3, - tmpx, lx); - lx = l; - } + ADD_RIGHT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &right, + r, y0, x2, y1, + rx, tmpx); + rx = r; + } - /* Right Edge */ - if (r < x2) - { - rx = EDGE_X (&right, y3); - if (y2rx < right.bx) - { - tmpx = y2rx - (rx - right.bx); - rx = right.bx; - } else - tmpx = y2rx; - - ADD_RIGHT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &right, - r, y2, x2, y3, - tmpx, rx); - rx = r; - } + /* Left/Top Edge intersection */ + if (lx < l) + { + area = _glitz_pixel_area (l++, y0, + top, bottom, + &left, &right); - /* Left/Bottom Edge intersection */ - if (lx < l) - { - area = _glitz_pixel_area (l++, y2, - top, bottom, - &left, &right); + ADD_LEFT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + lx, y0, l, y1, + area); + } - ADD_LEFT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - lx, y2, l, y3, - area); - } - - /* Bottom Edge */ - while (l < r) - { - if (l < lspan || l >= rspan) - { - area = _glitz_pixel_area (l, y2, - top, bottom, - &left, &right); - - tmpx = l++; - - ADD_PIXEL (vptr, tptr, offset, size, - tmp0, - tbase, tsize, - tmpx, y2, l, y3, - area); - } - else - { - area = bottom - y2; - ADD_BOTTOM_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - lspan, y2, rspan, y3, - area); - l = rspan; - } - } + /* Top Edge */ + while (l < r) + { + if (l < lspan || l >= rspan) + { + area = _glitz_pixel_area (l, y0, + top, bottom, + &left, &right); - /* Bottom/Right Edge intersection */ - if (rx > r) - { - area = _glitz_pixel_area (r, y2, - top, bottom, - &left, &right); + tmpx = l++; - ADD_RIGHT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - r, y2, rx, y3, - area); - } - } - else - { - y2lx = EDGE_X (&left, y2); - y2rx = EDGE_X (&right, y2); - } + ADD_PIXEL (vptr, tptr, offset, size, + tmp0, + tbase, tsize, + tmpx, y0, l, y1, + area); + } + else + { + area = MIN (bottom, y1) - top; + ADD_TOP_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + lspan, y0, rspan, y1, + area); + l = rspan; + } + } - /* - MIDDLE rectangle - W - +---+---------------------------------+--------+------+ - | \ | / | - | \ | / | - | \ lE | / rE | H - TH - BH - | \ | / | - | \ | / | - +---------+---------------------------+--+------------+ + /* Top/Right Edge intersection */ + if (rx > r) + { + area = _glitz_pixel_area (r, y0, + top, bottom, + &left, &right); - The following set sub-rectangles might need to be generated - to render the middle span of the trapezoid correctly. - - lE = Left Edge - rE = Right Edge + ADD_RIGHT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + r, y0, rx, y1, + area); + } + } + else + { + y1lx = EDGE_X (&left, y1); + y1rx = EDGE_X (&right, y1); + } - If floor (MIN (rE)) < ceil (MAX (lE)) a number of left and right - edges needs to be generated as pixels intersected by both edges - needs to be calculated separately in a middle span. - */ - if (y1 < y2) - { - left.tx = y1lx; - right.tx = y1rx; + /* + BOTTOM rectangle + W + +--+------+---------+------------------+---------+----+----+ + | \ | | | | / | + | \ | | | |/ | + | \| | | /| | 1 + | |\ lEbE | bE | bErE / | | + | lE | +------+------------------|----+ | rE | + | | | | | | + +---------+---------+------------------+---------+---------+ - do { - if (left.tx > y2rx) - { - rx = lx = ceilf (left.tx); - if (right.dx) - y = floorf (EDGE_Y (&right, rx)); - else - y = y2; - } - else - { - rx = lx = floorf (MIN (right.tx, y2rx)); - if (left.dx) - y = floorf (EDGE_Y (&left, rx)); - else - y = y2; - } + The following set sub-rectangles might need to be generated + to render the bottom span of the trapezoid correctly. - if (y == y1) - y = y1 + 1.0f; + lE = Left Edge + bE = Top Edge + rE = Right Edge + lEbE = Left/Bottom Edge intersection + bErE = Bottom/Right Edge intersection + */ - if (y > y1 && y < y2) - { - left.bx = EDGE_X (&left, y); - right.bx = EDGE_X (&right, y); - } - else - { - y = y2; - left.bx = y2lx; - right.bx = y2rx; - } + y2 = floorf (bottom); + if (y2 != bottom && y2 >= y1) + { + y3 = ceilf (bottom); + lx = x1; + rx = x2; - if (lx > right.tx) - lx = floorf (right.tx); + if (y2 > y1) + { + y2lx = EDGE_X (&left, y2); + y2rx = EDGE_X (&right, y2); + } + else + { + y2lx = y1lx; + y2rx = y1rx; + } - if (lx > right.bx) - lx = floorf (right.bx); + l = MAX (left.bx, y2lx); + r = MIN (right.bx, y2rx); - if (rx < left.tx) - rx = ceilf (left.tx); + lspan = ceilf (l); + rspan = floorf (r); - if (rx < left.bx) - rx = ceilf (left.bx); + l = floorf (l); + if (l > rspan) + l = rspan; - /* Left Edge */ - if (lx > x1) - { - if (left.dx) - { - ADD_LEFT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &left, - x1, y1, lx, y, - left.tx, left.bx); - } - else - { - area = lx - left.x0; - ADD_LEFT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - x1, y1, lx, y, - area); - } - } + r = ceilf (r); + if (r < lspan) + r = lspan; - /* Middle Span */ - while (lx < rx) - { - tmpy = y1; - tmpx = lx++; - - while (tmpy < y) - { - y0 = tmpy++; - area = _glitz_pixel_area (tmpx, y0, - y0, y2, - &left, &right); - - ADD_PIXEL (vptr, tptr, offset, size, - tmp0, - tbase, tsize, - tmpx, y0, lx, tmpy, - area); - } - } - - /* Right Edge */ - if (rx < x2) - { - if (right.dx) - { - ADD_RIGHT_EDGE (vptr, tptr, offset, size, - tmp0, tmp1, tmp2, tmp3, - tbase, tsize, &right, - rx, y1, x2, y, - right.tx, right.bx); - } - else - { - area = right.x0 - rx; - ADD_RIGHT_SPAN (vptr, tptr, offset, size, - tmp0, tmp1, - tbase, tsize, - rx, y1, x2, y, - area); - } - } + /* Left Edge */ + if (l > x1) + { + lx = EDGE_X (&left, y3); + if (y2lx > left.bx) + { + tmpx = y2lx + (left.bx - lx); + lx = left.bx; + } else + tmpx = y2lx; - left.tx = left.bx; - right.tx = right.bx; - y1 = y; - } while (y < y2); - } + ADD_LEFT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &left, + x1, y2, l, y3, + tmpx, lx); + lx = l; + } - toff = offset; + /* Right Edge */ + if (r < x2) + { + rx = EDGE_X (&right, y3); + if (y2rx < right.bx) + { + tmpx = y2rx - (rx - right.bx); + rx = right.bx; + } else + tmpx = y2rx; + + ADD_RIGHT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &right, + r, y2, x2, y3, + tmpx, rx); + rx = r; + } + + /* Left/Bottom Edge intersection */ + if (lx < l) + { + area = _glitz_pixel_area (l++, y2, + top, bottom, + &left, &right); + + ADD_LEFT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + lx, y2, l, y3, + area); + } + + /* Bottom Edge */ + while (l < r) + { + if (l < lspan || l >= rspan) + { + area = _glitz_pixel_area (l, y2, + top, bottom, + &left, &right); + + tmpx = l++; + + ADD_PIXEL (vptr, tptr, offset, size, + tmp0, + tbase, tsize, + tmpx, y2, l, y3, + area); + } + else + { + area = bottom - y2; + ADD_BOTTOM_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + lspan, y2, rspan, y3, + area); + l = rspan; + } + } + + /* Bottom/Right Edge intersection */ + if (rx > r) + { + area = _glitz_pixel_area (r, y2, + top, bottom, + &left, &right); + + ADD_RIGHT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + r, y2, rx, y3, + area); + } + } + else + { + y2lx = EDGE_X (&left, y2); + y2rx = EDGE_X (&right, y2); + } + + /* + MIDDLE rectangle + W + +---+---------------------------------+--------+------+ + | \ | / | + | \ | / | + | \ lE | / rE | H - TH - BH + | \ | / | + | \ | / | + +---------+---------------------------+--+------------+ + + The following set sub-rectangles might need to be generated + to render the middle span of the trapezoid correctly. + + lE = Left Edge + rE = Right Edge + + If floor (MIN (rE)) < ceil (MAX (lE)) a number of left and right + edges needs to be generated as pixels intersected by both edges + needs to be calculated separately in a middle span. + */ + if (y1 < y2) + { + left.tx = y1lx; + right.tx = y1rx; + + do { + if (left.tx > y2rx) + { + rx = lx = ceilf (left.tx); + if (right.dx) + y = floorf (EDGE_Y (&right, rx)); + else + y = y2; + } + else + { + rx = lx = floorf (MIN (right.tx, y2rx)); + if (left.dx) + y = floorf (EDGE_Y (&left, rx)); + else + y = y2; + } + + if (y == y1) + y = y1 + 1.0f; + + if (y > y1 && y < y2) + { + left.bx = EDGE_X (&left, y); + right.bx = EDGE_X (&right, y); + } + else + { + y = y2; + left.bx = y2lx; + right.bx = y2rx; + } + + if (lx > right.tx) + lx = floorf (right.tx); + + if (lx > right.bx) + lx = floorf (right.bx); + + if (rx < left.tx) + rx = ceilf (left.tx); + + if (rx < left.bx) + rx = ceilf (left.bx); + + /* Left Edge */ + if (lx > x1) + { + if (left.dx) + { + ADD_LEFT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &left, + x1, y1, lx, y, + left.tx, left.bx); + } + else + { + area = lx - left.x0; + ADD_LEFT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + x1, y1, lx, y, + area); + } + } + + /* Middle Span */ + while (lx < rx) + { + tmpy = y1; + tmpx = lx++; + + while (tmpy < y) + { + y0 = tmpy++; + area = _glitz_pixel_area (tmpx, y0, + y0, y2, + &left, &right); + + ADD_PIXEL (vptr, tptr, offset, size, + tmp0, + tbase, tsize, + tmpx, y0, lx, tmpy, + area); + } + } + + /* Right Edge */ + if (rx < x2) + { + if (right.dx) + { + ADD_RIGHT_EDGE (vptr, tptr, offset, size, + tmp0, tmp1, tmp2, tmp3, + tbase, tsize, &right, + rx, y1, x2, y, + right.tx, right.bx); + } + else + { + area = right.x0 - rx; + ADD_RIGHT_SPAN (vptr, tptr, offset, size, + tmp0, tmp1, + tbase, tsize, + rx, y1, x2, y, + area); + } + } + + left.tx = left.bx; + right.tx = right.bx; + y1 = y; + } while (y < y2); + } + + toff = offset; } return toff; diff --git a/gfx/cairo/glitz/src/glitz_util.c b/gfx/cairo/glitz/src/glitz_util.c index 369dbe9aad4..3a2bb6a8ef4 100644 --- a/gfx/cairo/glitz/src/glitz_util.c +++ b/gfx/cairo/glitz/src/glitz_util.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -33,335 +33,369 @@ #include static glitz_extension_map gl_extensions[] = { - { 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, "GL_EXT_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, "GL_NV_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, - { 0.0, "GL_ARB_texture_non_power_of_two", - GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK }, - { 0.0, "GL_ARB_texture_mirrored_repeat", - GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK }, - { 0.0, "GL_ARB_texture_border_clamp", - GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK }, - { 0.0, "GL_ARB_texture_env_combine", - GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK }, - { 0.0, "GL_EXT_texture_env_combine", - GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK }, - { 0.0, "GL_ARB_texture_env_dot3", GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK }, - { 0.0, "GL_ARB_multisample", GLITZ_FEATURE_MULTISAMPLE_MASK }, - { 0.0, "GL_NV_multisample_filter_hint", - GLITZ_FEATURE_MULTISAMPLE_FILTER_HINT_MASK }, - { 0.0, "GL_ARB_multitexture", GLITZ_FEATURE_MULTITEXTURE_MASK }, - { 0.0, "GL_EXT_multi_draw_arrays", GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK }, - { 0.0, "GL_ARB_fragment_program", GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK }, - { 0.0, "GL_ARB_vertex_buffer_object", - GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK }, - { 0.0, "GL_ARB_pixel_buffer_object", - GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, - { 0.0, "GL_EXT_pixel_buffer_object", - GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, - { 0.0, "GL_EXT_blend_color", GLITZ_FEATURE_BLEND_COLOR_MASK }, - { 0.0, "GL_ARB_imaging", GLITZ_FEATURE_BLEND_COLOR_MASK }, - { 0.0, "GL_APPLE_packed_pixels", GLITZ_FEATURE_PACKED_PIXELS_MASK }, - { 0.0, "GL_EXT_framebuffer_object", GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK }, - { 0.0, NULL, 0 } + { 0.0, "GL_ARB_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, "GL_EXT_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, "GL_NV_texture_rectangle", GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK }, + { 0.0, "GL_ARB_texture_non_power_of_two", + GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK }, + { 0.0, "GL_ARB_texture_mirrored_repeat", + GLITZ_FEATURE_TEXTURE_MIRRORED_REPEAT_MASK }, + { 0.0, "GL_ARB_texture_border_clamp", + GLITZ_FEATURE_TEXTURE_BORDER_CLAMP_MASK }, + { 0.0, "GL_ARB_texture_env_combine", + GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK }, + { 0.0, "GL_EXT_texture_env_combine", + GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK }, + { 0.0, "GL_ARB_texture_env_dot3", GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK }, + { 0.0, "GL_ARB_multisample", GLITZ_FEATURE_MULTISAMPLE_MASK }, + { 0.0, "GL_NV_multisample_filter_hint", + GLITZ_FEATURE_MULTISAMPLE_FILTER_HINT_MASK }, + { 0.0, "GL_ARB_multitexture", GLITZ_FEATURE_MULTITEXTURE_MASK }, + { 0.0, "GL_EXT_multi_draw_arrays", GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK }, + { 0.0, "GL_ARB_fragment_program", GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK }, + { 0.0, "GL_ARB_vertex_buffer_object", + GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK }, + { 0.0, "GL_ARB_pixel_buffer_object", + GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, + { 0.0, "GL_EXT_pixel_buffer_object", + GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK }, + { 0.0, "GL_EXT_blend_color", GLITZ_FEATURE_BLEND_COLOR_MASK }, + { 0.0, "GL_ARB_imaging", GLITZ_FEATURE_BLEND_COLOR_MASK }, + { 0.0, "GL_APPLE_packed_pixels", GLITZ_FEATURE_PACKED_PIXELS_MASK }, + { 0.0, "GL_EXT_framebuffer_object", + GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK }, + { 0.0, NULL, 0 } }; static glitz_bool_t _glitz_extension_check (const char *extensions, - const char *ext_name) + const char *ext_name) { - char *end; - char *p = (char *) extensions; - int ext_name_len = strlen (ext_name); + char *end; + char *p = (char *) extensions; + int ext_name_len = strlen (ext_name); - if (! p) - return 0; + if (! p) + return 0; - end = p + strlen (p); + end = p + strlen (p); - while (p < end) { - int n = strcspn (p, " "); + while (p < end) { + int n = strcspn (p, " "); - if ((ext_name_len == n) && (strncmp (ext_name, p, n) == 0)) { - return 1; + if ((ext_name_len == n) && (strncmp (ext_name, p, n) == 0)) { + return 1; + } + p += (n + 1); } - p += (n + 1); - } - return 0; + return 0; } unsigned long glitz_extensions_query (glitz_gl_float_t version, - const char *extensions_string, - glitz_extension_map *extensions_map) + const char *extensions_string, + glitz_extension_map *extensions_map) { - unsigned long mask = 0; - int i; + unsigned long mask = 0; + int i; - for (i = 0; extensions_map[i].name; i++) - if (((extensions_map[i].version > 1.0) && - (version >= extensions_map[i].version)) || - _glitz_extension_check (extensions_string, extensions_map[i].name)) - mask |= extensions_map[i].mask; + for (i = 0; extensions_map[i].name; i++) + if (((extensions_map[i].version > 1.0) && + (version >= extensions_map[i].version)) || + _glitz_extension_check (extensions_string, extensions_map[i].name)) + mask |= extensions_map[i].mask; - return mask; + return mask; } static glitz_status_t _glitz_query_gl_extensions (glitz_gl_proc_address_list_t *gl, - glitz_gl_float_t *gl_version, - unsigned long *feature_mask) + glitz_gl_float_t *gl_version, + unsigned long *feature_mask) { - const char *gl_extensions_string; + const char *gl_extensions_string; - *gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION)); - if (*gl_version < 1.2f) - return GLITZ_STATUS_NOT_SUPPORTED; - - gl_extensions_string = (const char *) gl->get_string (GLITZ_GL_EXTENSIONS); - - *feature_mask = glitz_extensions_query (*gl_version, - gl_extensions_string, - gl_extensions); - - if ((*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) && - (*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK)) { - glitz_gl_int_t max_texture_units; - - gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units); - if (max_texture_units >= 3) - *feature_mask |= GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK; - } + *gl_version = atof ((const char *) gl->get_string (GLITZ_GL_VERSION)); + if (*gl_version < 1.2f) + return GLITZ_STATUS_NOT_SUPPORTED; - return GLITZ_STATUS_SUCCESS; + gl_extensions_string = (const char *) gl->get_string (GLITZ_GL_EXTENSIONS); + + *feature_mask = glitz_extensions_query (*gl_version, + gl_extensions_string, + gl_extensions); + + if ((*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_COMBINE_MASK) && + (*feature_mask & GLITZ_FEATURE_TEXTURE_ENV_DOT3_MASK)) { + glitz_gl_int_t max_texture_units; + + gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_UNITS, &max_texture_units); + if (max_texture_units >= 3) + *feature_mask |= GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK; + } + + return GLITZ_STATUS_SUCCESS; } static void _glitz_gl_proc_address_lookup (glitz_backend_t *backend, - glitz_get_proc_address_proc_t get_proc_address, - void *closure) + glitz_get_proc_address_proc_t get_proc_address, + void *closure) { - if (backend->feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) { - if (backend->gl_version >= 1.4f) { - backend->gl.blend_color = (glitz_gl_blend_color_t) - get_proc_address ("glBlendColor", closure); - } else { - backend->gl.blend_color = (glitz_gl_blend_color_t) - get_proc_address ("glBlendColorEXT", closure); + if (backend->feature_mask & GLITZ_FEATURE_BLEND_COLOR_MASK) { + if (backend->gl_version >= 1.4f) { + backend->gl->blend_color = (glitz_gl_blend_color_t) + get_proc_address ("glBlendColor", closure); + } else { + backend->gl->blend_color = (glitz_gl_blend_color_t) + get_proc_address ("glBlendColorEXT", closure); + } + + if (!backend->gl->blend_color) + backend->feature_mask &= ~GLITZ_FEATURE_BLEND_COLOR_MASK; } - if (!backend->gl.blend_color) - backend->feature_mask &= ~GLITZ_FEATURE_BLEND_COLOR_MASK; - } + if (backend->feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK) { + if (backend->gl_version >= 1.3f) { + backend->gl->active_texture = (glitz_gl_active_texture_t) + get_proc_address ("glActiveTexture", closure); + backend->gl->client_active_texture = + (glitz_gl_client_active_texture_t) + get_proc_address ("glClientActiveTexture", closure); + } else { + backend->gl->active_texture = (glitz_gl_active_texture_t) + get_proc_address ("glActiveTextureARB", closure); + backend->gl->client_active_texture = + (glitz_gl_client_active_texture_t) + get_proc_address ("glClientActiveTextureARB", closure); + } - if (backend->feature_mask & GLITZ_FEATURE_MULTITEXTURE_MASK) { - if (backend->gl_version >= 1.3f) { - backend->gl.active_texture = (glitz_gl_active_texture_t) - get_proc_address ("glActiveTexture", closure); - backend->gl.client_active_texture = (glitz_gl_client_active_texture_t) - get_proc_address ("glClientActiveTexture", closure); - } else { - backend->gl.active_texture = (glitz_gl_active_texture_t) - get_proc_address ("glActiveTextureARB", closure); - backend->gl.client_active_texture = (glitz_gl_client_active_texture_t) - get_proc_address ("glClientActiveTextureARB", closure); + if ((!backend->gl->active_texture) || + (!backend->gl->client_active_texture)) { + backend->feature_mask &= ~GLITZ_FEATURE_MULTITEXTURE_MASK; + backend->feature_mask &= + ~GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK; + } } - if ((!backend->gl.active_texture) || - (!backend->gl.client_active_texture)) { - backend->feature_mask &= ~GLITZ_FEATURE_MULTITEXTURE_MASK; - backend->feature_mask &= ~GLITZ_FEATURE_PER_COMPONENT_RENDERING_MASK; - } - } + if (backend->feature_mask & GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) { + backend->gl->multi_draw_arrays = (glitz_gl_multi_draw_arrays_t) + get_proc_address ("glMultiDrawArraysEXT", closure); - if (backend->feature_mask & GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK) { - backend->gl.multi_draw_arrays = (glitz_gl_multi_draw_arrays_t) - get_proc_address ("glMultiDrawArraysEXT", closure); - - if (!backend->gl.multi_draw_arrays) - backend->feature_mask &= ~GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK; - } - - if (backend->feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) { - backend->gl.gen_programs = (glitz_gl_gen_programs_t) - get_proc_address ("glGenProgramsARB", closure); - backend->gl.delete_programs = (glitz_gl_delete_programs_t) - get_proc_address ("glDeleteProgramsARB", closure); - backend->gl.program_string = (glitz_gl_program_string_t) - get_proc_address ("glProgramStringARB", closure); - backend->gl.bind_program = (glitz_gl_bind_program_t) - get_proc_address ("glBindProgramARB", closure); - backend->gl.program_local_param_4fv = (glitz_gl_program_local_param_4fv_t) - get_proc_address ("glProgramLocalParameter4fvARB", closure); - backend->gl.get_program_iv = (glitz_gl_get_program_iv_t) - get_proc_address ("glGetProgramivARB", closure); - - if ((!backend->gl.gen_programs) || - (!backend->gl.delete_programs) || - (!backend->gl.program_string) || - (!backend->gl.bind_program) || - (!backend->gl.program_local_param_4fv)) - backend->feature_mask &= ~GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK; - } - - if ((backend->feature_mask & GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK) || - (backend->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK)) { - if (backend->gl_version >= 1.5f) { - backend->gl.gen_buffers = (glitz_gl_gen_buffers_t) - get_proc_address ("glGenBuffers", closure); - backend->gl.delete_buffers = (glitz_gl_delete_buffers_t) - get_proc_address ("glDeleteBuffers", closure); - backend->gl.bind_buffer = (glitz_gl_bind_buffer_t) - get_proc_address ("glBindBuffer", closure); - backend->gl.buffer_data = (glitz_gl_buffer_data_t) - get_proc_address ("glBufferData", closure); - backend->gl.buffer_sub_data = (glitz_gl_buffer_sub_data_t) - get_proc_address ("glBufferSubData", closure); - backend->gl.get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t) - get_proc_address ("glGetBufferSubData", closure); - backend->gl.map_buffer = (glitz_gl_map_buffer_t) - get_proc_address ("glMapBuffer", closure); - backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t) - get_proc_address ("glUnmapBuffer", closure); - } else { - backend->gl.gen_buffers = (glitz_gl_gen_buffers_t) - get_proc_address ("glGenBuffersARB", closure); - backend->gl.delete_buffers = (glitz_gl_delete_buffers_t) - get_proc_address ("glDeleteBuffersARB", closure); - backend->gl.bind_buffer = (glitz_gl_bind_buffer_t) - get_proc_address ("glBindBufferARB", closure); - backend->gl.buffer_data = (glitz_gl_buffer_data_t) - get_proc_address ("glBufferDataARB", closure); - backend->gl.buffer_sub_data = (glitz_gl_buffer_sub_data_t) - get_proc_address ("glBufferSubDataARB", closure); - backend->gl.get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t) - get_proc_address ("glGetBufferSubDataARB", closure); - backend->gl.map_buffer = (glitz_gl_map_buffer_t) - get_proc_address ("glMapBufferARB", closure); - backend->gl.unmap_buffer = (glitz_gl_unmap_buffer_t) - get_proc_address ("glUnmapBufferARB", closure); + if (!backend->gl->multi_draw_arrays) + backend->feature_mask &= ~GLITZ_FEATURE_MULTI_DRAW_ARRAYS_MASK; } - if ((!backend->gl.gen_buffers) || - (!backend->gl.delete_buffers) || - (!backend->gl.bind_buffer) || - (!backend->gl.buffer_data) || - (!backend->gl.buffer_sub_data) || - (!backend->gl.get_buffer_sub_data) || - (!backend->gl.map_buffer) || - (!backend->gl.unmap_buffer)) { - backend->feature_mask &= ~GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK; - backend->feature_mask &= ~GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; - } - } + if (backend->feature_mask & GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK) { + backend->gl->gen_programs = (glitz_gl_gen_programs_t) + get_proc_address ("glGenProgramsARB", closure); + backend->gl->delete_programs = (glitz_gl_delete_programs_t) + get_proc_address ("glDeleteProgramsARB", closure); + backend->gl->program_string = (glitz_gl_program_string_t) + get_proc_address ("glProgramStringARB", closure); + backend->gl->bind_program = (glitz_gl_bind_program_t) + get_proc_address ("glBindProgramARB", closure); + backend->gl->program_local_param_4fv = + (glitz_gl_program_local_param_4fv_t) + get_proc_address ("glProgramLocalParameter4fvARB", closure); + backend->gl->get_program_iv = (glitz_gl_get_program_iv_t) + get_proc_address ("glGetProgramivARB", closure); - if (backend->feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) { - backend->gl.gen_framebuffers = (glitz_gl_gen_framebuffers_t) - get_proc_address ("glGenFramebuffersEXT", closure); - backend->gl.delete_framebuffers = (glitz_gl_delete_framebuffers_t) - get_proc_address ("glDeleteFramebuffersEXT", closure); - backend->gl.bind_framebuffer = (glitz_gl_bind_framebuffer_t) - get_proc_address ("glBindFramebufferEXT", closure); - backend->gl.check_framebuffer_status = - (glitz_gl_check_framebuffer_status_t) - get_proc_address ("glCheckFramebufferStatusEXT", closure); - backend->gl.framebuffer_texture_2d = (glitz_gl_framebuffer_texture_2d_t) - get_proc_address ("glFramebufferTexture2DEXT", closure); - - if ((!backend->gl.gen_framebuffers) || - (!backend->gl.delete_framebuffers) || - (!backend->gl.bind_framebuffer) || - (!backend->gl.check_framebuffer_status) || - (!backend->gl.framebuffer_texture_2d)) - backend->feature_mask &= ~GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK; - } + if ((!backend->gl->gen_programs) || + (!backend->gl->delete_programs) || + (!backend->gl->program_string) || + (!backend->gl->bind_program) || + (!backend->gl->program_local_param_4fv)) + backend->feature_mask &= ~GLITZ_FEATURE_FRAGMENT_PROGRAM_MASK; + } + + if ((backend->feature_mask & GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK) || + (backend->feature_mask & GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK)) { + if (backend->gl_version >= 1.5f) { + backend->gl->gen_buffers = (glitz_gl_gen_buffers_t) + get_proc_address ("glGenBuffers", closure); + backend->gl->delete_buffers = (glitz_gl_delete_buffers_t) + get_proc_address ("glDeleteBuffers", closure); + backend->gl->bind_buffer = (glitz_gl_bind_buffer_t) + get_proc_address ("glBindBuffer", closure); + backend->gl->buffer_data = (glitz_gl_buffer_data_t) + get_proc_address ("glBufferData", closure); + backend->gl->buffer_sub_data = (glitz_gl_buffer_sub_data_t) + get_proc_address ("glBufferSubData", closure); + backend->gl->get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t) + get_proc_address ("glGetBufferSubData", closure); + backend->gl->map_buffer = (glitz_gl_map_buffer_t) + get_proc_address ("glMapBuffer", closure); + backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t) + get_proc_address ("glUnmapBuffer", closure); + } else { + backend->gl->gen_buffers = (glitz_gl_gen_buffers_t) + get_proc_address ("glGenBuffersARB", closure); + backend->gl->delete_buffers = (glitz_gl_delete_buffers_t) + get_proc_address ("glDeleteBuffersARB", closure); + backend->gl->bind_buffer = (glitz_gl_bind_buffer_t) + get_proc_address ("glBindBufferARB", closure); + backend->gl->buffer_data = (glitz_gl_buffer_data_t) + get_proc_address ("glBufferDataARB", closure); + backend->gl->buffer_sub_data = (glitz_gl_buffer_sub_data_t) + get_proc_address ("glBufferSubDataARB", closure); + backend->gl->get_buffer_sub_data = (glitz_gl_get_buffer_sub_data_t) + get_proc_address ("glGetBufferSubDataARB", closure); + backend->gl->map_buffer = (glitz_gl_map_buffer_t) + get_proc_address ("glMapBufferARB", closure); + backend->gl->unmap_buffer = (glitz_gl_unmap_buffer_t) + get_proc_address ("glUnmapBufferARB", closure); + } + + if ((!backend->gl->gen_buffers) || + (!backend->gl->delete_buffers) || + (!backend->gl->bind_buffer) || + (!backend->gl->buffer_data) || + (!backend->gl->buffer_sub_data) || + (!backend->gl->get_buffer_sub_data) || + (!backend->gl->map_buffer) || + (!backend->gl->unmap_buffer)) { + backend->feature_mask &= ~GLITZ_FEATURE_VERTEX_BUFFER_OBJECT_MASK; + backend->feature_mask &= ~GLITZ_FEATURE_PIXEL_BUFFER_OBJECT_MASK; + } + } + + if (backend->feature_mask & GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK) { + backend->gl->gen_framebuffers = (glitz_gl_gen_framebuffers_t) + get_proc_address ("glGenFramebuffersEXT", closure); + backend->gl->delete_framebuffers = (glitz_gl_delete_framebuffers_t) + get_proc_address ("glDeleteFramebuffersEXT", closure); + backend->gl->bind_framebuffer = (glitz_gl_bind_framebuffer_t) + get_proc_address ("glBindFramebufferEXT", closure); + backend->gl->framebuffer_renderbuffer = + (glitz_gl_framebuffer_renderbuffer_t) + get_proc_address ("glFramebufferRenderbufferEXT", closure); + backend->gl->framebuffer_texture_2d = + (glitz_gl_framebuffer_texture_2d_t) + get_proc_address ("glFramebufferTexture2DEXT", closure); + backend->gl->check_framebuffer_status = + (glitz_gl_check_framebuffer_status_t) + get_proc_address ("glCheckFramebufferStatusEXT", closure); + backend->gl->gen_renderbuffers = (glitz_gl_gen_renderbuffers_t) + get_proc_address ("glGenRenderbuffersEXT", closure); + backend->gl->delete_renderbuffers = (glitz_gl_delete_renderbuffers_t) + get_proc_address ("glDeleteRenderbuffersEXT", closure); + backend->gl->bind_renderbuffer = (glitz_gl_bind_renderbuffer_t) + get_proc_address ("glBindRenderbufferEXT", closure); + backend->gl->renderbuffer_storage = (glitz_gl_renderbuffer_storage_t) + get_proc_address ("glRenderbufferStorageEXT", closure); + backend->gl->get_renderbuffer_parameter_iv = + (glitz_gl_get_renderbuffer_parameter_iv_t) + get_proc_address ("glGetRenderbufferParameterivEXT", closure); + + if ((!backend->gl->gen_framebuffers) || + (!backend->gl->delete_framebuffers) || + (!backend->gl->bind_framebuffer) || + (!backend->gl->framebuffer_renderbuffer) || + (!backend->gl->framebuffer_texture_2d) || + (!backend->gl->check_framebuffer_status) || + (!backend->gl->gen_renderbuffers) || + (!backend->gl->delete_renderbuffers) || + (!backend->gl->bind_renderbuffer) || + (!backend->gl->renderbuffer_storage) || + (!backend->gl->get_renderbuffer_parameter_iv)) + backend->feature_mask &= ~GLITZ_FEATURE_FRAMEBUFFER_OBJECT_MASK; + } } void glitz_backend_init (glitz_backend_t *backend, - glitz_get_proc_address_proc_t get_proc_address, - void *closure) + glitz_get_proc_address_proc_t get_proc_address, + void *closure) { - if (!_glitz_query_gl_extensions (&backend->gl, - &backend->gl_version, - &backend->feature_mask)) { - _glitz_gl_proc_address_lookup (backend, get_proc_address, closure); - glitz_create_surface_formats (&backend->gl, - &backend->formats, - &backend->texture_formats, - &backend->n_formats); - } - - backend->gl.get_integer_v (GLITZ_GL_MAX_TEXTURE_SIZE, - &backend->max_texture_2d_size); - - if (backend->feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK) - backend->gl.get_integer_v (GLITZ_GL_MAX_RECTANGLE_TEXTURE_SIZE, - &backend->max_texture_rect_size); - else - backend->max_texture_rect_size = 0; + if (!_glitz_query_gl_extensions (backend->gl, + &backend->gl_version, + &backend->feature_mask)) { + _glitz_gl_proc_address_lookup (backend, get_proc_address, closure); + glitz_create_surface_formats (backend->gl, + &backend->formats, + &backend->texture_formats, + &backend->n_formats); + _glitz_add_drawable_formats (backend->gl, + backend->feature_mask, + &backend->drawable_formats, + &backend->n_drawable_formats); + } + + backend->gl->get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS, + backend->max_viewport_dims); + + backend->gl->get_integer_v (GLITZ_GL_MAX_TEXTURE_SIZE, + &backend->max_texture_2d_size); + + if (backend->feature_mask & GLITZ_FEATURE_TEXTURE_RECTANGLE_MASK) + backend->gl->get_integer_v (GLITZ_GL_MAX_RECTANGLE_TEXTURE_SIZE, + &backend->max_texture_rect_size); + else + backend->max_texture_rect_size = 0; } unsigned int glitz_uint_to_power_of_two (unsigned int x) { - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - - return (x + 1); + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return (x + 1); } void glitz_set_raster_pos (glitz_gl_proc_address_list_t *gl, - glitz_float_t x, - glitz_float_t y) + glitz_float_t x, + glitz_float_t y) { - gl->push_attrib (GLITZ_GL_TRANSFORM_BIT | GLITZ_GL_VIEWPORT_BIT); - gl->matrix_mode (GLITZ_GL_PROJECTION); - gl->push_matrix (); - gl->load_identity (); - gl->matrix_mode (GLITZ_GL_MODELVIEW); - gl->push_matrix (); - gl->load_identity (); - gl->depth_range (0, 1); - gl->viewport (-1, -1, 2, 2); - - gl->raster_pos_2f (0, 0); - gl->bitmap (0, 0, 1, 1, x, y, NULL); - - gl->pop_matrix (); - gl->matrix_mode (GLITZ_GL_PROJECTION); - gl->pop_matrix (); - gl->pop_attrib (); + gl->push_attrib (GLITZ_GL_TRANSFORM_BIT | GLITZ_GL_VIEWPORT_BIT); + gl->matrix_mode (GLITZ_GL_PROJECTION); + gl->push_matrix (); + gl->load_identity (); + gl->matrix_mode (GLITZ_GL_MODELVIEW); + gl->push_matrix (); + gl->load_identity (); + gl->depth_range (0, 1); + gl->viewport (-1, -1, 2, 2); + + gl->raster_pos_2f (0, 0); + gl->bitmap (0, 0, 1, 1, x, y, NULL); + + gl->pop_matrix (); + gl->matrix_mode (GLITZ_GL_PROJECTION); + gl->pop_matrix (); + gl->pop_attrib (); } void glitz_clamp_value (glitz_float_t *value, - glitz_float_t min, glitz_float_t max) + glitz_float_t min, glitz_float_t max) { - if (*value < min) - *value = min; - else if (*value > max) - *value = max; + if (*value < min) + *value = min; + else if (*value > max) + *value = max; } void glitz_initiate_state (glitz_gl_proc_address_list_t *gl) { - gl->hint (GLITZ_GL_PERSPECTIVE_CORRECTION_HINT, GLITZ_GL_FASTEST); - gl->disable (GLITZ_GL_CULL_FACE); - gl->depth_mask (GLITZ_GL_FALSE); - gl->polygon_mode (GLITZ_GL_FRONT_AND_BACK, GLITZ_GL_FILL); - gl->disable (GLITZ_GL_POLYGON_SMOOTH); - gl->disable (GLITZ_GL_LINE_SMOOTH); - gl->disable (GLITZ_GL_POINT_SMOOTH); - gl->shade_model (GLITZ_GL_FLAT); - gl->color_mask (GLITZ_GL_TRUE, GLITZ_GL_TRUE, GLITZ_GL_TRUE, GLITZ_GL_TRUE); - gl->enable (GLITZ_GL_SCISSOR_TEST); - gl->disable (GLITZ_GL_STENCIL_TEST); - gl->enable_client_state (GLITZ_GL_VERTEX_ARRAY); - gl->disable (GLITZ_GL_DEPTH_TEST); + gl->hint (GLITZ_GL_PERSPECTIVE_CORRECTION_HINT, GLITZ_GL_FASTEST); + gl->disable (GLITZ_GL_CULL_FACE); + gl->depth_mask (GLITZ_GL_FALSE); + gl->polygon_mode (GLITZ_GL_FRONT_AND_BACK, GLITZ_GL_FILL); + gl->disable (GLITZ_GL_POLYGON_SMOOTH); + gl->disable (GLITZ_GL_LINE_SMOOTH); + gl->disable (GLITZ_GL_POINT_SMOOTH); + gl->shade_model (GLITZ_GL_FLAT); + gl->color_mask (GLITZ_GL_TRUE, GLITZ_GL_TRUE, + GLITZ_GL_TRUE, GLITZ_GL_TRUE); + gl->enable (GLITZ_GL_SCISSOR_TEST); + gl->disable (GLITZ_GL_STENCIL_TEST); + gl->enable_client_state (GLITZ_GL_VERTEX_ARRAY); + gl->disable (GLITZ_GL_DEPTH_TEST); } diff --git a/gfx/cairo/glitz/src/glitzint.h b/gfx/cairo/glitz/src/glitzint.h index f6cee9a3087..277f9603226 100644 --- a/gfx/cairo/glitz/src/glitzint.h +++ b/gfx/cairo/glitz/src/glitzint.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -88,7 +88,7 @@ #define GLITZ_CONTEXT_STACK_SIZE 16 typedef struct _glitz_gl_proc_address_list_t { - + /* core */ glitz_gl_enable_t enable; glitz_gl_disable_t disable; @@ -145,6 +145,7 @@ typedef struct _glitz_gl_proc_address_list_t { glitz_gl_bind_texture_t bind_texture; glitz_gl_tex_image_2d_t tex_image_2d; glitz_gl_tex_parameter_i_t tex_parameter_i; + glitz_gl_tex_parameter_fv_t tex_parameter_fv; glitz_gl_get_tex_level_parameter_iv_t get_tex_level_parameter_iv; glitz_gl_copy_tex_sub_image_2d_t copy_tex_sub_image_2d; glitz_gl_get_integer_v_t get_integer_v; @@ -171,8 +172,14 @@ typedef struct _glitz_gl_proc_address_list_t { glitz_gl_gen_framebuffers_t gen_framebuffers; glitz_gl_delete_framebuffers_t delete_framebuffers; glitz_gl_bind_framebuffer_t bind_framebuffer; - glitz_gl_check_framebuffer_status_t check_framebuffer_status; + glitz_gl_framebuffer_renderbuffer_t framebuffer_renderbuffer; glitz_gl_framebuffer_texture_2d_t framebuffer_texture_2d; + glitz_gl_check_framebuffer_status_t check_framebuffer_status; + glitz_gl_gen_renderbuffers_t gen_renderbuffers; + glitz_gl_delete_renderbuffers_t delete_renderbuffers; + glitz_gl_bind_renderbuffer_t bind_renderbuffer; + glitz_gl_renderbuffer_storage_t renderbuffer_storage; + glitz_gl_get_renderbuffer_parameter_iv_t get_renderbuffer_parameter_iv; } glitz_gl_proc_address_list_t; typedef int glitz_surface_type_t; @@ -307,52 +314,81 @@ typedef struct _glitz_region_t { extern glitz_status_t __internal_linkage glitz_region_union (glitz_region_t *region, - glitz_box_t *box); + glitz_box_t *box); + +#define GLITZ_DRAWABLE_TYPE_WINDOW_MASK (1L << 0) +#define GLITZ_DRAWABLE_TYPE_PBUFFER_MASK (1L << 1) +#define GLITZ_DRAWABLE_TYPE_FBO_MASK (1L << 2) + +#define GLITZ_INT_FORMAT_WINDOW_MASK (1L << 17) +#define GLITZ_INT_FORMAT_PBUFFER_MASK (1L << 18) +#define GLITZ_INT_FORMAT_FBO_MASK (1L << 19) + +typedef struct _glitz_int_drawable_format_t { + glitz_drawable_format_t d; + unsigned int types; + int caveat; + union { + void *ptr; + long val; + unsigned long uval; + void *(*fptr) (void); + } u; +} glitz_int_drawable_format_t; typedef struct glitz_backend { glitz_drawable_t * (*create_pbuffer) (void *drawable, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); - + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); + void (*destroy) (void *drawable); - void + glitz_bool_t (*push_current) (void *drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint); + glitz_surface_t *surface, + glitz_constraint_t constraint); glitz_surface_t * (*pop_current) (void *drawable); void + (*attach_notify) (void *drawable, + glitz_surface_t *surface); + + void + (*detach_notify) (void *drawable, + glitz_surface_t *surface); + + glitz_bool_t (*swap_buffers) (void *drawable); + glitz_context_t * (*create_context) (void *drawable, - glitz_drawable_format_t *format); + glitz_drawable_format_t *format); void (*destroy_context) (void *context); void (*copy_context) (void *src, - void *dst, - unsigned long mask); + void *dst, + unsigned long mask); void - (*make_current) (void *context, - void *drawable); + (*make_current) (void *drawable, + void *context); glitz_function_pointer_t (*get_proc_address) (void *context, - const char *name); + const char *name); - glitz_gl_proc_address_list_t gl; - - glitz_drawable_format_t *drawable_formats; + glitz_gl_proc_address_list_t *gl; + + glitz_int_drawable_format_t *drawable_formats; int n_drawable_formats; glitz_gl_int_t *texture_formats; @@ -360,25 +396,30 @@ typedef struct glitz_backend { int n_formats; glitz_gl_float_t gl_version; + glitz_gl_int_t max_viewport_dims[2]; glitz_gl_int_t max_texture_2d_size; glitz_gl_int_t max_texture_rect_size; unsigned long feature_mask; - + glitz_program_map_t *program_map; } glitz_backend_t; struct _glitz_drawable { - glitz_backend_t *backend; - - int ref_count; - glitz_drawable_format_t *format; - int width, height; - glitz_rectangle_t viewport; - glitz_bool_t update_all; + glitz_backend_t *backend; + int ref_count; + glitz_int_drawable_format_t *format; + int width, height; + glitz_rectangle_t viewport; + glitz_bool_t update_all; + glitz_surface_t *front; + glitz_surface_t *back; }; #define GLITZ_GL_DRAWABLE(drawable) \ - glitz_gl_proc_address_list_t *gl = &(drawable)->backend->gl; + glitz_gl_proc_address_list_t *gl = (drawable)->backend->gl; + +#define DRAWABLE_IS_FBO(drawable) \ + ((drawable)->format->types == GLITZ_DRAWABLE_TYPE_FBO_MASK) typedef struct _glitz_vec2_t { glitz_float_t v[2]; @@ -405,30 +446,43 @@ typedef struct _glitz_vec4_t { #define TEXTURE_INVALID_SIZE(texture) \ ((texture)->flags & GLITZ_TEXTURE_FLAG_INVALID_SIZE_MASK) +typedef struct _glitz_texture_parameters { + glitz_gl_enum_t filter[2]; + glitz_gl_enum_t wrap[2]; + glitz_color_t border_color; +} glitz_texture_parameters_t; + typedef struct _glitz_texture { glitz_gl_uint_t name; glitz_gl_enum_t target; glitz_gl_int_t format; unsigned long flags; - - glitz_gl_enum_t filter; - glitz_gl_enum_t wrap; - - int width; - int height; - glitz_box_t box; - - glitz_float_t texcoord_width_unit; - glitz_float_t texcoord_height_unit; + glitz_texture_parameters_t param; + + int width; + int height; + + glitz_box_t box; + + glitz_float_t texcoord_width_unit; + glitz_float_t texcoord_height_unit; } glitz_texture_t; +struct _glitz_texture_object { + glitz_surface_t *surface; + int ref_count; + glitz_texture_parameters_t param; +}; + struct _glitz_buffer { glitz_gl_uint_t name; glitz_gl_enum_t target; void *data; int owns_data; int ref_count; + glitz_surface_t *front_surface; + glitz_surface_t *back_surface; glitz_drawable_t *drawable; }; @@ -538,10 +592,6 @@ typedef struct _glitz_geometry { #define SURFACE_PROJECTIVE_TRANSFORM(surface) \ ((surface)->flags & GLITZ_SURFACE_FLAG_PROJECTIVE_TRANSFORM_MASK) -#define SURFACE_DRAWABLE_HEIGHT(surface) \ - (((surface)->attached) ? \ - (surface)->attached->height: surface->texture.height) - typedef struct _glitz_filter_params_t glitz_filter_params_t; typedef struct _glitz_matrix { @@ -549,10 +599,6 @@ typedef struct _glitz_matrix { glitz_float_t m[16]; } glitz_matrix_t; -typedef struct _glitz_framebuffer { - glitz_gl_uint_t name; -} glitz_framebuffer_t; - #define GLITZ_DAMAGE_TEXTURE_MASK (1 << 0) #define GLITZ_DAMAGE_DRAWABLE_MASK (1 << 1) #define GLITZ_DAMAGE_SOLID_MASK (1 << 2) @@ -587,11 +633,12 @@ struct _glitz_surface { int *primcount; glitz_region_t texture_damage; glitz_region_t drawable_damage; - glitz_framebuffer_t framebuffer; + unsigned int flip_count; + glitz_gl_int_t fb; }; #define GLITZ_GL_SURFACE(surface) \ - glitz_gl_proc_address_list_t *gl = &(surface)->drawable->backend->gl; + glitz_gl_proc_address_list_t *gl = (surface)->drawable->backend->gl; struct _glitz_context { int ref_count; @@ -634,160 +681,169 @@ typedef struct _glitz_extension_map { extern void __internal_linkage glitz_set_operator (glitz_gl_proc_address_list_t *gl, - glitz_operator_t op); + glitz_operator_t op); unsigned long glitz_extensions_query (glitz_gl_float_t version, - const char *extensions_string, - glitz_extension_map *extensions_map); + const char *extensions_string, + glitz_extension_map *extensions_map); typedef glitz_function_pointer_t (* glitz_get_proc_address_proc_t) (const char *name, void *closure); void glitz_backend_init (glitz_backend_t *backend, - glitz_get_proc_address_proc_t get_proc_address, - void *closure); + glitz_get_proc_address_proc_t get_proc_address, + void *closure); extern unsigned int __internal_linkage glitz_uint_to_power_of_two (unsigned int x); extern void __internal_linkage glitz_set_raster_pos (glitz_gl_proc_address_list_t *gl, - glitz_float_t x, - glitz_float_t y); + glitz_float_t x, + glitz_float_t y); extern void __internal_linkage glitz_clamp_value (glitz_float_t *value, - glitz_float_t min, - glitz_float_t max); + glitz_float_t min, + glitz_float_t max); void glitz_initiate_state (glitz_gl_proc_address_list_t *gl); void glitz_create_surface_formats (glitz_gl_proc_address_list_t *gl, - glitz_format_t **formats, - glitz_gl_int_t **texture_formats, - int *n_formats); + glitz_format_t **formats, + glitz_gl_int_t **texture_formats, + int *n_formats); + +extern void __internal_linkage +_glitz_add_drawable_formats (glitz_gl_proc_address_list_t *gl, + unsigned long feature_mask, + glitz_int_drawable_format_t **formats, + int *n_formats); + +void +glitz_drawable_format_copy (const glitz_drawable_format_t *src, + glitz_drawable_format_t *dst, + unsigned long mask); glitz_drawable_format_t * -glitz_drawable_format_find (glitz_drawable_format_t *formats, - int n_formats, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count); +glitz_drawable_format_find (glitz_int_drawable_format_t *formats, + int n_formats, + unsigned long mask, + const glitz_int_drawable_format_t *templ, + int count); void glitz_texture_init (glitz_texture_t *texture, - int width, - int height, - glitz_gl_int_t texture_format, - unsigned long feature_mask, - glitz_bool_t unnormalized); + int width, + int height, + glitz_gl_int_t texture_format, + unsigned long feature_mask, + glitz_bool_t unnormalized); void glitz_texture_fini (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture); + glitz_texture_t *texture); void glitz_texture_size_check (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_int_t max_2d, - glitz_gl_int_t max_rect); + glitz_texture_t *texture, + glitz_gl_int_t max_2d, + glitz_gl_int_t max_rect); void glitz_texture_allocate (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture); + glitz_texture_t *texture); extern void __internal_linkage -glitz_texture_ensure_filter (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_enum_t filter); - -extern void __internal_linkage -glitz_texture_ensure_wrap (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_gl_enum_t wrap); +glitz_texture_ensure_parameters (glitz_gl_proc_address_list_t *gl, + glitz_texture_t *texture, + glitz_texture_parameters_t *param); void glitz_texture_bind (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture); + glitz_texture_t *texture); void glitz_texture_unbind (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture); + glitz_texture_t *texture); void glitz_texture_copy_drawable (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_drawable_t *drawable, - int x_drawable, - int y_drawable, - int width, - int height, - int x_texture, - int y_texture); + glitz_texture_t *texture, + glitz_drawable_t *drawable, + int x_drawable, + int y_drawable, + int width, + int height, + int x_texture, + int y_texture); void glitz_texture_set_tex_gen (glitz_gl_proc_address_list_t *gl, - glitz_texture_t *texture, - glitz_geometry_t *geometry, - int x_src, - int y_src, - unsigned long flags, - glitz_int_coordinate_t *coord); + glitz_texture_t *texture, + glitz_geometry_t *geometry, + int x_src, + int y_src, + unsigned long flags, + glitz_int_coordinate_t *coord); + +extern void __internal_linkage +_glitz_surface_sync_texture (glitz_surface_t *surface); extern glitz_texture_t __internal_linkage * glitz_surface_get_texture (glitz_surface_t *surface, - glitz_bool_t allocate); + glitz_bool_t allocate); extern void __internal_linkage glitz_surface_sync_solid (glitz_surface_t *surface); extern glitz_bool_t __internal_linkage glitz_surface_push_current (glitz_surface_t *surface, - glitz_constraint_t constraint); + glitz_constraint_t constraint); extern void __internal_linkage glitz_surface_pop_current (glitz_surface_t *surface); extern void __internal_linkage glitz_surface_damage (glitz_surface_t *surface, - glitz_box_t *box, - int what); + glitz_box_t *box, + int what); extern void __internal_linkage glitz_surface_sync_drawable (glitz_surface_t *surface); extern void __internal_linkage glitz_surface_status_add (glitz_surface_t *surface, - int flags); + int flags); extern unsigned long __internal_linkage glitz_status_to_status_mask (glitz_status_t status); - + extern glitz_status_t __internal_linkage glitz_status_pop_from_mask (unsigned long *mask); void glitz_program_map_init (glitz_program_map_t *map); - + void glitz_program_map_fini (glitz_gl_proc_address_list_t *gl, - glitz_program_map_t *map); + glitz_program_map_t *map); extern glitz_gl_uint_t __internal_linkage glitz_get_fragment_program (glitz_composite_op_t *op, - int fp_type, - int id); + int fp_type, + int id); extern void __internal_linkage glitz_composite_op_init (glitz_composite_op_t *op, - glitz_operator_t render_op, - glitz_surface_t *src, - glitz_surface_t *mask, - glitz_surface_t *dst); + glitz_operator_t render_op, + glitz_surface_t *src, + glitz_surface_t *mask, + glitz_surface_t *dst); extern void __internal_linkage glitz_composite_enable (glitz_composite_op_t *op); @@ -797,71 +853,69 @@ glitz_composite_disable (glitz_composite_op_t *op); extern void __internal_linkage * glitz_buffer_bind (glitz_buffer_t *buffer, - glitz_gl_enum_t target); + glitz_gl_enum_t target); extern void __internal_linkage glitz_buffer_unbind (glitz_buffer_t *buffer); extern glitz_status_t __internal_linkage glitz_filter_set_params (glitz_surface_t *surface, - glitz_filter_t filter, - glitz_fixed16_16_t *params, - int n_params); + glitz_filter_t filter, + glitz_fixed16_16_t *params, + int n_params); extern void __internal_linkage glitz_filter_set_type (glitz_surface_t *surface, - glitz_filter_t filter); + glitz_filter_t filter); extern glitz_gl_uint_t __internal_linkage glitz_filter_get_vertex_program (glitz_surface_t *surface, - glitz_composite_op_t *op); + glitz_composite_op_t *op); extern glitz_gl_uint_t __internal_linkage glitz_filter_get_fragment_program (glitz_surface_t *surface, - glitz_composite_op_t *op); + glitz_composite_op_t *op); extern void __internal_linkage glitz_filter_enable (glitz_surface_t *surface, - glitz_composite_op_t *op); + glitz_composite_op_t *op); extern void __internal_linkage glitz_geometry_enable_none (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *box); + glitz_surface_t *dst, + glitz_box_t *box); extern void __internal_linkage glitz_geometry_enable (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_box_t *box); + glitz_surface_t *dst, + glitz_box_t *box); extern void __internal_linkage glitz_geometry_disable (glitz_surface_t *dst); extern void __internal_linkage glitz_geometry_draw_arrays (glitz_gl_proc_address_list_t *gl, - glitz_surface_t *dst, - glitz_geometry_type_t type, - glitz_box_t *bounds, - int damage); + glitz_surface_t *dst, + glitz_geometry_type_t type, + glitz_box_t *bounds, + int damage); -extern void __internal_linkage -glitz_framebuffer_init (glitz_framebuffer_t *framebuffer); +void +_glitz_drawable_init (glitz_drawable_t *drawable, + glitz_int_drawable_format_t *format, + glitz_backend_t *backend, + int width, + int height); -extern void __internal_linkage -glitz_framebuffer_fini (glitz_gl_proc_address_list_t *gl, - glitz_framebuffer_t *framebuffer); - -extern void __internal_linkage -glitz_framebuffer_unbind (glitz_gl_proc_address_list_t *gl); - -extern glitz_bool_t __internal_linkage -glitz_framebuffer_complete (glitz_gl_proc_address_list_t *gl, - glitz_framebuffer_t *framebuffer, - glitz_texture_t *texture); +extern glitz_drawable_t __internal_linkage * +_glitz_fbo_drawable_create (glitz_drawable_t *other, + glitz_int_drawable_format_t *format, + int width, + int height); void _glitz_context_init (glitz_context_t *context, - glitz_drawable_t *drawable); + glitz_drawable_t *drawable); void _glitz_context_fini (glitz_context_t *context); @@ -912,8 +966,8 @@ typedef uint32_t glitz_fixed_1_16; typedef int32_t glitz_fixed_16_16; /* - * An unadorned "glitz_fixed" is the same as glitz_fixed_16_16, - * (since it's quite common in the code) + * An unadorned "glitz_fixed" is the same as glitz_fixed_16_16, + * (since it's quite common in the code) */ typedef glitz_fixed_16_16 glitz_fixed; @@ -953,14 +1007,15 @@ typedef glitz_fixed_16_16 glitz_fixed; #define sqrtf(_X) ((float)sqrt((double)(_X))) #endif -/* Avoid unnecessary PLT entries. */ +/* Avoid unnecessary PLT entries. */ -slim_hidden_proto(glitz_find_similar_drawable_format) +slim_hidden_proto(glitz_find_drawable_format) +slim_hidden_proto(glitz_find_pbuffer_format) +slim_hidden_proto(glitz_create_drawable) slim_hidden_proto(glitz_create_pbuffer_drawable) slim_hidden_proto(glitz_drawable_get_width) slim_hidden_proto(glitz_drawable_get_height) slim_hidden_proto(glitz_drawable_swap_buffers) -slim_hidden_proto(glitz_drawable_swap_buffers) slim_hidden_proto(glitz_drawable_flush) slim_hidden_proto(glitz_drawable_finish) slim_hidden_proto(glitz_drawable_get_features) diff --git a/gfx/cairo/glitz/src/glx/Makefile.in b/gfx/cairo/glitz/src/glx/Makefile.in index fc8ac91e893..a7f9319ea20 100644 --- a/gfx/cairo/glitz/src/glx/Makefile.in +++ b/gfx/cairo/glitz/src/glx/Makefile.in @@ -42,6 +42,8 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk +VISIBILITY_FLAGS = + MODULE = glitzglx LIBRARY_NAME = mozglitzglx LIBXUL_LIBRARY = 1 diff --git a/gfx/cairo/glitz/src/glx/glitz-glx.h b/gfx/cairo/glitz/src/glx/glitz-glx.h index d0e312556da..01f50b45575 100644 --- a/gfx/cairo/glitz/src/glx/glitz-glx.h +++ b/gfx/cairo/glitz/src/glx/glitz-glx.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -42,17 +42,24 @@ glitz_glx_init (const char *gl_library); void glitz_glx_fini (void); - - + + /* glitz_glx_format.c */ glitz_drawable_format_t * -glitz_glx_find_drawable_format (Display *display, - int screen, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count); - +glitz_glx_find_window_format (Display *display, + int screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + +glitz_drawable_format_t * +glitz_glx_find_pbuffer_format (Display *display, + int screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count); + glitz_drawable_format_t * glitz_glx_find_drawable_format_for_visual (Display *display, int screen, @@ -60,26 +67,26 @@ glitz_glx_find_drawable_format_for_visual (Display *display, XVisualInfo * glitz_glx_get_visual_info_from_format (Display *display, - int screen, - glitz_drawable_format_t *format); - + int screen, + glitz_drawable_format_t *format); + /* glitz_glx_drawable.c */ glitz_drawable_t * glitz_glx_create_drawable_for_window (Display *display, - int screen, - glitz_drawable_format_t *format, - Window window, - unsigned int width, - unsigned int height); + int screen, + glitz_drawable_format_t *format, + Window window, + unsigned int width, + unsigned int height); glitz_drawable_t * glitz_glx_create_pbuffer_drawable (Display *display, - int screen, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + int screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); #if defined(__cplusplus) || defined(c_plusplus) diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_context.c b/gfx/cairo/glitz/src/glx/glitz_glx_context.c index 5d6caad2413..e0f87a99c19 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_context.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_context.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -35,402 +35,448 @@ extern glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address; static void _glitz_glx_context_create (glitz_glx_screen_info_t *screen_info, - XID visualid, - GLXContext share_list, - glitz_glx_context_t *context) + XID visualid, + GLXContext share_list, + glitz_glx_context_t *context) { - int vis_info_count, i; - XVisualInfo *vis_infos; + int vis_info_count, i; + XVisualInfo *vis_infos; - vis_infos = XGetVisualInfo (screen_info->display_info->display, - 0, NULL, &vis_info_count); - for (i = 0; i < vis_info_count; i++) { - if (vis_infos[i].visual->visualid == visualid) - break; - } + vis_infos = XGetVisualInfo (screen_info->display_info->display, + 0, NULL, &vis_info_count); + for (i = 0; i < vis_info_count; i++) { + if (vis_infos[i].visual->visualid == visualid) + break; + } - context->context = glXCreateContext (screen_info->display_info->display, - &vis_infos[i], share_list, - GLITZ_GL_TRUE); - context->id = visualid; - context->fbconfig = (GLXFBConfig) 0; + context->context = glXCreateContext (screen_info->display_info->display, + &vis_infos[i], share_list, + GLITZ_GL_TRUE); + context->id = visualid; + context->fbconfig = (GLXFBConfig) 0; - XFree (vis_infos); + XFree (vis_infos); } static void _glitz_glx_context_create_using_fbconfig (glitz_glx_screen_info_t *screen_info, - XID fbconfigid, - GLXContext share_list, - glitz_glx_context_t *context) + XID fbconfigid, + GLXContext share_list, + glitz_glx_context_t *context) { - GLXFBConfig *fbconfigs; - int i, n_fbconfigs; - XVisualInfo *vinfo = NULL; - glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; + GLXFBConfig *fbconfigs; + int i, n_fbconfigs; + XVisualInfo *vinfo = NULL; + glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; - fbconfigs = glx->get_fbconfigs (screen_info->display_info->display, - screen_info->screen, &n_fbconfigs); - for (i = 0; i < n_fbconfigs; i++) { - int value; - - glx->get_fbconfig_attrib (screen_info->display_info->display, fbconfigs[i], - GLX_FBCONFIG_ID, &value); - if (value == (int) fbconfigid) - break; - } + fbconfigs = glx->get_fbconfigs (screen_info->display_info->display, + screen_info->screen, &n_fbconfigs); + for (i = 0; i < n_fbconfigs; i++) { + int value; - if (i < n_fbconfigs) - vinfo = glx->get_visual_from_fbconfig (screen_info->display_info->display, - fbconfigs[i]); + glx->get_fbconfig_attrib (screen_info->display_info->display, + fbconfigs[i], + GLX_FBCONFIG_ID, &value); + if (value == (int) fbconfigid) + break; + } - context->id = fbconfigid; - if (vinfo) { - context->context = glXCreateContext (screen_info->display_info->display, - vinfo, share_list, GLITZ_GL_TRUE); - XFree (vinfo); - } else if (glx->create_new_context) - context->context = - glx->create_new_context (screen_info->display_info->display, - fbconfigs[i], GLX_RGBA_TYPE, share_list, - GLITZ_GL_TRUE); - - if (context->context) - context->fbconfig = fbconfigs[i]; - else - context->fbconfig = (GLXFBConfig) 0; + if (i < n_fbconfigs) + vinfo = + glx->get_visual_from_fbconfig (screen_info->display_info->display, + fbconfigs[i]); - if (fbconfigs) - XFree (fbconfigs); + context->id = fbconfigid; + if (vinfo) { + context->context = + glXCreateContext (screen_info->display_info->display, + vinfo, share_list, GLITZ_GL_TRUE); + XFree (vinfo); + } else if (glx->create_new_context) + context->context = + glx->create_new_context (screen_info->display_info->display, + fbconfigs[i], GLX_RGBA_TYPE, share_list, + GLITZ_GL_TRUE); + + if (context->context) + context->fbconfig = fbconfigs[i]; + else + context->fbconfig = (GLXFBConfig) 0; + + if (fbconfigs) + XFree (fbconfigs); } static glitz_context_t * _glitz_glx_create_context (void *abstract_drawable, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; - glitz_glx_screen_info_t *screen_info = drawable->screen_info; - int format_id = screen_info->format_ids[format->id]; - glitz_glx_context_t *context; - - context = malloc (sizeof (glitz_glx_context_t)); - if (!context) - return NULL; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; + glitz_glx_screen_info_t *screen_info = drawable->screen_info; + unsigned long format_id = + screen_info->formats[format->id].u.uval; + glitz_glx_context_t *context; - _glitz_context_init (&context->base, &drawable->base); - - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) - _glitz_glx_context_create_using_fbconfig (screen_info, - format_id, - screen_info->root_context, - context); - else - _glitz_glx_context_create (screen_info, - format_id, - screen_info->root_context, - context); + context = malloc (sizeof (glitz_glx_context_t)); + if (!context) + return NULL; - return (glitz_context_t *) context; + _glitz_context_init (&context->base, &drawable->base); + + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) + _glitz_glx_context_create_using_fbconfig (screen_info, + format_id, + screen_info->root_context, + context); + else + _glitz_glx_context_create (screen_info, + format_id, + screen_info->root_context, + context); + + return (glitz_context_t *) context; } static void _glitz_glx_context_destroy (void *abstract_context) { - glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) - context->base.drawable; - - if (drawable->screen_info->display_info->thread_info->cctx == &context->base) - { - glXMakeCurrent (drawable->screen_info->display_info->display, - None, NULL); - - drawable->screen_info->display_info->thread_info->cctx = NULL; - } + glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + context->base.drawable; - glXDestroyContext (drawable->screen_info->display_info->display, - context->context); + if (drawable->screen_info->display_info->thread_info->cctx == + &context->base) + { + glXMakeCurrent (drawable->screen_info->display_info->display, + None, NULL); - _glitz_context_fini (&context->base); - - free (context); + drawable->screen_info->display_info->thread_info->cctx = NULL; + } + + glXDestroyContext (drawable->screen_info->display_info->display, + context->context); + + _glitz_context_fini (&context->base); + + free (context); } static void _glitz_glx_copy_context (void *abstract_src, - void *abstract_dst, - unsigned long mask) + void *abstract_dst, + unsigned long mask) { - glitz_glx_context_t *src = (glitz_glx_context_t *) abstract_src; - glitz_glx_context_t *dst = (glitz_glx_context_t *) abstract_dst; - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) - src->base.drawable; + glitz_glx_context_t *src = (glitz_glx_context_t *) abstract_src; + glitz_glx_context_t *dst = (glitz_glx_context_t *) abstract_dst; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + src->base.drawable; - glXCopyContext (drawable->screen_info->display_info->display, - src->context, dst->context, mask); + glXCopyContext (drawable->screen_info->display_info->display, + src->context, dst->context, mask); } static void -_glitz_glx_make_current (void *abstract_context, - void *abstract_drawable) +_glitz_glx_make_current (void *abstract_drawable, + void *abstract_context) { - glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; - glitz_glx_display_info_t *display_info = drawable->screen_info->display_info; - - if ((glXGetCurrentContext () != context->context) || - (glXGetCurrentDrawable () != drawable->drawable)) - { - if (display_info->thread_info->cctx) - { - glitz_context_t *ctx = display_info->thread_info->cctx; + glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; + glitz_glx_display_info_t *display_info = + drawable->screen_info->display_info; - if (ctx->lose_current) - ctx->lose_current (ctx->closure); - } - glXMakeCurrent (display_info->display, drawable->drawable, - context->context); - } + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_glx_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); - display_info->thread_info->cctx = &context->base; + if ((glXGetCurrentContext () != context->context) || + (glXGetCurrentDrawable () != drawable->drawable)) + { + if (display_info->thread_info->cctx) + { + glitz_context_t *ctx = display_info->thread_info->cctx; + + if (ctx->lose_current) + ctx->lose_current (ctx->closure); + } + + glXMakeCurrent (display_info->display, drawable->drawable, + context->context); + } + + display_info->thread_info->cctx = &context->base; } +static void +_glitz_glx_notify_dummy (void *abstract_drawable, + glitz_surface_t *surface) {} + static glitz_function_pointer_t _glitz_glx_context_get_proc_address (void *abstract_context, - const char *name) + const char *name) { - glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) - context->base.drawable; + glitz_glx_context_t *context = (glitz_glx_context_t *) abstract_context; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + context->base.drawable; - _glitz_glx_make_current (context, drawable); - - return glitz_glx_get_proc_address (name, drawable->screen_info); + /* _glitz_glx_make_current (drawable, context, NULL); */ + + return glitz_glx_get_proc_address (name, drawable->screen_info); } glitz_glx_context_t * glitz_glx_context_get (glitz_glx_screen_info_t *screen_info, - glitz_drawable_format_t *format) + glitz_drawable_format_t *format) { - glitz_glx_context_t *context; - glitz_glx_context_t **contexts = screen_info->contexts; - int index, n_contexts = screen_info->n_contexts; - XID format_id; + glitz_glx_context_t *context; + glitz_glx_context_t **contexts = screen_info->contexts; + int index, n_contexts = screen_info->n_contexts; + unsigned long format_id; - for (; n_contexts; n_contexts--, contexts++) - if ((*contexts)->id == screen_info->format_ids[format->id]) - return *contexts; + for (; n_contexts; n_contexts--, contexts++) + if ((*contexts)->id == screen_info->formats[format->id].u.uval) + return *contexts; - index = screen_info->n_contexts++; + index = screen_info->n_contexts++; - screen_info->contexts = - realloc (screen_info->contexts, - sizeof (glitz_glx_context_t *) * screen_info->n_contexts); - if (!screen_info->contexts) - return NULL; + screen_info->contexts = + realloc (screen_info->contexts, + sizeof (glitz_glx_context_t *) * screen_info->n_contexts); + if (!screen_info->contexts) + return NULL; - context = malloc (sizeof (glitz_glx_context_t)); - if (!context) - return NULL; - - screen_info->contexts[index] = context; + context = malloc (sizeof (glitz_glx_context_t)); + if (!context) + return NULL; - format_id = screen_info->format_ids[format->id]; + screen_info->contexts[index] = context; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) - _glitz_glx_context_create_using_fbconfig (screen_info, - format_id, - screen_info->root_context, - context); - else - _glitz_glx_context_create (screen_info, - format_id, - screen_info->root_context, - context); - - if (!screen_info->root_context) - screen_info->root_context = context->context; + format_id = screen_info->formats[format->id].u.uval; - memcpy (&context->backend.gl, - &_glitz_glx_gl_proc_address, - sizeof (glitz_gl_proc_address_list_t)); + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) + _glitz_glx_context_create_using_fbconfig (screen_info, + format_id, + screen_info->root_context, + context); + else + _glitz_glx_context_create (screen_info, + format_id, + screen_info->root_context, + context); - context->backend.create_pbuffer = glitz_glx_create_pbuffer; - context->backend.destroy = glitz_glx_destroy; - context->backend.push_current = glitz_glx_push_current; - context->backend.pop_current = glitz_glx_pop_current; - context->backend.swap_buffers = glitz_glx_swap_buffers; - - context->backend.create_context = _glitz_glx_create_context; - context->backend.destroy_context = _glitz_glx_context_destroy; - context->backend.copy_context = _glitz_glx_copy_context; - context->backend.make_current = _glitz_glx_make_current; - context->backend.get_proc_address = _glitz_glx_context_get_proc_address; - - context->backend.drawable_formats = screen_info->formats; - context->backend.n_drawable_formats = screen_info->n_formats; + if (!screen_info->root_context) + screen_info->root_context = context->context; - context->backend.texture_formats = NULL; - context->backend.formats = NULL; - context->backend.n_formats = 0; - - context->backend.program_map = &screen_info->program_map; - context->backend.feature_mask = 0; + context->backend.gl = &_glitz_glx_gl_proc_address; - context->initialized = 0; - - return context; + context->backend.create_pbuffer = glitz_glx_create_pbuffer; + context->backend.destroy = glitz_glx_destroy; + context->backend.push_current = glitz_glx_push_current; + context->backend.pop_current = glitz_glx_pop_current; + context->backend.attach_notify = _glitz_glx_notify_dummy; + context->backend.detach_notify = _glitz_glx_notify_dummy; + context->backend.swap_buffers = glitz_glx_swap_buffers; + + context->backend.create_context = _glitz_glx_create_context; + context->backend.destroy_context = _glitz_glx_context_destroy; + context->backend.copy_context = _glitz_glx_copy_context; + context->backend.make_current = _glitz_glx_make_current; + context->backend.get_proc_address = _glitz_glx_context_get_proc_address; + + context->backend.drawable_formats = NULL; + context->backend.n_drawable_formats = 0; + + if (screen_info->n_formats) + { + int size; + + size = sizeof (glitz_int_drawable_format_t) * screen_info->n_formats; + context->backend.drawable_formats = malloc (size); + if (context->backend.drawable_formats) + { + memcpy (context->backend.drawable_formats, screen_info->formats, + size); + context->backend.n_drawable_formats = screen_info->n_formats; + } + } + + context->backend.texture_formats = NULL; + context->backend.formats = NULL; + context->backend.n_formats = 0; + + context->backend.program_map = &screen_info->program_map; + context->backend.feature_mask = 0; + + context->initialized = 0; + + return context; } void glitz_glx_context_destroy (glitz_glx_screen_info_t *screen_info, - glitz_glx_context_t *context) + glitz_glx_context_t *context) { - if (context->backend.formats) - free (context->backend.formats); + if (context->backend.drawable_formats) + free (context->backend.drawable_formats); - if (context->backend.texture_formats) - free (context->backend.texture_formats); - - glXDestroyContext (screen_info->display_info->display, - context->context); - free (context); + if (context->backend.formats) + free (context->backend.formats); + + if (context->backend.texture_formats) + free (context->backend.texture_formats); + + glXDestroyContext (screen_info->display_info->display, + context->context); + free (context); } static void _glitz_glx_context_initialize (glitz_glx_screen_info_t *screen_info, - glitz_glx_context_t *context) + glitz_glx_context_t *context) { - const char *version; - - glitz_backend_init (&context->backend, - glitz_glx_get_proc_address, - (void *) screen_info); + const char *version; - context->backend.gl.get_integer_v (GLITZ_GL_MAX_VIEWPORT_DIMS, - context->max_viewport_dims); + glitz_backend_init (&context->backend, + glitz_glx_get_proc_address, + (void *) screen_info); - glitz_initiate_state (&_glitz_glx_gl_proc_address); + glitz_initiate_state (&_glitz_glx_gl_proc_address); - version = (const char *) context->backend.gl.get_string (GLITZ_GL_VERSION); - if (version) - { - /* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures when - using nvidia's binary driver. Seems like a driver issue, but I'm not - sure yet. Turning of NPOT GL_TEXTURE_2D textures until this have been - solved. */ - if (strstr (version, "NVIDIA 61.11") || - strstr (version, "NVIDIA 66.29")) + version = (const char *) + context->backend.gl->get_string (GLITZ_GL_VERSION); + if (version) { - context->backend.feature_mask &= - ~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK; + /* Having trouble with TexSubImage2D to NPOT GL_TEXTURE_2D textures + when using nvidia's binary driver. Seems like a driver issue, but + I'm not sure yet. Turning of NPOT GL_TEXTURE_2D textures until this + have been solved. */ + if (strstr (version, "NVIDIA 61.11") || + strstr (version, "NVIDIA 66.29")) + { + context->backend.feature_mask &= + ~GLITZ_FEATURE_TEXTURE_NON_POWER_OF_TWO_MASK; + } } - } - - context->initialized = 1; + + context->initialized = 1; } static void _glitz_glx_context_make_current (glitz_glx_drawable_t *drawable, - glitz_bool_t finish) + glitz_bool_t finish) { - glitz_glx_display_info_t *display_info = drawable->screen_info->display_info; - - if (finish) - glFinish (); + glitz_glx_display_info_t *display_info = + drawable->screen_info->display_info; - if (display_info->thread_info->cctx) - { - glitz_context_t *ctx = display_info->thread_info->cctx; + if (finish) + glFinish (); - if (ctx->lose_current) - ctx->lose_current (ctx->closure); + if (display_info->thread_info->cctx) + { + glitz_context_t *ctx = display_info->thread_info->cctx; - display_info->thread_info->cctx = NULL; - } + if (ctx->lose_current) + ctx->lose_current (ctx->closure); - glXMakeCurrent (display_info->display, - drawable->drawable, - drawable->context->context); - - drawable->base.update_all = 1; - - if (!drawable->context->initialized) - _glitz_glx_context_initialize (drawable->screen_info, drawable->context); + display_info->thread_info->cctx = NULL; + } + + glXMakeCurrent (display_info->display, + drawable->drawable, + drawable->context->context); + + drawable->base.update_all = 1; + + if (!drawable->context->initialized) + _glitz_glx_context_initialize (drawable->screen_info, + drawable->context); } static void _glitz_glx_context_update (glitz_glx_drawable_t *drawable, - glitz_constraint_t constraint) + glitz_constraint_t constraint) { glitz_glx_display_info_t *dinfo = drawable->screen_info->display_info; GLXContext context = NULL; - + switch (constraint) { case GLITZ_NONE: - break; + break; case GLITZ_ANY_CONTEXT_CURRENT: - if (!dinfo->thread_info->cctx) - context = glXGetCurrentContext (); - - if (context == (GLXContext) 0) - _glitz_glx_context_make_current (drawable, 0); - break; - case GLITZ_CONTEXT_CURRENT: - if (!dinfo->thread_info->cctx) - context = glXGetCurrentContext (); + if (!dinfo->thread_info->cctx) + context = glXGetCurrentContext (); - if (context != drawable->context->context) - _glitz_glx_context_make_current (drawable, (context)? 1: 0); - break; + if (context == (GLXContext) 0) + _glitz_glx_context_make_current (drawable, 0); + break; + case GLITZ_CONTEXT_CURRENT: + if (!dinfo->thread_info->cctx) + context = glXGetCurrentContext (); + + if (context != drawable->context->context) + _glitz_glx_context_make_current (drawable, (context)? 1: 0); + break; case GLITZ_DRAWABLE_CURRENT: - if (!dinfo->thread_info->cctx) - context = glXGetCurrentContext (); + if (!dinfo->thread_info->cctx) + context = glXGetCurrentContext (); - if ((context != drawable->context->context) || - (glXGetCurrentDrawable () != drawable->drawable)) - _glitz_glx_context_make_current (drawable, (context)? 1: 0); - break; + if (drawable->base.width != drawable->width || + drawable->base.height != drawable->height) + _glitz_glx_drawable_update_size (drawable, + drawable->base.width, + drawable->base.height); + + if ((context != drawable->context->context) || + (glXGetCurrentDrawable () != drawable->drawable)) + _glitz_glx_context_make_current (drawable, (context)? 1: 0); + break; } } -void +glitz_bool_t glitz_glx_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint) + glitz_surface_t *surface, + glitz_constraint_t constraint) { - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; - glitz_glx_context_info_t *context_info; - int index; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; + glitz_glx_context_info_t *context_info; + int index; - index = drawable->screen_info->context_stack_size++; + index = drawable->screen_info->context_stack_size++; - context_info = &drawable->screen_info->context_stack[index]; - context_info->drawable = drawable; - context_info->surface = surface; - context_info->constraint = constraint; - - _glitz_glx_context_update (context_info->drawable, constraint); + context_info = &drawable->screen_info->context_stack[index]; + context_info->drawable = drawable; + context_info->surface = surface; + context_info->constraint = constraint; + + _glitz_glx_context_update (context_info->drawable, constraint); + + return 1; } glitz_surface_t * glitz_glx_pop_current (void *abstract_drawable) { - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; - glitz_glx_context_info_t *context_info = NULL; - int index; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; + glitz_glx_context_info_t *context_info = NULL; + int index; - drawable->screen_info->context_stack_size--; - index = drawable->screen_info->context_stack_size - 1; + drawable->screen_info->context_stack_size--; + index = drawable->screen_info->context_stack_size - 1; - context_info = &drawable->screen_info->context_stack[index]; + context_info = &drawable->screen_info->context_stack[index]; - if (context_info->drawable) - _glitz_glx_context_update (context_info->drawable, - context_info->constraint); - - if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) - return context_info->surface; - - return NULL; + if (context_info->drawable) + _glitz_glx_context_update (context_info->drawable, + context_info->constraint); + + if (context_info->constraint == GLITZ_DRAWABLE_CURRENT) + return context_info->surface; + + return NULL; } diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_drawable.c b/gfx/cairo/glitz/src/glx/glitz_glx_drawable.c index f770476fd86..7c809255332 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_drawable.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_drawable.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,172 +31,212 @@ static glitz_glx_drawable_t * _glitz_glx_create_drawable (glitz_glx_screen_info_t *screen_info, - glitz_glx_context_t *context, - glitz_drawable_format_t *format, - GLXDrawable glx_drawable, - GLXPbuffer glx_pbuffer, - int width, - int height) + glitz_glx_context_t *context, + glitz_drawable_format_t *format, + GLXDrawable glx_drawable, + GLXPbuffer glx_pbuffer, + int width, + int height) { - glitz_glx_drawable_t *drawable; - - if (width <= 0 || height <= 0) - return NULL; + glitz_glx_drawable_t *drawable; - drawable = (glitz_glx_drawable_t *) malloc (sizeof (glitz_glx_drawable_t)); - if (drawable == NULL) - return NULL; + drawable = (glitz_glx_drawable_t *) malloc (sizeof (glitz_glx_drawable_t)); + if (drawable == NULL) + return NULL; - drawable->base.ref_count = 1; - drawable->screen_info = screen_info; - drawable->context = context; - drawable->drawable = glx_drawable; - drawable->pbuffer = glx_pbuffer; - drawable->base.format = format; - drawable->base.backend = &context->backend; + drawable->screen_info = screen_info; + drawable->context = context; + drawable->drawable = glx_drawable; + drawable->pbuffer = glx_pbuffer; + drawable->width = width; + drawable->height = height; - glitz_drawable_update_size (&drawable->base, width, height); + _glitz_drawable_init (&drawable->base, + &screen_info->formats[format->id], + &context->backend, + width, height); - if (!context->initialized) { - glitz_glx_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT); - glitz_glx_pop_current (drawable); - } - - if (width > context->max_viewport_dims[0] || - height > context->max_viewport_dims[1]) { - free (drawable); - return NULL; - } - - screen_info->drawables++; - - return drawable; + if (!context->initialized) { + glitz_glx_push_current (drawable, NULL, GLITZ_CONTEXT_CURRENT); + glitz_glx_pop_current (drawable); + } + + if (width > context->backend.max_viewport_dims[0] || + height > context->backend.max_viewport_dims[1]) { + free (drawable); + return NULL; + } + + screen_info->drawables++; + + return drawable; +} + +glitz_bool_t +_glitz_glx_drawable_update_size (glitz_glx_drawable_t *drawable, + int width, + int height) +{ + if (drawable->pbuffer) + { + glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer); + drawable->drawable = drawable->pbuffer = + glitz_glx_pbuffer_create (drawable->screen_info, + drawable->context->fbconfig, + (int) width, (int) height); + if (!drawable->pbuffer) + return 0; + } + + drawable->width = width; + drawable->height = height; + + return 1; } static glitz_drawable_t * _glitz_glx_create_pbuffer_drawable (glitz_glx_screen_info_t *screen_info, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_glx_drawable_t *drawable; - glitz_glx_context_t *context; - GLXPbuffer pbuffer; + glitz_glx_drawable_t *drawable; + glitz_glx_context_t *context; + GLXPbuffer pbuffer; - if (!format->types.pbuffer) - return NULL; - - context = glitz_glx_context_get (screen_info, format); - if (!context) - return NULL; + context = glitz_glx_context_get (screen_info, format); + if (!context) + return NULL; - pbuffer = glitz_glx_pbuffer_create (screen_info, context->fbconfig, - (int) width, (int) height); - if (!pbuffer) - return NULL; - - drawable = _glitz_glx_create_drawable (screen_info, context, format, - pbuffer, pbuffer, - width, height); - if (!drawable) { - glitz_glx_pbuffer_destroy (screen_info, pbuffer); - return NULL; - } - - return &drawable->base; + pbuffer = glitz_glx_pbuffer_create (screen_info, context->fbconfig, + (int) width, (int) height); + if (!pbuffer) + return NULL; + + drawable = _glitz_glx_create_drawable (screen_info, context, format, + pbuffer, pbuffer, + width, height); + if (!drawable) { + glitz_glx_pbuffer_destroy (screen_info, pbuffer); + return NULL; + } + + return &drawable->base; } glitz_drawable_t * glitz_glx_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_glx_drawable_t *templ = (glitz_glx_drawable_t *) abstract_templ; + glitz_glx_drawable_t *templ = (glitz_glx_drawable_t *) abstract_templ; - return _glitz_glx_create_pbuffer_drawable (templ->screen_info, format, - width, height); + return _glitz_glx_create_pbuffer_drawable (templ->screen_info, format, + width, height); } glitz_drawable_t * glitz_glx_create_drawable_for_window (Display *display, - int screen, - glitz_drawable_format_t *format, - Window window, - unsigned int width, - unsigned int height) + int screen, + glitz_drawable_format_t *format, + Window window, + unsigned int width, + unsigned int height) { - glitz_glx_drawable_t *drawable; - glitz_glx_screen_info_t *screen_info; - glitz_glx_context_t *context; + glitz_glx_drawable_t *drawable; + glitz_glx_screen_info_t *screen_info; + glitz_glx_context_t *context; + glitz_int_drawable_format_t *iformat; - screen_info = glitz_glx_screen_info_get (display, screen); - if (!screen_info) - return NULL; - - context = glitz_glx_context_get (screen_info, format); - if (!context) - return NULL; - - drawable = _glitz_glx_create_drawable (screen_info, context, format, - window, (GLXPbuffer) 0, - width, height); - if (!drawable) - return NULL; + screen_info = glitz_glx_screen_info_get (display, screen); + if (!screen_info) + return NULL; - return &drawable->base; + if (format->id >= screen_info->n_formats) + return NULL; + + iformat = &screen_info->formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK)) + return NULL; + + context = glitz_glx_context_get (screen_info, format); + if (!context) + return NULL; + + drawable = _glitz_glx_create_drawable (screen_info, context, format, + window, (GLXPbuffer) 0, + width, height); + if (!drawable) + return NULL; + + return &drawable->base; } slim_hidden_def(glitz_glx_create_drawable_for_window); glitz_drawable_t * glitz_glx_create_pbuffer_drawable (Display *display, - int screen, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height) + int screen, + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height) { - glitz_glx_screen_info_t *screen_info; + glitz_glx_screen_info_t *screen_info; + glitz_int_drawable_format_t *iformat; - screen_info = glitz_glx_screen_info_get (display, screen); - if (!screen_info) - return NULL; + screen_info = glitz_glx_screen_info_get (display, screen); + if (!screen_info) + return NULL; - return _glitz_glx_create_pbuffer_drawable (screen_info, format, - width, height); + if (format->id >= screen_info->n_formats) + return NULL; + + iformat = &screen_info->formats[format->id]; + if (!(iformat->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK)) + return NULL; + + return _glitz_glx_create_pbuffer_drawable (screen_info, format, + width, height); } slim_hidden_def(glitz_glx_create_pbuffer_drawable); void glitz_glx_destroy (void *abstract_drawable) { - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; - drawable->screen_info->drawables--; - if (drawable->screen_info->drawables == 0) { - /* - * Last drawable? We have to destroy all fragment programs as this may - * be our last chance to have a context current. - */ - glitz_glx_push_current (abstract_drawable, NULL, GLITZ_CONTEXT_CURRENT); - glitz_program_map_fini (&drawable->base.backend->gl, - &drawable->screen_info->program_map); - glitz_glx_pop_current (abstract_drawable); - } + drawable->screen_info->drawables--; + if (drawable->screen_info->drawables == 0) { + /* + * Last drawable? We have to destroy all fragment programs as this may + * be our last chance to have a context current. + */ + glitz_glx_push_current (abstract_drawable, NULL, + GLITZ_CONTEXT_CURRENT); + glitz_program_map_fini (drawable->base.backend->gl, + &drawable->screen_info->program_map); + glitz_glx_pop_current (abstract_drawable); + } - if (glXGetCurrentDrawable () == drawable->drawable) - glXMakeCurrent (drawable->screen_info->display_info->display, None, NULL); - - if (drawable->pbuffer) - glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer); - - free (drawable); + if (glXGetCurrentDrawable () == drawable->drawable) + glXMakeCurrent (drawable->screen_info->display_info->display, + None, NULL); + + if (drawable->pbuffer) + glitz_glx_pbuffer_destroy (drawable->screen_info, drawable->pbuffer); + + free (drawable); } -void +glitz_bool_t glitz_glx_swap_buffers (void *abstract_drawable) { - glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) abstract_drawable; + glitz_glx_drawable_t *drawable = (glitz_glx_drawable_t *) + abstract_drawable; - glXSwapBuffers (drawable->screen_info->display_info->display, - drawable->drawable); + glXSwapBuffers (drawable->screen_info->display_info->display, + drawable->drawable); + + return 1; } diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_extension.c b/gfx/cairo/glitz/src/glx/glitz_glx_extension.c index 42d674861f4..3953b3400c3 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_extension.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_extension.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -30,41 +30,42 @@ #include "glitz_glxint.h" static glitz_extension_map glx_extensions[] = { - { 0.0, "GLX_SGIX_fbconfig", GLITZ_GLX_FEATURE_FBCONFIG_MASK }, - { 0.0, "GLX_SGIX_pbuffer", GLITZ_GLX_FEATURE_PBUFFER_MASK }, - { 0.0, "GLX_SGI_make_current_read", - GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK }, - { 0.0, "GLX_ARB_multisample", GLITZ_GLX_FEATURE_MULTISAMPLE_MASK }, - { 0.0, NULL, 0 } + { 0.0, "GLX_EXT_visual_rating", GLITZ_GLX_FEATURE_VISUAL_RATING_MASK }, + { 0.0, "GLX_SGIX_fbconfig", GLITZ_GLX_FEATURE_FBCONFIG_MASK }, + { 0.0, "GLX_SGIX_pbuffer", GLITZ_GLX_FEATURE_PBUFFER_MASK }, + { 0.0, "GLX_SGI_make_current_read", + GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK }, + { 0.0, "GLX_ARB_multisample", GLITZ_GLX_FEATURE_MULTISAMPLE_MASK }, + { 0.0, NULL, 0 } }; void glitz_glx_query_extensions (glitz_glx_screen_info_t *screen_info, - glitz_gl_float_t glx_version) + glitz_gl_float_t glx_version) { - const char *glx_extensions_string; + const char *glx_extensions_string; - glx_extensions_string = - glXQueryExtensionsString (screen_info->display_info->display, - screen_info->screen); - - screen_info->glx_feature_mask = - glitz_extensions_query (glx_version, - glx_extensions_string, - glx_extensions); - - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) { - const char *vendor; + glx_extensions_string = + glXQueryExtensionsString (screen_info->display_info->display, + screen_info->screen); - vendor = glXGetClientString (screen_info->display_info->display, - GLX_VENDOR); - - if (vendor) { - - /* NVIDIA's driver seem to support multisample with pbuffers */ - if (!strncmp ("NVIDIA", vendor, 6)) - screen_info->glx_feature_mask |= - GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK; + screen_info->glx_feature_mask = + glitz_extensions_query (glx_version, + glx_extensions_string, + glx_extensions); + + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) { + const char *vendor; + + vendor = glXGetClientString (screen_info->display_info->display, + GLX_VENDOR); + + if (vendor) { + + /* NVIDIA's driver seem to support multisample with pbuffers */ + if (!strncmp ("NVIDIA", vendor, 6)) + screen_info->glx_feature_mask |= + GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK; + } } - } } diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_format.c b/gfx/cairo/glitz/src/glx/glitz_glx_format.c index 51670fc506b..0e18e79b696 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_format.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_format.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -34,390 +34,459 @@ static int _glitz_glx_format_compare (const void *elem1, - const void *elem2) + const void *elem2) { - int i, score[2]; - glitz_drawable_format_t *format[2]; - - format[0] = (glitz_drawable_format_t *) elem1; - format[1] = (glitz_drawable_format_t *) elem2; - i = score[0] = score[1] = 0; + glitz_int_drawable_format_t *format[2]; + int i, score[2]; - for (; i < 2; i++) { - if (format[i]->color.red_size) { - if (format[i]->color.red_size == 8) - score[i] += 5; - score[i] += 10; + format[0] = (glitz_int_drawable_format_t *) elem1; + format[1] = (glitz_int_drawable_format_t *) elem2; + i = score[0] = score[1] = 0; + + for (; i < 2; i++) + { + if (format[i]->d.color.red_size) + { + if (format[i]->d.color.red_size >= 8) + score[i] += 5; + + score[i] += 10; + } + + if (format[i]->d.color.alpha_size) + { + if (format[i]->d.color.alpha_size >= 8) + score[i] += 5; + + score[i] += 10; + } + + if (format[i]->d.stencil_size) + score[i] += 5; + + if (format[i]->d.depth_size) + score[i] += 5; + + if (format[i]->d.doublebuffer) + score[i] += 10; + + if (format[i]->d.samples > 1) + score[i] -= (20 - format[i]->d.samples); + + if (format[i]->types & GLITZ_DRAWABLE_TYPE_WINDOW_MASK) + score[i] += 10; + + if (format[i]->types & GLITZ_DRAWABLE_TYPE_PBUFFER_MASK) + score[i] += 10; + + if (format[i]->caveat) + score[i] -= 1000; } - if (format[i]->color.green_size) { - if (format[i]->color.green_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->color.alpha_size) { - if (format[i]->color.alpha_size == 8) - score[i] += 5; - score[i] += 10; - } - - if (format[i]->stencil_size) - score[i] += 5; - - if (format[i]->depth_size) - score[i] += 5; - - if (format[i]->doublebuffer) - score[i] += 10; - - if (format[i]->types.window) - score[i] += 10; - - if (format[i]->types.pbuffer) - score[i] += 10; - - if (format[i]->samples > 1) - score[i] -= (20 - format[i]->samples); - } - - return score[1] - score[0]; + return score[1] - score[0]; } static void -_glitz_add_format (glitz_glx_screen_info_t *screen_info, - glitz_drawable_format_t *format, - XID id) +_glitz_add_format (glitz_glx_screen_info_t *screen_info, + glitz_int_drawable_format_t *format) { int n = screen_info->n_formats; - - screen_info->formats = - realloc (screen_info->formats, - sizeof (glitz_drawable_format_t) * (n + 1)); - screen_info->format_ids = - realloc (screen_info->format_ids, sizeof (XID) * (n + 1)); - if (screen_info->formats && screen_info->format_ids) { - screen_info->formats[n] = *format; - screen_info->formats[n].id = n; - screen_info->format_ids[n] = id; - screen_info->n_formats++; + screen_info->formats = + realloc (screen_info->formats, + sizeof (glitz_int_drawable_format_t) * (n + 1)); + if (screen_info->formats) + { + screen_info->formats[n] = *format; + screen_info->formats[n].d.id = n; + screen_info->n_formats++; } } static void _glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info) { - Display *display; - glitz_drawable_format_t format; - XVisualInfo visual_templ; - XVisualInfo *visuals; - int i, num_visuals; - - display = screen_info->display_info->display; + Display *display; + glitz_int_drawable_format_t format; + XVisualInfo visual_templ; + XVisualInfo *visuals; + int i, num_visuals; - visual_templ.screen = screen_info->screen; - visuals = XGetVisualInfo (display, VisualScreenMask, - &visual_templ, &num_visuals); + display = screen_info->display_info->display; - /* No pbuffers without fbconfigs */ - format.types.window = 1; - format.types.pbuffer = 0; - format.id = 0; + visual_templ.screen = screen_info->screen; + visuals = XGetVisualInfo (display, VisualScreenMask, + &visual_templ, &num_visuals); - for (i = 0; i < num_visuals; i++) { - int value; - - if ((glXGetConfig (display, &visuals[i], GLX_USE_GL, &value) != 0) || - (value == 0)) - continue; - - glXGetConfig (display, &visuals[i], GLX_RGBA, &value); - if (value == 0) - continue; + /* No pbuffers without fbconfigs */ + format.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK; + format.d.id = 0; - /* Stereo is not supported yet */ - glXGetConfig (display, &visuals[i], GLX_STEREO, &value); - if (value != 0) - continue; - - glXGetConfig (display, &visuals[i], GLX_RED_SIZE, &value); - format.color.red_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_GREEN_SIZE, &value); - format.color.green_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_BLUE_SIZE, &value); - format.color.blue_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_ALPHA_SIZE, &value); - format.color.alpha_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_DEPTH_SIZE, &value); - format.depth_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_STENCIL_SIZE, &value); - format.stencil_size = (unsigned short) value; - glXGetConfig (display, &visuals[i], GLX_DOUBLEBUFFER, &value); - format.doublebuffer = (value) ? 1: 0; + for (i = 0; i < num_visuals; i++) + { + int value; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) { - glXGetConfig (display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, &value); - if (value) { - glXGetConfig (display, &visuals[i], GLX_SAMPLES_ARB, &value); - format.samples = (unsigned short) (value > 1)? value: 1; - } else - format.samples = 1; - } else - format.samples = 1; - - _glitz_add_format (screen_info, &format, visuals[i].visualid); - } - - if (visuals) - XFree (visuals); + if ((glXGetConfig (display, &visuals[i], GLX_USE_GL, &value) != 0) || + (value == 0)) + continue; + + glXGetConfig (display, &visuals[i], GLX_RGBA, &value); + if (value == 0) + continue; + + /* Stereo is not supported yet */ + glXGetConfig (display, &visuals[i], GLX_STEREO, &value); + if (value != 0) + continue; + + glXGetConfig (display, &visuals[i], GLX_RED_SIZE, &value); + format.d.color.red_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_GREEN_SIZE, &value); + format.d.color.green_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_BLUE_SIZE, &value); + format.d.color.blue_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_ALPHA_SIZE, &value); + format.d.color.alpha_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_DEPTH_SIZE, &value); + format.d.depth_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_STENCIL_SIZE, &value); + format.d.stencil_size = (unsigned short) value; + glXGetConfig (display, &visuals[i], GLX_DOUBLEBUFFER, &value); + format.d.doublebuffer = (value) ? 1: 0; + + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_VISUAL_RATING_MASK) + { + glXGetConfig (display, &visuals[i], GLX_VISUAL_CAVEAT_EXT, &value); + switch (value) { + case GLX_SLOW_VISUAL_EXT: + case GLX_NON_CONFORMANT_VISUAL_EXT: + format.caveat = 1; + break; + default: + format.caveat = 0; + break; + } + } + else + format.caveat = 0; + + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) + { + glXGetConfig (display, &visuals[i], GLX_SAMPLE_BUFFERS_ARB, + &value); + if (value) + { + glXGetConfig (display, &visuals[i], GLX_SAMPLES_ARB, &value); + format.d.samples = (unsigned short) (value > 1)? value: 1; + } + else + format.d.samples = 1; + } + else + format.d.samples = 1; + + format.u.uval = visuals[i].visualid; + + _glitz_add_format (screen_info, &format); + } + + if (visuals) + XFree (visuals); } static glitz_status_t _glitz_glx_query_formats_using_fbconfigs (glitz_glx_screen_info_t *screen_info) { - glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; - Display *display; - glitz_drawable_format_t format; - GLXFBConfig *fbconfigs; - int i, num_configs; - XID id; - - display = screen_info->display_info->display; + glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; + Display *display; + glitz_int_drawable_format_t format; + GLXFBConfig *fbconfigs; + int i, num_configs; - fbconfigs = glx->get_fbconfigs (display, screen_info->screen, &num_configs); - if (!fbconfigs) { - /* fbconfigs are not supported, falling back to visuals */ - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK; - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; - - return GLITZ_STATUS_NOT_SUPPORTED; - } + display = screen_info->display_info->display; - for (i = 0; i < num_configs; i++) { - int value; - - if ((glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_RENDER_TYPE, &value) != 0) || - (!(value & GLX_RGBA_BIT))) - continue; + fbconfigs = glx->get_fbconfigs (display, screen_info->screen, + &num_configs); + if (!fbconfigs) + { + /* fbconfigs are not supported, falling back to visuals */ + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK; + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; - /* Stereo is not supported yet */ - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STEREO, &value); - if (value != 0) - continue; + return GLITZ_STATUS_NOT_SUPPORTED; + } - glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_DRAWABLE_TYPE, &value); - if (!((value & GLX_WINDOW_BIT) || (value & GLX_PBUFFER_BIT))) - continue; - - format.types.window = (value & GLX_WINDOW_BIT)? 1: 0; - format.types.pbuffer = (value & GLX_PBUFFER_BIT)? 1: 0; - format.id = 0; - - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID, &value); - id = (XID) value; + for (i = 0; i < num_configs; i++) + { + int value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_RED_SIZE, &value); - format.color.red_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_GREEN_SIZE, &value); - format.color.green_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_BLUE_SIZE, &value); - format.color.blue_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_ALPHA_SIZE, &value); - format.color.alpha_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DEPTH_SIZE, &value); - format.depth_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STENCIL_SIZE, &value); - format.stencil_size = (unsigned short) value; - glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DOUBLEBUFFER, &value); - format.doublebuffer = (value)? 1: 0; + if ((glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_RENDER_TYPE, &value) != 0) || + (!(value & GLX_RGBA_BIT))) + continue; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) { - glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_SAMPLE_BUFFERS_ARB, &value); - if (value) { - glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_SAMPLES_ARB, &value); - format.samples = (unsigned short) (value > 1)? value: 1; - if (format.samples > 1) { - if (!(screen_info->glx_feature_mask & - GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK)) - format.types.pbuffer = 0; - } - } else - format.samples = 1; - } else - format.samples = 1; - - _glitz_add_format (screen_info, &format, id); - } - - if (fbconfigs) - XFree (fbconfigs); + /* Stereo is not supported yet */ + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STEREO, &value); + if (value != 0) + continue; - return GLITZ_STATUS_SUCCESS; + glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_DRAWABLE_TYPE, &value); + if (!((value & GLX_WINDOW_BIT) || (value & GLX_PBUFFER_BIT))) + continue; + + format.types = 0; + if (value & GLX_WINDOW_BIT) + format.types |= GLITZ_DRAWABLE_TYPE_WINDOW_MASK; + + if (value & GLX_PBUFFER_BIT) + format.types |= GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + + format.d.id = 0; + + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_FBCONFIG_ID, + &value); + format.u.uval = value; + + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_RED_SIZE, &value); + format.d.color.red_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_GREEN_SIZE, + &value); + format.d.color.green_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_BLUE_SIZE, + &value); + format.d.color.blue_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_ALPHA_SIZE, + &value); + format.d.color.alpha_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DEPTH_SIZE, + &value); + format.d.depth_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_STENCIL_SIZE, + &value); + format.d.stencil_size = (unsigned short) value; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_DOUBLEBUFFER, + &value); + format.d.doublebuffer = (value)? 1: 0; + glx->get_fbconfig_attrib (display, fbconfigs[i], GLX_CONFIG_CAVEAT, + &value); + switch (value) { + case GLX_SLOW_VISUAL_EXT: + case GLX_NON_CONFORMANT_VISUAL_EXT: + format.caveat = 1; + break; + default: + format.caveat = 0; + break; + } + + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_MULTISAMPLE_MASK) + { + glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_SAMPLE_BUFFERS_ARB, &value); + if (value) + { + glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_SAMPLES_ARB, &value); + format.d.samples = (unsigned short) (value > 1)? value: 1; + if (format.d.samples > 1) + { + if (!(screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK)) + format.types &= ~GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + } + } + else + format.d.samples = 1; + } + else + format.d.samples = 1; + + _glitz_add_format (screen_info, &format); + } + + if (fbconfigs) + XFree (fbconfigs); + + return GLITZ_STATUS_SUCCESS; } void glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info) { - glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED; - XID *new_ids; - int i; + glitz_status_t status = GLITZ_STATUS_NOT_SUPPORTED; + int i; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) - status = _glitz_glx_query_formats_using_fbconfigs (screen_info); + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) + status = _glitz_glx_query_formats_using_fbconfigs (screen_info); - if (status) - _glitz_glx_query_formats (screen_info); + if (status) + _glitz_glx_query_formats (screen_info); - if (!screen_info->n_formats) - return; + if (!screen_info->n_formats) + return; - qsort (screen_info->formats, screen_info->n_formats, - sizeof (glitz_drawable_format_t), _glitz_glx_format_compare); + qsort (screen_info->formats, screen_info->n_formats, + sizeof (glitz_int_drawable_format_t), _glitz_glx_format_compare); - /* - * Update XID list so that it matches the sorted format list. - */ - new_ids = malloc (sizeof (XID) * screen_info->n_formats); - if (!new_ids) { - screen_info->n_formats = 0; - return; - } - - for (i = 0; i < screen_info->n_formats; i++) { - new_ids[i] = screen_info->format_ids[screen_info->formats[i].id]; - screen_info->formats[i].id = i; - } - - free (screen_info->format_ids); - screen_info->format_ids = new_ids; + for (i = 0; i < screen_info->n_formats; i++) + screen_info->formats[i].d.id = i; } glitz_drawable_format_t * -glitz_glx_find_drawable_format (Display *display, - int screen, - unsigned long mask, - const glitz_drawable_format_t *templ, - int count) +glitz_glx_find_window_format (Display *display, + int screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) { - glitz_glx_screen_info_t *screen_info = - glitz_glx_screen_info_get (display, screen); + glitz_int_drawable_format_t itempl; + glitz_glx_screen_info_t *screen_info = + glitz_glx_screen_info_get (display, screen); - return glitz_drawable_format_find (screen_info->formats, - screen_info->n_formats, - mask, templ, count); + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_WINDOW_MASK; + mask |= GLITZ_INT_FORMAT_WINDOW_MASK; + + return glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + mask, &itempl, count); } -slim_hidden_def(glitz_glx_find_drawable_format); +slim_hidden_def(glitz_glx_find_window_format); + +glitz_drawable_format_t * +glitz_glx_find_pbuffer_format (Display *display, + int screen, + unsigned long mask, + const glitz_drawable_format_t *templ, + int count) +{ + glitz_int_drawable_format_t itempl; + glitz_glx_screen_info_t *screen_info = + glitz_glx_screen_info_get (display, screen); + + glitz_drawable_format_copy (templ, &itempl.d, mask); + + itempl.types = GLITZ_DRAWABLE_TYPE_PBUFFER_MASK; + mask |= GLITZ_INT_FORMAT_PBUFFER_MASK; + + return glitz_drawable_format_find (screen_info->formats, + screen_info->n_formats, + mask, &itempl, count); +} +slim_hidden_def(glitz_glx_find_pbuffer_format); glitz_drawable_format_t * glitz_glx_find_drawable_format_for_visual (Display *display, - int screen, - VisualID visual_id) + int screen, + VisualID visual_id) { glitz_drawable_format_t *format = NULL; glitz_glx_screen_info_t *screen_info; - int i; + int i; screen_info = glitz_glx_screen_info_get (display, screen); if (!screen_info) - return NULL; + return NULL; if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) { - glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; - GLXFBConfig *fbconfigs; - int fid, n_fbconfigs; - - fid = -1; - fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs); - for (i = 0; i < n_fbconfigs; i++) - { - XVisualInfo *visinfo; - - visinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]); - if (visinfo && visinfo->visualid == visual_id) - { - int value; + glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; + GLXFBConfig *fbconfigs; + int fid, n_fbconfigs; - glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_FBCONFIG_ID, &value); - for (fid = 0; fid < screen_info->n_formats; fid++) - { - if (screen_info->format_ids[fid] == value) - { - format = screen_info->formats + fid; - break; - } - } - - if (format) - break; - } - } - - if (fbconfigs) - XFree (fbconfigs); + fid = -1; + fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs); + for (i = 0; i < n_fbconfigs; i++) + { + XVisualInfo *visinfo; + + visinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]); + if (visinfo && visinfo->visualid == visual_id) + { + int value; + + glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_FBCONFIG_ID, &value); + for (fid = 0; fid < screen_info->n_formats; fid++) + { + if (screen_info->formats[fid].u.uval == value) + { + format = &screen_info->formats[fid].d; + break; + } + } + + if (format) + break; + } + } + + if (fbconfigs) + XFree (fbconfigs); } else { - for (i = 0; i < screen_info->n_formats; i++) - { - if (visual_id == screen_info->format_ids[i]) - { - format = screen_info->formats + i; - break; - } - } + for (i = 0; i < screen_info->n_formats; i++) + { + if (visual_id == screen_info->formats[i].u.uval) + { + format = &screen_info->formats[i].d; + break; + } + } } - + return format; } slim_hidden_def(glitz_glx_find_drawable_format_for_visual); XVisualInfo * glitz_glx_get_visual_info_from_format (Display *display, - int screen, - glitz_drawable_format_t *format) + int screen, + glitz_drawable_format_t *format) { - XVisualInfo *vinfo = NULL; - glitz_glx_screen_info_t *screen_info = - glitz_glx_screen_info_get (display, screen); - glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; + XVisualInfo *vinfo = NULL; + glitz_glx_screen_info_t *screen_info = + glitz_glx_screen_info_get (display, screen); + glitz_glx_static_proc_address_list_t *glx = &screen_info->glx; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) { - GLXFBConfig *fbconfigs; - int i, n_fbconfigs; - int fbconfigid = screen_info->format_ids[format->id]; + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) + { + GLXFBConfig *fbconfigs; + int i, n_fbconfigs; + int fbconfigid = screen_info->formats[format->id].u.uval; + + fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs); + for (i = 0; i < n_fbconfigs; i++) + { + int value; + + glx->get_fbconfig_attrib (display, fbconfigs[i], + GLX_FBCONFIG_ID, &value); + if (value == fbconfigid) + break; + } + + if (i < n_fbconfigs) + vinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]); + + if (fbconfigs) + XFree (fbconfigs); - fbconfigs = glx->get_fbconfigs (display, screen, &n_fbconfigs); - for (i = 0; i < n_fbconfigs; i++) { - int value; - - glx->get_fbconfig_attrib (display, fbconfigs[i], - GLX_FBCONFIG_ID, &value); - if (value == fbconfigid) - break; } - - if (i < n_fbconfigs) - vinfo = glx->get_visual_from_fbconfig (display, fbconfigs[i]); - - if (fbconfigs) - XFree (fbconfigs); - - } else { - XVisualInfo templ; - int n_items; - - templ.visualid = screen_info->format_ids[format->id]; - - vinfo = XGetVisualInfo (display, VisualIDMask, &templ, &n_items); - } - - return vinfo; + else + { + XVisualInfo templ; + int n_items; + + templ.visualid = screen_info->formats[format->id].u.uval; + + vinfo = XGetVisualInfo (display, VisualIDMask, &templ, &n_items); + } + + return vinfo; } slim_hidden_def(glitz_glx_get_visual_info_from_format); diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_info.c b/gfx/cairo/glitz/src/glx/glitz_glx_info.c index def1de73f7c..5f7f28720df 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_info.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_info.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -34,219 +34,244 @@ glitz_gl_proc_address_list_t _glitz_glx_gl_proc_address = { - /* core */ - (glitz_gl_enable_t) glEnable, - (glitz_gl_disable_t) glDisable, - (glitz_gl_get_error_t) glGetError, - (glitz_gl_get_string_t) glGetString, - (glitz_gl_enable_client_state_t) glEnableClientState, - (glitz_gl_disable_client_state_t) glDisableClientState, - (glitz_gl_vertex_pointer_t) glVertexPointer, - (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, - (glitz_gl_draw_arrays_t) glDrawArrays, - (glitz_gl_tex_env_f_t) glTexEnvf, - (glitz_gl_tex_env_fv_t) glTexEnvfv, - (glitz_gl_tex_gen_i_t) glTexGeni, - (glitz_gl_tex_gen_fv_t) glTexGenfv, - (glitz_gl_color_4us_t) glColor4us, - (glitz_gl_color_4f_t) glColor4f, - (glitz_gl_scissor_t) glScissor, - (glitz_gl_blend_func_t) glBlendFunc, - (glitz_gl_clear_t) glClear, - (glitz_gl_clear_color_t) glClearColor, - (glitz_gl_clear_stencil_t) glClearStencil, - (glitz_gl_stencil_func_t) glStencilFunc, - (glitz_gl_stencil_op_t) glStencilOp, - (glitz_gl_push_attrib_t) glPushAttrib, - (glitz_gl_pop_attrib_t) glPopAttrib, - (glitz_gl_matrix_mode_t) glMatrixMode, - (glitz_gl_push_matrix_t) glPushMatrix, - (glitz_gl_pop_matrix_t) glPopMatrix, - (glitz_gl_load_identity_t) glLoadIdentity, - (glitz_gl_load_matrix_f_t) glLoadMatrixf, - (glitz_gl_depth_range_t) glDepthRange, - (glitz_gl_viewport_t) glViewport, - (glitz_gl_raster_pos_2f_t) glRasterPos2f, - (glitz_gl_bitmap_t) glBitmap, - (glitz_gl_read_buffer_t) glReadBuffer, - (glitz_gl_draw_buffer_t) glDrawBuffer, - (glitz_gl_copy_pixels_t) glCopyPixels, - (glitz_gl_flush_t) glFlush, - (glitz_gl_finish_t) glFinish, - (glitz_gl_pixel_store_i_t) glPixelStorei, - (glitz_gl_ortho_t) glOrtho, - (glitz_gl_scale_f_t) glScalef, - (glitz_gl_translate_f_t) glTranslatef, - (glitz_gl_hint_t) glHint, - (glitz_gl_depth_mask_t) glDepthMask, - (glitz_gl_polygon_mode_t) glPolygonMode, - (glitz_gl_shade_model_t) glShadeModel, - (glitz_gl_color_mask_t) glColorMask, - (glitz_gl_read_pixels_t) glReadPixels, - (glitz_gl_get_tex_image_t) glGetTexImage, - (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, - (glitz_gl_gen_textures_t) glGenTextures, - (glitz_gl_delete_textures_t) glDeleteTextures, - (glitz_gl_bind_texture_t) glBindTexture, - (glitz_gl_tex_image_2d_t) glTexImage2D, - (glitz_gl_tex_parameter_i_t) glTexParameteri, - (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, - (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, - (glitz_gl_get_integer_v_t) glGetIntegerv, + /* core */ + (glitz_gl_enable_t) glEnable, + (glitz_gl_disable_t) glDisable, + (glitz_gl_get_error_t) glGetError, + (glitz_gl_get_string_t) glGetString, + (glitz_gl_enable_client_state_t) glEnableClientState, + (glitz_gl_disable_client_state_t) glDisableClientState, + (glitz_gl_vertex_pointer_t) glVertexPointer, + (glitz_gl_tex_coord_pointer_t) glTexCoordPointer, + (glitz_gl_draw_arrays_t) glDrawArrays, + (glitz_gl_tex_env_f_t) glTexEnvf, + (glitz_gl_tex_env_fv_t) glTexEnvfv, + (glitz_gl_tex_gen_i_t) glTexGeni, + (glitz_gl_tex_gen_fv_t) glTexGenfv, + (glitz_gl_color_4us_t) glColor4us, + (glitz_gl_color_4f_t) glColor4f, + (glitz_gl_scissor_t) glScissor, + (glitz_gl_blend_func_t) glBlendFunc, + (glitz_gl_clear_t) glClear, + (glitz_gl_clear_color_t) glClearColor, + (glitz_gl_clear_stencil_t) glClearStencil, + (glitz_gl_stencil_func_t) glStencilFunc, + (glitz_gl_stencil_op_t) glStencilOp, + (glitz_gl_push_attrib_t) glPushAttrib, + (glitz_gl_pop_attrib_t) glPopAttrib, + (glitz_gl_matrix_mode_t) glMatrixMode, + (glitz_gl_push_matrix_t) glPushMatrix, + (glitz_gl_pop_matrix_t) glPopMatrix, + (glitz_gl_load_identity_t) glLoadIdentity, + (glitz_gl_load_matrix_f_t) glLoadMatrixf, + (glitz_gl_depth_range_t) glDepthRange, + (glitz_gl_viewport_t) glViewport, + (glitz_gl_raster_pos_2f_t) glRasterPos2f, + (glitz_gl_bitmap_t) glBitmap, + (glitz_gl_read_buffer_t) glReadBuffer, + (glitz_gl_draw_buffer_t) glDrawBuffer, + (glitz_gl_copy_pixels_t) glCopyPixels, + (glitz_gl_flush_t) glFlush, + (glitz_gl_finish_t) glFinish, + (glitz_gl_pixel_store_i_t) glPixelStorei, + (glitz_gl_ortho_t) glOrtho, + (glitz_gl_scale_f_t) glScalef, + (glitz_gl_translate_f_t) glTranslatef, + (glitz_gl_hint_t) glHint, + (glitz_gl_depth_mask_t) glDepthMask, + (glitz_gl_polygon_mode_t) glPolygonMode, + (glitz_gl_shade_model_t) glShadeModel, + (glitz_gl_color_mask_t) glColorMask, + (glitz_gl_read_pixels_t) glReadPixels, + (glitz_gl_get_tex_image_t) glGetTexImage, + (glitz_gl_tex_sub_image_2d_t) glTexSubImage2D, + (glitz_gl_gen_textures_t) glGenTextures, + (glitz_gl_delete_textures_t) glDeleteTextures, + (glitz_gl_bind_texture_t) glBindTexture, + (glitz_gl_tex_image_2d_t) glTexImage2D, + (glitz_gl_tex_parameter_i_t) glTexParameteri, + (glitz_gl_tex_parameter_fv_t) glTexParameterfv, + (glitz_gl_get_tex_level_parameter_iv_t) glGetTexLevelParameteriv, + (glitz_gl_copy_tex_sub_image_2d_t) glCopyTexSubImage2D, + (glitz_gl_get_integer_v_t) glGetIntegerv, - /* extensions */ - (glitz_gl_blend_color_t) 0, - (glitz_gl_active_texture_t) 0, - (glitz_gl_client_active_texture_t) 0, - (glitz_gl_multi_draw_arrays_t) 0, - (glitz_gl_gen_programs_t) 0, - (glitz_gl_delete_programs_t) 0, - (glitz_gl_program_string_t) 0, - (glitz_gl_bind_program_t) 0, - (glitz_gl_program_local_param_4fv_t) 0, - (glitz_gl_get_program_iv_t) 0, - (glitz_gl_gen_buffers_t) 0, - (glitz_gl_delete_buffers_t) 0, - (glitz_gl_bind_buffer_t) 0, - (glitz_gl_buffer_data_t) 0, - (glitz_gl_buffer_sub_data_t) 0, - (glitz_gl_get_buffer_sub_data_t) 0, - (glitz_gl_map_buffer_t) 0, - (glitz_gl_unmap_buffer_t) 0 + /* extensions */ + (glitz_gl_blend_color_t) 0, + (glitz_gl_active_texture_t) 0, + (glitz_gl_client_active_texture_t) 0, + (glitz_gl_multi_draw_arrays_t) 0, + (glitz_gl_gen_programs_t) 0, + (glitz_gl_delete_programs_t) 0, + (glitz_gl_program_string_t) 0, + (glitz_gl_bind_program_t) 0, + (glitz_gl_program_local_param_4fv_t) 0, + (glitz_gl_get_program_iv_t) 0, + (glitz_gl_gen_buffers_t) 0, + (glitz_gl_delete_buffers_t) 0, + (glitz_gl_bind_buffer_t) 0, + (glitz_gl_buffer_data_t) 0, + (glitz_gl_buffer_sub_data_t) 0, + (glitz_gl_get_buffer_sub_data_t) 0, + (glitz_gl_map_buffer_t) 0, + (glitz_gl_unmap_buffer_t) 0, + (glitz_gl_gen_framebuffers_t) 0, + (glitz_gl_delete_framebuffers_t) 0, + (glitz_gl_bind_framebuffer_t) 0, + (glitz_gl_framebuffer_renderbuffer_t) 0, + (glitz_gl_framebuffer_texture_2d_t) 0, + (glitz_gl_check_framebuffer_status_t) 0, + (glitz_gl_gen_renderbuffers_t) 0, + (glitz_gl_delete_renderbuffers_t) 0, + (glitz_gl_bind_renderbuffer_t) 0, + (glitz_gl_renderbuffer_storage_t) 0, + (glitz_gl_get_renderbuffer_parameter_iv_t) 0 }; glitz_function_pointer_t glitz_glx_get_proc_address (const char *name, - void *closure) + void *closure) { - glitz_glx_screen_info_t *screen_info = (glitz_glx_screen_info_t *) closure; - glitz_glx_thread_info_t *info = screen_info->display_info->thread_info; - glitz_function_pointer_t address = NULL; + glitz_glx_screen_info_t *screen_info = (glitz_glx_screen_info_t *) closure; + glitz_glx_thread_info_t *info = screen_info->display_info->thread_info; + glitz_function_pointer_t address = NULL; - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK) - address = screen_info->glx.get_proc_address ((glitz_gl_ubyte_t *) name); - - if (!address) { - if (!info->dlhand) - info->dlhand = dlopen (info->gl_library, RTLD_LAZY); - - if (info->dlhand) { - dlerror (); - address = (glitz_function_pointer_t) dlsym (info->dlhand, name); - if (dlerror () != NULL) - address = NULL; + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK) + address = + screen_info->glx.get_proc_address ((glitz_gl_ubyte_t *) name); + + if (!address) { + if (!info->dlhand) + info->dlhand = dlopen (info->gl_library, RTLD_LAZY); + + if (info->dlhand) { + dlerror (); + address = (glitz_function_pointer_t) dlsym (info->dlhand, name); + if (dlerror () != NULL) + address = NULL; + } } - } - - return address; + + return address; } static void _glitz_glx_proc_address_lookup (glitz_glx_screen_info_t *screen_info) { - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) { - if (screen_info->glx_version >= 1.3f) { - screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t) - glitz_glx_get_proc_address ("glXGetFBConfigs", (void *) screen_info); - screen_info->glx.get_fbconfig_attrib = (glitz_glx_get_fbconfig_attrib_t) - glitz_glx_get_proc_address ("glXGetFBConfigAttrib", - (void *) screen_info); - screen_info->glx.get_visual_from_fbconfig = - (glitz_glx_get_visual_from_fbconfig_t) - glitz_glx_get_proc_address ("glXGetVisualFromFBConfig", - (void *) screen_info); - screen_info->glx.create_new_context = (glitz_glx_create_new_context_t) - glitz_glx_get_proc_address ("glXCreateNewContext", - (void *) screen_info); + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_FBCONFIG_MASK) { + if (screen_info->glx_version >= 1.3f) { + screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t) + glitz_glx_get_proc_address ("glXGetFBConfigs", + (void *) screen_info); + screen_info->glx.get_fbconfig_attrib = + (glitz_glx_get_fbconfig_attrib_t) + glitz_glx_get_proc_address ("glXGetFBConfigAttrib", + (void *) screen_info); + screen_info->glx.get_visual_from_fbconfig = + (glitz_glx_get_visual_from_fbconfig_t) + glitz_glx_get_proc_address ("glXGetVisualFromFBConfig", + (void *) screen_info); + screen_info->glx.create_new_context = + (glitz_glx_create_new_context_t) + glitz_glx_get_proc_address ("glXCreateNewContext", + (void *) screen_info); - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) { - screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t) - glitz_glx_get_proc_address ("glXCreatePbuffer", - (void *) screen_info); - screen_info->glx.destroy_pbuffer = (glitz_glx_destroy_pbuffer_t) - glitz_glx_get_proc_address ("glXDestroyPbuffer", - (void *) screen_info); - screen_info->glx.query_drawable = (glitz_glx_query_drawable_t) - glitz_glx_get_proc_address ("glXQueryDrawable", - (void *) screen_info); - } - } else { - screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t) - glitz_glx_get_proc_address ("glXGetFBConfigsSGIX", - (void *) screen_info); - screen_info->glx.get_fbconfig_attrib = (glitz_glx_get_fbconfig_attrib_t) - glitz_glx_get_proc_address ("glXGetFBConfigAttribSGIX", - (void *) screen_info); - screen_info->glx.get_visual_from_fbconfig = - (glitz_glx_get_visual_from_fbconfig_t) - glitz_glx_get_proc_address ("glXGetVisualFromFBConfigSGIX", - (void *) screen_info); - screen_info->glx.create_new_context = (glitz_glx_create_new_context_t) - glitz_glx_get_proc_address ("glXCreateContextWithConfigSGIX", - (void *) screen_info); + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) + { + screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t) + glitz_glx_get_proc_address ("glXCreatePbuffer", + (void *) screen_info); + screen_info->glx.destroy_pbuffer = + (glitz_glx_destroy_pbuffer_t) + glitz_glx_get_proc_address ("glXDestroyPbuffer", + (void *) screen_info); + screen_info->glx.query_drawable = + (glitz_glx_query_drawable_t) + glitz_glx_get_proc_address ("glXQueryDrawable", + (void *) screen_info); + } + } else { + screen_info->glx.get_fbconfigs = (glitz_glx_get_fbconfigs_t) + glitz_glx_get_proc_address ("glXGetFBConfigsSGIX", + (void *) screen_info); + screen_info->glx.get_fbconfig_attrib = + (glitz_glx_get_fbconfig_attrib_t) + glitz_glx_get_proc_address ("glXGetFBConfigAttribSGIX", + (void *) screen_info); + screen_info->glx.get_visual_from_fbconfig = + (glitz_glx_get_visual_from_fbconfig_t) + glitz_glx_get_proc_address ("glXGetVisualFromFBConfigSGIX", + (void *) screen_info); + screen_info->glx.create_new_context = + (glitz_glx_create_new_context_t) + glitz_glx_get_proc_address ("glXCreateContextWithConfigSGIX", + (void *) screen_info); - if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) { - screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t) - glitz_glx_get_proc_address ("glXCreateGLXPbufferSGIX", - (void *) screen_info); - screen_info->glx.destroy_pbuffer = (glitz_glx_destroy_pbuffer_t) - glitz_glx_get_proc_address ("glXDestroyGLXPbufferSGIX", - (void *) screen_info); - screen_info->glx.query_drawable = (glitz_glx_query_drawable_t) - glitz_glx_get_proc_address ("glXQueryGLXPbufferSGIX", - (void *) screen_info); - } + if (screen_info->glx_feature_mask & GLITZ_GLX_FEATURE_PBUFFER_MASK) + { + screen_info->glx.create_pbuffer = (glitz_glx_create_pbuffer_t) + glitz_glx_get_proc_address ("glXCreateGLXPbufferSGIX", + (void *) screen_info); + screen_info->glx.destroy_pbuffer = + (glitz_glx_destroy_pbuffer_t) + glitz_glx_get_proc_address ("glXDestroyGLXPbufferSGIX", + (void *) screen_info); + screen_info->glx.query_drawable = (glitz_glx_query_drawable_t) + glitz_glx_get_proc_address ("glXQueryGLXPbufferSGIX", + (void *) screen_info); + } + } + + if ((!screen_info->glx.create_pbuffer) || + (!screen_info->glx.destroy_pbuffer) || + (!screen_info->glx.query_drawable)) + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; + + if ((!screen_info->glx.get_fbconfigs) || + (!screen_info->glx.get_fbconfig_attrib) || + (!screen_info->glx.get_visual_from_fbconfig) || + (!screen_info->glx.create_new_context)) { + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK; + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; + } + } else + screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; + + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK) { + if (screen_info->glx_version >= 1.3f) { + screen_info->glx.make_context_current = + (glitz_glx_make_context_current_t) + glitz_glx_get_proc_address ("glXMakeContextCurrent", + (void *) screen_info); + } else { + screen_info->glx.make_context_current = + (glitz_glx_make_context_current_t) + glitz_glx_get_proc_address ("glXMakeCurrentReadSGI", + (void *) screen_info); + } + + if (!screen_info->glx.make_context_current) + screen_info->glx_feature_mask &= + ~GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK; } - if ((!screen_info->glx.create_pbuffer) || - (!screen_info->glx.destroy_pbuffer) || - (!screen_info->glx.query_drawable)) - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; + if (screen_info->glx_feature_mask & + GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK) { + if (screen_info->glx_version >= 1.4f) { + screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t) + glitz_glx_get_proc_address ("glXGetProcAddress", + (void *) screen_info); + } else { + screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t) + glitz_glx_get_proc_address ("glXGetProcAddressARB", + (void *) screen_info); + } - if ((!screen_info->glx.get_fbconfigs) || - (!screen_info->glx.get_fbconfig_attrib) || - (!screen_info->glx.get_visual_from_fbconfig) || - (!screen_info->glx.create_new_context)) { - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_FBCONFIG_MASK; - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; + if (!screen_info->glx.get_proc_address) + screen_info->glx_feature_mask &= + ~GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK; } - } else - screen_info->glx_feature_mask &= ~GLITZ_GLX_FEATURE_PBUFFER_MASK; - - if (screen_info->glx_feature_mask & - GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK) { - if (screen_info->glx_version >= 1.3f) { - screen_info->glx.make_context_current = - (glitz_glx_make_context_current_t) - glitz_glx_get_proc_address ("glXMakeContextCurrent", - (void *) screen_info); - } else { - screen_info->glx.make_context_current = - (glitz_glx_make_context_current_t) - glitz_glx_get_proc_address ("glXMakeCurrentReadSGI", - (void *) screen_info); - } - - if (!screen_info->glx.make_context_current) - screen_info->glx_feature_mask &= - ~GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK; - } - - if (screen_info->glx_feature_mask & - GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK) { - if (screen_info->glx_version >= 1.4f) { - screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t) - glitz_glx_get_proc_address ("glXGetProcAddress", (void *) screen_info); - } else { - screen_info->glx.get_proc_address = (glitz_glx_get_proc_address_t) - glitz_glx_get_proc_address ("glXGetProcAddressARB", - (void *) screen_info); - } - - if (!screen_info->glx.get_proc_address) - screen_info->glx_feature_mask &= - ~GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK; - } } static void @@ -258,27 +283,27 @@ _glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info); static void _glitz_glx_thread_info_fini (glitz_glx_thread_info_t *thread_info) { - int i; - - for (i = 0; i < thread_info->n_displays; i++) - _glitz_glx_display_destroy (thread_info->displays[i]); + int i; - free (thread_info->displays); - - thread_info->displays = NULL; - thread_info->n_displays = 0; + for (i = 0; i < thread_info->n_displays; i++) + _glitz_glx_display_destroy (thread_info->displays[i]); - if (thread_info->gl_library) { - free (thread_info->gl_library); - thread_info->gl_library = NULL; - } + free (thread_info->displays); - if (thread_info->dlhand) { - dlclose (thread_info->dlhand); - thread_info->dlhand = NULL; - } - - thread_info->cctx = NULL; + thread_info->displays = NULL; + thread_info->n_displays = 0; + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + if (thread_info->dlhand) { + dlclose (thread_info->dlhand); + thread_info->dlhand = NULL; + } + + thread_info->cctx = NULL; } #ifdef XTHREADS @@ -293,108 +318,108 @@ static xthread_key_t info_tsd; static void _glitz_glx_thread_info_init (glitz_glx_thread_info_t *thread_info) { - thread_info->displays = NULL; - thread_info->n_displays = 0; - thread_info->gl_library = NULL; - thread_info->dlhand = NULL; - thread_info->cctx = NULL; + thread_info->displays = NULL; + thread_info->n_displays = 0; + thread_info->gl_library = NULL; + thread_info->dlhand = NULL; + thread_info->cctx = NULL; } static void _glitz_glx_thread_info_destroy (glitz_glx_thread_info_t *thread_info) { - xthread_set_specific (info_tsd, NULL); - - if (thread_info) { - _glitz_glx_thread_info_fini (thread_info); - free (thread_info); - } + xthread_set_specific (info_tsd, NULL); + + if (thread_info) { + _glitz_glx_thread_info_fini (thread_info); + free (thread_info); + } } static void _tsd_destroy (void *p) { - if (p) { - _glitz_glx_thread_info_fini ((glitz_glx_thread_info_t *) p); - free (p); - } + if (p) { + _glitz_glx_thread_info_fini ((glitz_glx_thread_info_t *) p); + free (p); + } } static glitz_glx_thread_info_t * _glitz_glx_thread_info_get (const char *gl_library) { - glitz_glx_thread_info_t *thread_info; - void *p; - - if (!tsd_initialized) { - xthread_key_create (&info_tsd, _tsd_destroy); - tsd_initialized = 1; - } + glitz_glx_thread_info_t *thread_info; + void *p; - xthread_get_specific (info_tsd, &p); - - if (p == NULL) { - thread_info = malloc (sizeof (glitz_glx_thread_info_t)); - _glitz_glx_thread_info_init (thread_info); - - xthread_set_specific (info_tsd, thread_info); - } else - thread_info = (glitz_glx_thread_info_t *) p; - - if (gl_library) { - int len = strlen (gl_library); - - if (thread_info->gl_library) { - free (thread_info->gl_library); - thread_info->gl_library = NULL; + if (!tsd_initialized) { + xthread_key_create (&info_tsd, _tsd_destroy); + tsd_initialized = 1; } - - thread_info->gl_library = malloc (len + 1); - if (thread_info->gl_library) { - memcpy (thread_info->gl_library, gl_library, len); - thread_info->gl_library[len] = '\0'; - } - } - return thread_info; + xthread_get_specific (info_tsd, &p); + + if (p == NULL) { + thread_info = malloc (sizeof (glitz_glx_thread_info_t)); + _glitz_glx_thread_info_init (thread_info); + + xthread_set_specific (info_tsd, thread_info); + } else + thread_info = (glitz_glx_thread_info_t *) p; + + if (gl_library) { + int len = strlen (gl_library); + + if (thread_info->gl_library) { + free (thread_info->gl_library); + thread_info->gl_library = NULL; + } + + thread_info->gl_library = malloc (len + 1); + if (thread_info->gl_library) { + memcpy (thread_info->gl_library, gl_library, len); + thread_info->gl_library[len] = '\0'; + } + } + + return thread_info; } #else /* not thread safe */ static glitz_glx_thread_info_t thread_info = { - NULL, - 0, - NULL, - NULL + NULL, + 0, + NULL, + NULL }; static void _glitz_glx_thread_info_destroy (glitz_glx_thread_info_t *thread_info) { - if (thread_info) - _glitz_glx_thread_info_fini (thread_info); + if (thread_info) + _glitz_glx_thread_info_fini (thread_info); } static glitz_glx_thread_info_t * _glitz_glx_thread_info_get (const char *gl_library) { - if (gl_library) { - int len = strlen (gl_library); + if (gl_library) { + int len = strlen (gl_library); - if (thread_info.gl_library) { - free (thread_info.gl_library); - thread_info.gl_library = NULL; + if (thread_info.gl_library) { + free (thread_info.gl_library); + thread_info.gl_library = NULL; + } + + thread_info.gl_library = malloc (len + 1); + if (thread_info.gl_library) { + memcpy (thread_info.gl_library, gl_library, len); + thread_info.gl_library[len] = '\0'; + } } - - thread_info.gl_library = malloc (len + 1); - if (thread_info.gl_library) { - memcpy (thread_info.gl_library, gl_library, len); - thread_info.gl_library[len] = '\0'; - } - } - - return &thread_info; + + return &thread_info; } #endif @@ -402,143 +427,142 @@ _glitz_glx_thread_info_get (const char *gl_library) static glitz_glx_display_info_t * _glitz_glx_display_info_get (Display *display) { - glitz_glx_display_info_t *display_info; - glitz_glx_thread_info_t *thread_info = _glitz_glx_thread_info_get (NULL); - glitz_glx_display_info_t **displays = thread_info->displays; - int index, n_displays = thread_info->n_displays; + glitz_glx_display_info_t *display_info; + glitz_glx_thread_info_t *thread_info = _glitz_glx_thread_info_get (NULL); + glitz_glx_display_info_t **displays = thread_info->displays; + int index, n_displays = thread_info->n_displays; - for (; n_displays; n_displays--, displays++) - if ((*displays)->display == display) - return *displays; + for (; n_displays; n_displays--, displays++) + if ((*displays)->display == display) + return *displays; - index = thread_info->n_displays++; + index = thread_info->n_displays++; - thread_info->displays = - realloc (thread_info->displays, - sizeof (glitz_glx_display_info_t *) * thread_info->n_displays); + thread_info->displays = + realloc (thread_info->displays, + sizeof (glitz_glx_display_info_t *) * + thread_info->n_displays); - display_info = malloc (sizeof (glitz_glx_display_info_t)); - thread_info->displays[index] = display_info; - - display_info->thread_info = thread_info; - display_info->display = display; - display_info->screens = NULL; - display_info->n_screens = 0; - - return display_info; + display_info = malloc (sizeof (glitz_glx_display_info_t)); + thread_info->displays[index] = display_info; + + display_info->thread_info = thread_info; + display_info->display = display; + display_info->screens = NULL; + display_info->n_screens = 0; + + return display_info; } static void _glitz_glx_display_destroy (glitz_glx_display_info_t *display_info) { - int i; - - for (i = 0; i < display_info->n_screens; i++) - _glitz_glx_screen_destroy (display_info->screens[i]); + int i; - if (display_info->screens) - free (display_info->screens); - - free (display_info); + for (i = 0; i < display_info->n_screens; i++) + _glitz_glx_screen_destroy (display_info->screens[i]); + + if (display_info->screens) + free (display_info->screens); + + free (display_info); } glitz_glx_screen_info_t * glitz_glx_screen_info_get (Display *display, - int screen) + int screen) { - glitz_glx_screen_info_t *screen_info; - glitz_glx_display_info_t *display_info = - _glitz_glx_display_info_get (display); - glitz_glx_screen_info_t **screens = display_info->screens; - int error_base, event_base, index, n_screens = display_info->n_screens; + glitz_glx_screen_info_t *screen_info; + glitz_glx_display_info_t *display_info = + _glitz_glx_display_info_get (display); + glitz_glx_screen_info_t **screens = display_info->screens; + int error_base, event_base, index, n_screens = display_info->n_screens; - for (; n_screens; n_screens--, screens++) - if ((*screens)->screen == screen) - return *screens; + for (; n_screens; n_screens--, screens++) + if ((*screens)->screen == screen) + return *screens; - index = display_info->n_screens++; + index = display_info->n_screens++; - display_info->screens = - realloc (display_info->screens, - sizeof (glitz_glx_screen_info_t *) * display_info->n_screens); - - screen_info = malloc (sizeof (glitz_glx_screen_info_t)); - display_info->screens[index] = screen_info; - - screen_info->display_info = display_info; - screen_info->screen = screen; - screen_info->drawables = 0; - screen_info->formats = NULL; - screen_info->format_ids = NULL; - screen_info->n_formats = 0; + display_info->screens = + realloc (display_info->screens, + sizeof (glitz_glx_screen_info_t *) * display_info->n_screens); - screen_info->contexts = NULL; - screen_info->n_contexts = 0; - - memset (&screen_info->glx, 0, sizeof (glitz_glx_static_proc_address_list_t)); + screen_info = malloc (sizeof (glitz_glx_screen_info_t)); + display_info->screens[index] = screen_info; - glitz_program_map_init (&screen_info->program_map); - - screen_info->root_context = (GLXContext) 0; - screen_info->glx_feature_mask = 0; + screen_info->display_info = display_info; + screen_info->screen = screen; + screen_info->drawables = 0; + screen_info->formats = NULL; + screen_info->n_formats = 0; - if (glXQueryExtension (display, &error_base, &event_base)) { - int major, minor; - - if (glXQueryVersion (display, &major, &minor)) { - screen_info->glx_version = major + minor / 10.0f; - if (major > 1 || (major > 0 || minor >= 2)) { - glitz_glx_query_extensions (screen_info, screen_info->glx_version); - _glitz_glx_proc_address_lookup (screen_info); - glitz_glx_query_formats (screen_info); - } + screen_info->contexts = NULL; + screen_info->n_contexts = 0; + + memset (&screen_info->glx, 0, + sizeof (glitz_glx_static_proc_address_list_t)); + + glitz_program_map_init (&screen_info->program_map); + + screen_info->root_context = (GLXContext) 0; + screen_info->glx_feature_mask = 0; + + if (glXQueryExtension (display, &error_base, &event_base)) { + int major, minor; + + if (glXQueryVersion (display, &major, &minor)) { + screen_info->glx_version = major + minor / 10.0f; + if (major > 1 || (major > 0 || minor >= 2)) { + glitz_glx_query_extensions (screen_info, + screen_info->glx_version); + _glitz_glx_proc_address_lookup (screen_info); + glitz_glx_query_formats (screen_info); + } + } } - } - screen_info->context_stack_size = 1; - screen_info->context_stack->drawable = NULL; - screen_info->context_stack->surface = NULL; - screen_info->context_stack->constraint = GLITZ_NONE; - - return screen_info; + screen_info->context_stack_size = 1; + screen_info->context_stack->drawable = NULL; + screen_info->context_stack->surface = NULL; + screen_info->context_stack->constraint = GLITZ_NONE; + + return screen_info; } static void _glitz_glx_screen_destroy (glitz_glx_screen_info_t *screen_info) { - Display *display = screen_info->display_info->display; - int i; + Display *display = screen_info->display_info->display; + int i; - if (screen_info->root_context) - glXMakeCurrent (display, None, NULL); - - for (i = 0; i < screen_info->n_contexts; i++) - glitz_glx_context_destroy (screen_info, screen_info->contexts[i]); + if (screen_info->root_context) + glXMakeCurrent (display, None, NULL); - if (screen_info->contexts) - free (screen_info->contexts); - - if (screen_info->formats) - free (screen_info->formats); + for (i = 0; i < screen_info->n_contexts; i++) + glitz_glx_context_destroy (screen_info, screen_info->contexts[i]); - if (screen_info->format_ids) - free (screen_info->format_ids); + if (screen_info->contexts) + free (screen_info->contexts); - free (screen_info); + if (screen_info->formats) + free (screen_info->formats); + + free (screen_info); } void glitz_glx_init (const char *gl_library) { - _glitz_glx_thread_info_get (gl_library); + _glitz_glx_thread_info_get (gl_library); } slim_hidden_def(glitz_glx_init); void glitz_glx_fini (void) { - glitz_glx_thread_info_t *info = _glitz_glx_thread_info_get (NULL); + glitz_glx_thread_info_t *info = _glitz_glx_thread_info_get (NULL); - _glitz_glx_thread_info_destroy (info); + _glitz_glx_thread_info_destroy (info); } slim_hidden_def(glitz_glx_fini); diff --git a/gfx/cairo/glitz/src/glx/glitz_glx_pbuffer.c b/gfx/cairo/glitz/src/glx/glitz_glx_pbuffer.c index 3af899f5d56..b5a9ecfe3d8 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glx_pbuffer.c +++ b/gfx/cairo/glitz/src/glx/glitz_glx_pbuffer.c @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -31,37 +31,37 @@ GLXPbuffer glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info, - GLXFBConfig fbconfig, - int width, - int height) + GLXFBConfig fbconfig, + int width, + int height) { - if (fbconfig) { - int attributes[9]; + Display *dpy = screen_info->display_info->display; - attributes[0] = GLX_PBUFFER_WIDTH; - attributes[1] = width; + if (fbconfig) { + int attributes[9]; - attributes[2] = GLX_PBUFFER_HEIGHT; - attributes[3] = height; - - attributes[4] = GLX_LARGEST_PBUFFER; - attributes[5] = 0; + attributes[0] = GLX_PBUFFER_WIDTH; + attributes[1] = width; - attributes[6] = GLX_PRESERVED_CONTENTS; - attributes[7] = 1; - attributes[8] = 0; + attributes[2] = GLX_PBUFFER_HEIGHT; + attributes[3] = height; - return - screen_info->glx.create_pbuffer (screen_info->display_info->display, - fbconfig, attributes); - } else - return (GLXPbuffer) 0; + attributes[4] = GLX_LARGEST_PBUFFER; + attributes[5] = 0; + + attributes[6] = GLX_PRESERVED_CONTENTS; + attributes[7] = 1; + attributes[8] = 0; + + return screen_info->glx.create_pbuffer (dpy, fbconfig, attributes); + } else + return (GLXPbuffer) 0; } -void +void glitz_glx_pbuffer_destroy (glitz_glx_screen_info_t *screen_info, - GLXPbuffer pbuffer) + GLXPbuffer pbuffer) { - screen_info->glx.destroy_pbuffer (screen_info->display_info->display, - pbuffer); + screen_info->glx.destroy_pbuffer (screen_info->display_info->display, + pbuffer); } diff --git a/gfx/cairo/glitz/src/glx/glitz_glxext.h b/gfx/cairo/glitz/src/glx/glitz_glxext.h index fd8bde02fbd..015e76aa024 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glxext.h +++ b/gfx/cairo/glitz/src/glx/glitz_glxext.h @@ -95,25 +95,25 @@ typedef XID GLXPbuffer; #endif typedef glitz_function_pointer_t (* glitz_glx_get_proc_address_t) - (const glitz_gl_ubyte_t *); + (const glitz_gl_ubyte_t *); typedef GLXFBConfig *(* glitz_glx_get_fbconfigs_t) - (Display *display, int screen, int *n_elements); + (Display *display, int screen, int *n_elements); typedef int (* glitz_glx_get_fbconfig_attrib_t) - (Display *display, GLXFBConfig config, int attribute, int *value); + (Display *display, GLXFBConfig config, int attribute, int *value); typedef XVisualInfo *(* glitz_glx_get_visual_from_fbconfig_t) - (Display *display, GLXFBConfig config); + (Display *display, GLXFBConfig config); typedef GLXPbuffer (* glitz_glx_create_pbuffer_t) - (Display *display, GLXFBConfig config, const int *attrib_list); + (Display *display, GLXFBConfig config, const int *attrib_list); typedef void (* glitz_glx_destroy_pbuffer_t) - (Display *display, GLXPbuffer pbuffer); + (Display *display, GLXPbuffer pbuffer); typedef void (* glitz_glx_query_drawable_t) - (Display *display, GLXDrawable drawable, - int attribute, unsigned int *value); + (Display *display, GLXDrawable drawable, + int attribute, unsigned int *value); typedef Bool (* glitz_glx_make_context_current_t) - (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + (Display *display, GLXDrawable draw, GLXDrawable read, GLXContext ctx); typedef GLXContext (* glitz_glx_create_new_context_t) - (Display *display, GLXFBConfig config, int render_type, - GLXContext share_list, Bool direct); + (Display *display, GLXFBConfig config, int render_type, + GLXContext share_list, Bool direct); #ifndef GLX_ARB_multisample #define GLX_SAMPLE_BUFFERS_ARB 0x186a0 @@ -121,8 +121,8 @@ typedef GLXContext (* glitz_glx_create_new_context_t) #endif typedef Bool *(* glitz_glx_bind_tex_image_t) - (Display *display, GLXPbuffer pbuffer, int buffer); + (Display *display, GLXPbuffer pbuffer, int buffer); typedef Bool (* glitz_glx_release_tex_image_t) - (Display *display, GLXPbuffer pbuffer, int buffer); + (Display *display, GLXPbuffer pbuffer, int buffer); #endif /* GLITZ_GLXEXT_H_INCLUDED */ diff --git a/gfx/cairo/glitz/src/glx/glitz_glxint.h b/gfx/cairo/glitz/src/glx/glitz_glxint.h index 023a79bd890..fde67193dd1 100644 --- a/gfx/cairo/glitz/src/glx/glitz_glxint.h +++ b/gfx/cairo/glitz/src/glx/glitz_glxint.h @@ -1,6 +1,6 @@ /* * Copyright © 2004 David Reveman - * + * * Permission to use, copy, modify, distribute, and sell this software * and its documentation for any purpose is hereby granted without * fee, provided that the above copyright notice appear in all copies @@ -12,11 +12,11 @@ * software for any purpose. It is provided "as is" without express or * implied warranty. * - * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN * NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS - * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * @@ -36,139 +36,143 @@ #include "glitz_glxext.h" -#define GLITZ_GLX_FEATURE_FBCONFIG_MASK (1L << 0) -#define GLITZ_GLX_FEATURE_PBUFFER_MASK (1L << 1) -#define GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK (1L << 2) -#define GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK (1L << 3) -#define GLITZ_GLX_FEATURE_MULTISAMPLE_MASK (1L << 4) -#define GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK (1L << 5) +#define GLITZ_GLX_FEATURE_VISUAL_RATING_MASK (1L << 0) +#define GLITZ_GLX_FEATURE_FBCONFIG_MASK (1L << 1) +#define GLITZ_GLX_FEATURE_PBUFFER_MASK (1L << 2) +#define GLITZ_GLX_FEATURE_MAKE_CURRENT_READ_MASK (1L << 3) +#define GLITZ_GLX_FEATURE_GET_PROC_ADDRESS_MASK (1L << 4) +#define GLITZ_GLX_FEATURE_MULTISAMPLE_MASK (1L << 5) +#define GLITZ_GLX_FEATURE_PBUFFER_MULTISAMPLE_MASK (1L << 6) typedef struct _glitz_glx_drawable glitz_glx_drawable_t; typedef struct _glitz_glx_screen_info_t glitz_glx_screen_info_t; typedef struct _glitz_glx_display_info_t glitz_glx_display_info_t; typedef struct _glitz_glx_static_proc_address_list_t { - glitz_glx_get_proc_address_t get_proc_address; - glitz_glx_get_fbconfigs_t get_fbconfigs; - glitz_glx_get_fbconfig_attrib_t get_fbconfig_attrib; - glitz_glx_get_visual_from_fbconfig_t get_visual_from_fbconfig; - glitz_glx_create_pbuffer_t create_pbuffer; - glitz_glx_destroy_pbuffer_t destroy_pbuffer; - glitz_glx_query_drawable_t query_drawable; - glitz_glx_make_context_current_t make_context_current; - glitz_glx_create_new_context_t create_new_context; + glitz_glx_get_proc_address_t get_proc_address; + glitz_glx_get_fbconfigs_t get_fbconfigs; + glitz_glx_get_fbconfig_attrib_t get_fbconfig_attrib; + glitz_glx_get_visual_from_fbconfig_t get_visual_from_fbconfig; + glitz_glx_create_pbuffer_t create_pbuffer; + glitz_glx_destroy_pbuffer_t destroy_pbuffer; + glitz_glx_query_drawable_t query_drawable; + glitz_glx_make_context_current_t make_context_current; + glitz_glx_create_new_context_t create_new_context; } glitz_glx_static_proc_address_list_t; typedef struct _glitz_glx_thread_info_t { - glitz_glx_display_info_t **displays; - int n_displays; - char *gl_library; - void *dlhand; - glitz_context_t *cctx; + glitz_glx_display_info_t **displays; + int n_displays; + char *gl_library; + void *dlhand; + glitz_context_t *cctx; } glitz_glx_thread_info_t; struct _glitz_glx_display_info_t { - glitz_glx_thread_info_t *thread_info; - Display *display; - glitz_glx_screen_info_t **screens; - int n_screens; + glitz_glx_thread_info_t *thread_info; + Display *display; + glitz_glx_screen_info_t **screens; + int n_screens; }; typedef struct _glitz_glx_context_info_t { - glitz_glx_drawable_t *drawable; - glitz_surface_t *surface; - glitz_constraint_t constraint; + glitz_glx_drawable_t *drawable; + glitz_surface_t *surface; + glitz_constraint_t constraint; } glitz_glx_context_info_t; typedef struct _glitz_glx_context_t { - glitz_context_t base; - GLXContext context; - glitz_format_id_t id; - GLXFBConfig fbconfig; - glitz_backend_t backend; - glitz_gl_int_t max_viewport_dims[2]; - glitz_gl_int_t max_texture_2d_size; - glitz_gl_int_t max_texture_rect_size; - glitz_bool_t initialized; + glitz_context_t base; + GLXContext context; + glitz_format_id_t id; + GLXFBConfig fbconfig; + glitz_backend_t backend; + glitz_bool_t initialized; } glitz_glx_context_t; struct _glitz_glx_screen_info_t { - glitz_glx_display_info_t *display_info; - int screen; - int drawables; - glitz_drawable_format_t *formats; - XID *format_ids; - int n_formats; - glitz_glx_context_t **contexts; - int n_contexts; - glitz_glx_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; - int context_stack_size; - GLXContext root_context; - unsigned long glx_feature_mask; - glitz_gl_float_t glx_version; - glitz_glx_static_proc_address_list_t glx; - glitz_program_map_t program_map; + glitz_glx_display_info_t *display_info; + int screen; + int drawables; + glitz_int_drawable_format_t *formats; + int n_formats; + glitz_glx_context_t **contexts; + int n_contexts; + glitz_glx_context_info_t context_stack[GLITZ_CONTEXT_STACK_SIZE]; + int context_stack_size; + GLXContext root_context; + unsigned long glx_feature_mask; + glitz_gl_float_t glx_version; + glitz_glx_static_proc_address_list_t glx; + glitz_program_map_t program_map; }; struct _glitz_glx_drawable { - glitz_drawable_t base; - - glitz_glx_screen_info_t *screen_info; - glitz_glx_context_t *context; - GLXDrawable drawable; - GLXDrawable pbuffer; + glitz_drawable_t base; + + glitz_glx_screen_info_t *screen_info; + glitz_glx_context_t *context; + GLXDrawable drawable; + GLXDrawable pbuffer; + int width; + int height; }; extern void __internal_linkage glitz_glx_query_extensions (glitz_glx_screen_info_t *screen_info, - glitz_gl_float_t glx_version); + glitz_gl_float_t glx_version); extern glitz_glx_screen_info_t __internal_linkage * glitz_glx_screen_info_get (Display *display, - int screen); + int screen); extern glitz_function_pointer_t __internal_linkage glitz_glx_get_proc_address (const char *name, - void *closure); + void *closure); extern glitz_glx_context_t __internal_linkage * glitz_glx_context_get (glitz_glx_screen_info_t *screen_info, - glitz_drawable_format_t *format); + glitz_drawable_format_t *format); extern void __internal_linkage glitz_glx_context_destroy (glitz_glx_screen_info_t *screen_info, - glitz_glx_context_t *context); + glitz_glx_context_t *context); extern void __internal_linkage glitz_glx_query_formats (glitz_glx_screen_info_t *screen_info); +extern glitz_bool_t __internal_linkage +_glitz_glx_drawable_update_size (glitz_glx_drawable_t *drawable, + int width, + int height); + extern GLXPbuffer __internal_linkage glitz_glx_pbuffer_create (glitz_glx_screen_info_t *screen_info, - GLXFBConfig fbconfig, - int width, - int height); + GLXFBConfig fbconfig, + int width, + int height); extern void __internal_linkage glitz_glx_pbuffer_destroy (glitz_glx_screen_info_t *screen_info, - GLXPbuffer pbuffer); + GLXPbuffer pbuffer); extern glitz_drawable_t __internal_linkage * glitz_glx_create_pbuffer (void *abstract_templ, - glitz_drawable_format_t *format, - unsigned int width, - unsigned int height); + glitz_drawable_format_t *format, + unsigned int width, + unsigned int height); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_glx_push_current (void *abstract_drawable, - glitz_surface_t *surface, - glitz_constraint_t constraint); + glitz_surface_t *surface, + glitz_constraint_t constraint); extern glitz_surface_t __internal_linkage * glitz_glx_pop_current (void *abstract_drawable); void glitz_glx_make_current (void *abstract_drawable, - glitz_constraint_t constraint); + glitz_constraint_t constraint); extern glitz_status_t __internal_linkage glitz_glx_make_current_read (void *abstract_surface); @@ -176,14 +180,15 @@ glitz_glx_make_current_read (void *abstract_surface); extern void __internal_linkage glitz_glx_destroy (void *abstract_drawable); -extern void __internal_linkage +extern glitz_bool_t __internal_linkage glitz_glx_swap_buffers (void *abstract_drawable); -/* Avoid unnecessary PLT entries. */ +/* Avoid unnecessary PLT entries. */ slim_hidden_proto(glitz_glx_init) slim_hidden_proto(glitz_glx_fini) -slim_hidden_proto(glitz_glx_find_drawable_format) +slim_hidden_proto(glitz_glx_find_window_format) +slim_hidden_proto(glitz_glx_find_pbuffer_format) slim_hidden_proto(glitz_glx_find_drawable_format_for_visual) slim_hidden_proto(glitz_glx_get_visual_info_from_format) slim_hidden_proto(glitz_glx_create_drawable_for_window) diff --git a/gfx/cairo/libpixman/src/Makefile.in b/gfx/cairo/libpixman/src/Makefile.in index 3c49955c292..4d07eeae504 100644 --- a/gfx/cairo/libpixman/src/Makefile.in +++ b/gfx/cairo/libpixman/src/Makefile.in @@ -43,6 +43,8 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk +VISIBILITY_FLAGS = + MODULE = libpixman LIBRARY_NAME = mozlibpixman LIBXUL_LIBRARY = 1 @@ -50,8 +52,8 @@ LIBXUL_LIBRARY = 1 CSRCS = \ fbcompose.c \ fbedge.c \ + fbpict.c \ fbtrap.c \ - ic.c \ icblt.c \ icbltone.c \ iccolor.c \ @@ -73,7 +75,7 @@ ifdef MOZ_X11 #DEFINES += -DUSE_MMX endif -EXPORTS = pixman.h pixman-remap.h mozstdint.h +EXPORTS = pixman.h pixman-remap.h LOCAL_INCLUDES = -I$(srcdir) diff --git a/gfx/cairo/libpixman/src/fbcompose.c b/gfx/cairo/libpixman/src/fbcompose.c index 8b3799b8487..fe07662420c 100644 --- a/gfx/cairo/libpixman/src/fbcompose.c +++ b/gfx/cairo/libpixman/src/fbcompose.c @@ -26,7 +26,6 @@ #ifdef HAVE_CONFIG_H #include #endif -#include #include "pixman-xserver-compat.h" #include "fbpict.h" @@ -586,7 +585,7 @@ static fetchProc fetchProcForPicture (PicturePtr pict) case PICT_a1: return fbFetch_a1; case PICT_g1: return fbFetch_g1; default: - return 0; + return NULL; } } @@ -1014,7 +1013,7 @@ static fetchPixelProc fetchPixelProcForPicture (PicturePtr pict) case PICT_a1: return fbFetchPixel_a1; case PICT_g1: return fbFetchPixel_g1; default: - return 0; + return NULL; } } @@ -1050,7 +1049,7 @@ fbStore_a8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexe int i; CARD32 *pixel = (CARD32 *)bits + x; for (i = 0; i < width; ++i) - *pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16); + *pixel++ = (values[i] & 0xff00ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16); } static FASTCALL void @@ -1059,7 +1058,7 @@ fbStore_x8b8g8r8 (FbBits *bits, const CARD32 *values, int x, int width, miIndexe int i; CARD32 *pixel = (CARD32 *)bits + x; for (i = 0; i < width; ++i) - *pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) && 0xff) | ((values[i] & 0xff) << 16); + *pixel++ = (values[i] & 0x0000ff00) | ((values[i] >> 16) & 0xff) | ((values[i] & 0xff) << 16); } static FASTCALL void @@ -1450,7 +1449,7 @@ static storeProc storeProcForPicture (PicturePtr pict) case PICT_a1: return fbStore_a1; case PICT_g1: return fbStore_g1; default: - return 0; + return NULL; } } @@ -1954,7 +1953,7 @@ fbCombineConjointXorU (CARD32 *dest, const CARD32 *src, int width) static CombineFuncU fbCombineFuncU[] = { fbCombineClear, fbCombineSrcU, - 0, /* CombineDst */ + NULL, /* CombineDst */ fbCombineOverU, fbCombineOverReverseU, fbCombineInU, @@ -1966,11 +1965,11 @@ static CombineFuncU fbCombineFuncU[] = { fbCombineXorU, fbCombineAddU, fbCombineSaturateU, - 0, - 0, + NULL, + NULL, fbCombineClear, fbCombineSrcU, - 0, /* CombineDst */ + NULL, /* CombineDst */ fbCombineDisjointOverU, fbCombineSaturateU, /* DisjointOverReverse */ fbCombineDisjointInU, @@ -1980,13 +1979,13 @@ static CombineFuncU fbCombineFuncU[] = { fbCombineDisjointAtopU, fbCombineDisjointAtopReverseU, fbCombineDisjointXorU, - 0, - 0, - 0, - 0, + NULL, + NULL, + NULL, + NULL, fbCombineClear, fbCombineSrcU, - 0, /* CombineDst */ + NULL, /* CombineDst */ fbCombineConjointOverU, fbCombineConjointOverReverseU, fbCombineConjointInU, @@ -2575,7 +2574,7 @@ fbCombineConjointXorC (CARD32 *dest, CARD32 *src, CARD32 *mask, int width) static CombineFuncC fbCombineFuncC[] = { fbCombineClearC, fbCombineSrcC, - 0, /* Dest */ + NULL, /* Dest */ fbCombineOverC, fbCombineOverReverseC, fbCombineInC, @@ -2587,11 +2586,11 @@ static CombineFuncC fbCombineFuncC[] = { fbCombineXorC, fbCombineAddC, fbCombineSaturateC, - 0, - 0, + NULL, + NULL, fbCombineClearC, /* 0x10 */ fbCombineSrcC, - 0, /* Dest */ + NULL, /* Dest */ fbCombineDisjointOverC, fbCombineSaturateC, /* DisjointOverReverse */ fbCombineDisjointInC, @@ -2601,13 +2600,13 @@ static CombineFuncC fbCombineFuncC[] = { fbCombineDisjointAtopC, fbCombineDisjointAtopReverseC, fbCombineDisjointXorC, /* 0x1b */ - 0, - 0, - 0, - 0, + NULL, + NULL, + NULL, + NULL, fbCombineClearC, fbCombineSrcC, - 0, /* Dest */ + NULL, /* Dest */ fbCombineConjointOverC, fbCombineConjointOverReverseC, fbCombineConjointInC, @@ -2639,7 +2638,7 @@ static void fbFetchSolid(PicturePtr pict, int x, int y, int width, CARD32 *buffe #ifdef PIXMAN_INDEXED_FORMATS miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; #else - miIndexedPtr indexed = 0; + miIndexedPtr indexed = NULL; #endif fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); @@ -2662,7 +2661,7 @@ static void fbFetch(PicturePtr pict, int x, int y, int width, CARD32 *buffer) #ifdef PIXMAN_INDEXED_FORMATS miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; #else - miIndexedPtr indexed = 0; + miIndexedPtr indexed = NULL; #endif fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); @@ -2904,8 +2903,9 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 #ifdef PIXMAN_INDEXED_FORMATS miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; #else - miIndexedPtr indexed = 0; + miIndexedPtr indexed = NULL; #endif + Bool projective = FALSE; fetch = fetchPixelProcForPicture(pict); @@ -2929,6 +2929,7 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 unit.vector[1] = 0; unit.vector[2] = 0; } + projective = (unit.vector[2] != 0); if (pict->filter == PIXMAN_FILTER_NEAREST || pict->filter == PIXMAN_FILTER_FAST) { @@ -2939,8 +2940,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height); - x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width); + if (projective) { + y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height); + x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width); + } else { + y = MOD(v.vector[1]>>16, pict->pDrawable->height); + x = MOD(v.vector[0]>>16, pict->pDrawable->width); + } buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); } v.vector[0] += unit.vector[0]; @@ -2952,8 +2958,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height); - x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width); + if (projective) { + y = MOD(DIV(v.vector[1],v.vector[2]), pict->pDrawable->height); + x = MOD(DIV(v.vector[0],v.vector[2]), pict->pDrawable->width); + } else { + y = MOD(v.vector[1]>>16, pict->pDrawable->height); + x = MOD(v.vector[0]>>16, pict->pDrawable->width); + } if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); else @@ -2971,8 +2982,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - y = DIV(v.vector[1],v.vector[2]); - x = DIV(v.vector[0],v.vector[2]); + if (projective) { + y = DIV(v.vector[1],v.vector[2]); + x = DIV(v.vector[0],v.vector[2]); + } else { + y = v.vector[1]>>16; + x = v.vector[0]>>16; + } buffer[i] = ((x < box.x1) | (x >= box.x2) | (y < box.y1) | (y >= box.y2)) ? 0 : fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); } @@ -2985,8 +3001,13 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - y = DIV(v.vector[1],v.vector[2]); - x = DIV(v.vector[0],v.vector[2]); + if (projective) { + y = DIV(v.vector[1],v.vector[2]); + x = DIV(v.vector[0],v.vector[2]); + } else { + y = v.vector[1]>>16; + x = v.vector[0]>>16; + } if (pixman_region_contains_point (pict->pCompositeClip, x, y, &box)) buffer[i] = fetch(bits + (y + pict->pDrawable->y)*stride, x + pict->pDrawable->x, indexed); else @@ -3006,19 +3027,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty, k; + int x1, x2, y1, y2, distx, idistx, disty, idisty; FbBits *b; CARD32 tl, tr, bl, br, r; - xFixed_48_16 div; + CARD32 ft, fb; - div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((xFixed)div >> 8) & 0xff; + if (projective) { + xFixed_48_16 div; + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((xFixed)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } x2 = x1 + 1; - div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; y2 = y1 + 1; - disty = ((xFixed)div >> 8) & 0xff; idistx = 256 - distx; idisty = 256 - disty; @@ -3036,13 +3065,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 bl = fetch(b, x1 + pict->pDrawable->x, indexed); br = fetch(b, x2 + pict->pDrawable->x, indexed); - r = 0; - for (k = 0; k < 32; k += 8) { - CARD32 t, b; - t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx; - b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx; - r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k; - } + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); buffer[i] = r; } v.vector[0] += unit.vector[0]; @@ -3054,19 +3088,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty, k; + int x1, x2, y1, y2, distx, idistx, disty, idisty; FbBits *b; CARD32 tl, tr, bl, br, r; - xFixed_48_16 div; + CARD32 ft, fb; - div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((xFixed)div >> 8) & 0xff; + if (projective) { + xFixed_48_16 div; + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((xFixed)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } x2 = x1 + 1; - div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; y2 = y1 + 1; - disty = ((xFixed)div >> 8) & 0xff; idistx = 256 - distx; idisty = 256 - disty; @@ -3088,13 +3130,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) ? fetch(b, x2 + pict->pDrawable->x, indexed) : 0; - r = 0; - for (k = 0; k < 32; k += 8) { - CARD32 t, b; - t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx; - b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx; - r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k; - } + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); buffer[i] = r; } v.vector[0] += unit.vector[0]; @@ -3109,20 +3156,28 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off, k; + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; FbBits *b; CARD32 tl, tr, bl, br, r; Bool x1_out, x2_out, y1_out, y2_out; - xFixed_48_16 div; + CARD32 ft, fb; - div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((xFixed)div >> 8) & 0xff; + if (projective) { + xFixed_48_16 div; + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((xFixed)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } x2 = x1 + 1; - div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; y2 = y1 + 1; - disty = ((xFixed)div >> 8) & 0xff; idistx = 256 - distx; idisty = 256 - disty; @@ -3141,13 +3196,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 bl = x1_out|y2_out ? 0 : fetch(b, x_off, indexed); br = x2_out|y2_out ? 0 : fetch(b, x_off + 1, indexed); - r = 0; - for (k = 0; k < 32; k += 8) { - CARD32 t, b; - t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx; - b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx; - r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k; - } + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); buffer[i] = r; } v.vector[0] += unit.vector[0]; @@ -3159,19 +3219,27 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 if (!v.vector[2]) { buffer[i] = 0; } else { - int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off, k; + int x1, x2, y1, y2, distx, idistx, disty, idisty, x_off; FbBits *b; CARD32 tl, tr, bl, br, r; - xFixed_48_16 div; + CARD32 ft, fb; - div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; - x1 = div >> 16; - distx = ((xFixed)div >> 8) & 0xff; + if (projective) { + xFixed_48_16 div; + div = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2]; + x1 = div >> 16; + distx = ((xFixed)div >> 8) & 0xff; + div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; + y1 = div >> 16; + disty = ((xFixed)div >> 8) & 0xff; + } else { + x1 = v.vector[0] >> 16; + distx = (v.vector[0] >> 8) & 0xff; + y1 = v.vector[1] >> 16; + disty = (v.vector[1] >> 8) & 0xff; + } x2 = x1 + 1; - div = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2]; - y1 = div >> 16; y2 = y1 + 1; - disty = ((xFixed)div >> 8) & 0xff; idistx = 256 - distx; idisty = 256 - disty; @@ -3189,13 +3257,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 br = pixman_region_contains_point(pict->pCompositeClip, x2, y2, &box) ? fetch(b, x_off + 1, indexed) : 0; - r = 0; - for (k = 0; k < 32; k += 8) { - CARD32 t, b; - t = FbGet8(tl,k) * idistx + FbGet8(tr,k) * distx; - b = FbGet8(bl,k) * idistx + FbGet8(br,k) * distx; - r |= ((((t * idisty) + (b * disty)) >> 16) & 0xff) << k; - } + ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx; + fb = FbGet8(bl,0) * idistx + FbGet8(br,0) * distx; + r = (((ft * idisty + fb * disty) >> 16) & 0xff); + ft = FbGet8(tl,8) * idistx + FbGet8(tr,8) * distx; + fb = FbGet8(bl,8) * idistx + FbGet8(br,8) * distx; + r |= (((ft * idisty + fb * disty) >> 8) & 0xff00); + ft = FbGet8(tl,16) * idistx + FbGet8(tr,16) * distx; + fb = FbGet8(bl,16) * idistx + FbGet8(br,16) * distx; + r |= (((ft * idisty + fb * disty)) & 0xff0000); + ft = FbGet8(tl,24) * idistx + FbGet8(tr,24) * distx; + fb = FbGet8(bl,24) * idistx + FbGet8(br,24) * distx; + r |= (((ft * idisty + fb * disty) << 8) & 0xff000000); buffer[i] = r; } v.vector[0] += unit.vector[0]; @@ -3219,12 +3292,18 @@ static void fbFetchTransformed(PicturePtr pict, int x, int y, int width, CARD32 int x1, x2, y1, y2, x, y; INT32 srtot, sgtot, sbtot, satot; xFixed *p = params; - xFixed_48_16 tmp; - tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff; - x1 = xFixedToInt(tmp); + + if (projective) { + xFixed_48_16 tmp; + tmp = ((xFixed_48_16)v.vector[0] << 16)/v.vector[2] - xoff; + x1 = xFixedToInt(tmp); + tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff; + y1 = xFixedToInt(tmp); + } else { + x1 = xFixedToInt(v.vector[0] - xoff); + y1 = xFixedToInt(v.vector[1] - yoff); + } x2 = x1 + cwidth; - tmp = ((xFixed_48_16)v.vector[1] << 16)/v.vector[2] - yoff; - y1 = xFixedToInt(tmp); y2 = y1 + cheight; srtot = sgtot = sbtot = satot = 0; @@ -3305,7 +3384,7 @@ static void fbStore(PicturePtr pict, int x, int y, int width, CARD32 *buffer) #ifdef PIXMAN_INDEXED_FORMATS miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; #else - miIndexedPtr indexed = 0; + miIndexedPtr indexed = NULL; #endif fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff); @@ -3328,7 +3407,7 @@ static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3 #ifdef PIXMAN_INDEXED_FORMATS miIndexedPtr indexed = (miIndexedPtr) pict->pFormat->index.devPrivate; #else - miIndexedPtr indexed = 0; + miIndexedPtr indexed = NULL; #endif miIndexedPtr aindexed; @@ -3342,7 +3421,7 @@ static void fbStoreExternalAlpha(PicturePtr pict, int x, int y, int width, CARD3 #ifdef PIXMAN_INDEXED_FORMATS aindexed = (miIndexedPtr) pict->alphaMap->pFormat->index.devPrivate; #else - aindexed = 0; + aindexed = NULL; #endif ax = x; @@ -3373,10 +3452,10 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) CARD32 *dest_buffer = src_buffer + data->width; int i; scanStoreProc store; - scanFetchProc fetchSrc = 0, fetchMask = 0, fetchDest = 0; + scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL; if (data->op == PIXMAN_OPERATOR_CLEAR) - fetchSrc = 0; + fetchSrc = NULL; else if (!data->src->pDrawable) { #ifdef PIXMAN_GRADIENTS if (data->src->pSourcePict) @@ -3418,7 +3497,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) else fetchMask = fbFetchTransformed; } else { - fetchMask = 0; + fetchMask = NULL; } if (data->dest->alphaMap) { @@ -3429,7 +3508,7 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) store = fbStore; } if (data->op == PIXMAN_OPERATOR_CLEAR || data->op == PIXMAN_OPERATOR_SRC) - fetchDest = 0; + fetchDest = NULL; if (fetchSrc && fetchMask && data->mask && data->mask->componentAlpha && PICT_FORMAT_RGB(data->mask->format_code)) { CARD32 *mask_buffer = dest_buffer + data->width; @@ -3465,8 +3544,8 @@ fbCompositeRect (const FbComposeData *data, CARD32 *scanline_buffer) fetchMask(data->mask, data->xMask, data->yMask, data->width, dest_buffer); composeFunctions.combineMaskU(src_buffer, dest_buffer, data->width); } - fetchSrc = 0; - fetchMask = 0; + fetchSrc = NULL; + fetchMask = NULL; } for (i = 0; i < data->height; ++i) { diff --git a/gfx/cairo/libpixman/src/fbmmx.c b/gfx/cairo/libpixman/src/fbmmx.c index 347a5121455..2ba7d8b15b3 100644 --- a/gfx/cairo/libpixman/src/fbmmx.c +++ b/gfx/cairo/libpixman/src/fbmmx.c @@ -44,7 +44,9 @@ #endif #include +#ifdef USE_SSE #include /* for _mm_shuffle_pi16 and _MM_SHUFFLE */ +#endif #ifdef RENDER @@ -374,11 +376,17 @@ mmxCombineMaskU (CARD32 *src, const CARD32 *mask, int width) { const CARD32 *end = mask + width; while (mask < end) { - __m64 a = load8888(*mask); - __m64 s = load8888(*src); - a = expand_alpha(a); - s = pix_multiply(s, a); - *src = store8888(s); + CARD32 mmask = *mask; + CARD32 maska = mmask >> 24; + if (maska == 0) { + *src = 0; + } else if (maska != 0xff) { + __m64 a = load8888(mmask); + __m64 s = load8888(*src); + a = expand_alpha(a); + s = pix_multiply(s, a); + *src = store8888(s); + } ++src; ++mask; } @@ -392,10 +400,16 @@ mmxCombineOverU (CARD32 *dest, const CARD32 *src, int width) const CARD32 *end = dest + width; while (dest < end) { - __m64 s, sa; - s = load8888(*src); - sa = expand_alpha(s); - *dest = store8888(over(s, sa, load8888(*dest))); + CARD32 ssrc = *src; + CARD32 a = ssrc >> 24; + if (a == 0xff) { + *dest = ssrc; + } else if (a) { + __m64 s, sa; + s = load8888(ssrc); + sa = expand_alpha(s); + *dest = store8888(over(s, sa, load8888(*dest))); + } ++dest; ++src; } @@ -874,7 +888,7 @@ fbCompositeSolid_nx8888mmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); if (src >> 24 == 0) return; @@ -952,7 +966,7 @@ fbCompositeSolid_nx0565mmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); if (src >> 24 == 0) return; @@ -1037,7 +1051,7 @@ fbCompositeSolidMask_nx8888x8888Cmmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (srca == 0) @@ -1338,6 +1352,56 @@ fbCompositeSrc_x888x8x8888mmx (pixman_operator_t op, _mm_empty(); } +void +fbCompositeSrc_8888x8888mmx (pixman_operator_t op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height) +{ + CARD32 *dstLine, *dst; + CARD32 *srcLine, *src, s; + FbStride dstStride, srcStride; + CARD8 a; + CARD16 w; + + fbComposeGetStart (pDst, xDst, yDst, CARD32, dstStride, dstLine, 1); + fbComposeGetStart (pSrc, xSrc, ySrc, CARD32, srcStride, srcLine, 1); + + while (height--) + { + dst = dstLine; + dstLine += dstStride; + src = srcLine; + srcLine += srcStride; + w = width; + + while (w--) + { + s = *src++; + a = s >> 24; + if (a == 0xff) + *dst = s; + else if (a) { + __m64 ms, sa; + ms = load8888(s); + sa = expand_alpha(ms); + *dst = store8888(over(ms, sa, load8888(*dst))); + } + dst++; + } + } + _mm_empty(); +} + + void fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, PicturePtr pSrc, @@ -1362,7 +1426,7 @@ fbCompositeSolidMask_nx8x8888mmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (srca == 0) @@ -1477,7 +1541,7 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (srca == 0) @@ -1513,6 +1577,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, __m64 vdest = in(vsrc, expand_alpha_rev ((__m64)m)); *dst = store8888(vdest); } + else + { + *dst = 0; + } w--; mask++; @@ -1543,6 +1611,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, *(__m64 *)dst = pack8888(dest0, dest1); } + else + { + *dst = 0; + } mask += 2; dst += 2; @@ -1561,6 +1633,10 @@ fbCompositeSolidMaskSrc_nx8x8888mmx (pixman_operator_t op, vdest = in(vsrc, expand_alpha_rev ((__m64)m)); *dst = store8888(vdest); } + else + { + *dst = 0; + } w--; mask++; @@ -1596,7 +1672,7 @@ fbCompositeSolidMask_nx8x0565mmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (srca == 0) @@ -1937,7 +2013,7 @@ fbCompositeSolidMask_nx8888x0565Cmmx (pixman_operator_t op, CHECKPOINT(); - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (srca == 0) @@ -2397,107 +2473,4 @@ fbCompositeCopyAreammx (pixman_operator_t op, width, height); } -#if !defined(__amd64__) && !defined(__x86_64__) - -enum CPUFeatures { - NoFeatures = 0, - MMX = 0x1, - MMX_Extensions = 0x2, - SSE = 0x6, - SSE2 = 0x8, - CMOV = 0x10 -}; - -static unsigned int detectCPUFeatures(void) { - unsigned int result; - char vendor[13]; - vendor[0] = 0; - vendor[12] = 0; - /* see p. 118 of amd64 instruction set manual Vol3 */ - __asm__ ("push %%ebx\n" - "pushf\n" - "pop %%eax\n" - "mov %%eax, %%ebx\n" - "xor $0x00200000, %%eax\n" - "push %%eax\n" - "popf\n" - "pushf\n" - "pop %%eax\n" - "mov $0x0, %%edx\n" - "xor %%ebx, %%eax\n" - "jz skip\n" - - "mov $0x00000000, %%eax\n" - "cpuid\n" - "mov %%ebx, %1\n" - "mov %%edx, %2\n" - "mov %%ecx, %3\n" - "mov $0x00000001, %%eax\n" - "cpuid\n" - "skip:\n" - "pop %%ebx\n" - "mov %%edx, %0\n" - : "=r" (result), - "=m" (vendor[0]), - "=m" (vendor[4]), - "=m" (vendor[8]) - : - : "%eax", "%ecx", "%edx" - ); - - unsigned int features = 0; - if (result) { - /* result now contains the standard feature bits */ - if (result & (1 << 15)) - features |= CMOV; - if (result & (1 << 23)) - features |= MMX; - if (result & (1 << 25)) - features |= SSE; - if (result & (1 << 26)) - features |= SSE2; - if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) { - /* check for AMD MMX extensions */ - - unsigned int result; - __asm__("push %%ebx\n" - "mov $0x80000000, %%eax\n" - "cpuid\n" - "xor %%edx, %%edx\n" - "cmp $0x1, %%eax\n" - "jge skip2\n" - "mov $0x80000001, %%eax\n" - "cpuid\n" - "skip2:\n" - "mov %%edx, %0\n" - "pop %%ebx\n" - : "=r" (result) - : - : "%eax", "%ecx", "%edx" - ); - if (result & (1<<22)) - features |= MMX_Extensions; - } - } - return features; -} - -Bool -fbHaveMMX (void) -{ - static Bool initialized = FALSE; - static Bool mmx_present; - - if (!initialized) - { - unsigned int features = detectCPUFeatures(); - mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions); - initialized = TRUE; - } - - return mmx_present; -} -#endif /* __amd64__ */ - - #endif /* RENDER */ diff --git a/gfx/cairo/libpixman/src/fbmmx.h b/gfx/cairo/libpixman/src/fbmmx.h index d9de56a57a7..5da42a0662d 100644 --- a/gfx/cairo/libpixman/src/fbmmx.h +++ b/gfx/cairo/libpixman/src/fbmmx.h @@ -198,6 +198,18 @@ void fbCompositeSrc_8888x8x8888mmx (pixman_operator_t op, INT16 yDst, CARD16 width, CARD16 height); +void fbCompositeSrc_8888x8888mmx (pixman_operator_t op, + PicturePtr pSrc, + PicturePtr pMask, + PicturePtr pDst, + INT16 xSrc, + INT16 ySrc, + INT16 xMask, + INT16 yMask, + INT16 xDst, + INT16 yDst, + CARD16 width, + CARD16 height); Bool fbCopyAreammx (FbPixels *pSrc, FbPixels *pDst, int src_x, diff --git a/gfx/cairo/libpixman/src/fbpict.c b/gfx/cairo/libpixman/src/fbpict.c index ac78f32b144..3e2a26cd505 100644 --- a/gfx/cairo/libpixman/src/fbpict.c +++ b/gfx/cairo/libpixman/src/fbpict.c @@ -1,5 +1,5 @@ /* - * $Id: fbpict.c,v 1.1 2005-08-20 05:34:02 vladimir%pobox.com Exp $ + * $Id: fbpict.c,v 1.4 2006-01-18 22:15:25 vladimir%pobox.com Exp $ * * Copyright © 2000 SuSE, Inc. * @@ -119,30 +119,29 @@ fbIn24 (CARD32 x, CARD8 y) } #if IMAGE_BYTE_ORDER == LSBFirst - #define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \ +# define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \ temp=count&3; \ where-=temp; \ workingWhere=(CARD32 *)where; \ workingVal=*workingWhere++; \ count=4-temp; \ workingVal>>=(8*temp) - #define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)&0xff; (y)>>=8; (x)--;} - #define readPackedSource(where) readPacked(where,ws,workingSource,wsrc) - #define readPackedDest(where) readPacked(where,wd,workingiDest,widst) - #define writePacked(what) workingoDest>>=8; workingoDest|=(what<<24); ww--; if(!ww) { ww=4; *wodst++=workingoDest; } +# define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)&0xff; (y)>>=8; (x)--;} +# define readPackedSource(where) readPacked(where,ws,workingSource,wsrc) +# define readPackedDest(where) readPacked(where,wd,workingiDest,widst) +# define writePacked(what) workingoDest>>=8; workingoDest|=(what<<24); ww--; if(!ww) { ww=4; *wodst++=workingoDest; } #else - #warning "I havn't tested fbCompositeTrans_0888xnx0888() on big endian yet!" - #define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \ +# define setupPackedReader(count,temp,where,workingWhere,workingVal) count=(long)where; \ temp=count&3; \ where-=temp; \ workingWhere=(CARD32 *)where; \ workingVal=*workingWhere++; \ count=4-temp; \ workingVal<<=(8*temp) - #define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)>>24; (y)<<=8; (x)--;} - #define readPackedSource(where) readPacked(where,ws,workingSource,wsrc) - #define readPackedDest(where) readPacked(where,wd,workingiDest,widst) - #define writePacked(what) workingoDest<<=8; workingoDest|=what; ww--; if(!ww) { ww=4; *wodst++=workingoDest; } +# define readPacked(where,x,y,z) {if(!(x)) { (x)=4; y=*z++; } where=(y)>>24; (y)<<=8; (x)--;} +# define readPackedSource(where) readPacked(where,ws,workingSource,wsrc) +# define readPackedDest(where) readPacked(where,wd,workingiDest,widst) +# define writePacked(what) workingoDest<<=8; workingoDest|=what; ww--; if(!ww) { ww=4; *wodst++=workingoDest; } #endif /* * Naming convention: @@ -170,7 +169,7 @@ fbCompositeSolidMask_nx8x8888 (pixman_operator_t op, FbStride dstStride, maskStride; CARD16 w; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); dstMask = FbFullMask (pDst->pDrawable->depth); srca = src >> 24; @@ -229,7 +228,7 @@ fbCompositeSolidMask_nx8888x8888C (pixman_operator_t op, CARD16 w; CARD32 m, n, o, p; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); dstMask = FbFullMask (pDst->pDrawable->depth); srca = src >> 24; @@ -303,7 +302,7 @@ fbCompositeSolidMask_nx8x0888 (pixman_operator_t op, CARD16 w; CARD32 rs,gs,bs,rd,gd,bd; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; srcia = 255-srca; @@ -399,7 +398,7 @@ fbCompositeSolidMask_nx8x0565 (pixman_operator_t op, FbStride dstStride, maskStride; CARD16 w,src16; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); if (src == 0) return; @@ -477,7 +476,7 @@ fbCompositeSolidMask_nx8888x0565 (pixman_operator_t op, FbStride dstStride, maskStride; CARD16 w, src16; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); if (src == 0) return; @@ -556,7 +555,7 @@ fbCompositeSolidMask_nx8888x0565C (pixman_operator_t op, CARD16 w; CARD32 m, n, o; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); srca = src >> 24; if (src == 0) @@ -927,7 +926,7 @@ fbCompositeSolidMask_nx1xn (pixman_operator_t op, int maskXoff, maskYoff; FbBits src; - fbComposeGetSolid(pSrc, src); + fbComposeGetSolid(pSrc, pDst, src); if ((src & 0xff000000) != 0xff000000) { @@ -1009,7 +1008,7 @@ fbCompositeTrans_0565xnx0565(pixman_operator_t op, CARD16 s_16, d_16; CARD32 s_32, d_32; - fbComposeGetSolid (pMask, mask); + fbComposeGetSolid (pMask, pDst, mask); maskAlpha = mask >> 27; if (!maskAlpha) @@ -1111,7 +1110,7 @@ fbCompositeTrans_0888xnx0888(pixman_operator_t op, FbBits mask; CARD16 maskAlpha,maskiAlpha; - fbComposeGetSolid (pMask, mask); + fbComposeGetSolid (pMask, pDst, mask); maskAlpha = mask >> 24; maskiAlpha= 255-maskAlpha; @@ -1361,7 +1360,7 @@ pixman_composite (pixman_operator_t op, pixman_region16_t *region; int n; pixman_box16_t *pbox; - CompositeFunc func = 0; + CompositeFunc func = NULL; Bool srcRepeat = pSrc->pDrawable && pSrc->repeat == RepeatNormal; Bool maskRepeat = FALSE; Bool srcTransform = pSrc->transform != 0; @@ -1416,10 +1415,9 @@ pixman_composite (pixman_operator_t op, && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap #ifdef PIXMAN_CONVOLUTION && (pSrc->filter != PictFilterConvolution) - && (!pMask || pMask->filter != PictFilterConvolution)) -#else - && !pMask) + && (!pMask || pMask->filter != PictFilterConvolution) #endif + ) switch (op) { case PIXMAN_OPERATOR_OVER: if (pMask) @@ -1694,7 +1692,12 @@ pixman_composite (pixman_operator_t op, switch (pDst->format_code) { case PICT_a8r8g8b8: case PICT_x8r8g8b8: - func = fbCompositeSrc_8888x8888; +#ifdef USE_MMX + if (fbHaveMMX()) + func = fbCompositeSrc_8888x8888mmx; + else +#endif + func = fbCompositeSrc_8888x8888; break; case PICT_r8g8b8: func = fbCompositeSrc_8888x0888; @@ -1708,7 +1711,12 @@ pixman_composite (pixman_operator_t op, switch (pDst->format_code) { case PICT_a8b8g8r8: case PICT_x8b8g8r8: - func = fbCompositeSrc_8888x8888; +#ifdef USE_MMX + if (fbHaveMMX()) + func = fbCompositeSrc_8888x8888mmx; + else +#endif + func = fbCompositeSrc_8888x8888; break; case PICT_b8g8r8: func = fbCompositeSrc_8888x0888; @@ -1901,4 +1909,121 @@ pixman_composite (pixman_operator_t op, pixman_region_destroy (region); } slim_hidden_def(pixman_composite); + +/* The CPU detection code needs to be in a file not compiled with + * "-mmmx -msse", as gcc would generate CMOV instructions otherwise + * that would lead to SIGILL instructions on old CPUs that don't have + * it. + */ +#if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__) + +enum CPUFeatures { + NoFeatures = 0, + MMX = 0x1, + MMX_Extensions = 0x2, + SSE = 0x6, + SSE2 = 0x8, + CMOV = 0x10 +}; + +static unsigned int detectCPUFeatures(void) { + unsigned int result; + char vendor[13]; + vendor[0] = 0; + vendor[12] = 0; + /* see p. 118 of amd64 instruction set manual Vol3 */ + /* We need to be careful about the handling of %ebx and + * %esp here. We can't declare either one as clobbered + * since they are special registers (%ebx is the "PIC + * register" holding an offset to global data, %esp the + * stack pointer), so we need to make sure they have their + * original values when we access the output operands. + */ + __asm__ ("pushf\n" + "pop %%eax\n" + "mov %%eax, %%ecx\n" + "xor $0x00200000, %%eax\n" + "push %%eax\n" + "popf\n" + "pushf\n" + "pop %%eax\n" + "mov $0x0, %%edx\n" + "xor %%ecx, %%eax\n" + "jz 1f\n" + + "mov $0x00000000, %%eax\n" + "push %%ebx\n" + "cpuid\n" + "mov %%ebx, %%eax\n" + "pop %%ebx\n" + "mov %%eax, %1\n" + "mov %%edx, %2\n" + "mov %%ecx, %3\n" + "mov $0x00000001, %%eax\n" + "push %%ebx\n" + "cpuid\n" + "pop %%ebx\n" + "1:\n" + "mov %%edx, %0\n" + : "=r" (result), + "=m" (vendor[0]), + "=m" (vendor[4]), + "=m" (vendor[8]) + : + : "%eax", "%ecx", "%edx" + ); + + unsigned int features = 0; + if (result) { + /* result now contains the standard feature bits */ + if (result & (1 << 15)) + features |= CMOV; + if (result & (1 << 23)) + features |= MMX; + if (result & (1 << 25)) + features |= SSE; + if (result & (1 << 26)) + features |= SSE2; + if ((result & MMX) && !(result & SSE) && (strcmp(vendor, "AuthenticAMD") == 0)) { + /* check for AMD MMX extensions */ + + unsigned int result; + __asm__("push %%ebx\n" + "mov $0x80000000, %%eax\n" + "cpuid\n" + "xor %%edx, %%edx\n" + "cmp $0x1, %%eax\n" + "jge 1f\n" + "mov $0x80000001, %%eax\n" + "cpuid\n" + "1:\n" + "pop %%ebx\n" + "mov %%edx, %0\n" + : "=r" (result) + : + : "%eax", "%ecx", "%edx" + ); + if (result & (1<<22)) + features |= MMX_Extensions; + } + } + return features; +} + +Bool +fbHaveMMX (void) +{ + static Bool initialized = FALSE; + static Bool mmx_present; + + if (!initialized) + { + unsigned int features = detectCPUFeatures(); + mmx_present = (features & (MMX|MMX_Extensions)) == (MMX|MMX_Extensions); + initialized = TRUE; + } + + return mmx_present; +} +#endif /* USE_MMX && !amd64 */ #endif /* RENDER */ diff --git a/gfx/cairo/libpixman/src/fbpict.h b/gfx/cairo/libpixman/src/fbpict.h index 6e6fcc7f32d..77031a6eec9 100644 --- a/gfx/cairo/libpixman/src/fbpict.h +++ b/gfx/cairo/libpixman/src/fbpict.h @@ -1,5 +1,5 @@ /* - * $Id: fbpict.h,v 1.1 2005-08-20 05:34:02 vladimir%pobox.com Exp $ + * $Id: fbpict.h,v 1.5 2006-02-03 04:49:30 vladimir%pobox.com Exp $ * * Copyright © 2000 Keith Packard * 2005 Lars Knoll & Zack Rusin, Trolltech @@ -67,7 +67,9 @@ #define Green(x) (((x) >> 8) & 0xff) #define Blue(x) ((x) & 0xff) -#define fbComposeGetSolid(pict, bits) { \ +#define IsRGB(pict) ((pict)->image_format.red > (pict)->image_format.blue) + +#define fbComposeGetSolid(pict, dest, bits) { \ FbBits *__bits__; \ FbStride __stride__; \ int __bpp__; \ @@ -99,6 +101,12 @@ /* manage missing src alpha */ \ if ((pict)->image_format.alphaMask == 0) \ (bits) |= 0xff000000; \ + /* Handle RGB/BGR mismatch */ \ + if (dest && IsRGB(dest) != IsRGB(pict)) \ + bits = (((bits & 0xff000000)) | \ + ((bits & 0x00ff0000) >> 16) | \ + ((bits & 0x0000ff00)) | \ + ((bits & 0x000000ff) << 16)); \ } #define fbComposeGetStart(pict,x,y,type,stride,line,mul) {\ diff --git a/gfx/cairo/libpixman/src/ic.c b/gfx/cairo/libpixman/src/ic.c deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/gfx/cairo/libpixman/src/icbltone.c b/gfx/cairo/libpixman/src/icbltone.c index 58f6e19d8b6..30e64777903 100644 --- a/gfx/cairo/libpixman/src/icbltone.c +++ b/gfx/cairo/libpixman/src/icbltone.c @@ -130,7 +130,7 @@ fbLaneTable(int bpp) case 32: return fb32Lane; } - return 0; + return NULL; } #endif @@ -233,11 +233,11 @@ fbBltOne (FbStip *src, /* * Get pointer to stipple mask array for this depth */ - fbBits = 0; /* unused */ + fbBits = NULL; /* unused */ if (pixelsPerDst <= 8) fbBits = fbStippleTable(pixelsPerDst); #ifndef FBNOPIXADDR - fbLane = 0; + fbLane = NULL; if (transparent && fgand == 0 && dstBpp >= 8) fbLane = fbLaneTable(dstBpp); #endif diff --git a/gfx/cairo/libpixman/src/icimage.c b/gfx/cairo/libpixman/src/icimage.c index 86db4416b0c..83f04ff2b5e 100644 --- a/gfx/cairo/libpixman/src/icimage.c +++ b/gfx/cairo/libpixman/src/icimage.c @@ -120,13 +120,13 @@ pixman_image_init (pixman_image_t *image) image->componentAlpha = 0; image->compositeClipSource = 0; - image->alphaMap = 0; + image->alphaMap = NULL; image->alphaOrigin.x = 0; image->alphaOrigin.y = 0; image->clipOrigin.x = 0; image->clipOrigin.y = 0; - image->clientClip = 0; + image->clientClip = NULL; image->dither = 0L; @@ -148,7 +148,7 @@ pixman_image_init (pixman_image_t *image) image->transform = NULL; image->filter = PIXMAN_FILTER_NEAREST; - image->filter_params = 0; + image->filter_params = NULL; image->filter_nparams = 0; @@ -175,7 +175,7 @@ pixman_image_set_transform (pixman_image_t *image, } }; if (transform && memcmp (transform, &identity, sizeof (pixman_transform_t)) == 0) - transform = 0; + transform = NULL; if (transform) { @@ -192,7 +192,7 @@ pixman_image_set_transform (pixman_image_t *image, if (image->transform) { free (image->transform); - image->transform = 0; + image->transform = NULL; } } return 0; diff --git a/gfx/cairo/libpixman/src/icrect.c b/gfx/cairo/libpixman/src/icrect.c index 95306790c03..057498f624e 100644 --- a/gfx/cairo/libpixman/src/icrect.c +++ b/gfx/cairo/libpixman/src/icrect.c @@ -109,12 +109,13 @@ pixman_fill_rect_8bpp (pixman_image_t *dst, uint16_t height, pixman_bits_t *pixel) { + int value = (int) (*pixel); char *line; line = (char *)dst->pixels->data + xDst + yDst * dst->pixels->stride; while (height-- > 0) { - memset (line, *(char *)pixel, width); + memset (line, value, width); line += dst->pixels->stride; } } @@ -349,7 +350,7 @@ pixman_fill_rectangles (pixman_operator_t op, while (nRects--) { - pixman_composite (op, src, 0, dst, 0, 0, 0, 0, + pixman_composite (op, src, NULL, dst, 0, 0, 0, 0, rects->x, rects->y, rects->width, diff --git a/gfx/cairo/libpixman/src/ictrap.c b/gfx/cairo/libpixman/src/ictrap.c index 5e3431b127b..7856d5a6e13 100644 --- a/gfx/cairo/libpixman/src/ictrap.c +++ b/gfx/cairo/libpixman/src/ictrap.c @@ -1,5 +1,5 @@ /* - * $Id: ictrap.c,v 1.4 2005-08-20 05:34:02 vladimir%pobox.com Exp $ + * $Id: ictrap.c,v 1.8 2006-02-03 04:49:30 vladimir%pobox.com Exp $ * * Copyright © 2002 Keith Packard * @@ -34,7 +34,7 @@ FbCreateAlphaPicture (pixman_image_t *dst, int own_format = 0; if (width > 32767 || height > 32767) - return 0; + return NULL; if (!format) { @@ -44,7 +44,7 @@ FbCreateAlphaPicture (pixman_image_t *dst, else format = pixman_format_create (PIXMAN_FORMAT_NAME_A8); if (!format) - return 0; + return NULL; } image = pixman_image_create (format, width, height); diff --git a/gfx/cairo/libpixman/src/mozstdint.h b/gfx/cairo/libpixman/src/mozstdint.h deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/gfx/cairo/libpixman/src/pixman-remap.h b/gfx/cairo/libpixman/src/pixman-remap.h index dd2ba8dc450..5c2c2003a31 100644 --- a/gfx/cairo/libpixman/src/pixman-remap.h +++ b/gfx/cairo/libpixman/src/pixman-remap.h @@ -1,287 +1,56 @@ -#define fb16Lane _cairo_pixman_16_lane -#define fb32Lane _cairo_pixman_32_lane -#define fb8Lane _cairo_pixman_8_lane -#define fbAccessMap _cairo_pixman_access_map -#define fbBlt _cairo_pixman_blt -#define fbBlt24 _cairo_pixman_blt24 -#define fbBlt24Line _cairo_pixman_blt24_line -#define fbBltOne _cairo_pixman_blt_one -#define fbBltOne24 _cairo_pixman_blt_one24 -#define fbBltStip _cairo_pixman_blt_stip -#define fbBuildCompositeOperand _cairo_pixman_build_composite_operand -#define fbCombineAddC _cairo_pixman_combine_add_c -#define fbCombineAddU _cairo_pixman_combine_add_u -#define fbCombineAtopC _cairo_pixman_combine_atop_c -#define fbCombineAtopReverseC _cairo_pixman_combine_atop_reverse_c -#define fbCombineAtopReverseU _cairo_pixman_combine_atop_reverse_u -#define fbCombineAtopU _cairo_pixman_combine_atop_u -#define fbCombineClear _cairo_pixman_combine_clear -#define fbCombineClearC _cairo_pixman_combine_clear_c -#define fbCombineConjointAtopC _cairo_pixman_combine_conjoint_atop_c -#define fbCombineConjointAtopReverseC _cairo_pixman_combine_conjoint_atop_reverse_c -#define fbCombineConjointAtopReverseU _cairo_pixman_combine_conjoint_atop_reverse_u -#define fbCombineConjointAtopU _cairo_pixman_combine_conjoint_atop_u -#define fbCombineConjointGeneralC _cairo_pixman_combine_conjoint_general_c -#define fbCombineConjointGeneralU _cairo_pixman_combine_conjoint_general_u -#define fbCombineConjointInC _cairo_pixman_combine_conjoint_in_c -#define fbCombineConjointInPart _cairo_pixman_combine_conjoint_in_part -#define fbCombineConjointInReverseC _cairo_pixman_combine_conjoint_in_reverse_c -#define fbCombineConjointInReverseU _cairo_pixman_combine_conjoint_in_reverse_u -#define fbCombineConjointInU _cairo_pixman_combine_conjoint_in_u -#define fbCombineConjointOutC _cairo_pixman_combine_conjoint_out_c -#define fbCombineConjointOutPart _cairo_pixman_combine_conjoint_out_part -#define fbCombineConjointOutReverseC _cairo_pixman_combine_conjoint_out_reverse_c -#define fbCombineConjointOutReverseU _cairo_pixman_combine_conjoint_out_reverse_u -#define fbCombineConjointOutU _cairo_pixman_combine_conjoint_out_u -#define fbCombineConjointOverC _cairo_pixman_combine_conjoint_over_c -#define fbCombineConjointOverReverseC _cairo_pixman_combine_conjoint_over_reverse_c -#define fbCombineConjointOverReverseU _cairo_pixman_combine_conjoint_over_reverse_u -#define fbCombineConjointOverU _cairo_pixman_combine_conjoint_over_u -#define fbCombineConjointXorC _cairo_pixman_combine_conjoint_xor_c -#define fbCombineConjointXorU _cairo_pixman_combine_conjoint_xor_u -#define fbCombineDisjointAtopC _cairo_pixman_combine_disjoint_atop_c -#define fbCombineDisjointAtopReverseC _cairo_pixman_combine_disjoint_atop_reverse_c -#define fbCombineDisjointAtopReverseU _cairo_pixman_combine_disjoint_atop_reverse_u -#define fbCombineDisjointAtopU _cairo_pixman_combine_disjoint_atop_u -#define fbCombineDisjointGeneralC _cairo_pixman_combine_disjoint_general_c -#define fbCombineDisjointGeneralU _cairo_pixman_combine_disjoint_general_u -#define fbCombineDisjointInC _cairo_pixman_combine_disjoint_in_c -#define fbCombineDisjointInPart _cairo_pixman_combine_disjoint_in_part -#define fbCombineDisjointInReverseC _cairo_pixman_combine_disjoint_in_reverse_c -#define fbCombineDisjointInReverseU _cairo_pixman_combine_disjoint_in_reverse_u -#define fbCombineDisjointInU _cairo_pixman_combine_disjoint_in_u -#define fbCombineDisjointOutC _cairo_pixman_combine_disjoint_out_c -#define fbCombineDisjointOutPart _cairo_pixman_combine_disjoint_out_part -#define fbCombineDisjointOutReverseC _cairo_pixman_combine_disjoint_out_reverse_c -#define fbCombineDisjointOutReverseU _cairo_pixman_combine_disjoint_out_reverse_u -#define fbCombineDisjointOutU _cairo_pixman_combine_disjoint_out_u -#define fbCombineDisjointOverC _cairo_pixman_combine_disjoint_over_c -#define fbCombineDisjointOverReverseC _cairo_pixman_combine_disjoint_over_reverse_c -#define fbCombineDisjointOverReverseU _cairo_pixman_combine_disjoint_over_reverse_u -#define fbCombineDisjointOverU _cairo_pixman_combine_disjoint_over_u -#define fbCombineDisjointXorC _cairo_pixman_combine_disjoint_xor_c -#define fbCombineDisjointXorU _cairo_pixman_combine_disjoint_xor_u -#define fbCombineDst _cairo_pixman_combine_dst -#define fbCombineFuncC _cairo_pixman_combine_func_c -#define fbCombineFuncU _cairo_pixman_combine_func_u -#define fbCombineInC _cairo_pixman_combine_in_c -#define fbCombineInReverseC _cairo_pixman_combine_in_reverse_c -#define fbCombineInReverseU _cairo_pixman_combine_in_reverse_u -#define fbCombineInU _cairo_pixman_combine_in_u -#define fbCombineMaskAlphaC _cairo_pixman_combine_mask_alpha_c -#define fbCombineMaskAlphaU _cairo_pixman_combine_mask_alpha_u -#define fbCombineMaskC _cairo_pixman_combine_mask_c -#define fbCombineMaskU _cairo_pixman_combine_mask_u -#define fbCombineMaskValueC _cairo_pixman_combine_mask_value_c -#define fbCombineOutC _cairo_pixman_combine_out_c -#define fbCombineOutReverseC _cairo_pixman_combine_out_reverse_c -#define fbCombineOutReverseU _cairo_pixman_combine_out_reverse_u -#define fbCombineOutU _cairo_pixman_combine_out_u -#define fbCombineOverC _cairo_pixman_combine_over_c -#define fbCombineOverReverseC _cairo_pixman_combine_over_reverse_c -#define fbCombineOverReverseU _cairo_pixman_combine_over_reverse_u -#define fbCombineOverU _cairo_pixman_combine_over_u -#define fbCombineSaturateC _cairo_pixman_combine_saturate_c -#define fbCombineSaturateU _cairo_pixman_combine_saturate_u -#define fbCombineSrcC _cairo_pixman_combine_src_c -#define fbCombineSrcU _cairo_pixman_combine_src_u -#define fbCombineXorC _cairo_pixman_combine_xor_c -#define fbCombineXorU _cairo_pixman_combine_xor_u +#define pixman_add_trapezoids _cairo_pixman_add_trapezoids +#define INT_pixman_color_to_pixel _cairo_pixman_color_to_pixel +#define pixman_color_to_pixel _cairo_pixman_color_to_pixel +#define composeFunctions _cairo_pixman_compose_functions #define fbComposeSetupMMX _cairo_pixman_compose_setup_mmx +#define INT_pixman_composite _cairo_pixman_composite +#define pixman_composite _cairo_pixman_composite #define fbCompositeCopyAreammx _cairo_pixman_composite_copy_area_mmx -#define fbCompositeSolidMaskSrc_nx8x8888mmx _cairo_pixman_composite_solid_mask_src_nx8x8888mmx #define fbCompositeSolidMask_nx8888x0565Cmmx _cairo_pixman_composite_solid_mask_nx8888x0565Cmmx #define fbCompositeSolidMask_nx8888x8888Cmmx _cairo_pixman_composite_solid_mask_nx8888x8888Cmmx #define fbCompositeSolidMask_nx8x0565mmx _cairo_pixman_composite_solid_mask_nx8x0565mmx #define fbCompositeSolidMask_nx8x8888mmx _cairo_pixman_composite_solid_mask_nx8x8888mmx +#define fbCompositeSolidMaskSrc_nx8x8888mmx _cairo_pixman_composite_solid_mask_src_nx8x8888mmx #define fbCompositeSolid_nx0565mmx _cairo_pixman_composite_solid_nx0565mmx #define fbCompositeSolid_nx8888mmx _cairo_pixman_composite_solid_nx8888mmx -#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx -#define fbCompositeSrcAdd_8888x8888mmx _cairo_pixman_composite_src_add_8888x8888mmx #define fbCompositeSrc_8888RevNPx0565mmx _cairo_pixman_composite_src_8888RevNPx0565mmx #define fbCompositeSrc_8888RevNPx8888mmx _cairo_pixman_composite_src_8888RevNPx8888_mmx #define fbCompositeSrc_8888x8888mmx _cairo_pixman_composite_src_8888x8888mmx #define fbCompositeSrc_8888x8x8888mmx _cairo_pixman_composite_src_8888x8x8888mmx +#define fbCompositeSrcAdd_8000x8000mmx _cairo_pixman_composite_src_add_8000x8000mmx +#define fbCompositeSrcAdd_8888x8888mmx _cairo_pixman_composite_src_add_8888x8888mmx #define fbCompositeSrc_x888x8x8888mmx _cairo_pixman_composite_src_x888x8x8888mmx -#define fbCopyAreammx _cairo_pixman_copy_area_mmx -#define fbHaveMMX _cairo_pixman_have_mmx -#define fbSolidFillmmx _cairo_pixman_solid_fill_mmx -#define fbCompositeSolidMask_nx1xn _cairo_pixman_composite_solid_mask_nx1xn -#define fbCompositeSolidMask_nx8888x0565 _cairo_pixman_composite_solid_mask_nx8888x0565 -#define fbCompositeSolidMask_nx8888x0565C _cairo_pixman_composite_solid_mask_nx8888x0565_c -#define fbCompositeSolidMask_nx8888x8888C _cairo_pixman_composite_solid_mask_nx8888x8888_c -#define fbCompositeSolidMask_nx8x0565 _cairo_pixman_composite_solid_mask_nx8x0565 -#define fbCompositeSolidMask_nx8x0888 _cairo_pixman_composite_solid_mask_nx8x0888 -#define fbCompositeSolidMask_nx8x8888 _cairo_pixman_composite_solid_mask_nx8x8888 -#define fbCompositeSrc_0565x0565 _cairo_pixman_composite_src_0565x0565 -#define fbCompositeSrc_8888x0565 _cairo_pixman_composite_src_8888x0565 -#define fbCompositeSrc_8888x0888 _cairo_pixman_composite_src_8888x0888 -#define fbCompositeSrc_8888x8888 _cairo_pixman_composite_src_8888x8888 -#define fbCompositeSrcAdd_1000x1000 _cairo_pixman_composite_src_add_1000x1000 -#define fbCompositeSrcAdd_8000x8000 _cairo_pixman_composite_src_add_8000x8000 -#define fbCompositeSrcAdd_8888x8888 _cairo_pixman_composite_src_add_8888x8888 -#define fbCompositeSrcSrc_nxn _cairo_pixman_composite_src_src_nxn -#define fbCompositeTrans_0565xnx0565 _cairo_pixman_composite_trans_0565xnx0565 -#define fbCompositeTrans_0888xnx0888 _cairo_pixman_composite_trans_0888xnx0888 -#define FbComputeCompositeRegion _cairo_pixman_compute_composite_region -#define FbCreateAlphaPicture _cairo_pixman_create_alpha_picture -#define fbFetch_a1 _cairo_pixman_fetch_a1 -#define fbFetch_a1b1g1r1 _cairo_pixman_fetch_a1b1g1r1 -#define fbFetch_a1b5g5r5 _cairo_pixman_fetch_a1b5g5r5 -#define fbFetch_a1r1g1b1 _cairo_pixman_fetch_a1r1g1b1 -#define fbFetch_a1r5g5b5 _cairo_pixman_fetch_a1r5g5b5 -#define fbFetch_a2r2g2b2 _cairo_pixman_fetch_a2r2g2b2 -#define fbFetch_a4 _cairo_pixman_fetch_a4 -#define fbFetch_a4b4g4r4 _cairo_pixman_fetch_a4b4g4r4 -#define fbFetch_a4r4g4b4 _cairo_pixman_fetch_a4r4g4b4 -#define fbFetch_a8 _cairo_pixman_fetch_a8 -#define fbFetch_a8b8g8r8 _cairo_pixman_fetch_a8b8g8r8 -#define fbFetch_a8r8g8b8 _cairo_pixman_fetch_a8r8g8b8 -#define fbFetcha_a1 _cairo_pixman_fetcha_a1 -#define fbFetcha_a4 _cairo_pixman_fetcha_a4 -#define fbFetcha_a8 _cairo_pixman_fetcha_a8 -#define fbFetcha_external _cairo_pixman_fetcha_external -#define fbFetcha_transform _cairo_pixman_fetcha_transform -#define fbFetch_b1g2r1 _cairo_pixman_fetch_b1g2r1 -#define fbFetch_b2g3r3 _cairo_pixman_fetch_b2g3r3 -#define fbFetch_b5g6r5 _cairo_pixman_fetch_b5g6r5 -#define fbFetch_b8g8r8 _cairo_pixman_fetch_b8g8r8 -#define fbFetch_external _cairo_pixman_fetch_external -#define fbFetch_r1g2b1 _cairo_pixman_fetch_r1g2b1 -#define fbFetch_r3g3b2 _cairo_pixman_fetch_r3g3b2 -#define fbFetch_r5g6b5 _cairo_pixman_fetch_r5g6b5 -#define fbFetch_r8g8b8 _cairo_pixman_fetch_r8g8b8 -#define fbFetch_transform _cairo_pixman_fetch_transform -#define fbFetch_x1b5g5r5 _cairo_pixman_fetch_x1b5g5r5 -#define fbFetch_x1r5g5b5 _cairo_pixman_fetch_x1r5g5b5 -#define fbFetch_x4b4g4r4 _cairo_pixman_fetch_x4b4g4r4 -#define fbFetch_x4r4g4b4 _cairo_pixman_fetch_x4r4g4b4 -#define fbFetch_x8b8g8r8 _cairo_pixman_fetch_x8b8g8r8 -#define fbFetch_x8r8g8b8 _cairo_pixman_fetch_x8r8g8b8 -#define FbFillColor _cairo_pixman_fill_color -#define fbIn _cairo_pixman_in -#define fbIn24 _cairo_pixman_in24 -#define fbLaneTable _cairo_pixman_lane_table -#define FbMergeRopBits _cairo_pixman_merge_rop_bits -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) -#else -#define _FbOnes _cairo_pixman_ones -#endif -#define fbOver _cairo_pixman_over -#define fbOver24 _cairo_pixman_over24 -#define FbPixelsCreate _cairo_pixman_pixels_create -#define FbPixelsCreateForData _cairo_pixman_pixels_create_for_data -#define FbPixelsDestroy _cairo_pixman_pixels_destroy -#define FbPixelsInit _cairo_pixman_pixels_init -#define fbRasterizeEdges _cairo_pixman_rasterize_edges -#define fbRasterizeEdges1 _cairo_pixman_rasterize_edges1 -#define fbRasterizeEdges4 _cairo_pixman_rasterize_edges4 -#define fbRasterizeEdges8 _cairo_pixman_rasterize_edges8 -#define fbRasterizeTrapezoid _cairo_pixman_rasterize_trapezoid -#define FbRasterizeTriangle _cairo_pixman_rasterize_triangle -#define fbReplicatePixel _cairo_pixman_replicate_pixel -#define fbSet _cairo_pixman_set -#define fbSet_external _cairo_pixman_set_external -#define fbSet_transform _cairo_pixman_set_transform -#define fbStepDown _cairo_pixman_step_down -#define fbStepDown_external _cairo_pixman_step_down_external -#define fbStepDown_transform _cairo_pixman_step_down_transform -#define fbStepOver _cairo_pixman_step_over -#define fbStepOver_external _cairo_pixman_step_over_external -#define fbStepOver_transform _cairo_pixman_step_over_transform -#define fbStipple1Bits _cairo_pixman_stipple1_bits -#define fbStipple24Bits _cairo_pixman_stipple24_bits -#define fbStipple2Bits _cairo_pixman_stipple2_bits -#define fbStipple4Bits _cairo_pixman_stipple4_bits -#define fbStipple8Bits _cairo_pixman_stipple8_bits -#define fbStippleTable _cairo_pixman_stipple_table -#define fbStore_a1 _cairo_pixman_store_a1 -#define fbStore_a1b1g1r1 _cairo_pixman_store_a1b1g1r1 -#define fbStore_a1b5g5r5 _cairo_pixman_store_a1b5g5r5 -#define fbStore_a1r1g1b1 _cairo_pixman_store_a1r1g1b1 -#define fbStore_a1r5g5b5 _cairo_pixman_store_a1r5g5b5 -#define fbStore_a2r2g2b2 _cairo_pixman_store_a2r2g2b2 -#define fbStore_a4 _cairo_pixman_store_a4 -#define fbStore_a4b4g4r4 _cairo_pixman_store_a4b4g4r4 -#define fbStore_a4r4g4b4 _cairo_pixman_store_a4r4g4b4 -#define fbStore_a8 _cairo_pixman_store_a8 -#define fbStore_a8b8g8r8 _cairo_pixman_store_a8b8g8r8 -#define fbStore_a8r8g8b8 _cairo_pixman_store_a8r8g8b8 -#define fbStore_b1g2r1 _cairo_pixman_store_b1g2r1 -#define fbStore_b2g3r3 _cairo_pixman_store_b2g3r3 -#define fbStore_b5g6r5 _cairo_pixman_store_b5g6r5 -#define fbStore_b8g8r8 _cairo_pixman_store_b8g8r8 -#define fbStore_external _cairo_pixman_store_external -#define fbStore_r1g2b1 _cairo_pixman_store_r1g2b1 -#define fbStore_r3g3b2 _cairo_pixman_store_r3g3b2 -#define fbStore_r5g6b5 _cairo_pixman_store_r5g6b5 -#define fbStore_r8g8b8 _cairo_pixman_store_r8g8b8 -#define fbStore_x1b5g5r5 _cairo_pixman_store_x1b5g5r5 -#define fbStore_x1r5g5b5 _cairo_pixman_store_x1r5g5b5 -#define fbStore_x4b4g4r4 _cairo_pixman_store_x4b4g4r4 -#define fbStore_x4r4g4b4 _cairo_pixman_store_x4r4g4b4 -#define fbStore_x8b8g8r8 _cairo_pixman_store_x8b8g8r8 -#define fbStore_x8r8g8b8 _cairo_pixman_store_x8r8g8b8 -#define fbTransparentSpan _cairo_pixman_transparent_span -#define INT_pixman_color_to_pixel _cairo_pixman_color_to_pixel -#define INT_pixman_composite _cairo_pixman_composite -#define pixman_fill_rectangles _cairo_pixman_fill_rectangles -#define pixman_format_init _cairo_pixman_format_init -#define pixman_image_create _cairo_pixman_image_create -#define pixman_image_destroy _cairo_pixman_image_destroy -#define pixman_image_set_component_alpha _cairo_pixman_image_set_component_alpha -#define pixman_image_set_repeat _cairo_pixman_image_set_repeat -#define pixman_region_copy _cairo_pixman_region_copy -#define pixman_region_create_simple _cairo_pixman_region_create_simple -#define pixman_region_union _cairo_pixman_region_union -#define miIsSolidAlpha _cairo_pixman_is_solid_alpha -#define pixman_add_trapezoids _cairo_pixman_add_trapezoids -#define pixman_bits_per_pixel _cairo_pixman_bits_per_pixel -#define pixman_break _cairo_pixman_break -#define pixman_brokendata _cairo_pixman_brokendata -#define pixman_brokenregion _cairo_pixman_brokenregion -#define pixman_coalesce _cairo_pixman_coalesce -#define pixman_color_rects _cairo_pixman_color_rects -#define pixman_color_to_pixel _cairo_pixman_color_to_pixel -#define pixman_composite _cairo_pixman_composite -#define pixman_compositeGeneral _cairo_pixman_composite_general #define pixman_composite_trapezoids _cairo_pixman_composite_trapezoids -#define pixman_composite_triangles _cairo_pixman_composite_triangles #define pixman_composite_tri_fan _cairo_pixman_composite_tri_fan #define pixman_composite_tri_strip _cairo_pixman_composite_tri_strip -#define pixman_fill_rect_32bpp _cairo_pixman_fill_rect_32bpp -#define pixman_fill_rect_8bpp _cairo_pixman_fill_rect_8bpp +#define pixman_composite_triangles _cairo_pixman_composite_triangles +#define fbCopyAreammx _cairo_pixman_copy_area_mmx #define pixman_fill_rectangle _cairo_pixman_fill_rectangle #define pixman_fill_rectangles _cairo_pixman_fill_rectangles -#define pixman_fill_rect_general _cairo_pixman_fill_rect_general #define pixman_format_create _cairo_pixman_format_create #define pixman_format_create_masks _cairo_pixman_format_create_masks #define pixman_format_destroy _cairo_pixman_format_destroy #define pixman_format_get_masks _cairo_pixman_format_get_masks #define pixman_format_init _cairo_pixman_format_init +#if defined(USE_MMX) && !defined(__amd64__) && !defined(__x86_64__) +#define fbHaveMMX _cairo_pixman_have_mmx +#endif #define pixman_image_create _cairo_pixman_image_create #define pixman_image_create_for_data _cairo_pixman_image_create_for_data -#define pixman_image_createForPixels _cairo_pixman_image_create_for_pixels #define pixman_image_destroy _cairo_pixman_image_destroy -#define pixman_image_destroyClip _cairo_pixman_image_destroy_clip #define pixman_image_get_data _cairo_pixman_image_get_data #define pixman_image_get_depth _cairo_pixman_image_get_depth #define pixman_image_get_format _cairo_pixman_image_get_format #define pixman_image_get_height _cairo_pixman_image_get_height #define pixman_image_get_stride _cairo_pixman_image_get_stride #define pixman_image_get_width _cairo_pixman_image_get_width -#define pixman_image_init _cairo_pixman_image_init #define pixman_image_set_clip_region _cairo_pixman_image_set_clip_region #define pixman_image_set_component_alpha _cairo_pixman_image_set_component_alpha #define pixman_image_set_filter _cairo_pixman_image_set_filter #define pixman_image_set_repeat _cairo_pixman_image_set_repeat #define pixman_image_set_transform _cairo_pixman_image_set_transform -#define pixman_init _cairo_pixman_init -#define pixman_line_fixed_x _cairo_pixman_line_fixed_x -#define pixman_op _cairo_pixman_op +#define miIsSolidAlpha _cairo_pixman_is_solid_alpha #define pixman_pixel_to_color _cairo_pixman_pixel_to_color -#define pixman_point_fixed_bounds _cairo_pixman_point_fixed_bounds -#define pixman_rect_alloc _cairo_pixman_rect_alloc #define pixman_region_append _cairo_pixman_region_append #define pixman_region_contains_point _cairo_pixman_region_contains_point #define pixman_region_contains_rectangle _cairo_pixman_region_contains_rectangle @@ -290,34 +59,21 @@ #define pixman_region_create_simple _cairo_pixman_region_create_simple #define pixman_region_destroy _cairo_pixman_region_destroy #define pixman_region_empty _cairo_pixman_region_empty -#define pixman_region_emptyBox _cairo_pixman_region_empty_box -#define pixman_region_emptyData _cairo_pixman_region_empty_data #define pixman_region_extents _cairo_pixman_region_extents #define pixman_region_intersect _cairo_pixman_region_intersect -#define pixman_region_intersectO _cairo_pixman_region_intersect_o #define pixman_region_inverse _cairo_pixman_region_inverse #define pixman_region_not_empty _cairo_pixman_region_not_empty #define pixman_region_num_rects _cairo_pixman_region_num_rects #define pixman_region_rects _cairo_pixman_region_rects #define pixman_region_reset _cairo_pixman_region_reset #define pixman_region_subtract _cairo_pixman_region_subtract -#define pixman_region_subtractO _cairo_pixman_region_subtract_o #define pixman_region_translate _cairo_pixman_region_translate #define pixman_region_union _cairo_pixman_region_union -#define pixman_region_unionO _cairo_pixman_region_union_o #define pixman_region_union_rect _cairo_pixman_region_union_rect #define pixman_region_validate _cairo_pixman_region_validate -#define pixman_set_extents _cairo_pixman_set_extents -#define pixman_transform_point _cairo_pixman_transform_point -#define pixman_trapezoid_bounds _cairo_pixman_trapezoid_bounds -#define pixman_triangle_bounds _cairo_pixman_triangle_bounds -#define pixman_uninit _cairo_pixman_uninit -#define QuickSortRects _cairo_pixman_quick_sort_rects -#define QuickSortSpans _cairo_pixman_quick_sort_spans #define RenderEdgeInit _cairo_pixman_render_edge_init -#define _RenderEdgeMultiInit _cairo_pixman_render_edge_multi_init #define RenderEdgeStep _cairo_pixman_render_edge_step #define RenderLineFixedEdgeInit _cairo_pixman_render_line_fixed_edge_init #define RenderSampleCeilY _cairo_pixman_render_sample_ceil_y #define RenderSampleFloorY _cairo_pixman_render_sample_floor_y -#define composeFunctions _cairo_pixman_compose_functions +#define fbSolidFillmmx _cairo_pixman_solid_fill_mmx diff --git a/gfx/cairo/libpixman/src/pixman.h b/gfx/cairo/libpixman/src/pixman.h index 8b8fc9e95ba..a841926b748 100644 --- a/gfx/cairo/libpixman/src/pixman.h +++ b/gfx/cairo/libpixman/src/pixman.h @@ -54,7 +54,7 @@ ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ -/* $Id: pixman.h,v 1.7 2005-08-20 05:34:03 vladimir%pobox.com Exp $ */ +/* $Id: pixman.h,v 1.8 2005-10-06 04:02:08 vladimir%pobox.com Exp $ */ /* libic.h */ @@ -81,14 +81,21 @@ SOFTWARE. */ -#if HAVE_STDINT_H -# include -#elif HAVE_INTTYPES_H -# include -#elif HAVE_SYS_INT_TYPES_H +#if defined (__SVR4) && defined (__sun) # include +#elif defined (__OpenBSD__) || defined (_AIX) +# include +#elif defined (_MSC_VER) + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; + typedef __int32 int32_t; + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; #else -# include "mozstdint.h" +# include #endif #include "pixman-remap.h" diff --git a/gfx/cairo/libpixman/src/pixregion.c b/gfx/cairo/libpixman/src/pixregion.c index 659434b3458..e5660969ee7 100644 --- a/gfx/cairo/libpixman/src/pixregion.c +++ b/gfx/cairo/libpixman/src/pixregion.c @@ -46,8 +46,6 @@ SOFTWARE. ******************************************************************/ -#undef DEBUG - #include #include #include @@ -62,7 +60,7 @@ SOFTWARE. #endif #undef assert -#ifdef DEBUG +#ifdef DEBUG_PIXREGION #define assert(expr) {if (!(expr)) \ FatalError("Assertion failed file %s, line %d: expr\n", \ __FILE__, __LINE__); } @@ -210,7 +208,7 @@ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ } -#ifdef DEBUG +#ifdef DEBUG_PIXREGION int pixman_region16_print(rgn) pixman_region16_t * rgn; @@ -304,7 +302,7 @@ pixman_region16_valid(reg) } } -#endif /* DEBUG */ +#endif /* DEBUG_PIXREGION */ /* Create a new empty region */ @@ -1158,7 +1156,7 @@ pixman_region_union_rect(pixman_region16_t *dest, pixman_region16_t *source, pixman_region16_t region; if (!width || !height) - return PIXMAN_REGION_STATUS_SUCCESS; + return pixman_region_copy (dest, source); region.data = NULL; region.extents.x1 = x; region.extents.y1 = y; diff --git a/gfx/src/thebes/Makefile.in b/gfx/src/thebes/Makefile.in index 91006386a80..1a1d718d203 100644 --- a/gfx/src/thebes/Makefile.in +++ b/gfx/src/thebes/Makefile.in @@ -89,16 +89,9 @@ CPPSRCS = \ SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)mozutil_s.$(LIB_SUFFIX) \ $(DIST)/lib/$(LIB_PREFIX)gfxshared_s.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX) \ - $(DIST)/lib/$(LIB_PREFIX)thebes.$(LIB_SUFFIX) \ $(NULL) -ifdef MOZ_ENABLE_GLITZ -SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitz.$(LIB_SUFFIX) -endif - -EXTRA_DSO_LIBS = gkgfx +EXTRA_DSO_LIBS = gkgfx thebes ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2) CPPSRCS += nsSystemFontsGTK2.cpp @@ -110,7 +103,6 @@ CPPSRCS += nsFontMetricsPango.cpp \ endif ifdef MOZ_ENABLE_GLITZ -SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitzglx.$(LIB_SUFFIX) REQUIRES += glitzglx endif diff --git a/gfx/src/thebes/nsThebesDeviceContext.cpp b/gfx/src/thebes/nsThebesDeviceContext.cpp index 9ba066a37d2..1a48a0d1707 100644 --- a/gfx/src/thebes/nsThebesDeviceContext.cpp +++ b/gfx/src/thebes/nsThebesDeviceContext.cpp @@ -123,12 +123,12 @@ nsThebesDeviceContext::Init(nsNativeWidget aWidget) { #ifdef XP_WIN // XXX we should really look at the widget for printing and such, but this widget is currently always null... - HDC dc = GetDC(nsnull); + HDC dc = GetDC((HWND)aWidget); mPixelsToTwips = (float)NSIntPointsToTwips(72) / (float)GetDeviceCaps(dc, LOGPIXELSY); if (GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) mPixelsToTwips = (float)NSToIntRound(mPixelsToTwips); mTwipsToPixels = 1.0f / mPixelsToTwips; - ReleaseDC(nsnull, dc); + ReleaseDC((HWND)aWidget, dc); #else mTwipsToPixels = 96 / (float) NSIntPointsToTwips(72); mPixelsToTwips = 1.0f / mTwipsToPixels; @@ -411,12 +411,11 @@ nsThebesDeviceContext::GetGlitzDrawableFormat() glitz_drawable_format_t templ; memset(&templ, 0, sizeof(templ)); templ.samples = 1; // change this to change FSAA? - templ.types.window = 1; int defaultScreen = gdk_x11_get_default_screen(); - unsigned long mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_WINDOW_MASK; + unsigned long mask = GLITZ_FORMAT_SAMPLES_MASK; - format = glitz_glx_find_drawable_format (GDK_DISPLAY(), defaultScreen, mask, &templ, 0); + format = glitz_glx_find_window_format (GDK_DISPLAY(), defaultScreen, mask, &templ, 0); #endif return format; } diff --git a/gfx/src/thebes/nsThebesDrawingSurface.cpp b/gfx/src/thebes/nsThebesDrawingSurface.cpp index 24140a3d366..18666a17ef3 100644 --- a/gfx/src/thebes/nsThebesDrawingSurface.cpp +++ b/gfx/src/thebes/nsThebesDrawingSurface.cpp @@ -44,6 +44,7 @@ #include "gfxImageSurface.h" #ifdef MOZ_ENABLE_GTK2 +#include #include #include "gfxXlibSurface.h" # ifdef MOZ_ENABLE_GLITZ @@ -68,10 +69,21 @@ nsThebesDrawingSurface::~nsThebesDrawingSurface() { #ifdef WIN_XP if (mWidget) - nsNativeWidget nativeWidget = mWidget->FreeNativeData(mNativeWidget, NS_NATIVE_GRAPHIC); + mWidget->FreeNativeData(mNativeWidget, NS_NATIVE_GRAPHIC); #endif } +#ifdef MOZ_ENABLE_GTK2 +static cairo_user_data_key_t cairo_gtk_pixmap_unref_key; +static void do_gtk_pixmap_unref (void *data) +{ + GdkPixmap *pmap = (GdkPixmap*)data; + guint rc = ((GObject*)pmap)->ref_count; + //fprintf (stderr, "do_gtk_pixmap_unref: %p refcnt %d\n", pmap, rc); + gdk_pixmap_unref (pmap); +} +#endif + nsresult nsThebesDrawingSurface::Init(nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint32 aHeight, PRBool aFastAccess) { @@ -91,7 +103,24 @@ nsThebesDrawingSurface::Init(nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint mSurface = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32, aWidth, aHeight); } else { if (!UseGlitz()) { - mSurface = new gfxXlibSurface(GDK_DISPLAY(), GDK_VISUAL_XVISUAL(gdk_rgb_get_visual()), aWidth, aHeight); + mNativeWidget = ::gdk_pixmap_new(nsnull, mWidth, mHeight, 24); + { + guint rc = ((GObject*)mNativeWidget)->ref_count; + //fprintf (stderr, "do_gtk_pixmap_new: %p refcnt %d\n", mNativeWidget, rc); + } + gdk_drawable_set_colormap(GDK_DRAWABLE(mNativeWidget), gdk_rgb_get_colormap()); + + mSurface = new gfxXlibSurface(GDK_WINDOW_XDISPLAY(GDK_DRAWABLE(mNativeWidget)), + GDK_WINDOW_XWINDOW(GDK_DRAWABLE(mNativeWidget)), + GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(GDK_DRAWABLE(mNativeWidget)))); + + // we need some thebes wrappers for surface destructor hooks + cairo_surface_set_user_data (mSurface->CairoSurface(), + &cairo_gtk_pixmap_unref_key, + mNativeWidget, + do_gtk_pixmap_unref); + + //mSurface = new gfxXlibSurface(GDK_DISPLAY(), GDK_VISUAL_XVISUAL(gdk_rgb_get_visual()), aWidth, aHeight); } else { # if defined(MOZ_ENABLE_GLITZ) glitz_drawable_format_t *gdformat = (glitz_drawable_format_t*) aDC->GetGlitzDrawableFormat(); @@ -110,7 +139,7 @@ nsThebesDrawingSurface::Init(nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint aHeight, 0, NULL); - glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0); + glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); //fprintf (stderr, "## nsThebesDrawingSurface::Init Glitz PBUFFER %d %d\n", aWidth, aHeight); mSurface = new gfxGlitzSurface (gdraw, gsurf, PR_TRUE); @@ -120,8 +149,19 @@ nsThebesDrawingSurface::Init(nsThebesDeviceContext *aDC, PRUint32 aWidth, PRUint #elif XP_WIN if (aFastAccess) { mSurface = new gfxImageSurface(gfxImageSurface::ImageFormatARGB32, aWidth, aHeight); - } else { - mSurface = new gfxWindowsSurface(aWidth, aHeight); + } else { + // this may or may not be null. this is currently only called from a spot + // where this will be a hwnd + nsNativeWidget widget = aDC->GetWidget(); + HDC dc = nsnull; + if (widget) + dc = GetDC((HWND)widget); + + mSurface = new gfxWindowsSurface(dc, aWidth, aHeight); + + if (widget) + ReleaseDC((HWND)widget, dc); + } #else #error Write me! @@ -136,15 +176,15 @@ nsThebesDrawingSurface::Init (nsThebesDeviceContext *aDC, nsIWidget *aWidget) PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsThebesDrawingSurface::Init aDC %p aWidget %p\n", this, aDC, aWidget)); #ifdef MOZ_ENABLE_GTK2 - nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET); + mNativeWidget = aWidget->GetNativeData(NS_NATIVE_WIDGET); #elif XP_WIN mWidget = aWidget; // hold a pointer to this.. not a reference.. because we have to free the dc... - nsNativeWidget nativeWidget = aWidget->GetNativeData(NS_NATIVE_GRAPHIC); + mNativeWidget = aWidget->GetNativeData(NS_NATIVE_GRAPHIC); #else #error Write me! #endif - Init(aDC, nativeWidget); + Init(aDC, mNativeWidget); return NS_OK; } @@ -200,7 +240,7 @@ nsThebesDrawingSurface::Init (nsThebesDeviceContext *aDC, nsNativeWidget aWidget height, 0, NULL); - glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0); + glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); //fprintf (stderr, "## nsThebesDrawingSurface::Init Glitz DRAWABLE %p (DC: %p)\n", aWidget, aDC); diff --git a/gfx/src/thebes/nsThebesImage.cpp b/gfx/src/thebes/nsThebesImage.cpp index 12d362f2d26..de07762a73c 100644 --- a/gfx/src/thebes/nsThebesImage.cpp +++ b/gfx/src/thebes/nsThebesImage.cpp @@ -230,7 +230,7 @@ nsThebesImage::Optimize(nsIDeviceContext* aContext) 0, NULL); - glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR, 0, 0); + glitz_surface_attach (gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR); mOptSurface = new gfxGlitzSurface (gdraw, gsurf, PR_TRUE); # endif } @@ -517,20 +517,28 @@ nsThebesImage::DrawTile(nsIRenderingContext &aContext, #endif gfxMatrix savedMatrix = ctx->CurrentMatrix(); - PRBool reallyRepeating = PR_TRUE; - - /* Let's figure out if this really is repeating, or if we're just drawing a subrect */ - if (aTileRect.x + aTileRect.width > mWidth || - aTileRect.y + aTileRect.height > mHeight) - { - reallyRepeating = PR_TRUE; - } - - ctx->IdentityMatrix(); + PRBool reallyRepeating = PR_FALSE; PRInt32 x0 = aTileRect.x - aSXOffset; PRInt32 y0 = aTileRect.y - aSYOffset; + // Let's figure out if this really is repeating, or if we're just drawing a subrect + if (aTileRect.width > mWidth || + aTileRect.height > mHeight) + { + reallyRepeating = PR_TRUE; + } else { + // nope, just drawing a subrect, so let's not set CAIRO_EXTEND_REPEAT + // so that we don't get screwed by image surface fallbacks due to + // buggy RENDER implementations + if (aSXOffset > mWidth) + aSXOffset = aSXOffset % mWidth; + if (aSYOffset > mHeight) + aSYOffset = aSYOffset % mHeight; + } + + ctx->IdentityMatrix(); + ctx->Translate(gfxPoint(x0, y0)); nsRefPtr pat = new gfxPattern(ThebesSurface()); @@ -538,9 +546,15 @@ nsThebesImage::DrawTile(nsIRenderingContext &aContext, pat->SetExtend(CAIRO_EXTEND_REPEAT); ctx->NewPath(); + ctx->Rectangle(gfxRect(aSXOffset, aSYOffset, + aTileRect.width, aTileRect.height), + PR_TRUE); + ctx->SetPattern(pat); +#if 0 ctx->PixelSnappedRectangleAndSetPattern(gfxRect(aSXOffset, aSYOffset, aTileRect.width, aTileRect.height), pat); +#endif ctx->Fill(); ctx->SetMatrix(savedMatrix); diff --git a/gfx/src/thebes/nsThebesRenderingContext.cpp b/gfx/src/thebes/nsThebesRenderingContext.cpp index 7ba61f10878..720dbd98abf 100644 --- a/gfx/src/thebes/nsThebesRenderingContext.cpp +++ b/gfx/src/thebes/nsThebesRenderingContext.cpp @@ -101,10 +101,11 @@ nsThebesRenderingContext::Init(nsIDeviceContext* aContext, nsIWidget *aWidget) mDeviceContext = aContext; mWidget = aWidget; - mDrawingSurface = new nsThebesDrawingSurface(); - mDrawingSurface->Init(thebesDC, aWidget); + mLocalDrawingSurface = new nsThebesDrawingSurface(); + mLocalDrawingSurface->Init(thebesDC, aWidget); + mDrawingSurface = mLocalDrawingSurface; - mThebes = new gfxContext(mDrawingSurface->GetThebesSurface()); + mThebes = new gfxContext(mLocalDrawingSurface->GetThebesSurface()); //mThebes->SetColor(gfxRGBA(0.9, 0.0, 0.0, 0.3)); //mThebes->Paint(); @@ -125,9 +126,10 @@ nsThebesRenderingContext::Init(nsIDeviceContext* aContext, nsIDrawingSurface *aS mDeviceContext = aContext; mWidget = nsnull; - mDrawingSurface = (nsThebesDrawingSurface *) cds; + mLocalDrawingSurface = (nsThebesDrawingSurface *) cds; + mDrawingSurface = mLocalDrawingSurface; - mThebes = new gfxContext(mDrawingSurface->GetThebesSurface()); + mThebes = new gfxContext(mLocalDrawingSurface->GetThebesSurface()); //mThebes->SetColor(gfxRGBA(1.0, 1.0, 1.0, 1.0)); //mThebes->Paint(); @@ -153,9 +155,7 @@ nsThebesRenderingContext::Reset(void) { PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::Reset\n", this)); - nsRefPtr surf = mThebes->CurrentSurface(); - - mThebes = new gfxContext(surf); + mThebes = new gfxContext(mDrawingSurface->GetThebesSurface()); return (CommonInit()); } @@ -171,8 +171,14 @@ nsThebesRenderingContext::GetDeviceContext(nsIDeviceContext *& aDeviceContext) NS_IMETHODIMP nsThebesRenderingContext::SelectOffScreenDrawingSurface(nsIDrawingSurface *aSurface) { - NS_WARNING("Unimplemented function called"); - return NS_ERROR_NOT_IMPLEMENTED; + if (aSurface) + mDrawingSurface = NS_STATIC_CAST(nsThebesDrawingSurface*, aSurface); + else + mDrawingSurface = mLocalDrawingSurface; + + mThebes->SetTarget(mDrawingSurface->GetThebesSurface()); + + return NS_OK; } NS_IMETHODIMP @@ -241,10 +247,11 @@ nsThebesRenderingContext::SetClipRect(const nsRect& aRect, //return NS_OK; PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetClipRect [%d,%d,%d,%d] %d\n", this, aRect.x, aRect.y, aRect.width, aRect.height, aCombine)); - if (aCombine == nsClipCombine_kReplace) + if (aCombine == nsClipCombine_kReplace) { mThebes->ResetClip(); - else if (aCombine != nsClipCombine_kIntersect) + } else if (aCombine != nsClipCombine_kIntersect) { NS_WARNING("Unexpected usage of SetClipRect"); + } mThebes->NewPath(); mThebes->Rectangle(GFX_RECT_FROM_TWIPS_RECT(aRect), PR_TRUE); @@ -300,7 +307,6 @@ nsThebesRenderingContext::SetClipRegion(const nsIRegion& pxRegion, rects->mRects[i].height), PR_TRUE); } - mThebes->Clip(); evilPxRegion->FreeRects (rects); @@ -508,7 +514,7 @@ nsThebesRenderingContext::DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoor // we can't draw thick lines with gfx, so we always assume we want pixel-aligned // lines if the rendering context is at 1.0 scale gfxMatrix savedMatrix = mThebes->CurrentMatrix(); - if (savedMatrix.GetScaling() == gfxSize(1.0, 1.0)) { + if (!savedMatrix.HasNonTranslation()) { p0 = mThebes->UserToDevice(p0); p1 = mThebes->UserToDevice(p1); @@ -719,8 +725,14 @@ nsThebesRenderingContext::FillPolygon(const nsPoint twPoints[], PRInt32 aNumPoin void* nsThebesRenderingContext::GetNativeGraphicData(GraphicDataType aType) { - //if (mWidget && aType == NATIVE_GDK_DRAWABLE) - // return mWidget->GetNativeData(NS_NATIVE_WIDGET); + if (aType == NATIVE_GDK_DRAWABLE && + !nsThebesDrawingSurface::UseGlitz()) + { + if (mWidget && mDrawingSurface == mLocalDrawingSurface) + return mWidget->GetNativeData(NS_NATIVE_WIDGET); + else if (mDrawingSurface != mLocalDrawingSurface) + return mDrawingSurface->GetNativeWidget(); + } if (aType == NATIVE_THEBES_CONTEXT) return mThebes; if (aType == NATIVE_CAIRO_CONTEXT) @@ -784,78 +796,24 @@ nsThebesRenderingContext::DrawNativeWidgetPixmap(void* aSrcSurfaceBlack, NS_IMETHODIMP nsThebesRenderingContext::UseBackbuffer(PRBool* aUseBackbuffer) { - *aUseBackbuffer = PR_FALSE; *aUseBackbuffer = PR_TRUE; return NS_OK; } -nsresult nsThebesRenderingContext::AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsIDrawingSurface* &aBackbuffer, PRBool aCacheBackbuffer, PRUint32 aSurfFlags) -{ -#if 0 - nsRect newBounds; - nsresult rv = NS_OK; - - if (! aCacheBackbuffer) { - newBounds = aRequestedSize; - } else { - GetDrawingSurfaceSize(aMaxSize, aRequestedSize, newBounds); - } - - if ((nsnull == gBackbuffer) - || (gBackbufferBounds.width != newBounds.width) - || (gBackbufferBounds.height != newBounds.height)) - { - if (gBackbuffer) { - //destroy existing DS - DestroyDrawingSurface(gBackbuffer); - gBackbuffer = nsnull; - } - - rv = CreateDrawingSurface(newBounds, aSurfFlags, gBackbuffer); - // printf("Allocating a new drawing surface %d %d\n", newBounds.width, newBounds.height); - if (NS_SUCCEEDED(rv)) { - gBackbufferBounds = newBounds; - SelectOffScreenDrawingSurface(gBackbuffer); - } else { - gBackbufferBounds.SetRect(0,0,0,0); - gBackbuffer = nsnull; - } - } else { - SelectOffScreenDrawingSurface(gBackbuffer); - - float p2t; - nsCOMPtr dx; - GetDeviceContext(*getter_AddRefs(dx)); - p2t = dx->DevUnitsToAppUnits(); - nsRect bounds = aRequestedSize; - bounds *= p2t; - - SetClipRect(bounds, nsClipCombine_kReplace); - } - - aBackbuffer = gBackbuffer; - return rv; -#endif - return NS_ERROR_NOT_IMPLEMENTED; -} - - NS_IMETHODIMP nsThebesRenderingContext::GetBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, PRBool aForBlending, nsIDrawingSurface* &aBackbuffer) { - return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE, aForBlending ? NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS : 0); - //NS_WARNING("Unimplemented function called"); - //return NS_ERROR_NOT_IMPLEMENTED; + return AllocateBackbuffer(aRequestedSize, aMaxSize, aBackbuffer, PR_FALSE, + aForBlending ? NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS : 0); } NS_IMETHODIMP nsThebesRenderingContext::ReleaseBackbuffer(void) { - NS_WARNING("Unimplemented function called"); - return NS_ERROR_NOT_IMPLEMENTED; + return DestroyCachedBackbuffer(); } NS_IMETHODIMP @@ -931,29 +889,57 @@ nsThebesRenderingContext::DrawImage(imgIContainer *aImage, nsIntRect pxSr; pxSr.x = NSToIntRound(FROM_TWIPS(twSrcRect.x)); pxSr.y = NSToIntRound(FROM_TWIPS(twSrcRect.y)); - pxSr.width = NSToIntRound(FROM_TWIPS(twSrcRect.XMost())) - pxSr.x; - pxSr.height = NSToIntRound(FROM_TWIPS(twSrcRect.YMost())) - pxSr.y; + pxSr.width = NSToIntRound(FROM_TWIPS(twSrcRect.width)); + pxSr.height = NSToIntRound(FROM_TWIPS(twSrcRect.height)); // the dest rect is affected by the current transform; that'll be // handled by Image::Draw(), when we actually set up the rectangle. nsIntRect pxDr; pxDr.x = NSToIntRound(FROM_TWIPS(twDestRect.x)); pxDr.y = NSToIntRound(FROM_TWIPS(twDestRect.y)); - pxDr.width = NSToIntRound(FROM_TWIPS(twDestRect.XMost())) - pxDr.x; - pxDr.height = NSToIntRound(FROM_TWIPS(twDestRect.YMost())) - pxDr.y; + pxDr.width = NSToIntRound(FROM_TWIPS(twDestRect.width)); + pxDr.height = NSToIntRound(FROM_TWIPS(twDestRect.height)); - if (pxImgFrameRect != pxSr) { - double xscale = double(pxDr.width)/pxSr.width; - double yscale = double(pxDr.height)/pxSr.height; + if (pxImgFrameRect.x > 0) { + pxSr.x -= pxImgFrameRect.x; - nsIntRect pxScaledUpIRect; - pxScaledUpIRect.x = NSToCoordRound(pxImgFrameRect.x*xscale); - pxScaledUpIRect.y = NSToCoordRound(pxImgFrameRect.y*yscale); - pxScaledUpIRect.width = NSToCoordRound(pxImgFrameRect.XMost()*xscale) - pxScaledUpIRect.x; - pxScaledUpIRect.height = NSToCoordRound(pxImgFrameRect.YMost()*yscale) - pxScaledUpIRect.y; + nscoord scaled_x = pxSr.x; + if (pxDr.width != pxSr.width) { + PRFloat64 scale_ratio = PRFloat64(pxDr.width) / PRFloat64(pxSr.width); + scaled_x = NSToCoordRound(scaled_x * scale_ratio); + } - pxSr.IntersectRect(pxSr, pxImgFrameRect); - pxDr.IntersectRect(pxDr, pxScaledUpIRect); + if (pxSr.x < 0) { + pxDr.x -= scaled_x; + pxSr.width += pxSr.x; + pxDr.width += scaled_x; + if (pxSr.width <= 0 || pxDr.width <= 0) + return NS_OK; + pxSr.x = 0; + } else if (pxSr.x > pxImgFrameRect.width) { + return NS_OK; + } + } + + if (pxImgFrameRect.y > 0) { + pxSr.y -= pxImgFrameRect.y; + + nscoord scaled_y = pxSr.y; + if (pxDr.height != pxSr.height) { + PRFloat64 scale_ratio = PRFloat64(pxDr.height) / PRFloat64(pxSr.height); + scaled_y = NSToCoordRound(scaled_y * scale_ratio); + } + + if (pxSr.y < 0) { + pxDr.y -= scaled_y; + pxSr.height += pxSr.y; + pxDr.height += scaled_y; + if (pxSr.height <= 0 || pxDr.height <= 0) + return NS_OK; + pxSr.y = 0; + } else if (pxSr.y > pxImgFrameRect.height) { + return NS_OK; + } } return img->Draw(*this, mDrawingSurface, @@ -1399,6 +1385,40 @@ nsThebesRenderingContext::CopyOffScreenBits(nsIDrawingSurface *aSrcSurf, const nsRect &aDestBounds, PRUint32 aCopyFlags) { - NS_WARNING ("not used"); - return NS_ERROR_NOT_IMPLEMENTED; + // there's only one caller of this code, so this implementation is + // tailored to that one caller. + if (aCopyFlags != NS_COPYBITS_USE_SOURCE_CLIP_REGION) + NS_ERROR("CopyOffScreenBits called with unsupported copy flags"); + + nsRefPtr cursurf = mThebes->CurrentSurface(); + + mThebes->Save(); + mThebes->SetTarget(mLocalDrawingSurface->GetThebesSurface()); + mThebes->IdentityMatrix(); + + mThebes->Translate(gfxPoint(aDestBounds.x, aDestBounds.y)); + + // update debugging +#if 0 + mThebes->SetColor(gfxRGBA(1, 0, 0, 1)); + mThebes->NewPath(); + mThebes->Rectangle(gfxRect(0, 0, aDestBounds.width, aDestBounds.height), PR_TRUE); + mThebes->Fill(); + + //usleep(400000); + //Sleep(4); +#endif + + mThebes->SetSource(NS_STATIC_CAST(nsThebesDrawingSurface*,aSrcSurf)->GetThebesSurface(), + gfxPoint(FROM_TWIPS(aSrcX), FROM_TWIPS(aSrcY))); + + mThebes->NewPath(); + mThebes->Rectangle(gfxRect(0, 0, aDestBounds.width, aDestBounds.height), PR_TRUE); + mThebes->Fill(); + + mThebes->SetTarget(cursurf); + mThebes->Restore(); + + return NS_OK; } + diff --git a/gfx/src/thebes/nsThebesRenderingContext.h b/gfx/src/thebes/nsThebesRenderingContext.h index 2bf75192ec3..165d8406276 100644 --- a/gfx/src/thebes/nsThebesRenderingContext.h +++ b/gfx/src/thebes/nsThebesRenderingContext.h @@ -41,6 +41,7 @@ #include "nsCOMPtr.h" #include "nsIRenderingContext.h" +#include "nsRenderingContextImpl.h" #include "nsIDeviceContext.h" #include "nsIFontMetrics.h" #include "nsIWidget.h" @@ -59,7 +60,8 @@ class nsIImage; class nsThebesDrawingSurface; -class nsThebesRenderingContext : public nsIRenderingContext, public nsIThebesRenderingContext +class nsThebesRenderingContext : public nsIThebesRenderingContext, + public nsRenderingContextImpl { public: nsThebesRenderingContext(); @@ -242,9 +244,6 @@ public: void TransformCoord (nscoord *aX, nscoord *aY); - nsresult AllocateBackbuffer(const nsRect &aRequestedSize, const nsRect &aMaxSize, nsIDrawingSurface* &aBackbuffer, PRBool aCacheBackbuffer, PRUint32 aSurfFlags); - - protected: nsCOMPtr mDeviceContext; // cached pixels2twips, twips2pixels values @@ -259,9 +258,16 @@ protected: nsLineStyle mLineStyle; nscolor mColor; - nsRefPtr mThebes; + // this is always the local surface + nsCOMPtr mLocalDrawingSurface; + + // this is the current drawing surface; might be same + // as local, or might be offscreen nsCOMPtr mDrawingSurface; + // the rendering context + nsRefPtr mThebes; + // for handing out to people void UpdateTempTransformMatrix(); nsTransform2D mTempTransform; diff --git a/gfx/src/windows/nsRenderingContextWin.h b/gfx/src/windows/nsRenderingContextWin.h index 061dc88e4ca..ce6f23ca040 100644 --- a/gfx/src/windows/nsRenderingContextWin.h +++ b/gfx/src/windows/nsRenderingContextWin.h @@ -195,7 +195,6 @@ public: NS_IMETHOD CopyOffScreenBits(nsIDrawingSurface* aSrcSurf, PRInt32 aSrcX, PRInt32 aSrcY, const nsRect &aDestBounds, PRUint32 aCopyFlags); - // nsIRenderingContextWin NS_IMETHOD CreateDrawingSurface(HDC aDC, nsIDrawingSurface* &aSurface); diff --git a/gfx/thebes/public/Makefile.in b/gfx/thebes/public/Makefile.in index 85ae86bffee..5c9354cf91b 100644 --- a/gfx/thebes/public/Makefile.in +++ b/gfx/thebes/public/Makefile.in @@ -8,10 +8,13 @@ include $(DEPTH)/config/autoconf.mk MODULE = thebes +REQUIRES = cairo + EXPORTS = gfxASurface.h \ gfxColor.h \ gfxContext.h \ gfxFilter.h \ + gfxFont.h \ gfxImageSurface.h \ gfxMatrix.h \ gfxPattern.h \ @@ -22,16 +25,26 @@ EXPORTS = gfxASurface.h \ gfxTypes.h \ $(NULL) +ifdef MOZ_ENABLE_GLITZ +REQUIRES += glitz +EXPORTS += gfxGlitzSurface.h +endif + ifeq ($(MOZ_GFX_TOOLKIT),windows) -EXPORTS += gfxWindowsSurface.h +EXPORTS += gfxWindowsFonts.h \ + gfxWindowsSurface.h + +ifdef MOZ_ENABLE_GLITZ +REQUIRES += glitzwgl +endif endif ifeq ($(MOZ_GFX_TOOLKIT),gtk2) EXPORTS += gfxXlibSurface.h -endif ifdef MOZ_ENABLE_GLITZ -EXPORTS += gfxGlitzSurface.h +REQUIRES += glitzglx +endif endif include $(topsrcdir)/config/rules.mk diff --git a/gfx/thebes/public/gfxASurface.h b/gfx/thebes/public/gfxASurface.h index 20b30d4cefe..4f3c660e8c2 100644 --- a/gfx/thebes/public/gfxASurface.h +++ b/gfx/thebes/public/gfxASurface.h @@ -41,12 +41,13 @@ #include #include "gfxTypes.h" +#include "gfxRect.h" /** * A surface is something you can draw on. Instantiate a subclass of this * abstract class, and use gfxContext to draw on this surface. */ -class gfxASurface { +class NS_EXPORT gfxASurface { THEBES_DECL_REFCOUNTING_ABSTRACT public: @@ -64,6 +65,14 @@ public: /*** this DOES NOT addref the surface */ cairo_surface_t* CairoSurface() { return mSurface; } + void Flush() { cairo_surface_flush(mSurface); } + void MarkDirty() { cairo_surface_mark_dirty(mSurface); } + void MarkDirty(const gfxRect& r) { + cairo_surface_mark_dirty_rectangle(mSurface, + (int) r.pos.x, (int) r.pos.y, + (int) r.size.width, (int) r.size.height); + } + protected: void Init(cairo_surface_t* surface) { mDestroyed = PR_FALSE; diff --git a/gfx/thebes/public/gfxColor.h b/gfx/thebes/public/gfxColor.h index 24d9ba6d910..800bbd6ba8f 100644 --- a/gfx/thebes/public/gfxColor.h +++ b/gfx/thebes/public/gfxColor.h @@ -49,7 +49,7 @@ * XXX should this use doubles (instead of gfxFloat), for consistency with * cairo? */ -struct gfxRGBA { +struct NS_EXPORT gfxRGBA { gfxFloat r, g, b, a; gfxRGBA() { } diff --git a/gfx/thebes/public/gfxContext.h b/gfx/thebes/public/gfxContext.h index 2384fad51bc..98da7f3cd8c 100644 --- a/gfx/thebes/public/gfxContext.h +++ b/gfx/thebes/public/gfxContext.h @@ -64,7 +64,7 @@ class gfxTextRun; * When a path is drawn (stroked or filled), it is filled/stroked with a * pattern set by SetPattern, SetColor or SetSource. */ -class gfxContext { +class NS_EXPORT gfxContext { THEBES_DECL_REFCOUNTING public: @@ -74,8 +74,22 @@ public: gfxContext(gfxASurface *surface); ~gfxContext(); - // this does not addref + /** + * Return the current target surface + */ gfxASurface* CurrentSurface(); + + /** + * Set a new surface to render to; the previous + * surface is lost, but the current graphics state + * is maintained. + */ + void SetTarget(gfxASurface *surface); + + /** + * Return the raw cairo_t object. + * XXX this should go away at some point. + */ cairo_t* GetCairo() { return mCairo; } /** diff --git a/gfx/thebes/public/gfxFilter.h b/gfx/thebes/public/gfxFilter.h index d08222f5b70..79ed098b465 100644 --- a/gfx/thebes/public/gfxFilter.h +++ b/gfx/thebes/public/gfxFilter.h @@ -45,7 +45,7 @@ * * @see gfxContext::PushFilter, gfxContext::PopFilter */ -class gfxFilter { +class NS_EXPORT gfxFilter { static gfxFilter* CreateOpacityFilter(gfxFloat alpha); // CreateGaussianFilter, etc }; diff --git a/gfx/thebes/public/gfxGlitzSurface.h b/gfx/thebes/public/gfxGlitzSurface.h index 57c3d119f73..e30f47c6940 100644 --- a/gfx/thebes/public/gfxGlitzSurface.h +++ b/gfx/thebes/public/gfxGlitzSurface.h @@ -45,7 +45,7 @@ /** * A surface that wraps a glitz surface. */ -class gfxGlitzSurface : public gfxASurface { +class NS_EXPORT gfxGlitzSurface : public gfxASurface { THEBES_DECL_ISUPPORTS_INHERITED public: diff --git a/gfx/thebes/public/gfxImageSurface.h b/gfx/thebes/public/gfxImageSurface.h index fc5bd45a58c..3e544c78848 100644 --- a/gfx/thebes/public/gfxImageSurface.h +++ b/gfx/thebes/public/gfxImageSurface.h @@ -48,7 +48,7 @@ * purpose is for storing read-only images and using it as a source surface, * but it can also be drawn to. */ -class gfxImageSurface : public gfxASurface { +class NS_EXPORT gfxImageSurface : public gfxASurface { THEBES_DECL_ISUPPORTS_INHERITED public: diff --git a/gfx/thebes/public/gfxMatrix.h b/gfx/thebes/public/gfxMatrix.h index 87c552deefc..e9d54ce8859 100644 --- a/gfx/thebes/public/gfxMatrix.h +++ b/gfx/thebes/public/gfxMatrix.h @@ -64,7 +64,7 @@ * \ tx ty 1 / \ 1 / * */ -class gfxMatrix { +class NS_EXPORT gfxMatrix { protected: cairo_matrix_t mat; @@ -217,11 +217,6 @@ public: return ret; } - // XXX this is wrong and should go away - gfxSize GetScaling() const { - return gfxSize(mat.xx, mat.yy); - } - /** * Returns the translation component of this matrix. */ @@ -229,9 +224,13 @@ public: return gfxPoint(mat.x0, mat.y0); } - // XXX this is wrong and should go away - bool HasShear() const { - return ((mat.xy != 0.0) || (mat.yx != 0.0)); + /** + * Returns true if the matrix has any transform other + * than a straight translation + */ + bool HasNonTranslation() const { + return ((mat.xx != 1.0) || (mat.yy != 1.0) || + (mat.xy != 0.0) || (mat.yx != 0.0)); } }; diff --git a/gfx/thebes/public/gfxPattern.h b/gfx/thebes/public/gfxPattern.h index d05491c6f90..b3244059009 100644 --- a/gfx/thebes/public/gfxPattern.h +++ b/gfx/thebes/public/gfxPattern.h @@ -45,7 +45,7 @@ #include "gfxMatrix.h" #include "gfxTypes.h" -class gfxPattern { +class NS_EXPORT gfxPattern { THEBES_DECL_REFCOUNTING public: diff --git a/gfx/thebes/public/gfxPoint.h b/gfx/thebes/public/gfxPoint.h index d65d0f5694d..4710e1aaa8a 100644 --- a/gfx/thebes/public/gfxPoint.h +++ b/gfx/thebes/public/gfxPoint.h @@ -42,7 +42,7 @@ #include "gfxTypes.h" -struct gfxSize { +struct NS_EXPORT gfxSize { gfxFloat width, height; gfxSize() {} @@ -65,7 +65,7 @@ struct gfxSize { } }; -struct gfxPoint { +struct NS_EXPORT gfxPoint { gfxFloat x, y; gfxPoint() { } diff --git a/gfx/thebes/public/gfxRect.h b/gfx/thebes/public/gfxRect.h index acb76ac7858..48f327ab172 100644 --- a/gfx/thebes/public/gfxRect.h +++ b/gfx/thebes/public/gfxRect.h @@ -41,7 +41,7 @@ #include "gfxTypes.h" #include "gfxPoint.h" -struct gfxRect { +struct NS_EXPORT gfxRect { // pt? point? gfxPoint pos; gfxSize size; diff --git a/gfx/thebes/public/gfxRegion.h b/gfx/thebes/public/gfxRegion.h index 8261f30c45a..6916d3ba394 100644 --- a/gfx/thebes/public/gfxRegion.h +++ b/gfx/thebes/public/gfxRegion.h @@ -41,7 +41,7 @@ * ********************************************************* */ -class gfxRegion { +class NS_EXPORT gfxRegion { public: gfxRegion(const gfxRegion& r); gfxRegion(const gfxRect& r); diff --git a/gfx/thebes/public/gfxTextRun.h b/gfx/thebes/public/gfxTextRun.h index 6e9cecc3c71..e69de29bb2d 100644 --- a/gfx/thebes/public/gfxTextRun.h +++ b/gfx/thebes/public/gfxTextRun.h @@ -1,72 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Oracle Corporation code. - * - * The Initial Developer of the Original Code is Oracle Corporation. - * Portions created by the Initial Developer are Copyright (C) 2005 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Stuart Parmenter - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef GFX_TEXTRUN_H -#define GFX_TEXTRUN_H - -#include "prtypes.h" -#include "gfxTypes.h" - -class nsIFontMetrics; -class nsIAtom; - -class gfxTextRun { - // these do not copy the text - gfxTextRun(const char* ASCII, int length, nsIFontMetrics* font, nsIAtom* language); - gfxTextRun(const PRUnichar* unicode, int length, nsIFontMetrics* font, nsIAtom* language); - - enum { ClusterStart = 0x1 } CharFlags; - // ClusterStart: character is the first character of a cluster/glyph - void GetCharacterFlags(int pos, int len, CharFlags* flags); - - struct Dimensions { - gfxFloat ascent, descent, width, leftBearing, rightBearing; - }; - Dimensions MeasureText(int pos, int len); - - // Compute how many characters from this string starting at - // character 'pos' and up to length 'len' fit - // into the given width. 'breakflags' indicates our - // preferences about where we allow breaks. - // We will usually want to call MeasureText right afterwards, - // the implementor could optimize for that. - int GetCharsFit(int pos, int len, gfxFloat width, int breakflags); - - int GetPositionInString(gfxPoint& pt); -}; - -#endif diff --git a/gfx/thebes/public/gfxWindowsSurface.h b/gfx/thebes/public/gfxWindowsSurface.h index c798549ab80..f3c09b57734 100644 --- a/gfx/thebes/public/gfxWindowsSurface.h +++ b/gfx/thebes/public/gfxWindowsSurface.h @@ -42,7 +42,7 @@ #include -class gfxWindowsSurface : public gfxASurface { +class NS_EXPORT gfxWindowsSurface : public gfxASurface { THEBES_DECL_ISUPPORTS_INHERITED public: diff --git a/gfx/thebes/public/gfxXlibSurface.h b/gfx/thebes/public/gfxXlibSurface.h index 990a66137c1..7f92fb85f9b 100644 --- a/gfx/thebes/public/gfxXlibSurface.h +++ b/gfx/thebes/public/gfxXlibSurface.h @@ -44,7 +44,7 @@ #include #include -class gfxXlibSurface : public gfxASurface { +class NS_EXPORT gfxXlibSurface : public gfxASurface { THEBES_DECL_ISUPPORTS_INHERITED public: @@ -77,9 +77,14 @@ public: static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format); -protected: - PRBool mOwnsPixmap; + // take ownership of a passed-in Pixmap, calling XFreePixmap on it + // when the gfxXlibSurface is destroyed. + void TakePixmap(); +protected: + // if TakePixmap() was already called on this + PRBool mPixmapTaken; + Display *mDisplay; Drawable mDrawable; diff --git a/gfx/thebes/src/Makefile.in b/gfx/thebes/src/Makefile.in index 2294ca05596..65025e06a40 100644 --- a/gfx/thebes/src/Makefile.in +++ b/gfx/thebes/src/Makefile.in @@ -24,8 +24,19 @@ CPPSRCS = \ $(NULL) +SHARED_LIBRARY_LIBS += \ + $(DIST)/lib/$(LIB_PREFIX)mozcairo.$(LIB_SUFFIX) \ + $(DIST)/lib/$(LIB_PREFIX)mozlibpixman.$(LIB_SUFFIX) \ + $(NULL) + +EXTRA_DSO_LDOPTS += \ + $(NSPR_LIBS) \ + $(XPCOM_LIBS) + + ifeq ($(MOZ_GFX_TOOLKIT),windows) -CPPSRCS += gfxWindowsSurface.cpp +CPPSRCS += gfxWindowsFonts.cpp \ + gfxWindowsSurface.cpp endif ifeq ($(MOZ_GFX_TOOLKIT),gtk2) @@ -36,14 +47,25 @@ ifdef MOZ_ENABLE_GLITZ REQUIRES += glitz CPPSRCS += gfxGlitzSurface.cpp +SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitz.$(LIB_SUFFIX) + ifeq ($(MOZ_GFX_TOOLKIT),gtk2) REQUIRES += glitzglx +SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)mozglitzglx.$(LIB_SUFFIX) endif endif -FORCE_STATIC_LIB = 1 -# This library is used by other shared libs in a static build -FORCE_USE_PIC = 1 +#FORCE_STATIC_LIB = 1 +## This library is used by other shared libs in a static build +#FORCE_USE_PIC = 1 + +# Force use of PIC +FORCE_USE_PIC = 1 + +ifndef MOZ_ENABLE_LIBXUL +FORCE_SHARED_LIB = 1 +endif + include $(topsrcdir)/config/rules.mk diff --git a/gfx/thebes/src/gfxContext.cpp b/gfx/thebes/src/gfxContext.cpp index be4d95245bc..9ae5cf74cee 100644 --- a/gfx/thebes/src/gfxContext.cpp +++ b/gfx/thebes/src/gfxContext.cpp @@ -66,6 +66,12 @@ gfxASurface *gfxContext::CurrentSurface() return mSurface; } +void gfxContext::SetTarget(gfxASurface *target) +{ + cairo_set_target (mCairo, target->CairoSurface()); + mSurface = target; +} + void gfxContext::Save() { cairo_save(mCairo); diff --git a/gfx/thebes/src/gfxWindowsSurface.cpp b/gfx/thebes/src/gfxWindowsSurface.cpp index ce02b2d0baa..39ecc2095e8 100644 --- a/gfx/thebes/src/gfxWindowsSurface.cpp +++ b/gfx/thebes/src/gfxWindowsSurface.cpp @@ -50,23 +50,15 @@ gfxWindowsSurface::gfxWindowsSurface(HDC dc, unsigned long width, unsigned long { mDC = CreateCompatibleDC(dc); - HBITMAP tbits = nsnull; - - if (width > 0 && height > 0) - tbits = CreateCompatibleBitmap(dc, width, height); - else - tbits = CreateCompatibleBitmap(dc, 2, 2); + // Creating with width or height of 0 will create a + // 1x1 monotone bitmap, which isn't what we want + HBITMAP tbits = CreateCompatibleBitmap(dc, PR_MAX(2, width), PR_MAX(2, height)); mOrigBitmap = (HBITMAP)SelectObject(mDC, tbits); Init(cairo_win32_surface_create(mDC)); } -gfxWindowsSurface::gfxWindowsSurface(unsigned long width, unsigned long height) -{ - // Init(cairo_win32_surface_create(dc)); -} - gfxWindowsSurface::~gfxWindowsSurface() { Destroy(); diff --git a/gfx/thebes/src/gfxXlibSurface.cpp b/gfx/thebes/src/gfxXlibSurface.cpp index 6cf451e7986..6985d8f20b5 100644 --- a/gfx/thebes/src/gfxXlibSurface.cpp +++ b/gfx/thebes/src/gfxXlibSurface.cpp @@ -39,10 +39,19 @@ #include #include "gfxXlibSurface.h" +static cairo_user_data_key_t pixmap_free_key; + +typedef struct { + Display* dpy; + Pixmap pixmap; +} pixmap_free_struct; + +static void pixmap_free_func (void *); + THEBES_IMPL_REFCOUNTING(gfxXlibSurface) gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual) - : mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable) + : mPixmapTaken(PR_FALSE), mDisplay(dpy), mDrawable(drawable) { // figure out width/height/depth Window root_ignore; @@ -64,14 +73,14 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual) gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual, unsigned long width, unsigned long height) - : mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable), mWidth(width), mHeight(height) + : mPixmapTaken(PR_FALSE), mDisplay(dpy), mDrawable(drawable), mWidth(width), mHeight(height) { cairo_surface_t *surf = cairo_xlib_surface_create(dpy, drawable, visual, width, height); Init(surf); } gfxXlibSurface::gfxXlibSurface(Display* dpy, Visual* visual, unsigned long width, unsigned long height) - : mOwnsPixmap(PR_TRUE), mDisplay(dpy), mWidth(width), mHeight(height) + : mPixmapTaken(PR_FALSE), mDisplay(dpy), mWidth(width), mHeight(height) { mDrawable = (Drawable)XCreatePixmap(dpy, @@ -80,12 +89,14 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Visual* visual, unsigned long width DefaultDepth(dpy, DefaultScreen(dpy))); cairo_surface_t *surf = cairo_xlib_surface_create(dpy, mDrawable, visual, width, height); + Init(surf); + TakePixmap(); } gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, XRenderPictFormat *format, unsigned long width, unsigned long height) - : mOwnsPixmap(PR_FALSE), mDisplay(dpy), mDrawable(drawable), + : mPixmapTaken(PR_FALSE), mDisplay(dpy), mDrawable(drawable), mWidth(width), mHeight(height) { cairo_surface_t *surf = cairo_xlib_surface_create_with_xrender_format (dpy, drawable, @@ -96,7 +107,7 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, XRenderPictForma gfxXlibSurface::gfxXlibSurface(Display* dpy, XRenderPictFormat *format, unsigned long width, unsigned long height) - : mOwnsPixmap(PR_TRUE), mDisplay(dpy), mWidth(width), mHeight(height) + : mPixmapTaken(PR_FALSE), mDisplay(dpy), mWidth(width), mHeight(height) { mDrawable = (Drawable)XCreatePixmap(dpy, RootWindow(dpy, DefaultScreen(dpy)), @@ -107,14 +118,13 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, XRenderPictFormat *format, ScreenOfDisplay(dpy,DefaultScreen(dpy)), format, width, height); Init(surf); + TakePixmap(); } gfxXlibSurface::~gfxXlibSurface() { + //fprintf (stderr, "Destroying xlib surface %p (drawable %d)\n", this, mDrawable); Destroy(); - - if (mOwnsPixmap) - XFreePixmap(mDisplay, mDrawable); } XRenderPictFormat* @@ -137,3 +147,32 @@ gfxXlibSurface::FindRenderFormat(Display *dpy, gfxImageFormat format) return (XRenderPictFormat*)NULL; } + +void +gfxXlibSurface::TakePixmap() +{ + if (mPixmapTaken) + return; + + pixmap_free_struct *pfs = new pixmap_free_struct; + pfs->dpy = mDisplay; + pfs->pixmap = mDrawable; + + cairo_surface_set_user_data (CairoSurface(), + &pixmap_free_key, + pfs, + pixmap_free_func); + + mPixmapTaken = PR_TRUE; +} + +void +pixmap_free_func (void *data) +{ + pixmap_free_struct *pfs = (pixmap_free_struct*) data; + + //fprintf (stderr, "freeing pixmap %d\n", pfs->pixmap); + XFreePixmap (pfs->dpy, pfs->pixmap); + + delete pfs; +} diff --git a/widget/src/build/Makefile.in b/widget/src/build/Makefile.in index 8c62be6a1a4..ff25a8b01de 100644 --- a/widget/src/build/Makefile.in +++ b/widget/src/build/Makefile.in @@ -83,6 +83,10 @@ SHARED_LIBRARY_LIBS = \ $(DIST)/lib/$(LIB_PREFIX)xpwidgets_s.$(LIB_SUFFIX) \ $(NULL) +ifdef MOZ_ENABLE_CAIRO_GFX +SHARED_LIBRARY_LIBS += $(DIST)/lib/$(LIB_PREFIX)thebes.$(LIB_SUFFIX) +endif + EXTRA_DSO_LDOPTS = \ $(LIBS_DIR) \ $(EXTRA_DSO_LIBS) \ diff --git a/widget/src/gtk2/Makefile.in b/widget/src/gtk2/Makefile.in index 705a4ea958f..9ad6e274c1b 100644 --- a/widget/src/gtk2/Makefile.in +++ b/widget/src/gtk2/Makefile.in @@ -73,7 +73,6 @@ REQUIRES = xpcom \ ifeq ($(MOZ_ENABLE_CAIRO_GFX),1) REQUIRES += thebes cairo -EXTRA_DSO_LDOPTS += -lthebes $(MOZ_CAIRO_LIBS) endif CSRCS = \ @@ -113,6 +112,10 @@ EXTRA_DSO_LDOPTS += \ $(XLIBS) \ $(MOZ_GTK2_LIBS) +ifeq ($(MOZ_ENABLE_CAIRO_GFX),1) +EXTRA_DSO_LDOPTS += -lthebes +endif + EXPORTS = \ nsIGdkPixbufImage.h \ mozdrawingarea.h \ @@ -132,7 +135,7 @@ CXXFLAGS += $(MOZ_GTK2_CFLAGS) DEFINES += -DUSE_XIM -ifeq ($(MOZ_ENABLE_CAIRO_GFX),1) +ifdef MOZ_ENABLE_CAIRO_GFX DEFINES += -DCAIRO_GFX endif diff --git a/widget/src/gtk2/nsNativeThemeGTK.cpp b/widget/src/gtk2/nsNativeThemeGTK.cpp index bf35490080c..afd8ec707bc 100644 --- a/widget/src/gtk2/nsNativeThemeGTK.cpp +++ b/widget/src/gtk2/nsNativeThemeGTK.cpp @@ -61,6 +61,10 @@ #include +#ifdef MOZ_CAIRO_GFX +#include "gfxContext.h" +#endif + NS_IMPL_ISUPPORTS2(nsNativeThemeGTK, nsITheme, nsIObserver) static int gLastXError; @@ -426,6 +430,7 @@ nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext, &flags)) return NS_OK; +#ifndef MOZ_CAIRO_GFX GdkWindow* window = NS_STATIC_CAST(GdkWindow*, aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE)); @@ -473,6 +478,153 @@ nsNativeThemeGTK::DrawWidgetBackground(nsIRenderingContext* aContext, SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state); } } +#else + // Thebes gfx rendering; if we can get a GdkWindow and if we don't have any transform + // other than a translation, then just render directly. Otherwise, we can't do + // native themes yet, until we figure out how to intercept gtk rendering + + nsRefPtr ctx = (gfxContext*) aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + + nsIDeviceContext *dctx = nsnull; + aContext->GetDeviceContext(dctx); + double t2p = dctx->AppUnitsToDevUnits(); + + GdkRectangle gdk_rect = { aRect.x * t2p, + aRect.y * t2p, + aRect.width * t2p, + aRect.height * t2p }; + GdkRectangle gdk_clip = { aClipRect.x * t2p, + aClipRect.y * t2p, + aClipRect.width * t2p, + aClipRect.height * t2p }; + + GdkWindow *gdkwin = (GdkWindow*) aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE); + GdkDrawable *target_drawable = nsnull; + PRBool needs_thebes_composite = PR_FALSE; + + if (gdkwin && !ctx->CurrentMatrix().HasNonTranslation()) { + // we can draw straight to the gdkwin drawable; need to offset gdk_rect/gdk_clip + // by the current translation + target_drawable = gdkwin; + + gfxPoint t = ctx->CurrentMatrix().GetTranslation(); + gdk_rect.x += t.x; + gdk_rect.y += t.y; + gdk_clip.x += t.x; + gdk_clip.y += t.y; + + ctx->CurrentSurface()->Flush(); + } else { + // we can't draw directly to the gdkwin drawable because we're being transformed; + // so draw to our temporary pixmap and composite + + // .. except that we can't draw to the temporary pixmap just yet, so bail + SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType); + RefreshWidgetWindow(aFrame); + return NS_OK; + +#if 0 + PRUint32 maxsz = ((PRUint32)(aRect.width < aRect.height ? (aRect.height * t2p) : (aRect.width * t2p))) + 1; + + if (mGdkPixmapSize < maxsz) { + if (mGdkPixmap) { + mThebesSurface = nsnull; + g_object_unref(mGdkPixmap); + mGdkPixmap = nsnull; + } + + fprintf (stderr, "maxsz: %d\n", maxsz); + mGdkPixmap = gdk_pixmap_new (gdk_get_default_root_window(), + maxsz, + maxsz, + 32); + + mThebesSurface = new gfxXlibSurface (gdk_x11_get_default_xdisplay(), + GDK_PIXMAP_XID(mGdkPixmap), + gfxXlibSurface::FindRenderFormat(gdk_x11_get_default_xdisplay(), + gfxASurface::ImageFormatARGB32), + maxsz, maxsz); + + mGdkPixmapSize = maxsz; + } + + nsRefPtr gdkCtx = new gfxContext(mThebesSurface); + gdkCtx->SetOperator(gfxContext::OPERATOR_CLEAR); + gdkCtx->Paint(); + + target_drawable = mGdkPixmap; + needs_thebes_composite = PR_TRUE; +#endif + } + + if (gdk_clip.x < 0) { + gdk_clip.width += gdk_clip.x; + gdk_clip.x = 0; + } + + if (gdk_clip.y < 0) { + gdk_clip.height += gdk_clip.y; + gdk_clip.y = 0; + } + + if (gdk_clip.width < 0 || gdk_clip.height < 0) + return NS_OK; + + NS_ASSERTION(!IsWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType), + "Trying to render an unsafe widget!"); + + PRBool safeState = IsWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state); + XErrorHandler oldHandler = nsnull; + if (!safeState) { + gLastXError = 0; + oldHandler = XSetErrorHandler(NativeThemeErrorHandler); + } + + + moz_gtk_widget_paint(gtkWidgetType, target_drawable, &gdk_rect, &gdk_clip, &state, + flags); + + + if (!safeState) { + gdk_flush(); + XSetErrorHandler(oldHandler); + + if (gLastXError) { +#ifdef DEBUG + printf("GTK theme failed for widget type %d, error was %d, state was " + "[active=%d,focused=%d,inHover=%d,disabled=%Id]\n", + aWidgetType, gLastXError, state.active, state.focused, + state.inHover, state.disabled); +#endif + NS_WARNING("GTK theme failed; disabling unsafe widget"); + SetWidgetTypeDisabled(mDisabledWidgetTypes, aWidgetType); + // force refresh of the window, because the widget was not + // successfully drawn it must be redrawn using the default look + RefreshWidgetWindow(aFrame); + } else { + SetWidgetStateSafe(mSafeWidgetStates, aWidgetType, &state); + } + } + + if (needs_thebes_composite) { +#if 0 + ctx->Save(); + ctx->NewPath(); + ctx->Translate(gfxPoint(aRect.x * t2p, + aRect.y * t2p)); + nsRefPtr pat = new gfxPattern(mThebesSurface); + + ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, + aRect.width * t2p, + aRect.height * t2p), + pat); + ctx->Fill(); + ctx->Restore(); +#endif + } else { + ctx->CurrentSurface()->MarkDirty(); + } +#endif /* MOZ_CAIRO_GFX */ return NS_OK; } diff --git a/widget/src/gtkxtbin/gtk2xtbin.c b/widget/src/gtkxtbin/gtk2xtbin.c index 8186917ebbe..580628d0cd1 100644 --- a/widget/src/gtkxtbin/gtk2xtbin.c +++ b/widget/src/gtkxtbin/gtk2xtbin.c @@ -323,10 +323,17 @@ gtk_xtbin_new (GdkWindow *parent_window, String * f) /* Initialize the Xt toolkit */ xtbin->parent_window = parent_window; +#ifndef MOZ_CAIRO_GFX xt_client_init(&(xtbin->xtclient), GDK_VISUAL_XVISUAL(gdk_window_get_visual(parent_window )), GDK_COLORMAP_XCOLORMAP(gdk_window_get_colormap(parent_window)), gdk_window_get_visual(parent_window )->depth); +#else + xt_client_init(&(xtbin->xtclient), + GDK_VISUAL_XVISUAL(gdk_rgb_get_visual()), + GDK_COLORMAP_XCOLORMAP(gdk_rgb_get_colormap()), + gdk_rgb_get_visual()->depth); +#endif if (!xtbin->xtclient.xtdisplay) { /* If XtOpenDisplay failed, we can't go any further. diff --git a/widget/src/windows/Makefile.in b/widget/src/windows/Makefile.in index b8024ec800c..9c1cac4f313 100644 --- a/widget/src/windows/Makefile.in +++ b/widget/src/windows/Makefile.in @@ -69,6 +69,10 @@ REQUIRES = xpcom \ imglib2 \ $(NULL) +ifdef MOZ_ENABLE_CAIRO_GFX +REQUIRES += thebes cairo +endif + CPPSRCS = \ L_Ienumfe.cpp \ nsWindow.cpp \ @@ -117,11 +121,6 @@ endif include $(topsrcdir)/config/rules.mk - -ifeq ($(MOZ_ENABLE_CAIRO_GFX),1) -DEFINES += -DCAIRO_GFX -endif - # Silly case-insensitive fs export:: IENUMFE.CPP cp -a $< L_Ienumfe.cpp diff --git a/widget/src/windows/nsNativeThemeWin.cpp b/widget/src/windows/nsNativeThemeWin.cpp index c7dc90961fe..8b597fdbf1f 100644 --- a/widget/src/windows/nsNativeThemeWin.cpp +++ b/widget/src/windows/nsNativeThemeWin.cpp @@ -56,6 +56,10 @@ #include "nsIMenuFrame.h" #include +#ifdef MOZ_CAIRO_GFX +#include "gfxContext.h" +#include "gfxMatrix.h" +#endif /* * The following constants are used to determine how a widget is drawn using * Windows' Theme API. For more information on theme parts and states see @@ -684,7 +688,7 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, nsRect tr(aRect); nsRect cr(aClipRect); transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height); -#ifdef MOZ_THEBES +#ifdef MOZ_CAIRO_GFX tr.x = NSToCoordRound(tr.x * T2P); tr.y = NSToCoordRound(tr.y * T2P); tr.width = NSToCoordRound(tr.width * T2P); @@ -692,7 +696,7 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, #endif GetNativeRect(tr, widgetRect); transformMatrix->TransformCoord(&cr.x,&cr.y,&cr.width,&cr.height); -#ifdef MOZ_THEBES +#ifdef MOZ_CAIRO_GFX cr.x = NSToCoordRound(cr.x * T2P); cr.y = NSToCoordRound(cr.y * T2P); cr.width = NSToCoordRound(cr.width * T2P); @@ -702,7 +706,27 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC); if (!hdc) return NS_ERROR_FAILURE; - + + SaveDC(hdc); + SetGraphicsMode(hdc, GM_ADVANCED); + +#ifdef MOZ_CAIRO_GFX +#if 0 + gfxContext *c = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + gfxMatrix m = c->CurrentMatrix(); + XFORM xform; + double dm[6]; + m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]); + xform.eM11 = dm[0]; + xform.eM21 = dm[1]; + xform.eM12 = dm[2]; + xform.eM22 = dm[3]; + xform.eDx = dm[4]; + xform.eDy = dm[5]; + SetWorldTransform (hdc, &xform); +#endif +#endif + // For left edge and right edge tabs, we need to adjust the widget // rects and clip rects so that the edges don't get drawn. if (aWidgetType == NS_THEME_TAB_LEFT_EDGE || aWidgetType == NS_THEME_TAB_RIGHT_EDGE) { @@ -741,6 +765,9 @@ nsNativeThemeWin::DrawWidgetBackground(nsIRenderingContext* aContext, ::SetTextColor(hdc, oldColor); } } + + RestoreDC(hdc, -1); + return NS_OK; } @@ -1519,7 +1546,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon RECT widgetRect; nsRect tr(aRect); transformMatrix->TransformCoord(&tr.x,&tr.y,&tr.width,&tr.height); -#ifdef MOZ_THEBES +#ifdef MOZ_CAIRO_GFX tr.x = NSToCoordRound(tr.x * T2P); tr.y = NSToCoordRound(tr.y * T2P); tr.width = NSToCoordRound(tr.width * T2P); @@ -1529,6 +1556,27 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon HDC hdc = (HDC)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC); + SaveDC(hdc); + +#ifdef MOZ_CAIRO_GFX +#if 0 + SetGraphicsMode(hdc, GM_ADVANCED); + + gfxContext *c = (gfxContext*)aContext->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT); + gfxMatrix m = c->CurrentMatrix(); + XFORM xform; + double dm[6]; + m.ToValues(&dm[0], &dm[1], &dm[2], &dm[3], &dm[4], &dm[5]); + xform.eM11 = dm[0]; + xform.eM21 = dm[1]; + xform.eM12 = dm[2]; + xform.eM22 = dm[3]; + xform.eDx = dm[4]; + xform.eDy = dm[5]; + SetWorldTransform (hdc, &xform); +#endif +#endif + switch (aWidgetType) { // Draw button case NS_THEME_BUTTON: { @@ -1570,7 +1618,7 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon ::DrawFocusRect(hdc, &widgetRect); ::SetTextColor(hdc, oldColor); } - + RestoreDC(hdc, -1); return NS_OK; } // Draw controls with 2px 3D inset border @@ -1588,6 +1636,8 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1)); else ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1)); + + RestoreDC(hdc, -1); return NS_OK; } case NS_THEME_TREEVIEW: { @@ -1596,7 +1646,8 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon // Fill in window color background ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_WINDOW+1)); - + + RestoreDC(hdc, -1); return NS_OK; } // Draw ToolTip background @@ -1607,6 +1658,8 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon ::FrameRect(hdc, &widgetRect, brush); InflateRect(&widgetRect, -1, -1); ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_INFOBK+1)); + + RestoreDC(hdc, -1); return NS_OK; // Draw 3D face background controls case NS_THEME_PROGRESSBAR: @@ -1619,6 +1672,8 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon case NS_THEME_STATUSBAR: case NS_THEME_STATUSBAR_RESIZER_PANEL: { ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_BTNFACE+1)); + + RestoreDC(hdc, -1); return NS_OK; } // Draw 3D inset statusbar panel @@ -1627,12 +1682,16 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon widgetRect.right -= 2; // space between sibling status panels ::DrawEdge(hdc, &widgetRect, BDR_SUNKENOUTER, BF_RECT | BF_MIDDLE); + + RestoreDC(hdc, -1); return NS_OK; } // Draw scrollbar thumb case NS_THEME_SCROLLBAR_THUMB_VERTICAL: case NS_THEME_SCROLLBAR_THUMB_HORIZONTAL: ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_RECT | BF_MIDDLE); + + RestoreDC(hdc, -1); return NS_OK; // Draw scrollbar track background case NS_THEME_SCROLLBAR_TRACK_VERTICAL: @@ -1687,11 +1746,15 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon } // XXX should invert the part of the track being clicked here // but the track is never :active + + RestoreDC(hdc, -1); return NS_OK; } case NS_THEME_PROGRESSBAR_CHUNK: case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL: ::FillRect(hdc, &widgetRect, (HBRUSH) (COLOR_HIGHLIGHT+1)); + + RestoreDC(hdc, -1); return NS_OK; // Draw Tab case NS_THEME_TAB: @@ -1703,14 +1766,18 @@ nsresult nsNativeThemeWin::ClassicDrawWidgetBackground(nsIRenderingContext* aCon aWidgetType != NS_THEME_TAB_RIGHT_EDGE, aWidgetType != NS_THEME_TAB_LEFT_EDGE); + RestoreDC(hdc, -1); return NS_OK; } case NS_THEME_TAB_PANELS: ::DrawEdge(hdc, &widgetRect, EDGE_RAISED, BF_SOFT | BF_MIDDLE | BF_LEFT | BF_RIGHT | BF_BOTTOM); + + RestoreDC(hdc, -1); return NS_OK; } + RestoreDC(hdc, -1); return NS_ERROR_FAILURE; } diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index c9025b5b1d4..90a8b2d50d4 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -92,7 +92,7 @@ #include "resource.h" #include #include "prtime.h" -#ifdef CAIRO_GFX +#ifdef MOZ_CAIRO_GFX #include "nsIThebesRenderingContext.h" #else #include "nsIRenderingContextWin.h" @@ -5530,7 +5530,7 @@ PRBool nsWindow::OnPaint(HDC aDC) if (NS_SUCCEEDED(CallCreateInstance(kRenderingContextCID, &event.renderingContext))) { -#ifdef CAIRO_GFX +#ifdef MOZ_CAIRO_GFX nsIThebesRenderingContext *winrc; #else nsIRenderingContextWin *winrc;