/clutter/clutter-version.h
/clutter/gcov-report.txt
/clutter/clutter-json.h
-/clutter/cogl/cogl/cogl-defines.h
-/clutter/cogl/cogl/cogl-enum-types.[ch]
-/clutter/cogl/cogl/driver/gl/cogl-defines.h
-/clutter/cogl/cogl/driver/gles/cogl-defines.h
-/clutter/cogl/cogl/cogl-fixed-vertex-shader.[ch]
-/clutter/cogl/cogl/cogl-fixed-fragment-shader.[ch]
/clutter/egl/clutter-cex100.h
/build/autotools/*.m4
-/clutter/cogl/build/autotools/*.m4
!/build/autotools/introspection.m4
!/build/autotools/as-linguas.m4
!/build/autotools/as-compiler-flag.m4
doc/reference/clutter/clutter-docs.xml
doc/reference/clutter/*.stamp
doc/reference/clutter/*.bak
-doc/reference/cogl/cogl-*.txt
-!/doc/reference/cogl/cogl-sections.txt
-doc/reference/cogl/html
-doc/reference/cogl/tmpl
-doc/reference/cogl/xml
-doc/reference/cogl/cogl.args
-doc/reference/cogl/cogl.hierarchy
-doc/reference/cogl/cogl.interfaces
-doc/reference/cogl/cogl.prerequisites
-doc/reference/cogl/cogl.signals
-doc/reference/cogl/cogl-docs.xml
-doc/reference/cogl/*.stamp
-doc/reference/cogl/*.bak
-doc/reference/cogl-2.0/cogl-*.txt
-!/doc/reference/cogl-2.0/cogl-sections.txt
-doc/reference/cogl-2.0/html
-doc/reference/cogl-2.0/tmpl
-doc/reference/cogl-2.0/xml
-doc/reference/cogl-2.0/cogl.args
-doc/reference/cogl-2.0/cogl.hierarchy
-doc/reference/cogl-2.0/cogl.interfaces
-doc/reference/cogl-2.0/cogl.prerequisites
-doc/reference/cogl-2.0/cogl.signals
-doc/reference/cogl-2.0/cogl-docs.xml
-doc/reference/cogl-2.0/*.stamp
-doc/reference/cogl-2.0/*.bak
doc/reference/cally/cally-*.txt
!/doc/reference/cally/cally-sections.txt
doc/reference/cally/html
/po/remove-potcdate.sin
/po/remove-potcdate.sed
/po/stamp-po
-/clutter/cogl/po/POTFILES
-/clutter/cogl/po/*.gmo
-/clutter/cogl/po/Makefile.in.in
-/clutter/cogl/po/Makevars.template
-/clutter/cogl/po/Rules-quot
-/clutter/cogl/po/boldquot.sed
-/clutter/cogl/po/en@boldquot.header
-/clutter/cogl/po/en@quot.header
-/clutter/cogl/po/insert-header.sin
-/clutter/cogl/po/quot.sed
-/clutter/cogl/po/remove-potcdate.sin
-/clutter/cogl/po/remove-potcdate.sed
-/clutter/cogl/po/stamp-po
*.swn
*.swo
*.swp
Clutter currently requires:
• GLib ≥ @GLIB_REQ_VERSION@
+ • Cogl ≥ @COGL_REQ_VERSION@
• JSON-GLib ≥ @JSON_GLIB_REQ_VERSION@
• Atk ≥ @ATK_REQ_VERSION@
• Cairo ≥ @CAIRO_REQ_VERSION@
• PangoCairo ≥ @PANGO_REQ_VERSION@
- • OpenGL ≥ 1.3 (or 1.2 + multitexturing), or OpenGL ES 2.0 (or 1.1)
- • GLX, AGL, WGL or an EGL implementation
Clutter also has optional dependencies:
debugging notes. Only use in extreme performance and/or size
optimization cases, though it is strongly discouraged.
- --enable-cogl-debug=[no/minimum/yes]
- Controls COGL debugging level (default=minimum):
-
- yes:
- Support for COGL debugging notes through COGL_DEBUG and
- error checking for each GL primitive. This is useful mostly
- to debug COGL itself.
-
- minimum:
- Support for COGL debugging notes through COGL_DEBUG. This is
- the default for developers snapshots.
-
- no:
- Disable support for COGL runtime debugging notes.
-
--enable-maintainer-flags=[no/yes/error]
Use strict compiler flags. This defaults to 'yes' for building from
Git to 'no' for tarball releases. If 'error' is used, then -Werror
win32:
Microsoft Windows(tm) WGL backend.
- --with-imagebackend=[gdk-pixbuf/quartz/internal]
- Select the image loading backend used by COGL
-
- gdk-pixbuf:
- Depend on gdk-pixbuf-2.0 (default for the glx, eglx,
- eglnative, win32 flavours and recommended).
-
- quartz:
- Depend on CoreGraphics (default for the osx flavour).
-
- internal:
- Internal JPEG and PNG loader. Should only be used
- for testing on new platforms
-
- --with-gles=[1.1/2.0]
- Select the GLES version (for EGL backends) (default=1.1)
-
See also the INSTALL file generated by autotools for further information.
VERSIONING
# preamble
NULL =
-# we recurse only into Cogl
-if !USE_SYSTEM_COGL
-SUBDIRS = cogl
-endif
-
# common definitions
CLEANFILES =
DISTCLEANFILES =
-I$(top_builddir)/clutter \
$(NULL)
-if !USE_SYSTEM_COGL
-INCLUDES += \
- -I$(top_srcdir)/clutter/cogl \
- -I$(top_srcdir)/clutter/cogl/pango \
- -I$(top_builddir)/clutter/cogl \
- $(NULL)
-endif
-
AM_CPPFLAGS = \
-DCLUTTER_PREFIX=\""$(prefix)"\" \
-DCLUTTER_LIBDIR=\""$(libdir)"\" \
libclutter_@CLUTTER_SONAME_INFIX@_@CLUTTER_API_VERSION@_la_DEPENDENCIES = \
$(win32_resources)
-if !USE_SYSTEM_COGL
-libclutter_@CLUTTER_SONAME_INFIX@_@CLUTTER_API_VERSION@_la_LIBADD += \
- $(top_builddir)/clutter/cogl/cogl/libcogl.la \
- $(top_builddir)/clutter/cogl/pango/libcoglpango.la
-libclutter_@CLUTTER_SONAME_INFIX@_@CLUTTER_API_VERSION@_la_DEPENDENCIES += \
- $(top_builddir)/clutter/cogl/cogl/libcogl.la \
- $(top_builddir)/clutter/cogl/pango/libcoglpango.la
-endif
-
libclutter_@CLUTTER_SONAME_INFIX@_@CLUTTER_API_VERSION@_la_SOURCES = \
$(backend_source_c) \
$(backend_source_h) \
$(CLUTTER_LT_LDFLAGS) \
$(GCOV_LDFLAGS) \
-export-dynamic \
- -export-symbols-regex "^(clutter|cogl|cally).*" \
+ -export-symbols-regex "^(clutter|cally).*" \
-rpath $(libdir) \
$(win32_resources_ldflag) \
$(NULL)
--warn-all \
--c-include='clutter/clutter.h' \
--pkg-export=clutter-@CLUTTER_API_VERSION@
-if USE_SYSTEM_COGL
Clutter_@CLUTTER_API_VERSION_AM@_gir_INCLUDES += Cogl-1.0
-else
-Clutter_@CLUTTER_API_VERSION_AM@_gir_LIBS += \
- $(top_builddir)/clutter/cogl/cogl/libcogl.la \
- $(top_builddir)/clutter/cogl/pango/libcoglpango.la
-Clutter_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS += \
- --include-uninstalled=$(top_builddir)/clutter/cogl/cogl/Cogl-1.0.gir
-COGL_GIR_DEP=Cogl-1.0.gir
-endif
-
-if !USE_SYSTEM_COGL
-# Cogl.gir is used included into Clutter.gir, so it needs to be built
-# before the typelib is generated
-Clutter-@CLUTTER_API_VERSION@.typelib: Cogl-1.0.gir
-
-# We build Cogl.gir in the cogl/ subdir, but it needs to reference the shared
-# library that it's built into, so we delay compiling the gir into typelib
-# until after we've built the shared library. To create the final Cogl.gir
-# that we compile and install, we transfer the shared-library="" line from
-# Clutter.gir to Cogl.gir
-Cogl-1.0.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir cogl/cogl/Cogl-1.0.gir
- $(QUIET_GEN) \
- shlib=`sed -n 's/.*shared-library="\([^"]*\)".*/\1/p' < Clutter-@CLUTTER_API_VERSION@.gir` ; \
- sed "s/shared-library=\"[^\"]*\"/shared-library=\"$$shlib\"/"< $(top_builddir)/clutter/cogl/cogl/Cogl-1.0.gir > $@
-
-BUILT_GIRSOURCES += Cogl-1.0.gir
-endif
-
-Cally-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir $(COGL_GIR_DEP)
+
+Cally-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir
Cally_@CLUTTER_API_VERSION_AM@_gir_NAMESPACE = Cally
Cally_@CLUTTER_API_VERSION_AM@_gir_VERSION = @CLUTTER_API_VERSION@
# Note: it's important to pass --include-uninstalled for the Cogl-1.0.gir
# before the Clutter gir otherwise g-ir-scanner can get upset as it
# immediatly scans the Clutter gir file and may fail to find a Cogl-1.0.gir
-if USE_SYSTEM_COGL
Cally_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS += \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir
-else
-Cally_@CLUTTER_API_VERSION_AM@_gir_LIBS += \
- $(top_builddir)/clutter/cogl/cogl/libcogl.la \
- $(top_builddir)/clutter/cogl/pango/libcoglpango.la
-Cally_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS += \
- --include-uninstalled=$(top_builddir)/clutter/Cogl-1.0.gir \
- --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir
-endif
INTROSPECTION_GIRS += Cally-@CLUTTER_API_VERSION@.gir
if SUPPORT_X11
-ClutterX11-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir $(COGL_GIR_DEP)
+ClutterX11-@CLUTTER_API_VERSION@.gir: Makefile Clutter-@CLUTTER_API_VERSION@.gir
ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS = \
--identifier-prefix=ClutterX11 \
# Note: it's important to pass --include-uninstalled for the Cogl-1.0.gir
# before the Clutter gir otherwise g-ir-scanner can get upset as it
# immediatly scans the Clutter gir file and may fail to find a Cogl-1.0.gir
-if USE_SYSTEM_COGL
-ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS += \
- --include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir
-else
ClutterX11_@CLUTTER_API_VERSION_AM@_gir_SCANNERFLAGS += \
- --include-uninstalled=$(top_builddir)/clutter/Cogl-1.0.gir \
--include-uninstalled=$(top_builddir)/clutter/Clutter-@CLUTTER_API_VERSION@.gir
-ClutterX11_@CLUTTER_API_VERSION_AM@_gir_LIBS += \
- $(top_builddir)/clutter/cogl/cogl/libcogl.la \
- $(top_builddir)/clutter/cogl/pango/libcoglpango.la
-endif
INTROSPECTION_GIRS += ClutterX11-@CLUTTER_API_VERSION@.gir
endif # SUPPORT_X11
#include "clutter-version.h" /* For flavour define */
#include <cogl/cogl.h>
-
-#ifdef CLUTTER_USING_SYSTEM_COGL
#include <cogl/cogl-pango.h>
-#else
-#include "pango/cogl-pango.h"
-#endif
#include "cally.h" /* For accessibility support */
#include <glib/gi18n-lib.h>
-#ifdef CLUTTER_USING_SYSTEM_COGL
#include <cogl/cogl-pango.h>
-#else
-#include "pango/cogl-pango.h"
-#endif
#include "clutter-backend.h"
#include "clutter-effect.h"
+++ /dev/null
-SUBDIRS = cogl pango
-
-if COGL_STANDALONE_BUILD
-SUBDIRS += po examples
-endif
-
-ACLOCAL_AMFLAGS = -I build/autotools ${ACLOCAL_FLAGS}
+++ /dev/null
-#!/bin/sh
-# Run this to generate all the initial makefiles, etc.
-
-srcdir=`dirname $0`
-test -z "$srcdir" && srcdir=.
-
-ORIGDIR=`pwd`
-
-cd $srcdir
-PROJECT=Cogl
-TEST_TYPE=-f
-FILE=cogl/cogl.h
-
-test $TEST_TYPE $FILE || {
- echo "You must run this script in the top-level $PROJECT directory"
- exit 1
-}
-
-if automake-1.11 --version < /dev/null > /dev/null 2>&1 ; then
- AUTOMAKE=automake-1.11
- ACLOCAL=aclocal-1.11
- export AUTOMAKE ACLOCAL
-else
- echo
- echo "You must have automake 1.11.x installed to compile $PROJECT
-ECT."
- echo "Install the appropriate package for your distribution,"
- echo "or get the source tarball at http://ftp.gnu.org/gnu/automake/"
- exit 1
-fi
-
-(gtkdocize --version) < /dev/null > /dev/null 2>&1 || {
- echo
- echo "You must have gtk-doc installed to compile $PROJECT."
- echo "Install the appropriate package for your distribution,"
- echo "or get the source tarball at http://ftp.gnome.org/pub/GNOME/sources/gtk-doc/"
- exit 1
-}
-
-# NOCONFIGURE is used by gnome-common
-if test -z "$NOCONFIGURE"; then
- if test -z "$*"; then
- echo "I am going to run ./configure with no arguments - if you wish "
- echo "to pass any to it, please specify them on the $0 command line."
- fi
-fi
-
-if test -z "$ACLOCAL_FLAGS"; then
- acdir=`$ACLOCAL --print-ac-dir`
- m4list="glib-2.0.m4"
- for file in $m4list; do
- if [ ! -f "$acdir/$file" ]; then
- echo "WARNING: aclocal's directory is $acdir, but..."
- echo " no file $acdir/$file"
- echo " You may see fatal macro warnings below."
- echo " If these files are installed in /some/dir, set the ACLOCAL_FLAGS "
- echo " environment variable to \"-I /some/dir\", or install"
- echo " $acdir/$file."
- echo ""
- fi
- done
-fi
-
-rm -rf autom4te.cache
-
-gtkdocize || exit $?
-autoreconf -vfi || exit $?
-cd $ORIGDIR || exit $?
-
-if test -z "$NOCONFIGURE"; then
- $srcdir/configure $AUTOGEN_CONFIGURE_ARGS "$@" || exit $?
- echo "Now type 'make' to compile $PROJECT."
-fi
+++ /dev/null
-# Rules for generating enumeration types using glib-mkenums
-#
-# Define:
-# glib_enum_h = header template file
-# glib_enum_c = source template file
-# glib_enum_headers = list of headers to parse
-#
-# before including Makefile.am.enums. You will also need to have
-# the following targets already defined:
-#
-# CLEANFILES
-# DISTCLEANFILES
-# BUILT_SOURCES
-# EXTRA_DIST
-#
-# Author: Emmanuele Bassi <ebassi@linux.intel.com>
-
-# Basic sanity checks
-$(if $(GLIB_MKENUMS),,$(error Need to define GLIB_MKENUMS))
-
-$(if $(or $(glib_enum_h), \
- $(glib_enum_c)),, \
- $(error Need to define glib_enum_h and glib_enum_c))
-
-$(if $(glib_enum_headers),,$(error Need to define glib_enum_headers))
-
-enum_tmpl_h=$(addprefix $(srcdir)/, $(glib_enum_h:.h=.h.in))
-enum_tmpl_c=$(addprefix $(srcdir)/, $(glib_enum_c:.c=.c.in))
-
-CLEANFILES += stamp-enum-types
-DISTCLEANFILES += $(glib_enum_h) $(glib_enum_c)
-BUILT_SOURCES += $(glib_enum_h) $(glib_enum_c)
-EXTRA_DIST += $(enum_tmpl_h) $(enum_tmpl_c)
-
-stamp-enum-types: $(glib_enum_headers) $(enum_tmpl_h)
- $(AM_V_GEN)$(GLIB_MKENUMS) \
- --template $(enum_tmpl_h) \
- $(glib_enum_headers) > xgen-eh \
- && (cmp -s xgen-eh $(glib_enum_h) || cp -f xgen-eh $(glib_enum_h)) \
- && rm -f xgen-eh \
- && echo timestamp > $(@F)
-
-$(glib_enum_h): stamp-enum-types
- @true
-
-$(glib_enum_c): $(glib_enum_headers) $(glib_enum_h) $(enum_tmpl_c)
- $(AM_V_GEN)$(GLIB_MKENUMS) \
- --template $(enum_tmpl_c) \
- $(glib_enum_headers) > xgen-ec \
- && cp -f xgen-ec $(glib_enum_c) \
- && rm -f xgen-ec
+++ /dev/null
-# custom rules for quiet builds
-
-QUIET_GEN = $(AM_V_GEN)
-
-QUIET_LN = $(QUIET_LN_$(V))
-QUIET_LN_ = $(QUIET_LN_$(AM_DEFAULT_VERBOSITY))
-QUIET_LN_0 = @echo ' LN '$@;
-
-QUIET_RM = $(QUIET_RM_$(V))
-QUIET_RM_ = $(QUIET_RM_$(AM_DEFAULT_VERBOSITY))
-QUIET_RM_0 = @echo ' RM '$@;
-
-QUIET_SCAN = $(QUIET_SCAN_$(V))
-QUIET_SCAN_ = $(QUIET_SCAN_$(AM_DEFAULT_VERBOSITY))
-QUIET_SCAN_0 = @echo ' GISCAN '$@;
-
-QUIET_COMP = $(QUIET_COMP_$(V))
-QUIET_COMP_ = $(QUIET_COMP_$(AM_DEFAULT_VERBOSITY))
-QUIET_COMP_0 = @echo ' GICOMP '$@;
+++ /dev/null
-dnl as-compiler-flag.m4 0.1.0
-
-dnl autostars m4 macro for detection of compiler flags
-
-dnl David Schleef <ds@schleef.org>
-
-dnl $Id: as-compiler-flag.m4,v 1.1 2005/12/15 23:35:19 ds Exp $
-
-dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED])
-dnl Tries to compile with the given CFLAGS.
-dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags,
-dnl and ACTION-IF-NOT-ACCEPTED otherwise.
-
-AC_DEFUN([AS_COMPILER_FLAG],
-[
- AC_MSG_CHECKING([to see if compiler understands $1])
-
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $1"
-
- AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
- CFLAGS="$save_CFLAGS"
-
- if test "X$flag_ok" = Xyes ; then
- m4_ifvaln([$2],[$2])
- true
- else
- m4_ifvaln([$3],[$3])
- true
- fi
- AC_MSG_RESULT([$flag_ok])
-])
-
-dnl AS_COMPILER_FLAGS(VAR, FLAGS)
-dnl Tries to compile with the given CFLAGS.
-
-AC_DEFUN([AS_COMPILER_FLAGS],
-[
- list=$2
- flags_supported=""
- flags_unsupported=""
- AC_MSG_CHECKING([for supported compiler flags])
- for each in $list
- do
- save_CFLAGS="$CFLAGS"
- CFLAGS="$CFLAGS $each"
- AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no])
- CFLAGS="$save_CFLAGS"
-
- if test "X$flag_ok" = Xyes ; then
- flags_supported="$flags_supported $each"
- else
- flags_unsupported="$flags_unsupported $each"
- fi
- done
- AC_MSG_RESULT([$flags_supported])
- if test "X$flags_unsupported" != X ; then
- AC_MSG_WARN([unsupported compiler flags: $flags_unsupported])
- fi
- $1="$$1 $flags_supported"
-])
-
+++ /dev/null
-# Set ALL_ALL_LINGUAS based on the .po files present. Optional argument is the
-# name of the po directory. $podir/LINGUAS.ignore can be used to ignore a
-# subset of the po files.
-
-AC_DEFUN([AS_ALL_LINGUAS],
-[
- AC_MSG_CHECKING([for linguas])
- podir="m4_default([$1],[$srcdir/po])"
- linguas=`cd $podir && ls *.po 2>/dev/null | awk 'BEGIN { FS="."; ORS=" " } { print $[]1 }'`
- if test -f "$podir/LINGUAS.ignore"; then
- ALL_LINGUAS="";
- ignore_linguas=`sed -n -e 's/^\s\+\|\s\+$//g' -e '/^#/b' -e '/\S/!b' \
- -e 's/\s\+/\n/g' -e p "$podir/LINGUAS.ignore"`;
- for lang in $linguas; do
- if ! echo "$ignore_linguas" | grep -q "^${lang}$"; then
- ALL_LINGUAS="$ALL_LINGUAS $lang";
- fi;
- done;
- else
- ALL_LINGUAS="$linguas";
- fi;
- AC_SUBST([ALL_LINGUAS])
- AC_MSG_RESULT($ALL_LINGUAS)
-])
+++ /dev/null
-dnl -*- mode: autoconf -*-
-dnl Copyright 2009 Johan Dahlin
-dnl
-dnl This file is free software; the author(s) gives unlimited
-dnl permission to copy and/or distribute it, with or without
-dnl modifications, as long as this notice is preserved.
-dnl
-
-# serial 1
-
-m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
-[
- AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
- AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
- AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
-
- dnl enable/disable introspection
- m4_if([$2], [require],
- [dnl
- enable_introspection=yes
- ],[dnl
- AC_ARG_ENABLE(introspection,
- AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
- [Enable introspection for this build]),,
- [enable_introspection=auto])
- ])dnl
-
- AC_MSG_CHECKING([for gobject-introspection])
-
- dnl presence/version checking
- AS_CASE([$enable_introspection],
- [no], [dnl
- found_introspection="no (disabled, use --enable-introspection to enable)"
- ],dnl
- [yes],[dnl
- PKG_CHECK_EXISTS([gobject-introspection-1.0],,
- AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
- PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
- found_introspection=yes,
- AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
- ],dnl
- [auto],[dnl
- PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
- ],dnl
- [dnl
- AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
- ])dnl
-
- AC_MSG_RESULT([$found_introspection])
-
- INTROSPECTION_SCANNER=
- INTROSPECTION_COMPILER=
- INTROSPECTION_GENERATE=
- INTROSPECTION_GIRDIR=
- INTROSPECTION_TYPELIBDIR=
- if test "x$found_introspection" = "xyes"; then
- INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
- INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
- INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
- INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
- INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
- INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
- INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
- INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
- fi
- AC_SUBST(INTROSPECTION_SCANNER)
- AC_SUBST(INTROSPECTION_COMPILER)
- AC_SUBST(INTROSPECTION_GENERATE)
- AC_SUBST(INTROSPECTION_GIRDIR)
- AC_SUBST(INTROSPECTION_TYPELIBDIR)
- AC_SUBST(INTROSPECTION_CFLAGS)
- AC_SUBST(INTROSPECTION_LIBS)
- AC_SUBST(INTROSPECTION_MAKEFILE)
-
- AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
-])
-
-
-dnl Usage:
-dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
-
-AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
-[
- _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
-])
-
-dnl Usage:
-dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
-
-
-AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
-[
- _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
-])
+++ /dev/null
-include $(top_srcdir)/build/autotools/Makefile.am.silent
-
-# preamble
-
-NULL =
-
-SUBDIRS =
-
-BUILT_SOURCES =
-
-EXTRA_DIST =
-CLEANFILES =
-DISTCLEANFILES =
-
-noinst_LTLIBRARIES =
-lib_LTLIBRARIES =
-
-INCLUDES = \
- -I$(top_srcdir) \
- -I$(top_builddir) \
- -I$(srcdir)/tesselator \
- -I$(srcdir)/winsys \
- -I$(srcdir)/driver/$(COGL_DRIVER) \
- $(NULL)
-
-if COGL_STANDALONE_BUILD
-INCLUDES += \
- -I$(top_srcdir)/clutter/cogl \
- -I$(top_builddir)/clutter/cogl \
- $(NULL)
-else
-INCLUDES += \
- -I$(top_srcdir)/clutter/cogl \
- -I$(top_builddir)/clutter/cogl \
- $(NULL)
-endif
-
-AM_CPPFLAGS = \
- -DG_DISABLE_SINGLE_INCLUDES \
- -DG_DISABLE_DEPRECATED \
- -DG_LOG_DOMAIN=\"Cogl\" \
- -DCLUTTER_COMPILATION \
- $(NULL)
-
-AM_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
-
-BUILT_SOURCES += cogl-defines.h
-DISTCLEANFILES += cogl-defines.h
-EXTRA_DIST += cogl-defines.h.in
-
-# Note: The cogl-1.0/cogl-gl-1.0 files are essentially for
-# compatability only. I'm not really sure who could possibly be using
-# them so we may decide to remove them entirely at some point.
-pc_files = \
- cogl-1.0.pc \
- cogl-gl-1.0.pc
-
-if COGL_STANDALONE_BUILD
-pc_files += cogl-$(COGL_API_VERSION).pc
-endif
-
-cogl-gl-1.0.pc: cogl-1.0.pc
- $(QUIET_GEN)cp -f $< $(@F)
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = $(pc_files)
-
-EXTRA_DIST += cogl.pc.in
-DISTCLEANFILES += $(pc_files)
-
-# public headers
-cogl_public_h = \
- $(srcdir)/cogl-object.h \
- $(srcdir)/cogl-bitmap.h \
- $(srcdir)/cogl-buffer.h \
- $(srcdir)/cogl-color.h \
- $(srcdir)/cogl-fixed.h \
- $(srcdir)/cogl-material-compat.h \
- $(srcdir)/cogl-pipeline.h \
- $(srcdir)/cogl-vector.h \
- $(srcdir)/cogl-matrix.h \
- $(srcdir)/cogl-offscreen.h \
- $(srcdir)/cogl-primitives.h \
- $(srcdir)/cogl-path.h \
- $(srcdir)/cogl-pixel-array.h \
- $(srcdir)/cogl-shader.h \
- $(srcdir)/cogl-texture.h \
- $(srcdir)/cogl-texture-3d.h \
- $(srcdir)/cogl-types.h \
- $(srcdir)/cogl-vertex-buffer.h \
- $(srcdir)/cogl-index-array.h \
- $(srcdir)/cogl-vertex-array.h \
- $(srcdir)/cogl-indices.h \
- $(srcdir)/cogl-attribute.h \
- $(srcdir)/cogl-primitive.h \
- $(srcdir)/cogl-clip-state.h \
- $(srcdir)/cogl-framebuffer.h \
- $(srcdir)/cogl-clutter.h \
- $(srcdir)/cogl.h \
- $(NULL)
-
-cogl_experimental_h = \
- $(srcdir)/cogl-renderer.h \
- $(srcdir)/cogl-swap-chain.h \
- $(srcdir)/cogl-onscreen-template.h \
- $(srcdir)/cogl-display.h \
- $(srcdir)/cogl-context.h \
- $(srcdir)/cogl2-path.h \
- $(srcdir)/cogl2-clip-state.h \
- $(NULL)
-
-# driver sources
-cogl_driver_sources =
-
-if COGL_DRIVER_GL
-cogl_driver_sources += \
- $(srcdir)/driver/gl/cogl-feature-functions-gl.h \
- $(srcdir)/driver/gl/cogl-gl.c \
- $(srcdir)/driver/gl/cogl-texture-driver-gl.c \
- $(NULL)
-endif
-
-if COGL_DRIVER_GLES
-cogl_driver_sources += \
- $(srcdir)/driver/gles/cogl-feature-functions-gles.h \
- $(srcdir)/driver/gles/cogl-gles.c \
- $(srcdir)/driver/gles/cogl-texture-driver-gles.c \
- $(NULL)
-
-endif # COGL_DRIVER_GLES
-
-# winsys sources, common to all backends
-cogl_winsys_common_sources = \
- $(srcdir)/winsys/cogl-winsys-private.h \
- $(srcdir)/winsys/cogl-winsys.c \
- $(NULL)
-
-# tesselator sources
-cogl_tesselator_sources = \
- $(srcdir)/tesselator/dict-list.h \
- $(srcdir)/tesselator/dict.c \
- $(srcdir)/tesselator/dict.h \
- $(srcdir)/tesselator/geom.c \
- $(srcdir)/tesselator/geom.h \
- $(srcdir)/tesselator/gluos.h \
- $(srcdir)/tesselator/memalloc.h \
- $(srcdir)/tesselator/mesh.c \
- $(srcdir)/tesselator/mesh.h \
- $(srcdir)/tesselator/normal.c \
- $(srcdir)/tesselator/normal.h \
- $(srcdir)/tesselator/priorityq-heap.h \
- $(srcdir)/tesselator/priorityq-sort.h \
- $(srcdir)/tesselator/priorityq.c \
- $(srcdir)/tesselator/priorityq.h \
- $(srcdir)/tesselator/render.c \
- $(srcdir)/tesselator/render.h \
- $(srcdir)/tesselator/sweep.c \
- $(srcdir)/tesselator/sweep.h \
- $(srcdir)/tesselator/tess.c \
- $(srcdir)/tesselator/tess.h \
- $(srcdir)/tesselator/tesselator.h \
- $(srcdir)/tesselator/tessmono.c \
- $(srcdir)/tesselator/tessmono.h \
- $(srcdir)/tesselator/GL/glu.h \
- $(NULL)
-
-EXTRA_DIST += \
- $(srcdir)/tesselator/README \
- $(srcdir)/tesselator/priorityq-heap.c \
- $(NULL)
-
-# sources
-cogl_sources_c = \
- $(cogl_driver_sources) \
- $(cogl_winsys_common_sources) \
- $(cogl_tesselator_sources) \
- $(srcdir)/cogl-private.h \
- $(srcdir)/cogl-debug.h \
- $(srcdir)/cogl-debug-options.h \
- $(srcdir)/cogl-handle.h \
- $(srcdir)/cogl-context-private.h \
- $(srcdir)/cogl-context.c \
- $(srcdir)/cogl-renderer-private.h \
- $(srcdir)/cogl-renderer.h \
- $(srcdir)/cogl-renderer.c \
- $(srcdir)/cogl-swap-chain-private.h \
- $(srcdir)/cogl-swap-chain.h \
- $(srcdir)/cogl-swap-chain.c \
- $(srcdir)/cogl-onscreen-template-private.h \
- $(srcdir)/cogl-onscreen-template.h \
- $(srcdir)/cogl-onscreen-template.c \
- $(srcdir)/cogl-display-private.h \
- $(srcdir)/cogl-display.h \
- $(srcdir)/cogl-display.c \
- $(srcdir)/cogl-internal.h \
- $(srcdir)/cogl.c \
- $(srcdir)/cogl-object-private.h \
- $(srcdir)/cogl-object.h \
- $(srcdir)/cogl-object.c \
- $(srcdir)/cogl-util.h \
- $(srcdir)/cogl-util.c \
- $(srcdir)/cogl-bitmap-private.h \
- $(srcdir)/cogl-bitmap.c \
- $(srcdir)/cogl-bitmap-fallback.c \
- $(srcdir)/cogl-primitives-private.h \
- $(srcdir)/cogl-primitives.h \
- $(srcdir)/cogl-primitives.c \
- $(srcdir)/cogl-path-private.h \
- $(srcdir)/cogl-path.h \
- $(srcdir)/cogl-path.c \
- $(srcdir)/cogl2-path.h \
- $(srcdir)/cogl2-path.c \
- $(srcdir)/cogl-bitmap-pixbuf.c \
- $(srcdir)/cogl-clip-stack.h \
- $(srcdir)/cogl-clip-stack.c \
- $(srcdir)/cogl-clip-state-private.h \
- $(srcdir)/cogl-clip-state.h \
- $(srcdir)/cogl-clip-state.c \
- $(srcdir)/cogl2-clip-state.h \
- $(srcdir)/cogl2-clip-state.c \
- $(srcdir)/cogl-feature-private.h \
- $(srcdir)/cogl-feature-private.c \
- $(srcdir)/cogl-fixed.c \
- $(srcdir)/cogl-color-private.h \
- $(srcdir)/cogl-color.c \
- $(srcdir)/cogl-buffer-private.h \
- $(srcdir)/cogl-buffer.c \
- $(srcdir)/cogl-pixel-array-private.h \
- $(srcdir)/cogl-pixel-array.c \
- $(srcdir)/cogl-vertex-buffer-private.h \
- $(srcdir)/cogl-vertex-buffer.c \
- $(srcdir)/cogl-index-array-private.h \
- $(srcdir)/cogl-index-array.c \
- $(srcdir)/cogl-vertex-array-private.h \
- $(srcdir)/cogl-vertex-array.c \
- $(srcdir)/cogl-indices-private.h \
- $(srcdir)/cogl-indices.c \
- $(srcdir)/cogl-attribute-private.h \
- $(srcdir)/cogl-attribute.c \
- $(srcdir)/cogl-primitive-private.h \
- $(srcdir)/cogl-primitive.c \
- $(srcdir)/cogl-matrix.c \
- $(srcdir)/cogl-vector.c \
- $(srcdir)/cogl-matrix-private.h \
- $(srcdir)/cogl-matrix-stack.c \
- $(srcdir)/cogl-matrix-stack.h \
- $(srcdir)/cogl-pipeline.c \
- $(srcdir)/cogl-pipeline-private.h \
- $(srcdir)/cogl-pipeline-opengl.c \
- $(srcdir)/cogl-pipeline-opengl-private.h \
- $(srcdir)/cogl-pipeline-fragend-glsl.c \
- $(srcdir)/cogl-pipeline-fragend-glsl-private.h \
- $(srcdir)/cogl-pipeline-fragend-arbfp.c \
- $(srcdir)/cogl-pipeline-fragend-arbfp-private.h \
- $(srcdir)/cogl-pipeline-fragend-fixed.c \
- $(srcdir)/cogl-pipeline-fragend-fixed-private.h \
- $(srcdir)/cogl-pipeline-vertend-glsl.c \
- $(srcdir)/cogl-pipeline-vertend-glsl-private.h \
- $(srcdir)/cogl-pipeline-vertend-fixed.c \
- $(srcdir)/cogl-pipeline-vertend-fixed-private.h \
- $(srcdir)/cogl-pipeline-progend-glsl.c \
- $(srcdir)/cogl-pipeline-progend-glsl-private.h \
- $(srcdir)/cogl-material-compat.c \
- $(srcdir)/cogl-program.c \
- $(srcdir)/cogl-program-private.h \
- $(srcdir)/cogl-blend-string.c \
- $(srcdir)/cogl-blend-string.h \
- $(srcdir)/cogl-debug.c \
- $(srcdir)/cogl-sub-texture-private.h \
- $(srcdir)/cogl-texture-private.h \
- $(srcdir)/cogl-texture-2d-private.h \
- $(srcdir)/cogl-texture-2d-sliced-private.h \
- $(srcdir)/cogl-texture-3d-private.h \
- $(srcdir)/cogl-texture-driver.h \
- $(srcdir)/cogl-sub-texture.c \
- $(srcdir)/cogl-texture.c \
- $(srcdir)/cogl-texture-2d.c \
- $(srcdir)/cogl-texture-2d-sliced.c \
- $(srcdir)/cogl-texture-3d.c \
- $(srcdir)/cogl-texture-rectangle-private.h \
- $(srcdir)/cogl-texture-rectangle.c \
- $(srcdir)/cogl-rectangle-map.h \
- $(srcdir)/cogl-rectangle-map.c \
- $(srcdir)/cogl-atlas.h \
- $(srcdir)/cogl-atlas.c \
- $(srcdir)/cogl-atlas-texture-private.h \
- $(srcdir)/cogl-atlas-texture.c \
- $(srcdir)/cogl-blit.h \
- $(srcdir)/cogl-blit.c \
- $(srcdir)/cogl-spans.h \
- $(srcdir)/cogl-spans.c \
- $(srcdir)/cogl-journal-private.h \
- $(srcdir)/cogl-journal.c \
- $(srcdir)/cogl-framebuffer-private.h \
- $(srcdir)/cogl-framebuffer.c \
- $(srcdir)/cogl-matrix-mesa.h \
- $(srcdir)/cogl-matrix-mesa.c \
- $(srcdir)/cogl-profile.h \
- $(srcdir)/cogl-profile.c \
- $(srcdir)/cogl-flags.h \
- $(srcdir)/cogl-bitmask.h \
- $(srcdir)/cogl-bitmask.c \
- $(srcdir)/cogl-shader-boilerplate.h \
- $(srcdir)/cogl-shader-private.h \
- $(srcdir)/cogl-shader.c \
- $(srcdir)/cogl-gtype-private.h \
- $(srcdir)/cogl-point-in-poly-private.h \
- $(srcdir)/cogl-point-in-poly.c \
- $(srcdir)/cogl-clutter.c \
- $(NULL)
-
-if SUPPORT_XLIB
-cogl_experimental_h += \
- $(srcdir)/winsys/cogl-texture-pixmap-x11.h \
- $(srcdir)/cogl-xlib.h
-
-cogl_sources_c += \
- $(srcdir)/cogl-renderer-x11-private.h \
- $(srcdir)/cogl-renderer-xlib-private.h \
- $(srcdir)/cogl-renderer-xlib.c \
- $(srcdir)/cogl-display-xlib-private.h \
- $(srcdir)/cogl-xlib.c \
- $(srcdir)/winsys/cogl-texture-pixmap-x11.c \
- $(srcdir)/winsys/cogl-texture-pixmap-x11-private.h
-endif
-if SUPPORT_GLX
-cogl_sources_c += \
- $(srcdir)/cogl-renderer-glx-private.h \
- $(srcdir)/cogl-display-glx-private.h \
- $(srcdir)/winsys/cogl-winsys-glx-feature-functions.h \
- $(srcdir)/winsys/cogl-winsys-glx.c
-endif
-if SUPPORT_EGL_PLATFORM_POWERVR_X11
-cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c
-endif
-if SUPPORT_EGL_PLATFORM_POWERVR_NULL
-cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c
-endif
-if SUPPORT_EGL_PLATFORM_GDL
-cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-egl.c
-endif
-if SUPPORT_STUB
-cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-stub.c
-endif
-
-EXTRA_DIST += stb_image.c
-
-# glib-mkenums rules
-glib_enum_h = cogl-enum-types.h
-glib_enum_c = cogl-enum-types.c
-glib_enum_headers = $(cogl_public_h)
-include $(top_srcdir)/build/autotools/Makefile.am.enums
-
-if COGL_STANDALONE_BUILD
-lib_LTLIBRARIES += libcogl.la
-else
-noinst_LTLIBRARIES += libcogl.la
-endif
-
-libcogl_la_LIBADD = -lm $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS)
-if SUPPORT_GLX
-libcogl_la_LIBADD += -ldl
-endif
-if COGL_STANDALONE_BUILD
-# XXX: The aim is to eventually get rid of all private API exports
-# for coglpango.
-libcogl_la_LDFLAGS = \
- -no-undefined \
- -version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@ \
- -export-dynamic \
- -export-symbols-regex "^(cogl|_cogl_debug_flags|_cogl_atlas_new|_cogl_atlas_add_reorganize_callback|_cogl_atlas_reserve_space|_cogl_callback|_cogl_util_get_eye_planes_for_screen_poly).*"
-endif
-
-libcogl_la_SOURCES = $(cogl_sources_c)
-nodist_libcogl_la_SOURCES = $(BUILT_SOURCES)
-
-# Cogl installed headers
-cogl_headers = \
- $(cogl_public_h) \
- $(srcdir)/cogl-deprecated.h \
- $(NULL)
-
-if COGL_STANDALONE_BUILD
-coglincludedir = $(includedir)/cogl/cogl
-coglinclude_HEADERS = $(cogl_headers) $(cogl_experimental_h)
-nodist_coglinclude_HEADERS = cogl-defines.h cogl-enum-types.h
-else
-coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
-coglinclude_HEADERS = $(cogl_headers) $(cogl_experimental_h)
-nodist_coglinclude_HEADERS = cogl-defines.h cogl-enum-types.h
-endif
-
--include $(INTROSPECTION_MAKEFILE)
-
-INTROSPECTION_GIRS =
-
-if HAVE_INTROSPECTION
-Cogl-1.0.gir: libcogl.la Makefile
-
-Cogl_1_0_gir_NAMESPACE = Cogl
-Cogl_1_0_gir_VERSION = 1.0
-Cogl_1_0_gir_LIBS = libcogl.la
-Cogl_1_0_gir_FILES = $(cogl_headers) cogl-enum-types.h
-Cogl_1_0_gir_CFLAGS = $(INCLUDES) $(AM_CPPFLAGS)
-Cogl_1_0_gir_INCLUDES = GL-1.0 GObject-2.0
-Cogl_1_0_gir_EXPORT_PACKAGES = cogl-1.0
-Cogl_1_0_gir_SCANNERFLAGS = --warn-all --c-include='cogl/cogl.h'
-
-INTROSPECTION_GIRS += Cogl-1.0.gir
-
-girdir = $(datadir)/gir-1.0
-gir_DATA = $(INTROSPECTION_GIRS)
-
-CLEANFILES += $(INTROSPECTION_GIRS)
-endif
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-apiversion=1.0
-requires=@COGL_PKG_REQUIRES@
-backend=none #only kept for backward compatability
-winsys=none
-cogl=none #only kept for backward compatability
-driver=none
-
-Name: Cogl
-Description: An object oriented GL/GLES Abstraction/Utility Layer
-Version: @COGL_1_VERSION@
-Libs: -L${libdir} -lcogl -lcoglpango
-Cflags: -I${includedir}/clutter-${apiversion}
-Requires: ${requires}
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-apiversion=1.0
-requires=@COGL_PKG_REQUIRES@
-
-Name: Cogl
-Description: An object oriented GL/GLES Abstraction/Utility Layer
-Version: @COGL_1_VERSION@
-Libs: -L${libdir} -lcogl -lcoglpango
-Cflags: -I${includedir}/cogl
-Requires: ${requires}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_ATLAS_TEXTURE_H
-#define __COGL_ATLAS_TEXTURE_H
-
-#include "cogl-handle.h"
-#include "cogl-texture-private.h"
-#include "cogl-rectangle-map.h"
-#include "cogl-atlas.h"
-
-#define COGL_ATLAS_TEXTURE(tex) ((CoglAtlasTexture *) tex)
-
-typedef struct _CoglAtlasTexture CoglAtlasTexture;
-
-struct _CoglAtlasTexture
-{
- CoglTexture _parent;
-
- /* The format that the texture is in. This isn't necessarily the
- same format as the atlas texture because we can store
- pre-multiplied and non-pre-multiplied textures together */
- CoglPixelFormat format;
-
- /* The rectangle that was used to add this texture to the
- atlas. This includes the 1-pixel border */
- CoglRectangleMapEntry rectangle;
-
- /* The atlas that this texture is in. If the texture is no longer in
- an atlas then this will be NULL. A reference is taken on the
- atlas by the texture (but not vice versa so there is no cycle) */
- CoglAtlas *atlas;
-
- /* A CoglSubTexture representing the region for easy rendering */
- CoglHandle sub_texture;
-};
-
-GQuark
-_cogl_handle_atlas_texture_get_type (void);
-
-CoglHandle
-_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_atlas_texture_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-void
-_cogl_atlas_texture_add_reorganize_callback (GHookFunc callback,
- void *user_data);
-
-void
-_cogl_atlas_texture_remove_reorganize_callback (GHookFunc callback,
- void *user_data);
-
-#endif /* __COGL_ATLAS_TEXTURE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009,2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-atlas-texture-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-sub-texture-private.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-texture-driver.h"
-#include "cogl-rectangle-map.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-atlas.h"
-
-#include <stdlib.h>
-
-static void _cogl_atlas_texture_free (CoglAtlasTexture *sub_tex);
-
-COGL_TEXTURE_INTERNAL_DEFINE (AtlasTexture, atlas_texture);
-
-static const CoglTextureVtable cogl_atlas_texture_vtable;
-
-static CoglHandle
-_cogl_atlas_texture_create_sub_texture (CoglHandle full_texture,
- const CoglRectangleMapEntry *rectangle)
-{
- /* Create a subtexture for the given rectangle not including the
- 1-pixel border */
- return _cogl_sub_texture_new (full_texture,
- rectangle->x + 1,
- rectangle->y + 1,
- rectangle->width - 2,
- rectangle->height - 2);
-}
-
-static void
-_cogl_atlas_texture_update_position_cb (gpointer user_data,
- CoglHandle new_texture,
- const CoglRectangleMapEntry *rectangle)
-{
- CoglAtlasTexture *atlas_tex = user_data;
-
- /* Update the sub texture */
- if (atlas_tex->sub_texture)
- cogl_handle_unref (atlas_tex->sub_texture);
- atlas_tex->sub_texture =
- _cogl_atlas_texture_create_sub_texture (new_texture, rectangle);
-
- /* Update the position */
- atlas_tex->rectangle = *rectangle;
-}
-
-static void
-_cogl_atlas_texture_pre_reorganize_foreach_cb
- (const CoglRectangleMapEntry *entry,
- void *rectangle_data,
- void *user_data)
-{
- CoglAtlasTexture *atlas_tex = rectangle_data;
-
- /* Keep a reference to the texture because we don't want it to be
- destroyed during the reorganization */
- cogl_handle_ref (atlas_tex);
-
- /* Notify cogl-pipeline.c that the texture's underlying GL texture
- * storage is changing so it knows it may need to bind a new texture
- * if the CoglTexture is reused with the same texture unit. */
- _cogl_pipeline_texture_storage_change_notify (COGL_TEXTURE (atlas_tex));
-}
-
-static void
-_cogl_atlas_texture_pre_reorganize_cb (void *data)
-{
- CoglAtlas *atlas = data;
-
- /* We don't know if any journal entries currently depend on OpenGL
- * texture coordinates that would be invalidated by reorganizing
- * this atlas so we flush all journals before migrating.
- *
- * We are assuming that texture atlas migration never happens
- * during a flush so we don't have to consider recursion here.
- */
- cogl_flush ();
-
- if (atlas->map)
- _cogl_rectangle_map_foreach (atlas->map,
- _cogl_atlas_texture_pre_reorganize_foreach_cb,
- NULL);
-}
-
-typedef struct
-{
- CoglAtlasTexture **textures;
- /* Number of textures found so far */
- unsigned int n_textures;
-} CoglAtlasTextureGetRectanglesData;
-
-static void
-_cogl_atlas_texture_get_rectangles_cb (const CoglRectangleMapEntry *entry,
- void *rectangle_data,
- void *user_data)
-{
- CoglAtlasTextureGetRectanglesData *data = user_data;
-
- data->textures[data->n_textures++] = rectangle_data;
-}
-
-static void
-_cogl_atlas_texture_post_reorganize_cb (void *user_data)
-{
- CoglAtlas *atlas = user_data;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (atlas->map)
- {
- CoglAtlasTextureGetRectanglesData data;
- unsigned int i;
-
- data.textures = g_new (CoglAtlasTexture *,
- _cogl_rectangle_map_get_n_rectangles (atlas->map));
- data.n_textures = 0;
-
- /* We need to remove all of the references that we took during
- the preorganize callback. We have to get a separate array of
- the textures because CoglRectangleMap doesn't support
- removing rectangles during iteration */
- _cogl_rectangle_map_foreach (atlas->map,
- _cogl_atlas_texture_get_rectangles_cb,
- &data);
-
- for (i = 0; i < data.n_textures; i++)
- {
- /* Ignore textures that don't have an atlas yet. This will
- happen when a new texture is added because we allocate
- the structure for the texture so that it can get stored
- in the atlas but it isn't a valid object yet */
- if (data.textures[i]->atlas)
- cogl_object_unref (data.textures[i]);
- }
-
- g_free (data.textures);
- }
-
- /* Notify any listeners that an atlas has changed */
- g_hook_list_invoke (&ctx->atlas_reorganize_callbacks, FALSE);
-}
-
-static void
-_cogl_atlas_texture_atlas_destroyed_cb (void *user_data)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Remove the atlas from the global list */
- ctx->atlases = g_slist_remove (ctx->atlases, user_data);
-}
-
-static CoglAtlas *
-_cogl_atlas_texture_create_atlas (void)
-{
- static CoglUserDataKey atlas_private_key;
-
- CoglAtlas *atlas;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_RGBA_8888,
- 0,
- _cogl_atlas_texture_update_position_cb);
-
- _cogl_atlas_add_reorganize_callback (atlas,
- _cogl_atlas_texture_pre_reorganize_cb,
- _cogl_atlas_texture_post_reorganize_cb,
- atlas);
-
- ctx->atlases = g_slist_prepend (ctx->atlases, atlas);
-
- /* Set some data on the atlas so we can get notification when it is
- destroyed in order to remove it from the list. ctx->atlases
- effectively holds a weak reference. We don't need a strong
- reference because the atlas textures take a reference on the
- atlas so it will stay alive */
- cogl_object_set_user_data (COGL_OBJECT (atlas), &atlas_private_key, atlas,
- _cogl_atlas_texture_atlas_destroyed_cb);
-
- return atlas;
-}
-
-static void
-_cogl_atlas_texture_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_foreach_sub_texture_in_region (atlas_tex->sub_texture,
- virtual_tx_1,
- virtual_ty_1,
- virtual_tx_2,
- virtual_ty_2,
- callback,
- user_data);
-}
-
-static void
-_cogl_atlas_texture_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_set_wrap_mode_parameters (atlas_tex->sub_texture,
- wrap_mode_s,
- wrap_mode_t,
- wrap_mode_p);
-}
-
-static void
-_cogl_atlas_texture_remove_from_atlas (CoglAtlasTexture *atlas_tex)
-{
- if (atlas_tex->atlas)
- {
- _cogl_atlas_remove (atlas_tex->atlas,
- &atlas_tex->rectangle);
-
- cogl_object_unref (atlas_tex->atlas);
- atlas_tex->atlas = NULL;
- }
-}
-
-static void
-_cogl_atlas_texture_free (CoglAtlasTexture *atlas_tex)
-{
- _cogl_atlas_texture_remove_from_atlas (atlas_tex);
-
- cogl_handle_unref (atlas_tex->sub_texture);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (atlas_tex));
-}
-
-static int
-_cogl_atlas_texture_get_max_waste (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return cogl_texture_get_max_waste (atlas_tex->sub_texture);
-}
-
-static gboolean
-_cogl_atlas_texture_is_sliced (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return cogl_texture_is_sliced (atlas_tex->sub_texture);
-}
-
-static gboolean
-_cogl_atlas_texture_can_hardware_repeat (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return _cogl_texture_can_hardware_repeat (atlas_tex->sub_texture);
-}
-
-static void
-_cogl_atlas_texture_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_transform_coords_to_gl (atlas_tex->sub_texture, s, t);
-}
-
-static CoglTransformResult
-_cogl_atlas_texture_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return _cogl_texture_transform_quad_coords_to_gl (atlas_tex->sub_texture,
- coords);
-}
-
-static gboolean
-_cogl_atlas_texture_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return cogl_texture_get_gl_texture (atlas_tex->sub_texture,
- out_gl_handle,
- out_gl_target);
-}
-
-static void
-_cogl_atlas_texture_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_set_filters (atlas_tex->sub_texture, min_filter, mag_filter);
-}
-
-static void
-_cogl_atlas_texture_migrate_out_of_atlas (CoglAtlasTexture *atlas_tex)
-{
- /* Make sure this texture is not in the atlas */
- if (atlas_tex->atlas)
- {
- CoglHandle sub_texture;
-
- COGL_NOTE (ATLAS, "Migrating texture out of the atlas");
-
- /* We don't know if any journal entries currently depend on
- * OpenGL texture coordinates that would be invalidated by
- * migrating textures in this atlas so we flush all journals
- * before migrating.
- *
- * We are assuming that texture atlas migration never happens
- * during a flush so we don't have to consider recursion here.
- */
- cogl_flush ();
-
- sub_texture =
- _cogl_atlas_copy_rectangle (atlas_tex->atlas,
- atlas_tex->rectangle.x + 1,
- atlas_tex->rectangle.y + 1,
- atlas_tex->rectangle.width - 2,
- atlas_tex->rectangle.height - 2,
- COGL_TEXTURE_NO_ATLAS,
- atlas_tex->format);
-
- /* Notify cogl-pipeline.c that the texture's underlying GL texture
- * storage is changing so it knows it may need to bind a new texture
- * if the CoglTexture is reused with the same texture unit. */
- _cogl_pipeline_texture_storage_change_notify (atlas_tex);
-
- /* We need to unref the sub texture after doing the copy because
- the copy can involve rendering which might cause the texture
- to be used if it is used from a layer that is left in a
- texture unit */
- cogl_handle_unref (atlas_tex->sub_texture);
- atlas_tex->sub_texture = sub_texture;
-
- _cogl_atlas_texture_remove_from_atlas (atlas_tex);
- }
-}
-
-static void
-_cogl_atlas_texture_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- if ((flags & COGL_TEXTURE_NEEDS_MIPMAP))
- /* Mipmaps do not work well with the current atlas so instead
- we'll just migrate the texture out and use a regular texture */
- _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_pre_paint (atlas_tex->sub_texture, flags);
-}
-
-static void
-_cogl_atlas_texture_ensure_non_quad_rendering (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Sub textures can't support non-quad rendering so we'll just
- migrate the texture out */
- _cogl_atlas_texture_migrate_out_of_atlas (atlas_tex);
-
- /* Forward on to the sub texture */
- _cogl_texture_ensure_non_quad_rendering (atlas_tex->sub_texture);
-}
-
-static gboolean
-_cogl_atlas_texture_set_region_with_border (CoglAtlasTexture *atlas_tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglAtlas *atlas = atlas_tex->atlas;
-
- /* Copy the central data */
- if (!_cogl_texture_set_region_from_bitmap (atlas->texture,
- src_x, src_y,
- dst_x + atlas_tex->rectangle.x + 1,
- dst_y + atlas_tex->rectangle.y + 1,
- dst_width,
- dst_height,
- bmp))
- return FALSE;
-
- /* Update the left edge pixels */
- if (dst_x == 0 &&
- !_cogl_texture_set_region_from_bitmap (atlas->texture,
- src_x, src_y,
- atlas_tex->rectangle.x,
- dst_y + atlas_tex->rectangle.y + 1,
- 1, dst_height,
- bmp))
- return FALSE;
- /* Update the right edge pixels */
- if (dst_x + dst_width == atlas_tex->rectangle.width - 2 &&
- !_cogl_texture_set_region_from_bitmap (atlas->texture,
- src_x + dst_width - 1, src_y,
- atlas_tex->rectangle.x +
- atlas_tex->rectangle.width - 1,
- dst_y + atlas_tex->rectangle.y + 1,
- 1, dst_height,
- bmp))
- return FALSE;
- /* Update the top edge pixels */
- if (dst_y == 0 &&
- !_cogl_texture_set_region_from_bitmap (atlas->texture,
- src_x, src_y,
- dst_x + atlas_tex->rectangle.x + 1,
- atlas_tex->rectangle.y,
- dst_width, 1,
- bmp))
- return FALSE;
- /* Update the bottom edge pixels */
- if (dst_y + dst_height == atlas_tex->rectangle.height - 2 &&
- !_cogl_texture_set_region_from_bitmap (atlas->texture,
- src_x, src_y + dst_height - 1,
- dst_x + atlas_tex->rectangle.x + 1,
- atlas_tex->rectangle.y +
- atlas_tex->rectangle.height - 1,
- dst_width, 1,
- bmp))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_atlas_texture_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* If the texture is in the atlas then we need to copy the edge
- pixels to the border */
- if (atlas_tex->atlas)
- {
- gboolean ret;
-
- bmp = _cogl_bitmap_new_shared (bmp,
- _cogl_bitmap_get_format (bmp) &
- ~COGL_PREMULT_BIT,
- _cogl_bitmap_get_width (bmp),
- _cogl_bitmap_get_height (bmp),
- _cogl_bitmap_get_rowstride (bmp));
-
- /* Upload the data ignoring the premult bit */
- ret = _cogl_atlas_texture_set_region_with_border (atlas_tex,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp);
-
- cogl_object_unref (bmp);
-
- return ret;
- }
- else
- /* Otherwise we can just forward on to the sub texture */
- return _cogl_texture_set_region_from_bitmap (atlas_tex->sub_texture,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp);
-}
-
-static CoglPixelFormat
-_cogl_atlas_texture_get_format (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* We don't want to forward this on the sub-texture because it isn't
- the necessarily the same format. This will happen if the texture
- isn't pre-multiplied */
- return atlas_tex->format;
-}
-
-static GLenum
-_cogl_atlas_texture_get_gl_format (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return _cogl_texture_get_gl_format (atlas_tex->sub_texture);
-}
-
-static int
-_cogl_atlas_texture_get_width (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return cogl_texture_get_width (atlas_tex->sub_texture);
-}
-
-static int
-_cogl_atlas_texture_get_height (CoglTexture *tex)
-{
- CoglAtlasTexture *atlas_tex = COGL_ATLAS_TEXTURE (tex);
-
- /* Forward on to the sub texture */
- return cogl_texture_get_height (atlas_tex->sub_texture);
-}
-
-static gboolean
-_cogl_atlas_texture_can_use_format (CoglPixelFormat format)
-{
- /* We don't care about the ordering or the premult status and we can
- accept RGBA or RGB textures. Although we could also accept
- luminance and alpha only textures or 16-bit formats it seems that
- if the application is explicitly using these formats then they've
- got a reason to want the lower memory requirements so putting
- them in the atlas might not be a good idea */
- format &= ~(COGL_PREMULT_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT);
- return (format == COGL_PIXEL_FORMAT_RGB_888 ||
- format == COGL_PIXEL_FORMAT_RGBA_8888);
-}
-
-CoglHandle
-_cogl_atlas_texture_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglAtlasTexture *atlas_tex;
- CoglAtlas *atlas;
- GSList *l;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- /* Don't put textures in the atlas if the user has explicitly
- requested to disable it */
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ATLAS)))
- return COGL_INVALID_HANDLE;
-
- /* We can't put the texture in the atlas if there are any special
- flags. This precludes textures with COGL_TEXTURE_NO_ATLAS and
- COGL_TEXTURE_NO_SLICING from being atlased */
- if (flags)
- return COGL_INVALID_HANDLE;
-
- /* We can't atlas zero-sized textures because it breaks the atlas
- data structure */
- if (width < 1 || height < 1)
- return COGL_INVALID_HANDLE;
-
- /* If we can't use FBOs then it will be too slow to migrate textures
- and we shouldn't use the atlas */
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
- return COGL_INVALID_HANDLE;
-
- COGL_NOTE (ATLAS, "Adding texture of size %ix%i", width, height);
-
- /* If the texture is in a strange format then we won't use it */
- if (!_cogl_atlas_texture_can_use_format (internal_format))
- {
- COGL_NOTE (ATLAS, "Texture can not be added because the "
- "format is unsupported");
-
- return COGL_INVALID_HANDLE;
- }
-
- /* We need to allocate the texture now because we need the pointer
- to set as the data for the rectangle in the atlas */
- atlas_tex = g_new (CoglAtlasTexture, 1);
- /* Mark it as having no atlas so we don't try to unref it in
- _cogl_atlas_texture_post_reorganize_cb */
- atlas_tex->atlas = NULL;
-
- _cogl_texture_init (COGL_TEXTURE (atlas_tex),
- &cogl_atlas_texture_vtable);
-
- atlas_tex->sub_texture = COGL_INVALID_HANDLE;
-
- /* Look for an existing atlas that can hold the texture */
- for (l = ctx->atlases; l; l = l->next)
- /* Try to make some space in the atlas for the texture */
- if (_cogl_atlas_reserve_space (atlas = l->data,
- /* Add two pixels for the border */
- width + 2, height + 2,
- atlas_tex))
- {
- cogl_object_ref (atlas);
- break;
- }
-
- /* If we couldn't find a suitable atlas then start another */
- if (l == NULL)
- {
- atlas = _cogl_atlas_texture_create_atlas ();
- COGL_NOTE (ATLAS, "Created new atlas for textures: %p", atlas);
- if (!_cogl_atlas_reserve_space (atlas,
- /* Add two pixels for the border */
- width + 2, height + 2,
- atlas_tex))
- {
- /* Ok, this means we really can't add it to the atlas */
- cogl_object_unref (atlas);
- g_free (atlas_tex);
- return COGL_INVALID_HANDLE;
- }
- }
-
- atlas_tex->format = internal_format;
- atlas_tex->atlas = atlas;
-
- return _cogl_atlas_texture_handle_new (atlas_tex);
-}
-
-CoglHandle
-_cogl_atlas_texture_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglHandle atlas_tex_handle;
- CoglAtlasTexture *atlas_tex;
- CoglBitmap *dst_bmp;
- CoglBitmap *override_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- int bmp_width;
- int bmp_height;
- CoglPixelFormat bmp_format;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
-
- bmp_width = _cogl_bitmap_get_width (bmp);
- bmp_height = _cogl_bitmap_get_height (bmp);
- bmp_format = _cogl_bitmap_get_format (bmp);
-
- internal_format = _cogl_texture_determine_internal_format (bmp_format,
- internal_format);
-
- atlas_tex_handle = _cogl_atlas_texture_new_with_size (bmp_width, bmp_height,
- flags, internal_format);
-
- if (atlas_tex_handle == COGL_INVALID_HANDLE)
- return COGL_INVALID_HANDLE;
-
- atlas_tex = atlas_tex_handle;
-
- dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- if (dst_bmp == NULL)
- {
- cogl_handle_unref (atlas_tex_handle);
- return COGL_INVALID_HANDLE;
- }
-
- /* Make another bitmap so that we can override the format */
- override_bmp = _cogl_bitmap_new_shared (dst_bmp,
- _cogl_bitmap_get_format (dst_bmp) &
- ~COGL_PREMULT_BIT,
- _cogl_bitmap_get_width (dst_bmp),
- _cogl_bitmap_get_height (dst_bmp),
- _cogl_bitmap_get_rowstride (dst_bmp));
- cogl_object_unref (dst_bmp);
-
- /* Defer to set_region so that we can share the code for copying the
- edge pixels to the border. We don't want to pass the actual
- format of the converted texture because otherwise it will get
- unpremultiplied. */
- _cogl_atlas_texture_set_region_with_border (atlas_tex,
- 0, /* src_x */
- 0, /* src_y */
- 0, /* dst_x */
- 0, /* dst_y */
- bmp_width, /* dst_width */
- bmp_height, /* dst_height */
- override_bmp);
-
- cogl_object_unref (override_bmp);
-
- return atlas_tex_handle;
-}
-
-void
-_cogl_atlas_texture_add_reorganize_callback (GHookFunc callback,
- void *user_data)
-{
- GHook *hook;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- hook = g_hook_alloc (&ctx->atlas_reorganize_callbacks);
- hook->func = callback;
- hook->data = user_data;
- g_hook_prepend (&ctx->atlas_reorganize_callbacks, hook);
-}
-
-void
-_cogl_atlas_texture_remove_reorganize_callback (GHookFunc callback,
- void *user_data)
-{
- GHook *hook;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- hook = g_hook_find_func_data (&ctx->atlas_reorganize_callbacks,
- FALSE,
- callback,
- user_data);
-
- if (hook)
- g_hook_destroy_link (&ctx->atlas_reorganize_callbacks, hook);
-}
-
-static const CoglTextureVtable
-cogl_atlas_texture_vtable =
- {
- _cogl_atlas_texture_set_region,
- NULL, /* get_data */
- _cogl_atlas_texture_foreach_sub_texture_in_region,
- _cogl_atlas_texture_get_max_waste,
- _cogl_atlas_texture_is_sliced,
- _cogl_atlas_texture_can_hardware_repeat,
- _cogl_atlas_texture_transform_coords_to_gl,
- _cogl_atlas_texture_transform_quad_coords_to_gl,
- _cogl_atlas_texture_get_gl_texture,
- _cogl_atlas_texture_set_filters,
- _cogl_atlas_texture_pre_paint,
- _cogl_atlas_texture_ensure_non_quad_rendering,
- _cogl_atlas_texture_set_wrap_mode_parameters,
- _cogl_atlas_texture_get_format,
- _cogl_atlas_texture_get_gl_format,
- _cogl_atlas_texture_get_width,
- _cogl_atlas_texture_get_height,
- NULL /* is_foreign */
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-atlas.h"
-#include "cogl-rectangle-map.h"
-#include "cogl-context-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-debug.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-blit.h"
-
-#include <stdlib.h>
-
-static void _cogl_atlas_free (CoglAtlas *atlas);
-
-COGL_OBJECT_INTERNAL_DEFINE (Atlas, atlas);
-
-CoglAtlas *
-_cogl_atlas_new (CoglPixelFormat texture_format,
- CoglAtlasFlags flags,
- CoglAtlasUpdatePositionCallback update_position_cb)
-{
- CoglAtlas *atlas = g_new (CoglAtlas, 1);
-
- atlas->update_position_cb = update_position_cb;
- atlas->map = NULL;
- atlas->texture = NULL;
- atlas->flags = flags;
- atlas->texture_format = texture_format;
- g_hook_list_init (&atlas->pre_reorganize_callbacks, sizeof (GHook));
- g_hook_list_init (&atlas->post_reorganize_callbacks, sizeof (GHook));
-
- return _cogl_atlas_object_new (atlas);
-}
-
-static void
-_cogl_atlas_free (CoglAtlas *atlas)
-{
- COGL_NOTE (ATLAS, "%p: Atlas destroyed", atlas);
-
- if (atlas->texture)
- cogl_handle_unref (atlas->texture);
- if (atlas->map)
- _cogl_rectangle_map_free (atlas->map);
-
- g_hook_list_clear (&atlas->pre_reorganize_callbacks);
- g_hook_list_clear (&atlas->post_reorganize_callbacks);
-
- g_free (atlas);
-}
-
-typedef struct _CoglAtlasRepositionData
-{
- /* The current user data for this texture */
- void *user_data;
- /* The old and new positions of the texture */
- CoglRectangleMapEntry old_position;
- CoglRectangleMapEntry new_position;
-} CoglAtlasRepositionData;
-
-static void
-_cogl_atlas_migrate (CoglAtlas *atlas,
- unsigned int n_textures,
- CoglAtlasRepositionData *textures,
- CoglHandle old_texture,
- CoglHandle new_texture,
- void *skip_user_data)
-{
- unsigned int i;
- CoglBlitData blit_data;
-
- /* If the 'disable migrate' flag is set then we won't actually copy
- the textures to their new location. Instead we'll just invoke the
- callback to update the position */
- if ((atlas->flags & COGL_ATLAS_DISABLE_MIGRATION))
- for (i = 0; i < n_textures; i++)
- /* Update the texture position */
- atlas->update_position_cb (textures[i].user_data,
- new_texture,
- &textures[i].new_position);
- else
- {
- _cogl_blit_begin (&blit_data, new_texture, old_texture);
-
- for (i = 0; i < n_textures; i++)
- {
- /* Skip the texture that is being added because it doesn't contain
- any data yet */
- if (textures[i].user_data != skip_user_data)
- _cogl_blit (&blit_data,
- textures[i].old_position.x,
- textures[i].old_position.y,
- textures[i].new_position.x,
- textures[i].new_position.y,
- textures[i].new_position.width,
- textures[i].new_position.height);
-
- /* Update the texture position */
- atlas->update_position_cb (textures[i].user_data,
- new_texture,
- &textures[i].new_position);
- }
-
- _cogl_blit_end (&blit_data);
- }
-}
-
-typedef struct _CoglAtlasGetRectanglesData
-{
- CoglAtlasRepositionData *textures;
- /* Number of textures found so far */
- unsigned int n_textures;
-} CoglAtlasGetRectanglesData;
-
-static void
-_cogl_atlas_get_rectangles_cb (const CoglRectangleMapEntry *rectangle,
- void *rect_data,
- void *user_data)
-{
- CoglAtlasGetRectanglesData *data = user_data;
-
- data->textures[data->n_textures].old_position = *rectangle;
- data->textures[data->n_textures++].user_data = rect_data;
-}
-
-static void
-_cogl_atlas_get_next_size (unsigned int *map_width,
- unsigned int *map_height)
-{
- /* Double the size of the texture by increasing whichever dimension
- is smaller */
- if (*map_width < *map_height)
- *map_width <<= 1;
- else
- *map_height <<= 1;
-}
-
-static void
-_cogl_atlas_get_initial_size (CoglPixelFormat format,
- unsigned int *map_width,
- unsigned int *map_height)
-{
- unsigned int size;
- GLenum gl_intformat;
- GLenum gl_type;
-
- _cogl_pixel_format_to_gl (format,
- &gl_intformat,
- NULL, /* gl_format */
- &gl_type);
-
- /* At least on Intel hardware, the texture size will be rounded up
- to at least 1MB so we might as well try to aim for that as an
- initial minimum size. If the format is only 1 byte per pixel we
- can use 1024x1024, otherwise we'll assume it will take 4 bytes
- per pixel and use 512x512. */
- if (_cogl_get_format_bpp (format) == 1)
- size = 1024;
- else
- size = 512;
-
- /* Some platforms might not support this large size so we'll
- decrease the size until it can */
- while (size > 1 &&
- !_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
- gl_intformat,
- gl_type,
- size, size))
- size >>= 1;
-
- *map_width = size;
- *map_height = size;
-}
-
-static CoglRectangleMap *
-_cogl_atlas_create_map (CoglPixelFormat format,
- unsigned int map_width,
- unsigned int map_height,
- unsigned int n_textures,
- CoglAtlasRepositionData *textures)
-{
- GLenum gl_intformat;
- GLenum gl_type;
-
- _cogl_pixel_format_to_gl (format,
- &gl_intformat,
- NULL, /* gl_format */
- &gl_type);
-
- /* Keep trying increasingly larger atlases until we can fit all of
- the textures */
- while (_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
- gl_intformat,
- gl_type,
- map_width, map_height))
- {
- CoglRectangleMap *new_atlas = _cogl_rectangle_map_new (map_width,
- map_height,
- NULL);
- unsigned int i;
-
- COGL_NOTE (ATLAS, "Trying to resize the atlas to %ux%u",
- map_width, map_height);
-
- /* Add all of the textures and keep track of the new position */
- for (i = 0; i < n_textures; i++)
- if (!_cogl_rectangle_map_add (new_atlas,
- textures[i].old_position.width,
- textures[i].old_position.height,
- textures[i].user_data,
- &textures[i].new_position))
- break;
-
- /* If the atlas can contain all of the textures then we have a
- winner */
- if (i >= n_textures)
- return new_atlas;
- else
- COGL_NOTE (ATLAS, "Atlas size abandoned after trying "
- "%u out of %u textures",
- i, n_textures);
-
- _cogl_rectangle_map_free (new_atlas);
- _cogl_atlas_get_next_size (&map_width, &map_height);
- }
-
- /* If we get here then there's no atlas that can accommodate all of
- the rectangles */
-
- return NULL;
-}
-
-static CoglHandle
-_cogl_atlas_create_texture (CoglAtlas *atlas,
- int width,
- int height)
-{
- CoglHandle tex;
-
- if ((atlas->flags & COGL_ATLAS_CLEAR_TEXTURE))
- {
- guint8 *clear_data;
- CoglBitmap *clear_bmp;
- int bpp = _cogl_get_format_bpp (atlas->texture_format);
-
- /* Create a buffer of zeroes to initially clear the texture */
- clear_data = g_malloc0 (width * height * bpp);
- clear_bmp = _cogl_bitmap_new_from_data (clear_data,
- atlas->texture_format,
- width,
- height,
- width * bpp,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- tex = _cogl_texture_2d_new_from_bitmap (clear_bmp, COGL_TEXTURE_NONE,
- atlas->texture_format);
- cogl_object_unref (clear_bmp);
- }
- else
- tex = _cogl_texture_2d_new_with_size (width, height, COGL_TEXTURE_NONE,
- atlas->texture_format);
-
- return tex;
-}
-
-static int
-_cogl_atlas_compare_size_cb (const void *a,
- const void *b)
-{
- const CoglAtlasRepositionData *ta = a;
- const CoglAtlasRepositionData *tb = b;
- unsigned int a_size, b_size;
-
- a_size = ta->old_position.width * ta->old_position.height;
- b_size = tb->old_position.width * tb->old_position.height;
-
- return a_size < b_size ? 1 : a_size > b_size ? -1 : 0;
-}
-
-static void
-_cogl_atlas_notify_pre_reorganize (CoglAtlas *atlas)
-{
- g_hook_list_invoke (&atlas->pre_reorganize_callbacks, FALSE);
-}
-
-static void
-_cogl_atlas_notify_post_reorganize (CoglAtlas *atlas)
-{
- g_hook_list_invoke (&atlas->post_reorganize_callbacks, FALSE);
-}
-
-gboolean
-_cogl_atlas_reserve_space (CoglAtlas *atlas,
- unsigned int width,
- unsigned int height,
- void *user_data)
-{
- CoglAtlasGetRectanglesData data;
- CoglRectangleMap *new_map;
- CoglHandle new_tex;
- unsigned int map_width, map_height;
- gboolean ret;
- CoglRectangleMapEntry new_position;
-
- /* Check if we can fit the rectangle into the existing map */
- if (atlas->map &&
- _cogl_rectangle_map_add (atlas->map, width, height,
- user_data,
- &new_position))
- {
- COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste",
- atlas,
- _cogl_rectangle_map_get_width (atlas->map),
- _cogl_rectangle_map_get_height (atlas->map),
- _cogl_rectangle_map_get_n_rectangles (atlas->map),
- /* waste as a percentage */
- _cogl_rectangle_map_get_remaining_space (atlas->map) *
- 100 / (_cogl_rectangle_map_get_width (atlas->map) *
- _cogl_rectangle_map_get_height (atlas->map)));
-
- atlas->update_position_cb (user_data,
- atlas->texture,
- &new_position);
-
- return TRUE;
- }
-
- /* If we make it here then we need to reorganize the atlas. First
- we'll notify any users of the atlas that this is going to happen
- so that for example in CoglAtlasTexture it can notify that the
- storage has changed and cause a flush */
- _cogl_atlas_notify_pre_reorganize (atlas);
-
- /* Get an array of all the textures currently in the atlas. */
- data.n_textures = 0;
- if (atlas->map == NULL)
- data.textures = g_malloc (sizeof (CoglAtlasRepositionData));
- else
- {
- unsigned int n_rectangles =
- _cogl_rectangle_map_get_n_rectangles (atlas->map);
- data.textures = g_malloc (sizeof (CoglAtlasRepositionData) *
- (n_rectangles + 1));
- _cogl_rectangle_map_foreach (atlas->map,
- _cogl_atlas_get_rectangles_cb,
- &data);
- }
-
- /* Add the new rectangle as a dummy texture so that it can be
- positioned with the rest */
- data.textures[data.n_textures].old_position.x = 0;
- data.textures[data.n_textures].old_position.y = 0;
- data.textures[data.n_textures].old_position.width = width;
- data.textures[data.n_textures].old_position.height = height;
- data.textures[data.n_textures++].user_data = user_data;
-
- /* The atlasing algorithm works a lot better if the rectangles are
- added in decreasing order of size so we'll first sort the
- array */
- qsort (data.textures, data.n_textures,
- sizeof (CoglAtlasRepositionData),
- _cogl_atlas_compare_size_cb);
-
- /* Try to create a new atlas that can contain all of the textures */
- if (atlas->map)
- {
- map_width = _cogl_rectangle_map_get_width (atlas->map);
- map_height = _cogl_rectangle_map_get_height (atlas->map);
-
- /* If there is enough space in for the new rectangle in the
- existing atlas with at least 6% waste we'll start with the
- same size, otherwise we'll immediately double it */
- if ((map_width * map_height -
- _cogl_rectangle_map_get_remaining_space (atlas->map) +
- width * height) * 53 / 50 >
- map_width * map_height)
- _cogl_atlas_get_next_size (&map_width, &map_height);
- }
- else
- _cogl_atlas_get_initial_size (atlas->texture_format,
- &map_width, &map_height);
-
- new_map = _cogl_atlas_create_map (atlas->texture_format,
- map_width, map_height,
- data.n_textures, data.textures);
-
- /* If we can't create a map with the texture then give up */
- if (new_map == NULL)
- {
- COGL_NOTE (ATLAS, "%p: Could not fit texture in the atlas", atlas);
- ret = FALSE;
- }
- /* We need to migrate the existing textures into a new texture */
- else if ((new_tex = _cogl_atlas_create_texture
- (atlas,
- _cogl_rectangle_map_get_width (new_map),
- _cogl_rectangle_map_get_height (new_map))) == COGL_INVALID_HANDLE)
- {
- COGL_NOTE (ATLAS, "%p: Could not create a CoglTexture2D", atlas);
- _cogl_rectangle_map_free (new_map);
- ret = FALSE;
- }
- else
- {
- int waste;
-
- COGL_NOTE (ATLAS,
- "%p: Atlas %s with size %ix%i",
- atlas,
- atlas->map == NULL ||
- _cogl_rectangle_map_get_width (atlas->map) !=
- _cogl_rectangle_map_get_width (new_map) ||
- _cogl_rectangle_map_get_height (atlas->map) !=
- _cogl_rectangle_map_get_height (new_map) ?
- "resized" : "reorganized",
- _cogl_rectangle_map_get_width (new_map),
- _cogl_rectangle_map_get_height (new_map));
-
- if (atlas->map)
- {
- /* Move all the textures to the right position in the new
- texture. This will also update the texture's rectangle */
- _cogl_atlas_migrate (atlas,
- data.n_textures,
- data.textures,
- atlas->texture,
- new_tex,
- user_data);
- _cogl_rectangle_map_free (atlas->map);
- cogl_handle_unref (atlas->texture);
- }
- else
- /* We know there's only one texture so we can just directly
- update the rectangle from its new position */
- atlas->update_position_cb (data.textures[0].user_data,
- new_tex,
- &data.textures[0].new_position);
-
- atlas->map = new_map;
- atlas->texture = new_tex;
-
- waste = (_cogl_rectangle_map_get_remaining_space (atlas->map) *
- 100 / (_cogl_rectangle_map_get_width (atlas->map) *
- _cogl_rectangle_map_get_height (atlas->map)));
-
- COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste",
- atlas,
- _cogl_rectangle_map_get_width (atlas->map),
- _cogl_rectangle_map_get_height (atlas->map),
- _cogl_rectangle_map_get_n_rectangles (atlas->map),
- waste);
-
- ret = TRUE;
- }
-
- g_free (data.textures);
-
- _cogl_atlas_notify_post_reorganize (atlas);
-
- return ret;
-}
-
-void
-_cogl_atlas_remove (CoglAtlas *atlas,
- const CoglRectangleMapEntry *rectangle)
-{
- _cogl_rectangle_map_remove (atlas->map, rectangle);
-
- COGL_NOTE (ATLAS, "%p: Removed rectangle sized %ix%i",
- atlas,
- rectangle->width,
- rectangle->height);
- COGL_NOTE (ATLAS, "%p: Atlas is %ix%i, has %i textures and is %i%% waste",
- atlas,
- _cogl_rectangle_map_get_width (atlas->map),
- _cogl_rectangle_map_get_height (atlas->map),
- _cogl_rectangle_map_get_n_rectangles (atlas->map),
- _cogl_rectangle_map_get_remaining_space (atlas->map) *
- 100 / (_cogl_rectangle_map_get_width (atlas->map) *
- _cogl_rectangle_map_get_height (atlas->map)));
-};
-
-CoglHandle
-_cogl_atlas_copy_rectangle (CoglAtlas *atlas,
- unsigned int x,
- unsigned int y,
- unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format)
-{
- CoglHandle tex;
- CoglBlitData blit_data;
-
- /* Create a new texture at the right size */
- tex = cogl_texture_new_with_size (width, height, flags, format);
-
- /* Blit the data out of the atlas to the new texture. If FBOs
- aren't available this will end up having to copy the entire
- atlas texture */
- _cogl_blit_begin (&blit_data, tex, atlas->texture);
- _cogl_blit (&blit_data,
- x, y,
- 0, 0,
- width, height);
- _cogl_blit_end (&blit_data);
-
- return tex;
-}
-
-void
-_cogl_atlas_add_reorganize_callback (CoglAtlas *atlas,
- GHookFunc pre_callback,
- GHookFunc post_callback,
- void *user_data)
-{
- if (pre_callback)
- {
- GHook *hook = g_hook_alloc (&atlas->post_reorganize_callbacks);
- hook->func = pre_callback;
- hook->data = user_data;
- g_hook_prepend (&atlas->pre_reorganize_callbacks, hook);
- }
- if (post_callback)
- {
- GHook *hook = g_hook_alloc (&atlas->pre_reorganize_callbacks);
- hook->func = post_callback;
- hook->data = user_data;
- g_hook_prepend (&atlas->post_reorganize_callbacks, hook);
- }
-}
-
-void
-_cogl_atlas_remove_reorganize_callback (CoglAtlas *atlas,
- GHookFunc pre_callback,
- GHookFunc post_callback,
- void *user_data)
-{
- if (pre_callback)
- {
- GHook *hook = g_hook_find_func_data (&atlas->pre_reorganize_callbacks,
- FALSE,
- pre_callback,
- user_data);
- if (hook)
- g_hook_destroy_link (&atlas->pre_reorganize_callbacks, hook);
- }
- if (post_callback)
- {
- GHook *hook = g_hook_find_func_data (&atlas->post_reorganize_callbacks,
- FALSE,
- post_callback,
- user_data);
- if (hook)
- g_hook_destroy_link (&atlas->post_reorganize_callbacks, hook);
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __COGL_ATLAS_H
-#define __COGL_ATLAS_H
-
-#include "cogl-rectangle-map.h"
-#include "cogl-object-private.h"
-
-typedef void
-(* CoglAtlasUpdatePositionCallback) (void *user_data,
- CoglHandle new_texture,
- const CoglRectangleMapEntry *rect);
-
-typedef enum
-{
- COGL_ATLAS_CLEAR_TEXTURE = (1 << 0),
- COGL_ATLAS_DISABLE_MIGRATION = (1 << 1)
-} CoglAtlasFlags;
-
-typedef struct _CoglAtlas CoglAtlas;
-
-#define COGL_ATLAS(object) ((CoglAtlas *) object)
-
-struct _CoglAtlas
-{
- CoglObject _parent;
-
- CoglRectangleMap *map;
-
- CoglHandle texture;
- CoglPixelFormat texture_format;
- CoglAtlasFlags flags;
-
- CoglAtlasUpdatePositionCallback update_position_cb;
-
- GHookList pre_reorganize_callbacks;
- GHookList post_reorganize_callbacks;
-};
-
-CoglAtlas *
-_cogl_atlas_new (CoglPixelFormat texture_format,
- CoglAtlasFlags flags,
- CoglAtlasUpdatePositionCallback update_position_cb);
-
-gboolean
-_cogl_atlas_reserve_space (CoglAtlas *atlas,
- unsigned int width,
- unsigned int height,
- void *user_data);
-
-void
-_cogl_atlas_remove (CoglAtlas *atlas,
- const CoglRectangleMapEntry *rectangle);
-
-CoglHandle
-_cogl_atlas_copy_rectangle (CoglAtlas *atlas,
- unsigned int x,
- unsigned int y,
- unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format);
-
-void
-_cogl_atlas_add_reorganize_callback (CoglAtlas *atlas,
- GHookFunc pre_callback,
- GHookFunc post_callback,
- void *user_data);
-
-void
-_cogl_atlas_remove_reorganize_callback (CoglAtlas *atlas,
- GHookFunc pre_callback,
- GHookFunc post_callback,
- void *user_data);
-
-#endif /* __COGL_ATLAS_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_ATTRIBUTE_PRIVATE_H
-#define __COGL_ATTRIBUTE_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-attribute.h"
-
-typedef enum
-{
- COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY,
- COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY,
- COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY,
- COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY,
- COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY
-} CoglAttributeNameID;
-
-struct _CoglAttribute
-{
- CoglObject _parent;
-
- CoglVertexArray *array;
- char *name;
- CoglAttributeNameID name_id;
- gsize stride;
- gsize offset;
- int n_components;
- CoglAttributeType type;
- gboolean normalized;
- unsigned int texture_unit;
-
- int immutable_ref;
-};
-
-typedef enum
-{
- COGL_DRAW_SKIP_JOURNAL_FLUSH = 1 << 0,
- COGL_DRAW_SKIP_PIPELINE_VALIDATION = 1 << 1,
- COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH = 1 << 2,
- /* When flushing from the journal the logged pipeline will already
- contain the legacy state overrides so we don't want to apply them
- again when we flush the pipeline for drawing */
- COGL_DRAW_SKIP_LEGACY_STATE = 1 << 3,
- /* By default the vertex attribute drawing code will assume that if
- there is a color attribute array enabled then we can't determine
- if the colors will be opaque so we need to enabling
- blending. However when drawing from the journal we know what the
- contents of the color array is so we can override this by passing
- this flag. */
- COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE = 1 << 4
-} CoglDrawFlags;
-
-CoglAttribute *
-_cogl_attribute_immutable_ref (CoglAttribute *attribute);
-
-void
-_cogl_attribute_immutable_unref (CoglAttribute *attribute);
-
-void
-_cogl_draw_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglAttribute **attributes,
- CoglDrawFlags flags);
-
-void
-_cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglAttribute **attributes,
- CoglDrawFlags flags);
-
-void
-_cogl_attribute_disable_cached_arrays (void);
-
-#endif /* __COGL_ATTRIBUTE_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-context-private.h"
-#include "cogl-object-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-attribute.h"
-#include "cogl-attribute-private.h"
-#include "cogl-pipeline.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-indices-private.h"
-#ifdef HAVE_COGL_GLES2
-#include "cogl-pipeline-progend-glsl-private.h"
-#endif
-
-#include <string.h>
-#include <stdio.h>
-
-#if defined (HAVE_COGL_GL)
-
-#define glGenBuffers ctx->drv.pf_glGenBuffers
-#define glBindBuffer ctx->drv.pf_glBindBuffer
-#define glBufferData ctx->drv.pf_glBufferData
-#define glBufferSubData ctx->drv.pf_glBufferSubData
-#define glGetBufferSubData ctx->drv.pf_glGetBufferSubData
-#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
-#define glMapBuffer ctx->drv.pf_glMapBuffer
-#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
-#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
-#ifndef GL_ARRAY_BUFFER
-#define GL_ARRAY_BUFFER GL_ARRAY_BUFFER_ARB
-#endif
-
-#define glVertexAttribPointer ctx->drv.pf_glVertexAttribPointer
-#define glEnableVertexAttribArray ctx->drv.pf_glEnableVertexAttribArray
-#define glDisableVertexAttribArray ctx->drv.pf_glDisableVertexAttribArray
-#define MAY_HAVE_PROGRAMABLE_GL
-
-#define glDrawRangeElements(mode, start, end, count, type, indices) \
- ctx->drv.pf_glDrawRangeElements (mode, start, end, count, type, indices)
-
-#else /* GLES 1/2 */
-
-/* GLES doesn't have glDrawRangeElements, so we simply pretend it does
- * but that it makes no use of the start, end constraints: */
-#define glDrawRangeElements(mode, start, end, count, type, indices) \
- glDrawElements (mode, count, type, indices)
-
-/* This isn't defined in the GLES headers */
-#ifndef GL_UNSIGNED_INT
-#define GL_UNSIGNED_INT 0x1405
-#endif
-
-#ifdef HAVE_COGL_GLES2
-
-#define MAY_HAVE_PROGRAMABLE_GL
-
-#endif /* HAVE_COGL_GLES2 */
-
-#endif
-
-static void _cogl_attribute_free (CoglAttribute *attribute);
-
-COGL_OBJECT_DEFINE (Attribute, attribute);
-
-#if 0
-gboolean
-validate_gl_attribute (const char *name,
- int n_components,
- CoglAttributeNameID *name_id,
- gboolean *normalized,
- unsigned int *texture_unit)
-{
- name = name + 3; /* skip past "gl_" */
-
- *normalized = FALSE;
- *texture_unit = 0;
-
- if (strcmp (name, "Vertex") == 0)
- {
- if (G_UNLIKELY (n_components == 1))
- {
- g_critical ("glVertexPointer doesn't allow 1 component vertex "
- "positions so we currently only support \"gl_Vertex\" "
- "attributes where n_components == 2, 3 or 4");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
- }
- else if (strcmp (name, "Color") == 0)
- {
- if (G_UNLIKELY (n_components != 3 && n_components != 4))
- {
- g_critical ("glColorPointer expects 3 or 4 component colors so we "
- "currently only support \"gl_Color\" attributes where "
- "n_components == 3 or 4");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
- *normalized = TRUE;
- }
- else if (strncmp (name, "MultiTexCoord", strlen ("MultiTexCoord")) == 0)
- {
- if (sscanf (gl_attribute, "MultiTexCoord%u", texture_unit) != 1)
- {
- g_warning ("gl_MultiTexCoord attributes should include a\n"
- "texture unit number, E.g. gl_MultiTexCoord0\n");
- unit = 0;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
- }
- else if (strncmp (name, "Normal") == 0)
- {
- if (G_UNLIKELY (n_components != 3))
- {
- g_critical ("glNormalPointer expects 3 component normals so we "
- "currently only support \"gl_Normal\" attributes where "
- "n_components == 3");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
- *normalized = TRUE;
- }
- else
- {
- g_warning ("Unknown gl_* attribute name gl_%s\n", name);
- return FALSE;
- }
-
- return TRUE;
-}
-#endif
-
-gboolean
-validate_cogl_attribute (const char *name,
- int n_components,
- CoglAttributeNameID *name_id,
- gboolean *normalized,
- unsigned int *texture_unit)
-{
- name = name + 5; /* skip "cogl_" */
-
- *normalized = FALSE;
- *texture_unit = 0;
-
- if (strcmp (name, "position_in") == 0)
- {
- if (G_UNLIKELY (n_components == 1))
- {
- g_critical ("glVertexPointer doesn't allow 1 component vertex "
- "positions so we currently only support \"cogl_vertex\" "
- "attributes where n_components == 2, 3 or 4");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY;
- }
- else if (strcmp (name, "color_in") == 0)
- {
- if (G_UNLIKELY (n_components != 3 && n_components != 4))
- {
- g_critical ("glColorPointer expects 3 or 4 component colors so we "
- "currently only support \"cogl_color\" attributes where "
- "n_components == 3 or 4");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY;
- }
- else if (strcmp (name, "tex_coord_in") == 0)
- *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
- else if (strncmp (name, "tex_coord", strlen ("tex_coord")) == 0)
- {
- if (sscanf (name, "tex_coord%u_in", texture_unit) != 1)
- {
- g_warning ("Texture coordinate attributes should either be named "
- "\"cogl_tex_coord\" or named with a texture unit index "
- "like \"cogl_tex_coord2_in\"\n");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY;
- }
- else if (strcmp (name, "normal_in") == 0)
- {
- if (G_UNLIKELY (n_components != 3))
- {
- g_critical ("glNormalPointer expects 3 component normals so we "
- "currently only support \"cogl_normal\" attributes "
- "where n_components == 3");
- return FALSE;
- }
- *name_id = COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY;
- *normalized = TRUE;
- }
- else
- {
- g_warning ("Unknown cogl_* attribute name cogl_%s\n", name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-CoglAttribute *
-cogl_attribute_new (CoglVertexArray *array,
- const char *name,
- gsize stride,
- gsize offset,
- int n_components,
- CoglAttributeType type)
-{
- CoglAttribute *attribute = g_slice_new (CoglAttribute);
- gboolean status;
-
- attribute->array = cogl_object_ref (array);
- attribute->name = g_strdup (name);
- attribute->stride = stride;
- attribute->offset = offset;
- attribute->n_components = n_components;
- attribute->type = type;
- attribute->immutable_ref = 0;
-
- if (strncmp (name, "cogl_", 5) == 0)
- status = validate_cogl_attribute (attribute->name,
- n_components,
- &attribute->name_id,
- &attribute->normalized,
- &attribute->texture_unit);
-#if 0
- else if (strncmp (name, "gl_", 3) == 0)
- status = validate_gl_attribute (attribute->name,
- n_components,
- &attribute->name_id,
- &attribute->normalized,
- &attribute->texture_unit);
-#endif
- else
- {
- attribute->name_id = COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY;
- attribute->normalized = FALSE;
- attribute->texture_unit = 0;
- status = TRUE;
- }
-
- if (!status)
- {
- _cogl_attribute_free (attribute);
- return NULL;
- }
-
- return _cogl_attribute_object_new (attribute);
-}
-
-gboolean
-cogl_attribute_get_normalized (CoglAttribute *attribute)
-{
- g_return_val_if_fail (cogl_is_attribute (attribute), FALSE);
-
- return attribute->normalized;
-}
-
-static void
-warn_about_midscene_changes (void)
-{
- static gboolean seen = FALSE;
- if (!seen)
- {
- g_warning ("Mid-scene modification of attributes has "
- "undefined results\n");
- seen = TRUE;
- }
-}
-
-void
-cogl_attribute_set_normalized (CoglAttribute *attribute,
- gboolean normalized)
-{
- g_return_if_fail (cogl_is_attribute (attribute));
-
- if (G_UNLIKELY (attribute->immutable_ref))
- warn_about_midscene_changes ();
-
- attribute->normalized = normalized;
-}
-
-CoglVertexArray *
-cogl_attribute_get_array (CoglAttribute *attribute)
-{
- g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
-
- return attribute->array;
-}
-
-void
-cogl_attribute_set_array (CoglAttribute *attribute,
- CoglVertexArray *array)
-{
- g_return_if_fail (cogl_is_attribute (attribute));
-
- if (G_UNLIKELY (attribute->immutable_ref))
- warn_about_midscene_changes ();
-
- cogl_object_ref (array);
-
- cogl_object_unref (attribute->array);
- attribute->array = array;
-}
-
-CoglAttribute *
-_cogl_attribute_immutable_ref (CoglAttribute *attribute)
-{
- g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
-
- attribute->immutable_ref++;
- _cogl_buffer_immutable_ref (COGL_BUFFER (attribute->array));
- return attribute;
-}
-
-void
-_cogl_attribute_immutable_unref (CoglAttribute *attribute)
-{
- g_return_if_fail (cogl_is_attribute (attribute));
- g_return_if_fail (attribute->immutable_ref > 0);
-
- attribute->immutable_ref--;
- _cogl_buffer_immutable_unref (COGL_BUFFER (attribute->array));
-}
-
-static void
-_cogl_attribute_free (CoglAttribute *attribute)
-{
- g_free (attribute->name);
- cogl_object_unref (attribute->array);
-
- g_slice_free (CoglAttribute, attribute);
-}
-
-typedef struct
-{
- int unit;
- CoglPipelineFlushOptions options;
- guint32 fallback_layers;
-} ValidateLayerState;
-
-static gboolean
-validate_layer_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- CoglHandle texture =
- _cogl_pipeline_get_layer_texture (pipeline, layer_index);
- ValidateLayerState *state = user_data;
- gboolean status = TRUE;
-
- /* invalid textures will be handled correctly in
- * _cogl_pipeline_flush_layers_gl_state */
- if (texture == COGL_INVALID_HANDLE)
- goto validated;
-
- _cogl_texture_flush_journal_rendering (texture);
-
- /* Give the texture a chance to know that we're rendering
- non-quad shaped primitives. If the texture is in an atlas it
- will be migrated */
- _cogl_texture_ensure_non_quad_rendering (texture);
-
- /* We need to ensure the mipmaps are ready before deciding
- * anything else about the texture because the texture storate
- * could completely change if it needs to be migrated out of the
- * atlas and will affect how we validate the layer.
- */
- _cogl_pipeline_pre_paint_for_layer (pipeline, layer_index);
-
- if (!_cogl_texture_can_hardware_repeat (texture))
- {
- g_warning ("Disabling layer %d of the current source material, "
- "because texturing with the vertex buffer API is not "
- "currently supported using sliced textures, or textures "
- "with waste\n", layer_index);
-
- /* XXX: maybe we can add a mechanism for users to forcibly use
- * textures with waste where it would be their responsability to use
- * texture coords in the range [0,1] such that sampling outside isn't
- * required. We can then use a texture matrix (or a modification of
- * the users own matrix) to map 1 to the edge of the texture data.
- *
- * Potentially, given the same guarantee as above we could also
- * support a single sliced layer too. We would have to redraw the
- * vertices once for each layer, each time with a fiddled texture
- * matrix.
- */
- state->fallback_layers |= (1 << state->unit);
- state->options.flags |= COGL_PIPELINE_FLUSH_FALLBACK_MASK;
- }
-
-validated:
- state->unit++;
- return status;
-}
-
-static void
-toggle_enabled_cb (int bit_num, void *user_data)
-{
- const CoglBitmask *new_values = user_data;
- gboolean enabled = _cogl_bitmask_get (new_values, bit_num);
-
-#ifdef HAVE_COGL_GLES2
-
- if (enabled)
- GE( glEnableVertexAttribArray (bit_num) );
- else
- GE( glDisableVertexAttribArray (bit_num) );
-
-#else /* HAVE_COGL_GLES2 */
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- GE( glClientActiveTexture (GL_TEXTURE0 + bit_num) );
-
- if (enabled)
- GE( glEnableClientState (GL_TEXTURE_COORD_ARRAY) );
- else
- GE( glDisableClientState (GL_TEXTURE_COORD_ARRAY) );
-
-#endif /* HAVE_COGL_GLES2 */
-}
-
-static void
-set_enabled_arrays (CoglBitmask *value_cache,
- const CoglBitmask *new_values)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Get the list of bits that are different */
- _cogl_bitmask_clear_all (&ctx->arrays_to_change);
- _cogl_bitmask_set_bits (&ctx->arrays_to_change, value_cache);
- _cogl_bitmask_xor_bits (&ctx->arrays_to_change, new_values);
-
- /* Iterate over each bit to change */
- _cogl_bitmask_foreach (&ctx->arrays_to_change,
- toggle_enabled_cb,
- (void *) new_values);
-
- /* Store the new values */
- _cogl_bitmask_clear_all (value_cache);
- _cogl_bitmask_set_bits (value_cache, new_values);
-}
-
-static CoglHandle
-enable_gl_state (CoglDrawFlags flags,
- CoglAttribute **attributes,
- ValidateLayerState *state)
-{
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- int i;
-#ifdef MAY_HAVE_PROGRAMABLE_GL
- GLuint generic_index = 0;
-#endif
- unsigned long enable_flags = 0;
- gboolean skip_gl_color = FALSE;
- CoglPipeline *source;
- CoglPipeline *copy = NULL;
- int n_tex_coord_attribs = 0;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- /* In cogl_read_pixels we have a fast-path when reading a single
- * pixel and the scene is just comprised of simple rectangles still
- * in the journal. For this optimization to work we need to track
- * when the framebuffer really does get drawn to. */
- _cogl_framebuffer_dirty (framebuffer);
-
- source = cogl_get_source ();
-
- /* Iterate the attributes to work out whether blending needs to be
- enabled and how many texture coords there are. We need to do this
- before flushing the pipeline. */
- for (i = 0; attributes[i]; i++)
- switch (attributes[i]->name_id)
- {
- case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
- if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
- !_cogl_pipeline_get_real_blend_enabled (source))
- {
- CoglPipelineBlendEnable blend_enable =
- COGL_PIPELINE_BLEND_ENABLE_ENABLED;
- copy = cogl_pipeline_copy (source);
- _cogl_pipeline_set_blend_enabled (copy, blend_enable);
- source = copy;
- }
- skip_gl_color = TRUE;
- break;
-
- case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
- n_tex_coord_attribs++;
- break;
-
- default:
- break;
- }
-
- if (G_UNLIKELY (state->options.flags))
- {
- /* If we haven't already created a derived pipeline... */
- if (!copy)
- {
- copy = cogl_pipeline_copy (source);
- source = copy;
- }
- _cogl_pipeline_apply_overrides (source, &state->options);
-
- /* TODO:
- * overrides = cogl_pipeline_get_data (pipeline,
- * last_overrides_key);
- * if (overrides)
- * {
- * age = cogl_pipeline_get_age (pipeline);
- * XXX: actually we also need to check for legacy_state
- * and blending overrides for use of glColorPointer...
- * if (overrides->ags != age ||
- * memcmp (&overrides->options, &options,
- * sizeof (options) != 0)
- * {
- * cogl_object_unref (overrides->weak_pipeline);
- * g_slice_free (Overrides, overrides);
- * overrides = NULL;
- * }
- * }
- * if (!overrides)
- * {
- * overrides = g_slice_new (Overrides);
- * overrides->weak_pipeline =
- * cogl_pipeline_weak_copy (cogl_get_source ());
- * _cogl_pipeline_apply_overrides (overrides->weak_pipeline,
- * &options);
- *
- * cogl_pipeline_set_data (pipeline, last_overrides_key,
- * weak_overrides,
- * free_overrides_cb,
- * NULL);
- * }
- * source = overrides->weak_pipeline;
- */
- }
-
- if (G_UNLIKELY (ctx->legacy_state_set) &&
- (flags & COGL_DRAW_SKIP_LEGACY_STATE) == 0)
- {
- /* If we haven't already created a derived pipeline... */
- if (!copy)
- {
- copy = cogl_pipeline_copy (source);
- source = copy;
- }
- _cogl_pipeline_apply_legacy_state (source);
- }
-
- _cogl_pipeline_flush_gl_state (source, skip_gl_color, n_tex_coord_attribs);
-
- if (ctx->enable_backface_culling)
- enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
-
- _cogl_bitmask_clear_all (&ctx->temp_bitmask);
-
- /* Bind the attribute pointers. We need to do this after the
- pipeline is flushed because on GLES2 that is the only point when
- we can determine the attribute locations */
-
- for (i = 0; attributes[i]; i++)
- {
- CoglAttribute *attribute = attributes[i];
- CoglVertexArray *vertex_array;
- CoglBuffer *buffer;
- guint8 *base;
-#ifdef HAVE_COGL_GLES2
- int attrib_location;
-#endif
-
- vertex_array = cogl_attribute_get_array (attribute);
- buffer = COGL_BUFFER (vertex_array);
- base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY);
-
- switch (attribute->name_id)
- {
- case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
-#ifdef HAVE_COGL_GLES2
-
- attrib_location =
- _cogl_pipeline_progend_glsl_get_color_attribute (source);
- if (attrib_location != -1)
- {
- GE( glVertexAttribPointer (attrib_location,
- attribute->n_components,
- attribute->type,
- TRUE, /* normalize */
- attribute->stride,
- base + attribute->offset) );
-
- _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
- }
-
-#else
-
- enable_flags |= COGL_ENABLE_COLOR_ARRAY;
- /* GE (glEnableClientState (GL_COLOR_ARRAY)); */
- GE (glColorPointer (attribute->n_components,
- attribute->type,
- attribute->stride,
- base + attribute->offset));
-
-#endif
-
- break;
- case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
-#ifdef HAVE_COGL_GLES2
-
- attrib_location =
- _cogl_pipeline_progend_glsl_get_normal_attribute (source);
- if (attrib_location != -1)
- {
- GE( glVertexAttribPointer (attrib_location,
- attribute->n_components,
- attribute->type,
- TRUE, /* normalize */
- attribute->stride,
- base + attribute->offset) );
- _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
- }
-
-#else
-
- /* FIXME: go through cogl cache to enable normal array */
- GE (glEnableClientState (GL_NORMAL_ARRAY));
- GE (glNormalPointer (attribute->type,
- attribute->stride,
- base + attribute->offset));
-
-#endif
-
- break;
- case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
-#ifdef HAVE_COGL_GLES2
-
- attrib_location = _cogl_pipeline_progend_glsl_get_tex_coord_attribute
- (source, attribute->texture_unit);
- if (attrib_location != -1)
- {
- GE( glVertexAttribPointer (attrib_location,
- attribute->n_components,
- attribute->type,
- FALSE, /* normalize */
- attribute->stride,
- base + attribute->offset) );
- _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
- }
-#else
-
- GE (glClientActiveTexture (GL_TEXTURE0 +
- attribute->texture_unit));
- GE (glTexCoordPointer (attribute->n_components,
- attribute->type,
- attribute->stride,
- base + attribute->offset));
- _cogl_bitmask_set (&ctx->temp_bitmask,
- attribute->texture_unit, TRUE);
-
-#endif
- break;
- case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
-#ifdef HAVE_COGL_GLES2
-
- attrib_location =
- _cogl_pipeline_progend_glsl_get_position_attribute (source);
- if (attrib_location != -1)
- {
- GE( glVertexAttribPointer (attrib_location,
- attribute->n_components,
- attribute->type,
- FALSE, /* normalize */
- attribute->stride,
- base + attribute->offset) );
- _cogl_bitmask_set (&ctx->temp_bitmask, attrib_location, TRUE);
- }
-
-#else
-
- enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
- /* GE (glEnableClientState (GL_VERTEX_ARRAY)); */
- GE (glVertexPointer (attribute->n_components,
- attribute->type,
- attribute->stride,
- base + attribute->offset));
-
-#endif
- break;
- case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
- {
-#ifdef MAY_HAVE_PROGRAMABLE_GL
- /* FIXME: go through cogl cache to enable generic array. */
- /* FIXME: this is going to end up just using the builtins
- on GLES 2 */
- GE (glEnableVertexAttribArray (generic_index++));
- GE (glVertexAttribPointer (generic_index,
- attribute->n_components,
- attribute->type,
- attribute->normalized,
- attribute->stride,
- base + attribute->offset));
-#endif
- }
- break;
- default:
- g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
- }
-
- _cogl_buffer_unbind (buffer);
- }
-
- /* Flush the state of the attribute arrays */
- set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask);
-
- _cogl_enable (enable_flags);
- _cogl_flush_face_winding ();
-
- return source;
-}
-
-void
-_cogl_attribute_disable_cached_arrays (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_bitmask_clear_all (&ctx->temp_bitmask);
- set_enabled_arrays (&ctx->arrays_enabled, &ctx->temp_bitmask);
-}
-
-/* FIXME: we shouldn't be disabling state after drawing we should
- * just disable the things not needed after enabling state. */
-static void
-disable_gl_state (CoglAttribute **attributes,
- CoglPipeline *source)
-{
-#ifdef MAY_HAVE_PROGRAMABLE_GL
- GLuint generic_index = 0;
-#endif
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (G_UNLIKELY (source != cogl_get_source ()))
- cogl_object_unref (source);
-
- for (i = 0; attributes[i]; i++)
- {
- CoglAttribute *attribute = attributes[i];
-
- switch (attribute->name_id)
- {
- case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
- /* GE (glDisableClientState (GL_COLOR_ARRAY)); */
- break;
- case COGL_ATTRIBUTE_NAME_ID_NORMAL_ARRAY:
- /* FIXME: go through cogl cache to enable normal array */
-#ifndef HAVE_COGL_GLES2
- GE (glDisableClientState (GL_NORMAL_ARRAY));
-#endif
- break;
- case COGL_ATTRIBUTE_NAME_ID_TEXTURE_COORD_ARRAY:
- /* The enabled state of the texture coord arrays is
- cached in ctx->enabled_texcoord_arrays so we don't
- need to do anything here. The array will be disabled
- by the next drawing primitive if it is not
- required */
- break;
- case COGL_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
- /* GE (glDisableClientState (GL_VERTEX_ARRAY)); */
- break;
- case COGL_ATTRIBUTE_NAME_ID_CUSTOM_ARRAY:
-#ifdef MAY_HAVE_PROGRAMABLE_GL
- /* FIXME: go through cogl cache to enable generic array */
- GE (glDisableVertexAttribArray (generic_index++));
-#endif
- break;
- default:
- g_warning ("Unrecognised attribute type 0x%08x", attribute->type);
- }
- }
-}
-
-#ifdef COGL_ENABLE_DEBUG
-static int
-get_index (void *indices,
- CoglIndicesType type,
- int _index)
-{
- if (!indices)
- return _index;
-
- switch (type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- return ((guint8 *)indices)[_index];
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- return ((guint16 *)indices)[_index];
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- return ((guint32 *)indices)[_index];
- }
-
- g_return_val_if_reached (0);
-}
-
-static void
-add_line (void *vertices,
- void *indices,
- CoglIndicesType indices_type,
- CoglAttribute *attribute,
- int start,
- int end,
- CoglVertexP3 *lines,
- int *n_line_vertices)
-{
- int start_index = get_index (indices, indices_type, start);
- int end_index = get_index (indices, indices_type, end);
- float *v0 = (float *)((guint8 *)vertices + start_index * attribute->stride);
- float *v1 = (float *)((guint8 *)vertices + end_index * attribute->stride);
- float *o = (float *)(&lines[*n_line_vertices]);
- int i;
-
- for (i = 0; i < attribute->n_components; i++)
- *(o++) = *(v0++);
- for (;i < 3; i++)
- *(o++) = 0;
-
- for (i = 0; i < attribute->n_components; i++)
- *(o++) = *(v1++);
- for (;i < 3; i++)
- *(o++) = 0;
-
- *n_line_vertices += 2;
-}
-
-static CoglVertexP3 *
-get_wire_lines (CoglAttribute *attribute,
- CoglVerticesMode mode,
- int n_vertices_in,
- int *n_vertices_out,
- CoglIndices *_indices)
-{
- CoglVertexArray *vertex_array = cogl_attribute_get_array (attribute);
- void *vertices;
- CoglIndexArray *index_array;
- void *indices;
- CoglIndicesType indices_type;
- int i;
- int n_lines;
- CoglVertexP3 *out = NULL;
-
- vertices = cogl_buffer_map (COGL_BUFFER (vertex_array),
- COGL_BUFFER_ACCESS_READ, 0);
- if (_indices)
- {
- index_array = cogl_indices_get_array (_indices);
- indices = cogl_buffer_map (COGL_BUFFER (index_array),
- COGL_BUFFER_ACCESS_READ, 0);
- indices_type = cogl_indices_get_type (_indices);
- }
- else
- {
- index_array = NULL;
- indices = NULL;
- indices_type = COGL_INDICES_TYPE_UNSIGNED_BYTE;
- }
-
- *n_vertices_out = 0;
-
- if (mode == COGL_VERTICES_MODE_TRIANGLES &&
- (n_vertices_in % 3) == 0)
- {
- n_lines = n_vertices_in;
- out = g_new (CoglVertexP3, n_lines * 2);
- for (i = 0; i < n_vertices_in; i += 3)
- {
- add_line (vertices, indices, indices_type, attribute,
- i, i+1, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i+1, i+2, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i+2, i, out, n_vertices_out);
- }
- }
- else if (mode == COGL_VERTICES_MODE_TRIANGLE_FAN &&
- n_vertices_in >= 3)
- {
- n_lines = 2 * n_vertices_in - 3;
- out = g_new (CoglVertexP3, n_lines * 2);
-
- add_line (vertices, indices, indices_type, attribute,
- 0, 1, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- 1, 2, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- 0, 2, out, n_vertices_out);
-
- for (i = 3; i < n_vertices_in; i++)
- {
- add_line (vertices, indices, indices_type, attribute,
- i - 1, i, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- 0, i, out, n_vertices_out);
- }
- }
- else if (mode == COGL_VERTICES_MODE_TRIANGLE_STRIP &&
- n_vertices_in >= 3)
- {
- n_lines = 2 * n_vertices_in - 3;
- out = g_new (CoglVertexP3, n_lines * 2);
-
- add_line (vertices, indices, indices_type, attribute,
- 0, 1, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- 1, 2, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- 0, 2, out, n_vertices_out);
-
- for (i = 3; i < n_vertices_in; i++)
- {
- add_line (vertices, indices, indices_type, attribute,
- i - 1, i, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i - 2, i, out, n_vertices_out);
- }
- }
- /* In the journal we are a bit sneaky and actually use GL_QUADS
- * which isn't actually a valid CoglVerticesMode! */
-#ifdef HAVE_COGL_GL
- else if (mode == GL_QUADS && (n_vertices_in % 4) == 0)
- {
- n_lines = n_vertices_in;
- out = g_new (CoglVertexP3, n_lines * 2);
-
- for (i = 0; i < n_vertices_in; i += 4)
- {
- add_line (vertices, indices, indices_type, attribute,
- i, i + 1, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i + 1, i + 2, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i + 2, i + 3, out, n_vertices_out);
- add_line (vertices, indices, indices_type, attribute,
- i + 3, i, out, n_vertices_out);
- }
- }
-#endif
-
- if (vertices != NULL)
- cogl_buffer_unmap (COGL_BUFFER (vertex_array));
-
- if (indices != NULL)
- cogl_buffer_unmap (COGL_BUFFER (index_array));
-
- return out;
-}
-
-static void
-draw_wireframe (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglAttribute **attributes,
- CoglIndices *indices)
-{
- CoglAttribute *position = NULL;
- int i;
- int n_line_vertices;
- static CoglPipeline *wire_pipeline;
- CoglAttribute *wire_attribute[2];
- CoglVertexP3 *lines;
- CoglVertexArray *array;
-
- for (i = 0; attributes[i]; i++)
- {
- if (strcmp (attributes[i]->name, "cogl_position_in") == 0)
- {
- position = attributes[i];
- break;
- }
- }
- if (!position)
- return;
-
- lines = get_wire_lines (position,
- mode,
- n_vertices,
- &n_line_vertices,
- indices);
- array = cogl_vertex_array_new (sizeof (CoglVertexP3) * n_line_vertices,
- lines);
- wire_attribute[0] =
- cogl_attribute_new (array, "cogl_position_in",
- sizeof (CoglVertexP3),
- 0,
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- wire_attribute[1] = NULL;
- cogl_object_unref (array);
-
- if (!wire_pipeline)
- {
- wire_pipeline = cogl_pipeline_new ();
- cogl_pipeline_set_color4ub (wire_pipeline,
- 0x00, 0xff, 0x00, 0xff);
- }
-
- cogl_push_source (wire_pipeline);
-
- /* temporarily disable the wireframe to avoid recursion! */
- COGL_DEBUG_CLEAR_FLAG (COGL_DEBUG_WIREFRAME);
- _cogl_draw_attributes_array (COGL_VERTICES_MODE_LINES,
- 0,
- n_line_vertices,
- wire_attribute,
- COGL_DRAW_SKIP_JOURNAL_FLUSH |
- COGL_DRAW_SKIP_PIPELINE_VALIDATION |
- COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH |
- COGL_DRAW_SKIP_LEGACY_STATE);
-
- COGL_DEBUG_SET_FLAG (COGL_DEBUG_WIREFRAME);
-
- cogl_pop_source ();
-
- cogl_object_unref (wire_attribute[0]);
-}
-#endif
-
-static void
-flush_state (CoglDrawFlags flags,
- ValidateLayerState *state)
-{
- if (!(flags & COGL_DRAW_SKIP_JOURNAL_FLUSH))
- {
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- _cogl_journal_flush (framebuffer->journal, framebuffer);
- }
-
- state->unit = 0;
- state->options.flags = 0;
- state->fallback_layers = 0;
-
- if (!(flags & COGL_DRAW_SKIP_PIPELINE_VALIDATION))
- cogl_pipeline_foreach_layer (cogl_get_source (),
- validate_layer_cb,
- state);
-
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. We need to do this
- * before setting up the array pointers because setting up the clip
- * stack can cause some drawing which would change the array
- * pointers. */
- if (!(flags & COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH))
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- _cogl_get_read_framebuffer (),
- 0);
-}
-
-/* This can be called directly by the CoglJournal to draw attributes
- * skipping the implicit journal flush, the framebuffer flush and
- * pipeline validation. */
-void
-_cogl_draw_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglAttribute **attributes,
- CoglDrawFlags flags)
-{
- ValidateLayerState state;
- CoglPipeline *source;
-
- flush_state (flags, &state);
-
- source = enable_gl_state (flags, attributes, &state);
-
- GE (glDrawArrays ((GLenum)mode, first_vertex, n_vertices));
-
- /* FIXME: we shouldn't be disabling state after drawing we should
- * just disable the things not needed after enabling state. */
- disable_gl_state (attributes, source);
-
-#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
- draw_wireframe (mode, first_vertex, n_vertices, attributes, NULL);
-#endif
-}
-
-void
-cogl_draw_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglAttribute **attributes)
-{
- _cogl_draw_attributes_array (mode, first_vertex,
- n_vertices, attributes,
- 0 /* no flags */);
-}
-
-void
-cogl_draw_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- ...)
-{
- va_list ap;
- int n_attributes;
- CoglAttribute *attribute;
- CoglAttribute **attributes;
- int i;
-
- va_start (ap, n_vertices);
- for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
- ;
- va_end (ap);
-
- attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
- attributes[n_attributes] = NULL;
-
- va_start (ap, n_vertices);
- for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
- attributes[i] = attribute;
- va_end (ap);
-
- cogl_draw_attributes_array (mode, first_vertex, n_vertices,
- attributes);
-}
-
-static size_t
-sizeof_index_type (CoglIndicesType type)
-{
- switch (type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- return 1;
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- return 2;
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- return 4;
- }
- g_return_val_if_reached (0);
-}
-
-void
-_cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglAttribute **attributes,
- CoglDrawFlags flags)
-{
- ValidateLayerState state;
- CoglPipeline *source;
- CoglBuffer *buffer;
- guint8 *base;
- size_t array_offset;
- size_t index_size;
- GLenum indices_gl_type = 0;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- flush_state (flags, &state);
-
- source = enable_gl_state (flags, attributes, &state);
-
- buffer = COGL_BUFFER (cogl_indices_get_array (indices));
- base = _cogl_buffer_bind (buffer, COGL_BUFFER_BIND_TARGET_INDEX_ARRAY);
- array_offset = cogl_indices_get_offset (indices);
- index_size = sizeof_index_type (cogl_indices_get_type (indices));
-
- switch (cogl_indices_get_type (indices))
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- indices_gl_type = GL_UNSIGNED_BYTE;
- break;
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- indices_gl_type = GL_UNSIGNED_SHORT;
- break;
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- indices_gl_type = GL_UNSIGNED_INT;
- break;
- }
-
- GE (glDrawElements ((GLenum)mode,
- n_vertices,
- indices_gl_type,
- base + array_offset + index_size * first_vertex));
-
- _cogl_buffer_unbind (buffer);
-
- /* FIXME: we shouldn't be disabling state after drawing we should
- * just disable the things not needed after enabling state. */
- disable_gl_state (attributes, source);
-
-#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_WIREFRAME)))
- draw_wireframe (mode, first_vertex, n_vertices, attributes, indices);
-#endif
-}
-
-void
-cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglAttribute **attributes)
-{
- _cogl_draw_indexed_attributes_array (mode, first_vertex,
- n_vertices, indices, attributes,
- 0 /* no flags */);
-}
-
-void
-cogl_draw_indexed_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- ...)
-{
- va_list ap;
- int n_attributes;
- CoglAttribute **attributes;
- int i;
- CoglAttribute *attribute;
-
- va_start (ap, indices);
- for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
- ;
- va_end (ap);
-
- attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
- attributes[n_attributes] = NULL;
-
- va_start (ap, indices);
- for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
- attributes[i] = attribute;
- va_end (ap);
-
- cogl_draw_indexed_attributes_array (mode,
- first_vertex,
- n_vertices,
- indices,
- attributes);
-}
-
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_ATTRIBUTE_H__
-#define __COGL_ATTRIBUTE_H__
-
-#include <cogl/cogl-vertex-array.h>
-#include <cogl/cogl-indices.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-attribute
- * @short_description: Functions for declaring and drawing vertex
- * attributes
- *
- * FIXME
- */
-
-typedef struct _CoglAttribute CoglAttribute;
-
-/**
- * cogl_attribute_new:
- * @array: The #CoglVertexArray containing the actual attribute data
- * @name: The name of the attribute (used to reference it from GLSL)
- * @stride: The number of bytes to jump to get to the next attribute
- * value for the next vertex. (Usually
- * <pre>sizeof (MyVertex)</pre>)
- * @offset: The byte offset from the start of @array for the first
- * attribute value. (Usually
- * <pre>offsetof (MyVertex, component0)</pre>
- * @components: The number of components (e.g. 4 for an rgba color or
- * 3 for and (x,y,z) position)
- * @type: FIXME
- *
- * Describes the layout for a list of vertex attribute values (For
- * example, a list of texture coordinates or colors).
- *
- * The @name is used to access the attribute inside a GLSL vertex
- * shader and there are some special names you should use if they are
- * applicable:
- * <itemizedlist>
- * <listitem>"cogl_position_in" (used for vertex positions)</listitem>
- * <listitem>"cogl_color_in" (used for vertex colors)</listitem>
- * <listitem>"cogl_tex_coord0_in", "cogl_tex_coord1", ...
- * (used for vertex texture coordinates)</listitem>
- * <listitem>"cogl_normal_in" (used for vertex normals)</listitem>
- * </itemizedlist>
- *
- * The attribute values corresponding to different vertices can either
- * be tightly packed or interleaved with other attribute values. For
- * example it's common to define a structure for a single vertex like:
- * |[
- * typedef struct
- * {
- * float x, y, z; /<!-- -->* position attribute *<!-- -->/
- * float s, t; /<!-- -->* texture coordinate attribute *<!-- -->/
- * } MyVertex;
- * ]|
- *
- * And then create an array of vertex data something like:
- * |[
- * MyVertex vertices[100] = { .... }
- * ]|
- *
- * In this case, to describe either the position or texture coordinate
- * attribute you have to move <pre>sizeof (MyVertex)</pre> bytes to
- * move from one vertex to the next. This is called the attribute
- * @stride. If you weren't interleving attributes and you instead had
- * a packed array of float x, y pairs then the attribute stride would
- * be <pre>(2 * sizeof (float))</pre>. So the @stride is the number of
- * bytes to move to find the attribute value of the next vertex.
- *
- * Normally a list of attributes starts at the beginning of an array.
- * So for the <pre>MyVertex</pre> example above the @offset is the
- * offset inside the <pre>MyVertex</pre> structure to the first
- * component of the attribute. For the texture coordinate attribute
- * the offset would be <pre>offsetof (MyVertex, s)</pre> or instead of
- * using the offsetof macro you could use <pre>sizeof (float) * 3</pre>.
- * If you've divided your @array into blocks of non-interleved
- * attributes then you will need to calculate the @offset as the
- * number of bytes in blocks preceding the attribute you're
- * describing.
- *
- * An attribute often has more than one component. For example a color
- * is often comprised of 4 red, green, blue and alpha @components, and a
- * position may be comprised of 2 x and y @components. You should aim
- * to keep the number of components to a minimum as more components
- * means more data needs to be mapped into the GPU which can be a
- * bottlneck when dealing with a large number of vertices.
- *
- * Finally you need to specify the component data type. Here you
- * should aim to use the smallest type that meets your precision
- * requirements. Again the larger the type then more data needs to be
- * mapped into the GPU which can be a bottlneck when dealing with
- * a large number of vertices.
- *
- * Returns: A newly allocated #CoglAttribute describing the
- * layout for a list of attribute values stored in @array.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-/* XXX: look for a precedent to see if the stride/offset args should
- * have a different order. */
-CoglAttribute *
-cogl_attribute_new (CoglVertexArray *array,
- const char *name,
- gsize stride,
- gsize offset,
- int components,
- CoglAttributeType type);
-
-/**
- * cogl_is_attribute:
- * @object: A #CoglObject
- *
- * Gets whether the given object references a #CoglAttribute.
- *
- * Return value: %TRUE if the handle references a #CoglAttribute,
- * %FALSE otherwise
- */
-gboolean
-cogl_is_attribute (void *object);
-
-void
-cogl_draw_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- ...) G_GNUC_NULL_TERMINATED;
-
-void
-cogl_draw_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglAttribute **attributes);
-
-void
-cogl_draw_indexed_attributes (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- ...) G_GNUC_NULL_TERMINATED;
-
-void
-cogl_draw_indexed_attributes_array (CoglVerticesMode mode,
- int first_vertex,
- int n_vertices,
- CoglIndices *indices,
- CoglAttribute **attributes);
-
-G_END_DECLS
-
-#endif /* __COGL_ATTRIBUTE_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-bitmap-private.h"
-
-#include <string.h>
-
-/* TO rgba */
-
-inline static void
-_cogl_g_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[0];
- dst[1] = src[0];
- dst[2] = src[0];
- dst[3] = 255;
-}
-
-inline static void
-_cogl_rgb_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = 255;
-}
-
-inline static void
-_cogl_bgr_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[2];
- dst[1] = src[1];
- dst[2] = src[0];
- dst[3] = 255;
-}
-
-inline static void
-_cogl_bgra_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[2];
- dst[1] = src[1];
- dst[2] = src[0];
- dst[3] = src[3];
-}
-
-inline static void
-_cogl_argb_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[1];
- dst[1] = src[2];
- dst[2] = src[3];
- dst[3] = src[0];
-}
-
-inline static void
-_cogl_abgr_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
-}
-
-inline static void
-_cogl_rgba_to_rgba (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
- dst[3] = src[3];
-}
-
-/* FROM rgba */
-
-inline static void
-_cogl_rgba_to_g (const guint8 *src, guint8 *dst)
-{
- dst[0] = (src[0] + src[1] + src[2]) / 3;
-}
-
-inline static void
-_cogl_rgba_to_rgb (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[0];
- dst[1] = src[1];
- dst[2] = src[2];
-}
-
-inline static void
-_cogl_rgba_to_bgr (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[2];
- dst[1] = src[1];
- dst[2] = src[0];
-}
-
-inline static void
-_cogl_rgba_to_bgra (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[2];
- dst[1] = src[1];
- dst[2] = src[0];
- dst[3] = src[3];
-}
-
-inline static void
-_cogl_rgba_to_argb (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[3];
- dst[1] = src[0];
- dst[2] = src[1];
- dst[3] = src[2];
-}
-
-inline static void
-_cogl_rgba_to_abgr (const guint8 *src, guint8 *dst)
-{
- dst[0] = src[3];
- dst[1] = src[2];
- dst[2] = src[1];
- dst[3] = src[0];
-}
-
-/* (Un)Premultiplication */
-
-inline static void
-_cogl_unpremult_alpha_0 (guint8 *dst)
-{
- dst[0] = 0;
- dst[1] = 0;
- dst[2] = 0;
- dst[3] = 0;
-}
-
-inline static void
-_cogl_unpremult_alpha_last (guint8 *dst)
-{
- guint8 alpha = dst[3];
-
- dst[0] = (dst[0] * 255) / alpha;
- dst[1] = (dst[1] * 255) / alpha;
- dst[2] = (dst[2] * 255) / alpha;
-}
-
-inline static void
-_cogl_unpremult_alpha_first (guint8 *dst)
-{
- guint8 alpha = dst[0];
-
- dst[1] = (dst[1] * 255) / alpha;
- dst[2] = (dst[2] * 255) / alpha;
- dst[3] = (dst[3] * 255) / alpha;
-}
-
-/* No division form of floor((c*a + 128)/255) (I first encountered
- * this in the RENDER implementation in the X server.) Being exact
- * is important for a == 255 - we want to get exactly c.
- */
-#define MULT(d,a,t) \
- G_STMT_START { \
- t = d * a + 128; \
- d = ((t >> 8) + t) >> 8; \
- } G_STMT_END
-
-inline static void
-_cogl_premult_alpha_last (guint8 *dst)
-{
- guint8 alpha = dst[3];
- /* Using a separate temporary per component has given slightly better
- * code generation with GCC in the past; it shouldn't do any worse in
- * any case.
- */
- unsigned int t1, t2, t3;
- MULT(dst[0], alpha, t1);
- MULT(dst[1], alpha, t2);
- MULT(dst[2], alpha, t3);
-}
-
-inline static void
-_cogl_premult_alpha_first (guint8 *dst)
-{
- guint8 alpha = dst[0];
- unsigned int t1, t2, t3;
-
- MULT(dst[1], alpha, t1);
- MULT(dst[2], alpha, t2);
- MULT(dst[3], alpha, t3);
-}
-
-#undef MULT
-
-/* Use the SSE optimized version to premult four pixels at once when
- it is available. The same assembler code works for x86 and x86-64
- because it doesn't refer to any non-SSE registers directly */
-#if defined(__SSE2__) && defined(__GNUC__) \
- && (defined(__x86_64) || defined(__i386))
-#define COGL_USE_PREMULT_SSE2
-#endif
-
-#ifdef COGL_USE_PREMULT_SSE2
-
-inline static void
-_cogl_premult_alpha_last_four_pixels_sse2 (guint8 *p)
-{
- /* 8 copies of 128 used below */
- static const gint16 eight_halves[8] __attribute__ ((aligned (16))) =
- { 128, 128, 128, 128, 128, 128, 128, 128 };
- /* Mask of the rgb components of the four pixels */
- static const gint8 just_rgb[16] __attribute__ ((aligned (16))) =
- { 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00,
- 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00 };
- /* Each SSE register only holds two pixels because we need to work
- with 16-bit intermediate values. We still do four pixels by
- interleaving two registers in the hope that it will pipeline
- better */
- asm (/* Load eight_halves into xmm5 for later */
- "movdqa (%1), %%xmm5\n"
- /* Clear xmm3 */
- "pxor %%xmm3, %%xmm3\n"
- /* Load two pixels from p into the low half of xmm0 */
- "movlps (%0), %%xmm0\n"
- /* Load the next set of two pixels from p into the low half of xmm1 */
- "movlps 8(%0), %%xmm1\n"
- /* Unpack 8 bytes from the low quad-words in each register to 8
- 16-bit values */
- "punpcklbw %%xmm3, %%xmm0\n"
- "punpcklbw %%xmm3, %%xmm1\n"
- /* Copy alpha values of the first pixel in xmm0 to all
- components of the first pixel in xmm2 */
- "pshuflw $255, %%xmm0, %%xmm2\n"
- /* same for xmm1 and xmm3 */
- "pshuflw $255, %%xmm1, %%xmm3\n"
- /* The above also copies the second pixel directly so we now
- want to replace the RGB components with copies of the alpha
- components */
- "pshufhw $255, %%xmm2, %%xmm2\n"
- "pshufhw $255, %%xmm3, %%xmm3\n"
- /* Multiply the rgb components by the alpha */
- "pmullw %%xmm2, %%xmm0\n"
- "pmullw %%xmm3, %%xmm1\n"
- /* Add 128 to each component */
- "paddw %%xmm5, %%xmm0\n"
- "paddw %%xmm5, %%xmm1\n"
- /* Copy the results to temporary registers xmm4 and xmm5 */
- "movdqa %%xmm0, %%xmm4\n"
- "movdqa %%xmm1, %%xmm5\n"
- /* Divide the results by 256 */
- "psrlw $8, %%xmm0\n"
- "psrlw $8, %%xmm1\n"
- /* Add the temporaries back in */
- "paddw %%xmm4, %%xmm0\n"
- "paddw %%xmm5, %%xmm1\n"
- /* Divide again */
- "psrlw $8, %%xmm0\n"
- "psrlw $8, %%xmm1\n"
- /* Pack the results back as bytes */
- "packuswb %%xmm1, %%xmm0\n"
- /* Load just_rgb into xmm3 for later */
- "movdqa (%2), %%xmm3\n"
- /* Reload all four pixels into xmm2 */
- "movups (%0), %%xmm2\n"
- /* Mask out the alpha from the results */
- "andps %%xmm3, %%xmm0\n"
- /* Mask out the RGB from the original four pixels */
- "andnps %%xmm2, %%xmm3\n"
- /* Combine the two to get the right alpha values */
- "orps %%xmm3, %%xmm0\n"
- /* Write to memory */
- "movdqu %%xmm0, (%0)\n"
- : /* no outputs */
- : "r" (p), "r" (eight_halves), "r" (just_rgb)
- : "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
-}
-
-#endif /* COGL_USE_PREMULT_SSE2 */
-
-gboolean
-_cogl_bitmap_fallback_can_convert (CoglPixelFormat src, CoglPixelFormat dst)
-{
- if (src == dst)
- return FALSE;
-
- switch (src & COGL_UNORDERED_MASK)
- {
- case COGL_PIXEL_FORMAT_G_8:
- case COGL_PIXEL_FORMAT_24:
- case COGL_PIXEL_FORMAT_32:
-
- if ((dst & COGL_UNORDERED_MASK) != COGL_PIXEL_FORMAT_24 &&
- (dst & COGL_UNORDERED_MASK) != COGL_PIXEL_FORMAT_32 &&
- (dst & COGL_UNORDERED_MASK) != COGL_PIXEL_FORMAT_G_8)
- return FALSE;
- break;
-
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
-gboolean
-_cogl_bitmap_fallback_can_unpremult (CoglPixelFormat format)
-{
- return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
-}
-
-gboolean
-_cogl_bitmap_fallback_can_premult (CoglPixelFormat format)
-{
- return ((format & COGL_UNORDERED_MASK) == COGL_PIXEL_FORMAT_32);
-}
-
-CoglBitmap *
-_cogl_bitmap_fallback_convert (CoglBitmap *src_bmp,
- CoglPixelFormat dst_format)
-{
- guint8 *src_data;
- guint8 *dst_data;
- guint8 *src;
- guint8 *dst;
- int src_bpp;
- int dst_bpp;
- int src_rowstride;
- int dst_rowstride;
- int x,y;
- guint8 temp_rgba[4] = {0,0,0,0};
- int width, height;
- CoglPixelFormat src_format;
-
- src_format = _cogl_bitmap_get_format (src_bmp);
- src_rowstride = _cogl_bitmap_get_rowstride (src_bmp);
- width = _cogl_bitmap_get_width (src_bmp);
- height = _cogl_bitmap_get_height (src_bmp);
-
- /* Make sure conversion supported */
- if (!_cogl_bitmap_fallback_can_convert (src_format, dst_format))
- return NULL;
-
- src_data = _cogl_bitmap_map (src_bmp, COGL_BUFFER_ACCESS_READ, 0);
- if (src_data == NULL)
- return NULL;
-
- src_bpp = _cogl_get_format_bpp (src_format);
- dst_bpp = _cogl_get_format_bpp (dst_format);
-
- /* Initialize destination bitmap */
- dst_rowstride = sizeof(guint8) * dst_bpp * width;
- /* Copy the premult bit if the new format has an alpha channel */
- if ((dst_format & COGL_A_BIT))
- dst_format = ((src_format & COGL_PREMULT_BIT) |
- (dst_format & COGL_UNPREMULT_MASK));
-
- /* Allocate a new buffer to hold converted data */
- dst_data = g_malloc (height * dst_rowstride);
-
- /* FIXME: Optimize */
- for (y = 0; y < height; y++)
- {
- src = src_data + y * src_rowstride;
- dst = dst_data + y * dst_rowstride;
-
- for (x = 0; x < width; x++)
- {
- /* FIXME: Would be nice to at least remove this inner
- * branching, but not sure it can be done without
- * rewriting of the whole loop */
- switch (src_format & COGL_UNPREMULT_MASK)
- {
- case COGL_PIXEL_FORMAT_G_8:
- _cogl_g_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_RGB_888:
- _cogl_rgb_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_BGR_888:
- _cogl_bgr_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_RGBA_8888:
- _cogl_rgba_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_BGRA_8888:
- _cogl_bgra_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_ARGB_8888:
- _cogl_argb_to_rgba (src, temp_rgba); break;
- case COGL_PIXEL_FORMAT_ABGR_8888:
- _cogl_abgr_to_rgba (src, temp_rgba); break;
- default:
- break;
- }
-
- switch (dst_format & COGL_UNPREMULT_MASK)
- {
- case COGL_PIXEL_FORMAT_G_8:
- _cogl_rgba_to_g (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_RGB_888:
- _cogl_rgba_to_rgb (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_BGR_888:
- _cogl_rgba_to_bgr (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_RGBA_8888:
- _cogl_rgba_to_rgba (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_BGRA_8888:
- _cogl_rgba_to_bgra (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_ARGB_8888:
- _cogl_rgba_to_argb (temp_rgba, dst); break;
- case COGL_PIXEL_FORMAT_ABGR_8888:
- _cogl_rgba_to_abgr (temp_rgba, dst); break;
- default:
- break;
- }
-
- src += src_bpp;
- dst += dst_bpp;
- }
- }
-
- _cogl_bitmap_unmap (src_bmp);
-
- return _cogl_bitmap_new_from_data (dst_data,
- dst_format,
- width, height, dst_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-}
-
-gboolean
-_cogl_bitmap_fallback_unpremult (CoglBitmap *bmp)
-{
- guint8 *p, *data;
- int x,y;
- CoglPixelFormat format;
- int width, height;
- int rowstride;
-
- format = _cogl_bitmap_get_format (bmp);
- width = _cogl_bitmap_get_width (bmp);
- height = _cogl_bitmap_get_height (bmp);
- rowstride = _cogl_bitmap_get_rowstride (bmp);
-
- /* Make sure format supported for un-premultiplication */
- if (!_cogl_bitmap_fallback_can_unpremult (format))
- return FALSE;
-
- if ((data = _cogl_bitmap_map (bmp,
- COGL_BUFFER_ACCESS_READ |
- COGL_BUFFER_ACCESS_WRITE,
- 0)) == NULL)
- return FALSE;
-
- for (y = 0; y < height; y++)
- {
- p = (guint8*) data + y * rowstride;
-
- if (format & COGL_AFIRST_BIT)
- {
- for (x = 0; x < width; x++)
- {
- if (p[0] == 0)
- _cogl_unpremult_alpha_0 (p);
- else
- _cogl_unpremult_alpha_first (p);
- p += 4;
- }
- }
- else
- {
- for (x = 0; x < width; x++)
- {
- if (p[3] == 0)
- _cogl_unpremult_alpha_0 (p);
- else
- _cogl_unpremult_alpha_last (p);
- p += 4;
- }
- }
- }
-
- _cogl_bitmap_unmap (bmp);
-
- _cogl_bitmap_set_format (bmp, format & ~COGL_PREMULT_BIT);
-
- return TRUE;
-}
-
-gboolean
-_cogl_bitmap_fallback_premult (CoglBitmap *bmp)
-{
- guint8 *p, *data;
- int x,y;
- CoglPixelFormat format;
- int width, height;
- int rowstride;
-
- format = _cogl_bitmap_get_format (bmp);
- width = _cogl_bitmap_get_width (bmp);
- height = _cogl_bitmap_get_height (bmp);
- rowstride = _cogl_bitmap_get_rowstride (bmp);
-
- /* Make sure format supported for un-premultiplication */
- if (!_cogl_bitmap_fallback_can_premult (format))
- return FALSE;
-
- if ((data = _cogl_bitmap_map (bmp,
- COGL_BUFFER_ACCESS_READ |
- COGL_BUFFER_ACCESS_WRITE,
- 0)) == NULL)
- return FALSE;
-
- for (y = 0; y < height; y++)
- {
- p = (guint8*) data + y * rowstride;
-
- if (format & COGL_AFIRST_BIT)
- {
- for (x = 0; x < width; x++)
- {
- _cogl_premult_alpha_first (p);
- p += 4;
- }
- }
- else
- {
- x = width;
-
-#ifdef COGL_USE_PREMULT_SSE2
-
- /* Process 4 pixels at a time */
- while (x >= 4)
- {
- _cogl_premult_alpha_last_four_pixels_sse2 (p);
- p += 4 * 4;
- x -= 4;
- }
-
- /* If there are any pixels left we will fall through and
- handle them below */
-
-#endif /* COGL_USE_PREMULT_SSE2 */
-
- while (x-- > 0)
- {
- _cogl_premult_alpha_last (p);
- p += 4;
- }
- }
- }
-
- _cogl_bitmap_unmap (bmp);
-
- _cogl_bitmap_set_format (bmp, format | COGL_PREMULT_BIT);
-
- return TRUE;
-}
-
-CoglBitmap *
-_cogl_bitmap_fallback_from_file (const char *filename)
-{
- /* FIXME: use jpeglib, libpng, etc. manually maybe */
- return FALSE;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-bitmap-private.h"
-
-#include <string.h>
-
-#ifdef USE_QUARTZ
-#include <ApplicationServices/ApplicationServices.h>
-#elif defined(USE_GDKPIXBUF)
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#endif
-
-gboolean
-_cogl_bitmap_can_convert (CoglPixelFormat src, CoglPixelFormat dst)
-{
- return FALSE;
-}
-
-gboolean
-_cogl_bitmap_can_unpremult (CoglPixelFormat format)
-{
- return FALSE;
-}
-
-gboolean
-_cogl_bitmap_can_premult (CoglPixelFormat format)
-{
- return FALSE;
-}
-
-CoglBitmap *
-_cogl_bitmap_convert (CoglBitmap *bmp,
- CoglPixelFormat dst_format)
-{
- return NULL;
-}
-
-gboolean
-_cogl_bitmap_unpremult (CoglBitmap *dst_bmp)
-{
- return FALSE;
-}
-
-gboolean
-_cogl_bitmap_premult (CoglBitmap *dst_bmp)
-{
- return FALSE;
-}
-
-#ifdef USE_QUARTZ
-
-gboolean
-_cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height)
-{
- if (width)
- *width = 0;
-
- if (height)
- *height = 0;
-
- return TRUE;
-}
-
-/* the error does not contain the filename as the caller already has it */
-CoglBitmap *
-_cogl_bitmap_from_file (const char *filename,
- GError **error)
-{
- CFURLRef url;
- CGImageSourceRef image_source;
- CGImageRef image;
- int save_errno;
- CFStringRef type;
- gsize width, height, rowstride;
- guint8 *out_data;
- CGColorSpaceRef color_space;
- CGContextRef bitmap_context;
-
- g_assert (filename != NULL);
- g_assert (error == NULL || *error == NULL);
-
- url = CFURLCreateFromFileSystemRepresentation (NULL,
- (guchar *) filename,
- strlen (filename),
- false);
- image_source = CGImageSourceCreateWithURL (url, NULL);
- save_errno = errno;
- CFRelease (url);
-
- if (image_source == NULL)
- {
- /* doesn't exist, not readable, etc. */
- g_set_error_literal (error,
- COGL_BITMAP_ERROR,
- COGL_BITMAP_ERROR_FAILED,
- g_strerror (save_errno));
- return NULL;
- }
-
- /* Unknown images would be cleanly caught as zero width/height below, but try
- * to provide better error message
- */
- type = CGImageSourceGetType (image_source);
- if (type == NULL)
- {
- CFRelease (image_source);
- g_set_error_literal (error,
- COGL_BITMAP_ERROR,
- COGL_BITMAP_ERROR_UNKNOWN_TYPE,
- "Unknown image type");
- return NULL;
- }
-
- CFRelease (type);
-
- image = CGImageSourceCreateImageAtIndex (image_source, 0, NULL);
- CFRelease (image_source);
-
- width = CGImageGetWidth (image);
- height = CGImageGetHeight (image);
- if (width == 0 || height == 0)
- {
- /* incomplete or corrupt */
- CFRelease (image);
- g_set_error_literal (error,
- COGL_BITMAP_ERROR,
- COGL_BITMAP_ERROR_CORRUPT_IMAGE,
- "Image has zero width or height");
- return NULL;
- }
-
- /* allocate buffer big enough to hold pixel data */
- rowstride = 4 * width;
- out_data = g_malloc0 (height * rowstride);
-
- /* render to buffer */
- color_space = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB);
- bitmap_context = CGBitmapContextCreate (out_data,
- width, height, 8,
- rowstride, color_space,
- kCGImageAlphaPremultipliedFirst);
- CGColorSpaceRelease (color_space);
-
- {
- const CGRect rect = {{0, 0}, {width, height}};
-
- CGContextDrawImage (bitmap_context, rect, image);
- }
-
- CGImageRelease (image);
- CGContextRelease (bitmap_context);
-
- /* store bitmap info */
- return _cogl_bitmap_new_from_data (out_data,
- COGL_PIXEL_FORMAT_ARGB_8888,
- width, height,
- rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-}
-
-#elif defined(USE_GDKPIXBUF)
-
-gboolean
-_cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height)
-{
- g_return_val_if_fail (filename != NULL, FALSE);
-
- if (gdk_pixbuf_get_file_info (filename, width, height) != NULL)
- return TRUE;
-
- return FALSE;
-}
-
-static void
-_cogl_bitmap_unref_pixbuf (guint8 *pixels,
- void *pixbuf)
-{
- g_object_unref (pixbuf);
-}
-
-CoglBitmap *
-_cogl_bitmap_from_file (const char *filename,
- GError **error)
-{
- GdkPixbuf *pixbuf;
- gboolean has_alpha;
- GdkColorspace color_space;
- CoglPixelFormat pixel_format;
- int width;
- int height;
- int rowstride;
- int bits_per_sample;
- int n_channels;
-
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* Load from file using GdkPixbuf */
- pixbuf = gdk_pixbuf_new_from_file (filename, error);
- if (pixbuf == NULL)
- return FALSE;
-
- /* Get pixbuf properties */
- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
- color_space = gdk_pixbuf_get_colorspace (pixbuf);
- width = gdk_pixbuf_get_width (pixbuf);
- height = gdk_pixbuf_get_height (pixbuf);
- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
- bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
- n_channels = gdk_pixbuf_get_n_channels (pixbuf);
-
- /* According to current docs this should be true and so
- * the translation to cogl pixel format below valid */
- g_assert (bits_per_sample == 8);
-
- if (has_alpha)
- g_assert (n_channels == 4);
- else
- g_assert (n_channels == 3);
-
- /* Translate to cogl pixel format */
- switch (color_space)
- {
- case GDK_COLORSPACE_RGB:
- /* The only format supported by GdkPixbuf so far */
- pixel_format = has_alpha ?
- COGL_PIXEL_FORMAT_RGBA_8888 :
- COGL_PIXEL_FORMAT_RGB_888;
- break;
-
- default:
- /* Ouch, spec changed! */
- g_object_unref (pixbuf);
- return FALSE;
- }
-
- /* We just use the data directly from the pixbuf so that we don't
- have to copy to a seperate buffer. Note that Cogl is expected not
- to read past the end of bpp*width on the last row even if the
- rowstride is much larger so we don't need to worry about
- GdkPixbuf's semantics that it may under-allocate the buffer. */
- return _cogl_bitmap_new_from_data (gdk_pixbuf_get_pixels (pixbuf),
- pixel_format,
- width,
- height,
- rowstride,
- _cogl_bitmap_unref_pixbuf,
- pixbuf);
-}
-
-#else
-
-#include "stb_image.c"
-
-gboolean
-_cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height)
-{
- if (width)
- *width = 0;
-
- if (height)
- *height = 0;
-
- return TRUE;
-}
-
-CoglBitmap *
-_cogl_bitmap_from_file (const char *filename,
- GError **error)
-{
- CoglBitmap *bmp;
- int stb_pixel_format;
- int width;
- int height;
- guint8 *pixels;
-
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- /* Load from file using stb */
- pixels = stbi_load (filename,
- &width, &height, &stb_pixel_format,
- STBI_rgb_alpha);
- if (pixels == NULL)
- return FALSE;
-
- /* Store bitmap info */
- bmp = _cogl_bitmap_new_from_data (g_memdup (pixels, height * width * 4),
- COGL_PIXEL_FORMAT_RGBA_8888,
- width, height,
- width * 4,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- free (pixels);
-
- return bmp;
-}
-#endif
+++ /dev/null
-/*
- * Clutter COGL
- *
- * A basic GL/GLES Abstraction/Utility Layer
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2007 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_BITMAP_H
-#define __COGL_BITMAP_H
-
-#include <glib.h>
-
-#include "cogl-handle.h"
-#include "cogl-buffer.h"
-#include "cogl-bitmap.h"
-
-/*
- * CoglBitmapDestroyNotify:
- * @data: The image data
- * @destroy_data: The callback closure data that was given to
- * _cogl_bitmap_new_from_data().
- *
- * Function prototype that is used to destroy the bitmap data when
- * _cogl_bitmap_new_from_data() is called.
- */
-typedef void (* CoglBitmapDestroyNotify) (guint8 *data, void *destroy_data);
-
-/*
- * _cogl_bitmap_new_from_data:
- * @data: A pointer to the data. The bitmap will take ownership of this data.
- * @format: The format of the pixel data.
- * @width: The width of the bitmap.
- * @height: The height of the bitmap.
- * @rowstride: The rowstride of the bitmap (the number of bytes from
- * the start of one row of the bitmap to the next).
- * @destroy_fn: A function to be called when the bitmap is
- * destroyed. This should free @data. %NULL can be used instead if
- * no free is needed.
- * @destroy_fn_data: This pointer will get passed to @destroy_fn.
- *
- * Creates a bitmap using some existing data. The data is not copied
- * so the bitmap will take ownership of the data pointer. When the
- * bitmap is freed @destroy_fn will be called to free the data.
- *
- * Return value: A new %CoglBitmap.
- */
-CoglBitmap *
-_cogl_bitmap_new_from_data (guint8 *data,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride,
- CoglBitmapDestroyNotify destroy_fn,
- gpointer destroy_fn_data);
-
-/* The idea of this function is that it will create a bitmap that
- shares the actual data with another bitmap. This is needed for the
- atlas texture backend because it needs upload a bitmap to a sub
- texture but override the format so that it ignores the premult
- flag. */
-CoglBitmap *
-_cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride);
-
-/* This creates a cogl bitmap that internally references a pixel
- array. The data is not copied. _cogl_bitmap_map will divert to
- mapping the pixel array */
-CoglBitmap *
-_cogl_bitmap_new_from_buffer (CoglBuffer *buffer,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride,
- int offset);
-
-gboolean
-_cogl_bitmap_can_convert (CoglPixelFormat src, CoglPixelFormat dst);
-
-gboolean
-_cogl_bitmap_fallback_can_convert (CoglPixelFormat src, CoglPixelFormat dst);
-
-gboolean
-_cogl_bitmap_can_unpremult (CoglPixelFormat format);
-
-gboolean
-_cogl_bitmap_fallback_can_unpremult (CoglPixelFormat format);
-
-gboolean
-_cogl_bitmap_can_premult (CoglPixelFormat format);
-
-gboolean
-_cogl_bitmap_fallback_can_premult (CoglPixelFormat format);
-
-CoglBitmap *
-_cogl_bitmap_convert (CoglBitmap *bmp,
- CoglPixelFormat dst_format);
-CoglBitmap *
-_cogl_bitmap_fallback_convert (CoglBitmap *bmp,
- CoglPixelFormat dst_format);
-
-gboolean
-_cogl_bitmap_unpremult (CoglBitmap *dst_bmp);
-
-gboolean
-_cogl_bitmap_fallback_unpremult (CoglBitmap *dst_bmp);
-
-gboolean
-_cogl_bitmap_premult (CoglBitmap *dst_bmp);
-
-gboolean
-_cogl_bitmap_fallback_premult (CoglBitmap *dst_bmp);
-
-CoglBitmap *
-_cogl_bitmap_from_file (const char *filename,
- GError **error);
-
-CoglBitmap *
-_cogl_bitmap_fallback_from_file (const char *filename);
-
-gboolean
-_cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
- CoglPixelFormat dst_format);
-
-CoglBitmap *
-_cogl_bitmap_convert_format_and_premult (CoglBitmap *bmp,
- CoglPixelFormat dst_format);
-
-void
-_cogl_bitmap_copy_subregion (CoglBitmap *src,
- CoglBitmap *dst,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height);
-
-/* Creates a deep copy of the source bitmap */
-CoglBitmap *
-_cogl_bitmap_copy (CoglBitmap *src_bmp);
-
-gboolean
-_cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height);
-
-CoglPixelFormat
-_cogl_bitmap_get_format (CoglBitmap *bitmap);
-
-void
-_cogl_bitmap_set_format (CoglBitmap *bitmap,
- CoglPixelFormat format);
-
-int
-_cogl_bitmap_get_width (CoglBitmap *bitmap);
-
-int
-_cogl_bitmap_get_height (CoglBitmap *bitmap);
-
-int
-_cogl_bitmap_get_rowstride (CoglBitmap *bitmap);
-
-/* Maps the bitmap so that the pixels can be accessed directly or if
- the bitmap is just a memory bitmap then it just returns the pointer
- to memory. Note that the bitmap isn't guaranteed to allocated to
- the full size of rowstride*height so it is not safe to read up to
- the rowstride of the last row. This will be the case if the user
- uploads data using gdk_pixbuf_new_subpixbuf with a sub region
- containing the last row of the pixbuf because in that case the
- rowstride can be much larger than the width of the image */
-guint8 *
-_cogl_bitmap_map (CoglBitmap *bitmap,
- CoglBufferAccess access,
- CoglBufferMapHint hints);
-
-void
-_cogl_bitmap_unmap (CoglBitmap *bitmap);
-
-/* These two are replacements for map and unmap that should used when
- the pointer is going to be passed to GL for pixel packing or
- unpacking. The address might not be valid for reading if the bitmap
- was created with new_from_buffer but it will however be good to
- pass to glTexImage2D for example. The access should be READ for
- unpacking and WRITE for packing. It can not be both */
-guint8 *
-_cogl_bitmap_bind (CoglBitmap *bitmap,
- CoglBufferAccess access,
- CoglBufferMapHint hints);
-
-void
-_cogl_bitmap_unbind (CoglBitmap *bitmap);
-
-#endif /* __COGL_BITMAP_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-buffer-private.h"
-
-#include <string.h>
-
-struct _CoglBitmap
-{
- CoglHandleObject _parent;
- CoglPixelFormat format;
- int width;
- int height;
- int rowstride;
-
- guint8 *data;
- CoglBitmapDestroyNotify destroy_fn;
- void *destroy_fn_data;
-
- gboolean mapped;
- gboolean bound;
-
- /* If this is non-null then 'data' is ignored and instead it is
- fetched from this shared bitmap. */
- CoglBitmap *shared_bmp;
-
- /* If this is non-null then 'data' is treated as an offset into the
- buffer and map will divert to mapping the buffer */
- CoglBuffer *buffer;
-};
-
-static void _cogl_bitmap_free (CoglBitmap *bmp);
-
-COGL_OBJECT_DEFINE (Bitmap, bitmap);
-
-static void
-_cogl_bitmap_free (CoglBitmap *bmp)
-{
- g_assert (!bmp->mapped);
- g_assert (!bmp->bound);
-
- if (bmp->destroy_fn)
- bmp->destroy_fn (bmp->data, bmp->destroy_fn_data);
-
- if (bmp->shared_bmp)
- cogl_object_unref (bmp->shared_bmp);
-
- if (bmp->buffer)
- cogl_object_unref (bmp->buffer);
-
- g_slice_free (CoglBitmap, bmp);
-}
-
-int
-_cogl_get_format_bpp (CoglPixelFormat format)
-{
- int bpp_lut[] = {
- 0, /* invalid */
- 1, /* A_8 */
- 3, /* 888 */
- 4, /* 8888 */
- 2, /* 565 */
- 2, /* 4444 */
- 2, /* 5551 */
- 2, /* YUV */
- 1 /* G_8 */
- };
-
- return bpp_lut [format & COGL_UNORDERED_MASK];
-}
-
-gboolean
-_cogl_bitmap_convert_premult_status (CoglBitmap *bmp,
- CoglPixelFormat dst_format)
-{
- /* Do we need to unpremultiply? */
- if ((bmp->format & COGL_PREMULT_BIT) > 0 &&
- (dst_format & COGL_PREMULT_BIT) == 0)
- /* Try unpremultiplying using imaging library */
- return (_cogl_bitmap_unpremult (bmp)
- /* ... or try fallback */
- || _cogl_bitmap_fallback_unpremult (bmp));
-
- /* Do we need to premultiply? */
- if ((bmp->format & COGL_PREMULT_BIT) == 0 &&
- (dst_format & COGL_PREMULT_BIT) > 0)
- /* Try premultiplying using imaging library */
- return (_cogl_bitmap_premult (bmp)
- /* ... or try fallback */
- || _cogl_bitmap_fallback_premult (bmp));
-
- return TRUE;
-}
-
-CoglBitmap *
-_cogl_bitmap_convert_format_and_premult (CoglBitmap *bmp,
- CoglPixelFormat dst_format)
-{
- CoglPixelFormat src_format = _cogl_bitmap_get_format (bmp);
- CoglBitmap *dst_bmp;
-
- /* Is base format different (not considering premult status)? */
- if ((src_format & COGL_UNPREMULT_MASK) !=
- (dst_format & COGL_UNPREMULT_MASK))
- {
- /* Try converting using imaging library */
- if ((dst_bmp = _cogl_bitmap_convert (bmp, dst_format)) == NULL)
- {
- /* ... or try fallback */
- if ((dst_bmp = _cogl_bitmap_fallback_convert (bmp,
- dst_format)) == NULL)
- return NULL;
- }
- }
- else
- {
- int rowstride = _cogl_bitmap_get_rowstride (bmp);
- int height = _cogl_bitmap_get_height (bmp);
- guint8 *data;
-
- /* Copy the bitmap so that we can premultiply in-place */
-
- if ((data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)) == NULL)
- return NULL;
-
- dst_bmp = _cogl_bitmap_new_from_data (g_memdup (data, height * rowstride),
- src_format,
- _cogl_bitmap_get_width (bmp),
- height,
- rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- _cogl_bitmap_unmap (bmp);
- }
-
- src_format = _cogl_bitmap_get_format (dst_bmp);
-
- /* We only need to do a premult conversion if both formats have an
- alpha channel. If we're converting from RGB to RGBA then the
- alpha will have been filled with 255 so the premult won't do
- anything or if we are converting from RGBA to RGB we're losing
- information so either converting or not will be wrong for
- transparent pixels */
- if ((src_format & COGL_A_BIT) == COGL_A_BIT &&
- (dst_format & COGL_A_BIT) == COGL_A_BIT &&
- !_cogl_bitmap_convert_premult_status (dst_bmp, dst_format))
- {
- cogl_object_unref (dst_bmp);
- return NULL;
- }
-
- return dst_bmp;
-}
-
-CoglBitmap *
-_cogl_bitmap_copy (CoglBitmap *src_bmp)
-{
- CoglBitmap *dst_bmp;
- CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp);
- int bpp = _cogl_get_format_bpp (src_format);
- int width = _cogl_bitmap_get_width (src_bmp);
- int height = _cogl_bitmap_get_height (src_bmp);
- int dst_rowstride = width * bpp;
-
- /* Round the rowstride up to the next nearest multiple of 4 bytes */
- dst_rowstride = (dst_rowstride + 3) & ~3;
-
- dst_bmp = _cogl_bitmap_new_from_data (g_malloc (dst_rowstride * height),
- src_format,
- width, height,
- dst_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- _cogl_bitmap_copy_subregion (src_bmp,
- dst_bmp,
- 0, 0, /* src_x/y */
- 0, 0, /* dst_x/y */
- width, height);
-
- return dst_bmp;
-}
-
-void
-_cogl_bitmap_copy_subregion (CoglBitmap *src,
- CoglBitmap *dst,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height)
-{
- guint8 *srcdata;
- guint8 *dstdata;
- int bpp;
- int line;
-
- /* Intended only for fast copies when format is equal! */
- g_assert (src->format == dst->format);
- bpp = _cogl_get_format_bpp (src->format);
-
- if ((srcdata = _cogl_bitmap_map (src, COGL_BUFFER_ACCESS_READ, 0)))
- {
- if ((dstdata = _cogl_bitmap_map (dst, COGL_BUFFER_ACCESS_WRITE, 0)))
- {
- srcdata += src_y * src->rowstride + src_x * bpp;
- dstdata += dst_y * dst->rowstride + dst_x * bpp;
-
- for (line=0; line<height; ++line)
- {
- memcpy (dstdata, srcdata, width * bpp);
- srcdata += src->rowstride;
- dstdata += dst->rowstride;
- }
-
- _cogl_bitmap_unmap (dst);
- }
-
- _cogl_bitmap_unmap (src);
- }
-}
-
-gboolean
-cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height)
-{
- return _cogl_bitmap_get_size_from_file (filename, width, height);
-}
-
-CoglBitmap *
-_cogl_bitmap_new_from_data (guint8 *data,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride,
- CoglBitmapDestroyNotify destroy_fn,
- void *destroy_fn_data)
-{
- CoglBitmap *bmp = g_slice_new (CoglBitmap);
-
- bmp->format = format;
- bmp->width = width;
- bmp->height = height;
- bmp->rowstride = rowstride;
- bmp->data = data;
- bmp->destroy_fn = destroy_fn;
- bmp->destroy_fn_data = destroy_fn_data;
- bmp->mapped = FALSE;
- bmp->bound = FALSE;
- bmp->shared_bmp = NULL;
- bmp->buffer = NULL;
-
- return _cogl_bitmap_object_new (bmp);
-}
-
-CoglBitmap *
-_cogl_bitmap_new_shared (CoglBitmap *shared_bmp,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride)
-{
- CoglBitmap *bmp = _cogl_bitmap_new_from_data (NULL, /* data */
- format,
- width,
- height,
- rowstride,
- NULL, /* destroy_fn */
- NULL /* destroy_fn_data */);
-
- bmp->shared_bmp = cogl_object_ref (shared_bmp);
-
- return bmp;
-}
-
-CoglBitmap *
-cogl_bitmap_new_from_file (const char *filename,
- GError **error)
-{
- CoglBitmap *bmp;
-
- g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
-
- if ((bmp = _cogl_bitmap_from_file (filename, error)) == NULL)
- {
- /* Try fallback */
- if ((bmp = _cogl_bitmap_fallback_from_file (filename))
- && error && *error)
- {
- g_error_free (*error);
- *error = NULL;
- }
- }
-
- return bmp;
-}
-
-CoglBitmap *
-_cogl_bitmap_new_from_buffer (CoglBuffer *buffer,
- CoglPixelFormat format,
- int width,
- int height,
- int rowstride,
- int offset)
-{
- CoglBitmap *bmp;
-
- g_return_val_if_fail (cogl_is_buffer (buffer), NULL);
-
- bmp = _cogl_bitmap_new_from_data (NULL, /* data */
- format,
- width,
- height,
- rowstride,
- NULL, /* destroy_fn */
- NULL /* destroy_fn_data */);
-
- bmp->buffer = cogl_object_ref (buffer);
- bmp->data = GINT_TO_POINTER (offset);
-
- return bmp;
-}
-
-CoglPixelFormat
-_cogl_bitmap_get_format (CoglBitmap *bitmap)
-{
- return bitmap->format;
-}
-
-void
-_cogl_bitmap_set_format (CoglBitmap *bitmap,
- CoglPixelFormat format)
-{
- bitmap->format = format;
-}
-
-int
-_cogl_bitmap_get_width (CoglBitmap *bitmap)
-{
- return bitmap->width;
-}
-
-GQuark
-cogl_bitmap_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-bitmap-error-quark");
-}
-
-int
-_cogl_bitmap_get_height (CoglBitmap *bitmap)
-{
- return bitmap->height;
-}
-
-int
-_cogl_bitmap_get_rowstride (CoglBitmap *bitmap)
-{
- return bitmap->rowstride;
-}
-
-guint8 *
-_cogl_bitmap_map (CoglBitmap *bitmap,
- CoglBufferAccess access,
- CoglBufferMapHint hints)
-{
- /* Divert to another bitmap if this data is shared */
- if (bitmap->shared_bmp)
- return _cogl_bitmap_map (bitmap->shared_bmp, access, hints);
-
- g_assert (!bitmap->mapped);
-
- if (bitmap->buffer)
- {
- guint8 *data = cogl_buffer_map (bitmap->buffer,
- access,
- hints);
-
- COGL_NOTE (BITMAP, "A pixel array is being mapped from a bitmap. This "
- "usually means that some conversion on the pixel array is "
- "needed so a sub-optimal format is being used.");
-
- if (data)
- {
- bitmap->mapped = TRUE;
-
- return data + GPOINTER_TO_INT (bitmap->data);
- }
- else
- return NULL;
- }
- else
- {
- bitmap->mapped = TRUE;
-
- return bitmap->data;
- }
-}
-
-void
-_cogl_bitmap_unmap (CoglBitmap *bitmap)
-{
- /* Divert to another bitmap if this data is shared */
- if (bitmap->shared_bmp)
- return _cogl_bitmap_unmap (bitmap->shared_bmp);
-
- g_assert (bitmap->mapped);
- bitmap->mapped = FALSE;
-
- if (bitmap->buffer)
- cogl_buffer_unmap (bitmap->buffer);
-}
-
-guint8 *
-_cogl_bitmap_bind (CoglBitmap *bitmap,
- CoglBufferAccess access,
- CoglBufferMapHint hints)
-{
- guint8 *ptr;
-
- /* Divert to another bitmap if this data is shared */
- if (bitmap->shared_bmp)
- return _cogl_bitmap_bind (bitmap->shared_bmp, access, hints);
-
- g_assert (!bitmap->bound);
-
- /* If the bitmap wasn't created from a buffer then the
- implementation of bind is the same as map */
- if (bitmap->buffer == NULL)
- {
- guint8 *data = _cogl_bitmap_map (bitmap, access, hints);
- if (data)
- bitmap->bound = TRUE;
- return data;
- }
-
- bitmap->bound = TRUE;
-
- if (access == COGL_BUFFER_ACCESS_READ)
- ptr = _cogl_buffer_bind (bitmap->buffer,
- COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
- else if (access == COGL_BUFFER_ACCESS_WRITE)
- ptr = _cogl_buffer_bind (bitmap->buffer,
- COGL_BUFFER_BIND_TARGET_PIXEL_PACK);
- else
- g_assert_not_reached ();
-
- /* The data pointer actually stores the offset */
- return GPOINTER_TO_INT (bitmap->data) + ptr;
-}
-
-void
-_cogl_bitmap_unbind (CoglBitmap *bitmap)
-{
- /* Divert to another bitmap if this data is shared */
- if (bitmap->shared_bmp)
- return _cogl_bitmap_unbind (bitmap->shared_bmp);
-
- g_assert (bitmap->bound);
- bitmap->bound = FALSE;
-
- /* If the bitmap wasn't created from a pixel array then the
- implementation of unbind is the same as unmap */
- if (bitmap->buffer)
- _cogl_buffer_unbind (bitmap->buffer);
- else
- _cogl_bitmap_unmap (bitmap);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_BITMAP_H__
-#define __COGL_BITMAP_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-typedef struct _CoglBitmap CoglBitmap;
-
-/**
- * SECTION:cogl-bitmap
- * @short_description: Fuctions for loading images
- *
- * Cogl allows loading image data into memory as CoglBitmaps without
- * loading them immediately into GPU textures.
- *
- * #CoglBitmap is available since Cogl 1.0
- */
-
-
-/**
- * cogl_bitmap_new_from_file:
- * @filename: the file to load.
- * @error: a #GError or %NULL.
- *
- * Loads an image file from disk. This function can be safely called from
- * within a thread.
- *
- * Return value: a #CoglBitmap to the new loaded image data, or
- * %NULL if loading the image failed.
- *
- * Since: 1.0
- */
-CoglBitmap *
-cogl_bitmap_new_from_file (const char *filename,
- GError **error);
-
-/**
- * cogl_bitmap_get_size_from_file:
- * @filename: the file to check
- * @width: (out): return location for the bitmap width, or %NULL
- * @height: (out): return location for the bitmap height, or %NULL
- *
- * Parses an image file enough to extract the width and height
- * of the bitmap.
- *
- * Return value: %TRUE if the image was successfully parsed
- *
- * Since: 1.0
- */
-gboolean
-cogl_bitmap_get_size_from_file (const char *filename,
- int *width,
- int *height);
-
-/**
- * cogl_is_bitmap:
- * @handle: a #CoglHandle for a bitmap
- *
- * Checks whether @handle is a #CoglHandle for a bitmap
- *
- * Return value: %TRUE if the passed handle represents a bitmap,
- * and %FALSE otherwise
- *
- * Since: 1.0
- */
-gboolean
-cogl_is_bitmap (CoglHandle handle);
-
-/**
- * COGL_BITMAP_ERROR:
- *
- * #GError domain for bitmap errors.
- *
- * Since: 1.4
- */
-#define COGL_BITMAP_ERROR (cogl_bitmap_error_quark ())
-
-/**
- * CoglBitmapError:
- * @COGL_BITMAP_ERROR_FAILED: Generic failure code, something went
- * wrong.
- * @COGL_BITMAP_ERROR_UNKNOWN_TYPE: Unknown image type.
- * @COGL_BITMAP_ERROR_CORRUPT_IMAGE: An image file was broken somehow.
- *
- * Error codes that can be thrown when performing bitmap
- * operations. Note that gdk_pixbuf_new_from_file() can also throw
- * errors directly from the underlying image loading library. For
- * example, if GdkPixbuf is used then errors #GdkPixbufError<!-- -->s
- * will be used directly.
- *
- * Since: 1.4
- */
-typedef enum {
- COGL_BITMAP_ERROR_FAILED,
- COGL_BITMAP_ERROR_UNKNOWN_TYPE,
- COGL_BITMAP_ERROR_CORRUPT_IMAGE
-} CoglBitmapError;
-
-GQuark cogl_bitmap_error_quark (void);
-
-G_END_DECLS
-
-#endif /* __COGL_BITMAP_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <string.h>
-
-#include "cogl-bitmask.h"
-
-gboolean
-_cogl_bitmask_get_from_array (const CoglBitmask *bitmask,
- unsigned int bit_num)
-{
- GArray *array = (GArray *) *bitmask;
-
- /* If the index is off the end of the array then assume the bit is
- not set */
- if (bit_num >= sizeof (unsigned int) * 8 * array->len)
- return FALSE;
- else
- return !!(g_array_index (array, unsigned int,
- bit_num / (sizeof (unsigned int) * 8)) &
- (1 << (bit_num % (sizeof (unsigned int) * 8))));
-}
-
-static void
-_cogl_bitmask_convert_to_array (CoglBitmask *bitmask)
-{
- GArray *array;
- /* Fetch the old values, ignoring the least significant bit */
- unsigned int old_values = GPOINTER_TO_UINT (*bitmask) >> 1;
-
- array = g_array_new (FALSE, TRUE, sizeof (unsigned int));
- /* Copy the old values back in */
- g_array_append_val (array, old_values);
-
- *bitmask = (struct _CoglBitmaskImaginaryType *) array;
-}
-
-void
-_cogl_bitmask_set_in_array (CoglBitmask *bitmask,
- unsigned int bit_num,
- gboolean value)
-{
- GArray *array;
- unsigned int array_index, new_value_mask;
-
- /* If the bitmask is not already an array then we need to allocate one */
- if (!_cogl_bitmask_has_array (bitmask))
- _cogl_bitmask_convert_to_array (bitmask);
-
- array = (GArray *) *bitmask;
-
- array_index = bit_num / (sizeof (unsigned int) * 8);
- /* Grow the array if necessary. This will clear the new data */
- if (array_index >= array->len)
- g_array_set_size (array, array_index + 1);
-
- new_value_mask = 1 << (bit_num % (sizeof (unsigned int) * 8));
-
- if (value)
- g_array_index (array, unsigned int, array_index) |= new_value_mask;
- else
- g_array_index (array, unsigned int, array_index) &= ~new_value_mask;
-}
-
-void
-_cogl_bitmask_set_bits (CoglBitmask *dst,
- const CoglBitmask *src)
-{
- if (_cogl_bitmask_has_array (src))
- {
- GArray *src_array, *dst_array;
- int i;
-
- if (!_cogl_bitmask_has_array (dst))
- _cogl_bitmask_convert_to_array (dst);
-
- dst_array = (GArray *) *dst;
- src_array = (GArray *) *src;
-
- if (dst_array->len < src_array->len)
- g_array_set_size (dst_array, src_array->len);
-
- for (i = 0; i < src_array->len; i++)
- g_array_index (dst_array, unsigned int, i) |=
- g_array_index (src_array, unsigned int, i);
- }
- else if (_cogl_bitmask_has_array (dst))
- {
- GArray *dst_array;
-
- dst_array = (GArray *) *dst;
-
- g_array_index (dst_array, unsigned int, 0) |=
- (GPOINTER_TO_UINT (*src) >> 1);
- }
- else
- *dst = GUINT_TO_POINTER (GPOINTER_TO_UINT (*dst) |
- GPOINTER_TO_UINT (*src));
-}
-
-void
-_cogl_bitmask_set_range_in_array (CoglBitmask *bitmask,
- unsigned int n_bits,
- gboolean value)
-{
- GArray *array;
- unsigned int array_index, bit_index;
-
- if (n_bits == 0)
- return;
-
- /* If the bitmask is not already an array then we need to allocate one */
- if (!_cogl_bitmask_has_array (bitmask))
- _cogl_bitmask_convert_to_array (bitmask);
-
- array = (GArray *) *bitmask;
-
- /* Get the array index of the top most value that will be touched */
- array_index = (n_bits - 1) / (sizeof (unsigned int) * 8);
- /* Get the bit index of the top most value */
- bit_index = (n_bits - 1) % (sizeof (unsigned int) * 8);
- /* Grow the array if necessary. This will clear the new data */
- if (array_index >= array->len)
- g_array_set_size (array, array_index + 1);
-
- if (value)
- {
- /* Set the bits that are touching this index */
- g_array_index (array, unsigned int, array_index) |=
- ~(unsigned int) 0 >> (sizeof (unsigned int) * 8 - 1 - bit_index);
-
- /* Set all of the bits in any lesser indices */
- memset (array->data, 0xff, sizeof (unsigned int) * array_index);
- }
- else
- {
- /* Clear the bits that are touching this index */
- g_array_index (array, unsigned int, array_index) &=
- ~(unsigned int) 1 << bit_index;
-
- /* Clear all of the bits in any lesser indices */
- memset (array->data, 0x00, sizeof (unsigned int) * array_index);
- }
-}
-
-void
-_cogl_bitmask_xor_bits (CoglBitmask *dst,
- const CoglBitmask *src)
-{
- if (_cogl_bitmask_has_array (src))
- {
- GArray *src_array, *dst_array;
- int i;
-
- if (!_cogl_bitmask_has_array (dst))
- _cogl_bitmask_convert_to_array (dst);
-
- dst_array = (GArray *) *dst;
- src_array = (GArray *) *src;
-
- if (dst_array->len < src_array->len)
- g_array_set_size (dst_array, src_array->len);
-
- for (i = 0; i < src_array->len; i++)
- g_array_index (dst_array, unsigned int, i) ^=
- g_array_index (src_array, unsigned int, i);
- }
- else if (_cogl_bitmask_has_array (dst))
- {
- GArray *dst_array;
-
- dst_array = (GArray *) *dst;
-
- g_array_index (dst_array, unsigned int, 0) ^=
- (GPOINTER_TO_UINT (*src) >> 1);
- }
- else
- *dst = GUINT_TO_POINTER ((GPOINTER_TO_UINT (*dst) ^
- GPOINTER_TO_UINT (*src)) | 1);
-}
-
-void
-_cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask)
-{
- GArray *array = (GArray *) *bitmask;
-
- memset (array->data, 0, sizeof (unsigned int) * array->len);
-}
-
-void
-_cogl_bitmask_foreach (const CoglBitmask *bitmask,
- CoglBitmaskForeachFunc func,
- gpointer user_data)
-{
- if (_cogl_bitmask_has_array (bitmask))
- {
- GArray *array = (GArray *) *bitmask;
- int array_index;
-
- for (array_index = 0; array_index < array->len; array_index++)
- {
- unsigned int mask = g_array_index (array, unsigned int, array_index);
- int bit = 0;
-
- while (mask)
- {
- if (mask & 1)
- func (array_index * sizeof (unsigned int) * 8 + bit, user_data);
-
- bit++;
- mask >>= 1;
- }
- }
- }
- else
- {
- unsigned int mask = GPOINTER_TO_UINT (*bitmask) >> 1;
- int bit = 0;
-
- while (mask)
- {
- if (mask & 1)
- func (bit, user_data);
-
- bit++;
- mask >>= 1;
- }
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_BITMASK_H
-#define __COGL_BITMASK_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/*
- * CoglBitmask implements a growable array of bits. A CoglBitmask can
- * be allocated on the stack but it must be initialised with
- * _cogl_bitmask_init() before use and then destroyed with
- * _cogl_bitmask_destroy(). A CoglBitmask will try to avoid allocating
- * any memory unless more than 31 bits are needed.
- *
- * Internally a CoglBitmask is a pointer. If the least significant bit
- * of the pointer is 1 then the rest of the bits are directly used as
- * part of the bitmask, otherwise it is a pointer to a GArray of
- * unsigned ints. This relies on the fact the g_malloc will return a
- * pointer aligned to at least two bytes (so that the least
- * significant bit of the address is always 0)
- *
- * If the maximum possible bit number in the set is known at compile
- * time, it may make more sense to use the macros in cogl-flags.h
- * instead of this type.
- */
-
-typedef struct _CoglBitmaskImaginaryType *CoglBitmask;
-
-/* Internal helper macro to determine whether this bitmask has a
- GArray allocated or whether the pointer is just used directly */
-#define _cogl_bitmask_has_array(bitmask) \
- (!(GPOINTER_TO_UINT (*bitmask) & 1))
-
-/* Number of bits we can use before needing to allocate an array */
-#define COGL_BITMASK_MAX_DIRECT_BITS (sizeof (unsigned int) * 8 - 1)
-
-/*
- * _cogl_bitmask_init:
- * @bitmask: A pointer to a bitmask
- *
- * Initialises the cogl bitmask. This must be called before any other
- * bitmask functions are called. Initially all of the values are
- * zero
- */
-/* Set the last significant bit to mark that no array has been
- allocated yet */
-#define _cogl_bitmask_init(bitmask) \
- G_STMT_START { *(bitmask) = GUINT_TO_POINTER (1); } G_STMT_END
-
-gboolean
-_cogl_bitmask_get_from_array (const CoglBitmask *bitmask,
- unsigned int bit_num);
-
-void
-_cogl_bitmask_set_in_array (CoglBitmask *bitmask,
- unsigned int bit_num,
- gboolean value);
-
-void
-_cogl_bitmask_set_range_in_array (CoglBitmask *bitmask,
- unsigned int n_bits,
- gboolean value);
-
-void
-_cogl_bitmask_clear_all_in_array (CoglBitmask *bitmask);
-
-/*
- * cogl_bitmask_set_bits:
- * @dst: The bitmask to modify
- * @src: The bitmask to copy bits from
- *
- * This makes sure that all of the bits that are set in @src are also
- * set in @dst. Any unset bits in @src are left alone in @dst.
- */
-void
-_cogl_bitmask_set_bits (CoglBitmask *dst,
- const CoglBitmask *src);
-
-/*
- * cogl_bitmask_xor_bits:
- * @dst: The bitmask to modify
- * @src: The bitmask to copy bits from
- *
- * For every bit that is set in src, the corresponding bit in dst is
- * inverted.
- */
-void
-_cogl_bitmask_xor_bits (CoglBitmask *dst,
- const CoglBitmask *src);
-
-typedef void (* CoglBitmaskForeachFunc) (int bit_num, gpointer user_data);
-
-/*
- * cogl_bitmask_foreach:
- * @bitmask: A pointer to a bitmask
- * @func: A callback function
- * @user_data: A pointer to pass to the callback
- *
- * This calls @func for each bit that is set in @bitmask.
- */
-void
-_cogl_bitmask_foreach (const CoglBitmask *bitmask,
- CoglBitmaskForeachFunc func,
- gpointer user_data);
-
-/*
- * _cogl_bitmask_get:
- * @bitmask: A pointer to a bitmask
- * @bit_num: A bit number
- *
- * Return value: whether bit number @bit_num is set in @bitmask
- */
-static inline gboolean
-_cogl_bitmask_get (const CoglBitmask *bitmask, unsigned int bit_num)
-{
- if (_cogl_bitmask_has_array (bitmask))
- return _cogl_bitmask_get_from_array (bitmask, bit_num);
- else if (bit_num >= COGL_BITMASK_MAX_DIRECT_BITS)
- return FALSE;
- else
- return !!(GPOINTER_TO_UINT (*bitmask) & (1 << (bit_num + 1)));
-}
-
-/*
- * _cogl_bitmask_set:
- * @bitmask: A pointer to a bitmask
- * @bit_num: A bit number
- * @value: The new value
- *
- * Sets or resets a bit number @bit_num in @bitmask according to @value.
- */
-static inline void
-_cogl_bitmask_set (CoglBitmask *bitmask, unsigned int bit_num, gboolean value)
-{
- if (_cogl_bitmask_has_array (bitmask) ||
- bit_num >= COGL_BITMASK_MAX_DIRECT_BITS)
- _cogl_bitmask_set_in_array (bitmask, bit_num, value);
- else if (value)
- *bitmask = GUINT_TO_POINTER (GPOINTER_TO_UINT (*bitmask) |
- (1 << (bit_num + 1)));
- else
- *bitmask = GUINT_TO_POINTER (GPOINTER_TO_UINT (*bitmask) &
- ~(1 << (bit_num + 1)));
-}
-
-/*
- * _cogl_bitmask_set_range:
- * @bitmask: A pointer to a bitmask
- * @n_bits: The number of bits to set
- * @value: The value to set
- *
- * Sets the first @n_bits in @bitmask to @value.
- */
-static inline void
-_cogl_bitmask_set_range (CoglBitmask *bitmask,
- unsigned int n_bits,
- gboolean value)
-{
- if (_cogl_bitmask_has_array (bitmask) ||
- n_bits > COGL_BITMASK_MAX_DIRECT_BITS)
- _cogl_bitmask_set_range_in_array (bitmask, n_bits, value);
- else if (value)
- *bitmask = GUINT_TO_POINTER (GPOINTER_TO_UINT (*bitmask) |
- ~(~(unsigned int) 1 << n_bits));
- else
- *bitmask = GUINT_TO_POINTER (GPOINTER_TO_UINT (*bitmask) &
- ((~(unsigned int) 1 << n_bits) | 1));
-}
-
-/*
- * _cogl_bitmask_destroy:
- * @bitmask: A pointer to a bitmask
- *
- * Destroys any resources allocated by the bitmask
- */
-static inline void
-_cogl_bitmask_destroy (CoglBitmask *bitmask)
-{
- if (_cogl_bitmask_has_array (bitmask))
- g_array_free ((GArray *) *bitmask, TRUE);
-}
-
-/*
- * _cogl_bitmask_clear_all:
- * @bitmask: A pointer to a bitmask
- *
- * Clears all the bits in a bitmask without destroying any resources.
- */
-static inline void
-_cogl_bitmask_clear_all (CoglBitmask *bitmask)
-{
- if (_cogl_bitmask_has_array (bitmask))
- _cogl_bitmask_clear_all_in_array (bitmask);
- else
- *bitmask = GUINT_TO_POINTER (1);
-}
-
-G_END_DECLS
-
-#endif /* __COGL_BITMASK_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-debug.h"
-#include "cogl-blend-string.h"
-
-typedef enum _ParserState
-{
- PARSER_STATE_EXPECT_DEST_CHANNELS,
- PARSER_STATE_SCRAPING_DEST_CHANNELS,
- PARSER_STATE_EXPECT_FUNCTION_NAME,
- PARSER_STATE_SCRAPING_FUNCTION_NAME,
- PARSER_STATE_EXPECT_ARG_START,
- PARSER_STATE_EXPECT_STATEMENT_END
-} ParserState;
-
-typedef enum _ParserArgState
-{
- PARSER_ARG_STATE_START,
- PARSER_ARG_STATE_EXPECT_MINUS,
- PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME,
- PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME,
- PARSER_ARG_STATE_MAYBE_COLOR_MASK,
- PARSER_ARG_STATE_SCRAPING_MASK,
- PARSER_ARG_STATE_MAYBE_MULT,
- PARSER_ARG_STATE_EXPECT_OPEN_PAREN,
- PARSER_ARG_STATE_EXPECT_FACTOR,
- PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE,
- PARSER_ARG_STATE_MAYBE_MINUS,
- PARSER_ARG_STATE_EXPECT_CLOSE_PAREN,
- PARSER_ARG_STATE_EXPECT_END
-} ParserArgState;
-
-
-#define DEFINE_COLOR_SOURCE(NAME, NAME_LEN) \
- {/*.type = */COGL_BLEND_STRING_COLOR_SOURCE_ ## NAME, \
- /*.name = */#NAME, \
- /*.name_len = */NAME_LEN}
-
-static CoglBlendStringColorSourceInfo blending_color_sources[] = {
- DEFINE_COLOR_SOURCE (SRC_COLOR, 9),
- DEFINE_COLOR_SOURCE (DST_COLOR, 9),
- DEFINE_COLOR_SOURCE (CONSTANT, 8)
-};
-
-static CoglBlendStringColorSourceInfo tex_combine_color_sources[] = {
- DEFINE_COLOR_SOURCE (TEXTURE, 7),
- /* DEFINE_COLOR_SOURCE (TEXTURE_N, *) - handled manually */
- DEFINE_COLOR_SOURCE (PRIMARY, 7),
- DEFINE_COLOR_SOURCE (CONSTANT, 8),
- DEFINE_COLOR_SOURCE (PREVIOUS, 8)
-};
-
-static CoglBlendStringColorSourceInfo tex_combine_texture_n_color_source = {
- /*.type = */COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N,
- /*.name = */"TEXTURE_N",
- /*.name_len = */0
-};
-
-#undef DEFINE_COLOR_SOURCE
-
-#define DEFINE_FUNCTION(NAME, NAME_LEN, ARGC) \
- { /*.type = */COGL_BLEND_STRING_FUNCTION_ ## NAME, \
- /*.name = */#NAME, \
- /*.name_len = */NAME_LEN, \
- /*.argc = */ARGC }
-
-/* NB: These must be sorted so any name that's a subset of another
- * comes later than the longer name. */
-static CoglBlendStringFunctionInfo tex_combine_functions[] = {
- DEFINE_FUNCTION (REPLACE, 7, 1),
- DEFINE_FUNCTION (MODULATE, 8, 2),
- DEFINE_FUNCTION (ADD_SIGNED, 10, 2),
- DEFINE_FUNCTION (ADD, 3, 2),
- DEFINE_FUNCTION (INTERPOLATE, 11, 3),
- DEFINE_FUNCTION (SUBTRACT, 8, 2),
- DEFINE_FUNCTION (DOT3_RGBA, 9, 2),
- DEFINE_FUNCTION (DOT3_RGB, 8, 2)
-};
-
-static CoglBlendStringFunctionInfo blend_functions[] = {
- DEFINE_FUNCTION (ADD, 3, 2)
-};
-
-#undef DEFINE_FUNCTION
-
-GQuark
-cogl_blend_string_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-blend-string-error-quark");
-}
-
-void
-_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement,
- CoglBlendStringStatement *rgb,
- CoglBlendStringStatement *a)
-{
- int i;
-
- memcpy (rgb, statement, sizeof (CoglBlendStringStatement));
- memcpy (a, statement, sizeof (CoglBlendStringStatement));
-
- rgb->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
- a->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
-
- for (i = 0; i < statement->function->argc; i++)
- {
- CoglBlendStringArgument *arg = &statement->args[i];
- CoglBlendStringArgument *rgb_arg = &rgb->args[i];
- CoglBlendStringArgument *a_arg = &a->args[i];
-
- if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
- {
- rgb_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
- a_arg->source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
- }
-
- if (arg->factor.is_color &&
- arg->factor.source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
- {
- rgb_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
- a_arg->factor.source.mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
- }
- }
-}
-
-static gboolean
-validate_tex_combine_statements (CoglBlendStringStatement *statements,
- int n_statements,
- GError **error)
-{
- int i, j;
- const char *error_string;
- CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR;
-
- for (i = 0; i < n_statements; i++)
- {
- for (j = 0; j < statements[i].function->argc; j++)
- {
- CoglBlendStringArgument *arg = &statements[i].args[j];
- if (arg->source.is_zero)
- {
- error_string = "You can't use the constant '0' as a texture "
- "combine argument";
- goto error;
- }
- if (!arg->factor.is_one)
- {
- error_string = "Argument factors are only relevant to blending "
- "not texture combining";
- goto error;
- }
- }
- }
-
- return TRUE;
-
-error:
- g_set_error (error,
- COGL_BLEND_STRING_ERROR,
- detail,
- "Invalid texture combine string: %s",
- error_string);
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- g_debug ("Invalid texture combine string: %s",
- error_string);
- }
- return FALSE;
-}
-
-static gboolean
-validate_blend_statements (CoglBlendStringStatement *statements,
- int n_statements,
- GError **error)
-{
- int i, j;
- const char *error_string;
- CoglBlendStringError detail = COGL_BLEND_STRING_ERROR_INVALID_ERROR;
-
-#ifdef HAVE_COGL_GL
- _COGL_GET_CONTEXT (ctx, 0);
-#endif
-
-#ifdef HAVE_COGL_GL
- if (n_statements == 2)
- {
- /* glBlendEquationSeperate is GL 2.0 only */
- if (!ctx->drv.pf_glBlendEquationSeparate &&
- statements[0].function->type != statements[1].function->type)
- {
- error_string = "Separate blend functions for the RGB an A "
- "channels isn't supported by the driver";
- detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
- goto error;
- }
- }
-#elif defined(HAVE_COGL_GLES)
- if (n_statements != 1)
- {
- error_string = "Separate blend functions for the RGB an A "
- "channels isn't supported by the GLES 1";
- detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
- goto error;
- }
-#endif
-
- for (i = 0; i < n_statements; i++)
- for (j = 0; j < statements[i].function->argc; j++)
- {
- CoglBlendStringArgument *arg = &statements[i].args[j];
-
- if (arg->source.is_zero)
- continue;
-
- if ((j == 0 &&
- arg->source.info->type !=
- COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
- || (j == 1 &&
- arg->source.info->type !=
- COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR))
- {
- error_string = "For blending you must always use SRC_COLOR "
- "for arg0 and DST_COLOR for arg1";
- goto error;
- }
-
-#ifdef HAVE_COGL_GLES
- if (arg->factor.is_color &&
- arg->factor.source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
- {
- error_string = "GLES Doesn't support constant blend factors";
- detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
- goto error;
- }
-#endif
- }
-
- return TRUE;
-
-error:
- g_set_error (error,
- COGL_BLEND_STRING_ERROR,
- detail,
- "Invalid blend string: %s",
- error_string);
- return FALSE;
-}
-
-static gboolean
-validate_statements_for_context (CoglBlendStringStatement *statements,
- int n_statements,
- CoglBlendStringContext context,
- GError **error)
-{
- const char *error_string;
-
- if (n_statements == 1)
- {
- if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- {
- error_string = "You need to also give a blend statement for the RGB"
- "channels";
- goto error;
- }
- else if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
- {
- error_string = "You need to also give a blend statement for the "
- "Alpha channel";
- goto error;
- }
- }
-
- if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
- return validate_blend_statements (statements, n_statements, error);
- else
- return validate_tex_combine_statements (statements, n_statements, error);
-
-error:
- g_set_error (error,
- COGL_BLEND_STRING_ERROR,
- COGL_BLEND_STRING_ERROR_INVALID_ERROR,
- "Invalid %s string: %s",
- context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
- "blend" : "texture combine",
- error_string);
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- g_debug ("Invalid %s string: %s",
- context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
- "blend" : "texture combine",
- error_string);
- }
-
- return FALSE;
-}
-
-static void
-print_argument (CoglBlendStringArgument *arg)
-{
- const char *mask_names[] = {
- "RGB",
- "A",
- "RGBA"
- };
-
- g_print (" Arg:\n");
- g_print (" is zero = %s\n", arg->source.is_zero ? "yes" : "no");
- if (!arg->source.is_zero)
- {
- g_print (" color source = %s\n", arg->source.info->name);
- g_print (" one minus = %s\n", arg->source.one_minus ? "yes" : "no");
- g_print (" mask = %s\n", mask_names[arg->source.mask]);
- g_print (" texture = %d\n", arg->source.texture);
- g_print ("\n");
- g_print (" factor is_one = %s\n", arg->factor.is_one ? "yes" : "no");
- g_print (" factor is_src_alpha_saturate = %s\n",
- arg->factor.is_src_alpha_saturate ? "yes" : "no");
- g_print (" factor is_color = %s\n", arg->factor.is_color ? "yes" : "no");
- if (arg->factor.is_color)
- {
- g_print (" factor color:is zero = %s\n",
- arg->factor.source.is_zero ? "yes" : "no");
- g_print (" factor color:color source = %s\n",
- arg->factor.source.info->name);
- g_print (" factor color:one minus = %s\n",
- arg->factor.source.one_minus ? "yes" : "no");
- g_print (" factor color:mask = %s\n",
- mask_names[arg->factor.source.mask]);
- g_print (" factor color:texture = %d\n",
- arg->factor.source.texture);
- }
- }
-}
-
-static void
-print_statement (int num, CoglBlendStringStatement *statement)
-{
- const char *mask_names[] = {
- "RGB",
- "A",
- "RGBA"
- };
- int i;
- g_print ("Statement %d:\n", num);
- g_print (" Destination channel mask = %s\n",
- mask_names[statement->mask]);
- g_print (" Function = %s\n", statement->function->name);
- for (i = 0; i < statement->function->argc; i++)
- print_argument (&statement->args[i]);
-}
-
-static const CoglBlendStringFunctionInfo *
-get_function_info (const char *mark,
- const char *p,
- CoglBlendStringContext context)
-{
- gsize len = p - mark;
- CoglBlendStringFunctionInfo *functions;
- gsize array_len;
- int i;
-
- if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
- {
- functions = blend_functions;
- array_len = G_N_ELEMENTS (blend_functions);
- }
- else
- {
- functions = tex_combine_functions;
- array_len = G_N_ELEMENTS (tex_combine_functions);
- }
-
- for (i = 0; i < array_len; i++)
- {
- if (len >= functions[i].name_len
- && strncmp (mark, functions[i].name, functions[i].name_len) == 0)
- return &functions[i];
- }
- return NULL;
-}
-
-static const CoglBlendStringColorSourceInfo *
-get_color_src_info (const char *mark,
- const char *p,
- CoglBlendStringContext context)
-{
- gsize len = p - mark;
- CoglBlendStringColorSourceInfo *sources;
- gsize array_len;
- int i;
-
- if (context == COGL_BLEND_STRING_CONTEXT_BLENDING)
- {
- sources = blending_color_sources;
- array_len = G_N_ELEMENTS (blending_color_sources);
- }
- else
- {
- sources = tex_combine_color_sources;
- array_len = G_N_ELEMENTS (tex_combine_color_sources);
- }
-
- for (i = 0; i < array_len; i++)
- {
- if (len >= sources[i].name_len
- && strncmp (mark, sources[i].name, sources[i].name_len) == 0)
- return &sources[i];
- }
-
- if (len >= 9 &&
- strncmp (mark, "TEXTURE_", 8) == 0 &&
- g_ascii_isdigit (mark[8]))
- {
- return &tex_combine_texture_n_color_source;
- }
-
- return NULL;
-}
-
-static gboolean
-is_symbol_char (const char c)
-{
- return (g_ascii_isalpha (c) || c == '_') ? TRUE : FALSE;
-}
-
-static gboolean
-is_alphanum_char (const char c)
-{
- return (g_ascii_isalnum (c) || c == '_') ? TRUE : FALSE;
-}
-
-static gboolean
-parse_argument (const char *string, /* original user string */
- const char **ret_p, /* start of argument IN:OUT */
- const CoglBlendStringStatement *statement,
- int current_arg,
- CoglBlendStringArgument *arg, /* OUT */
- CoglBlendStringContext context,
- GError **error)
-{
- const char *p = *ret_p;
- const char *mark = NULL;
- const char *error_string = NULL;
- ParserArgState state = PARSER_ARG_STATE_START;
- gboolean parsing_factor = FALSE;
-
- arg->source.is_zero = FALSE;
- arg->source.info = NULL;
- arg->source.texture = 0;
- arg->source.one_minus = FALSE;
- arg->source.mask = statement->mask;
-
- arg->factor.is_one = FALSE;
- arg->factor.is_color = FALSE;
- arg->factor.is_src_alpha_saturate = FALSE;
-
- arg->factor.source.is_zero = FALSE;
- arg->factor.source.info = NULL;
- arg->factor.source.texture = 0;
- arg->factor.source.one_minus = FALSE;
- arg->factor.source.mask = statement->mask;
-
- do
- {
- if (g_ascii_isspace (*p))
- continue;
-
- if (*p == '\0')
- {
- error_string = "Unexpected end of string while parsing argument";
- goto error;
- }
-
- switch (state)
- {
- case PARSER_ARG_STATE_START:
- if (*p == '1')
- state = PARSER_ARG_STATE_EXPECT_MINUS;
- else if (*p == '0')
- {
- arg->source.is_zero = TRUE;
- state = PARSER_ARG_STATE_EXPECT_END;
- }
- else
- {
- p--; /* backtrack */
- state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
- }
- continue;
-
- case PARSER_ARG_STATE_EXPECT_MINUS:
- if (*p != '-')
- {
- error_string = "expected a '-' following the 1";
- goto error;
- }
- arg->source.one_minus = TRUE;
- state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
- continue;
-
- case PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME:
- if (!is_symbol_char (*p))
- {
- error_string = "expected a color source name";
- goto error;
- }
- state = PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME;
- mark = p;
- if (parsing_factor)
- arg->factor.is_color = TRUE;
-
- /* fall through */
- case PARSER_ARG_STATE_SCRAPING_COLOR_SRC_NAME:
- if (!is_symbol_char (*p))
- {
- CoglBlendStringColorSource *source =
- parsing_factor ? &arg->factor.source : &arg->source;
- source->info = get_color_src_info (mark, p, context);
- if (!source->info)
- {
- error_string = "Unknown color source name";
- goto error;
- }
- if (source->info->type ==
- COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N)
- {
- char *endp;
- source->texture =
- strtoul (&mark[strlen ("TEXTURE_")], &endp, 10);
- if (mark == endp)
- {
- error_string = "invalid texture number given with "
- "TEXTURE_N color source";
- goto error;
- }
- p = endp;
- }
- state = PARSER_ARG_STATE_MAYBE_COLOR_MASK;
- }
- else
- continue;
-
- /* fall through */
- case PARSER_ARG_STATE_MAYBE_COLOR_MASK:
- if (*p != '[')
- {
- p--; /* backtrack */
- if (!parsing_factor)
- state = PARSER_ARG_STATE_MAYBE_MULT;
- else
- state = PARSER_ARG_STATE_EXPECT_END;
- continue;
- }
- state = PARSER_ARG_STATE_SCRAPING_MASK;
- mark = p;
-
- /* fall through */
- case PARSER_ARG_STATE_SCRAPING_MASK:
- if (*p == ']')
- {
- gsize len = p - mark;
- CoglBlendStringColorSource *source =
- parsing_factor ? &arg->factor.source : &arg->source;
-
- if (len == 5 && strncmp (mark, "[RGBA", len) == 0)
- {
- if (statement->mask != COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
- {
- error_string = "You can't use an RGBA color mask if the "
- "statement hasn't also got an RGBA= mask";
- goto error;
- }
- source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA;
- }
- else if (len == 4 && strncmp (mark, "[RGB", len) == 0)
- source->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
- else if (len == 2 && strncmp (mark, "[A", len) == 0)
- source->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
- else
- {
- error_string = "Expected a channel mask of [RGBA]"
- "[RGB] or [A]";
- goto error;
- }
- if (parsing_factor)
- state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
- else
- state = PARSER_ARG_STATE_MAYBE_MULT;
- }
- continue;
-
- case PARSER_ARG_STATE_EXPECT_OPEN_PAREN:
- if (*p != '(')
- {
- error_string = "Expected '(' before blend factor - the parser "
- "currently requires that all blend factors "
- "following a '*' be surrounded in brackets";
- goto error;
- }
- parsing_factor = TRUE;
- state = PARSER_ARG_STATE_EXPECT_FACTOR;
- continue;
-
- case PARSER_ARG_STATE_EXPECT_FACTOR:
- if (*p == '1')
- state = PARSER_ARG_STATE_MAYBE_MINUS;
- else if (*p == '0')
- {
- arg->source.is_zero = TRUE;
- state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
- }
- else
- {
- state = PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE;
- mark = p;
- }
- continue;
-
- case PARSER_ARG_STATE_MAYBE_SRC_ALPHA_SATURATE:
- if (!is_symbol_char (*p))
- {
- gsize len = p - mark;
- if (len >= strlen ("SRC_ALPHA_SATURATE") &&
- strncmp (mark, "SRC_ALPHA_SATURATE", len) == 0)
- {
- arg->factor.is_src_alpha_saturate = TRUE;
- state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
- }
- else
- {
- state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
- p = mark - 1; /* backtrack */
- }
- }
- continue;
-
- case PARSER_ARG_STATE_MAYBE_MINUS:
- if (*p == '-')
- {
- arg->factor.source.one_minus = TRUE;
- state = PARSER_ARG_STATE_EXPECT_COLOR_SRC_NAME;
- }
- else
- {
- arg->factor.is_one = TRUE;
- state = PARSER_ARG_STATE_EXPECT_CLOSE_PAREN;
- }
- continue;
-
- case PARSER_ARG_STATE_EXPECT_CLOSE_PAREN:
- if (*p != ')')
- {
- error_string = "Expected closing parenthesis after blend factor";
- goto error;
- }
- state = PARSER_ARG_STATE_EXPECT_END;
- continue;
-
- case PARSER_ARG_STATE_MAYBE_MULT:
- if (*p == '*')
- {
- state = PARSER_ARG_STATE_EXPECT_OPEN_PAREN;
- continue;
- }
- arg->factor.is_one = TRUE;
- state = PARSER_ARG_STATE_EXPECT_END;
-
- /* fall through */
- case PARSER_ARG_STATE_EXPECT_END:
- if (*p != ',' && *p != ')')
- {
- error_string = "expected , or )";
- goto error;
- }
-
- *ret_p = p - 1;
- return TRUE;
- }
- }
- while (p++);
-
-error:
- {
- int offset = p - string;
- g_set_error (error,
- COGL_BLEND_STRING_ERROR,
- COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR,
- "Syntax error for argument %d at offset %d: %s",
- current_arg,
- offset,
- error_string);
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- g_debug ("Syntax error for argument %d at offset %d: %s",
- current_arg, offset, error_string);
- }
- return FALSE;
- }
-}
-
-int
-_cogl_blend_string_compile (const char *string,
- CoglBlendStringContext context,
- CoglBlendStringStatement *statements,
- GError **error)
-{
- const char *p = string;
- const char *mark = NULL;
- const char *error_string;
- ParserState state = PARSER_STATE_EXPECT_DEST_CHANNELS;
- CoglBlendStringStatement *statement = statements;
- int current_statement = 0;
- int current_arg = 0;
- int remaining_argc = 0;
-
-#if 0
- COGL_DEBUG_SET_FLAG (COGL_DEBUG_BLEND_STRINGS);
-#endif
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- COGL_NOTE (BLEND_STRINGS, "Compiling %s string:\n%s\n",
- context == COGL_BLEND_STRING_CONTEXT_BLENDING ?
- "blend" : "texture combine",
- string);
- }
-
- do
- {
- if (g_ascii_isspace (*p))
- continue;
-
- if (*p == '\0')
- {
- switch (state)
- {
- case PARSER_STATE_EXPECT_DEST_CHANNELS:
- if (current_statement != 0)
- goto finished;
- error_string = "Empty statement";
- goto error;
- case PARSER_STATE_SCRAPING_DEST_CHANNELS:
- error_string = "Expected an '=' following the destination "
- "channel mask";
- goto error;
- case PARSER_STATE_EXPECT_FUNCTION_NAME:
- error_string = "Expected a function name";
- goto error;
- case PARSER_STATE_SCRAPING_FUNCTION_NAME:
- error_string = "Expected parenthesis after the function name";
- goto error;
- case PARSER_STATE_EXPECT_ARG_START:
- error_string = "Expected to find the start of an argument";
- goto error;
- case PARSER_STATE_EXPECT_STATEMENT_END:
- error_string = "Expected closing parenthesis for statement";
- goto error;
- }
- }
-
- switch (state)
- {
- case PARSER_STATE_EXPECT_DEST_CHANNELS:
- mark = p;
- state = PARSER_STATE_SCRAPING_DEST_CHANNELS;
-
- /* fall through */
- case PARSER_STATE_SCRAPING_DEST_CHANNELS:
- if (*p != '=')
- continue;
- if (strncmp (mark, "RGBA", 4) == 0)
- statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGBA;
- else if (strncmp (mark, "RGB", 3) == 0)
- statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_RGB;
- else if (strncmp (mark, "A", 1) == 0)
- statement->mask = COGL_BLEND_STRING_CHANNEL_MASK_ALPHA;
- else
- {
- error_string = "Unknown destination channel mask; "
- "expected RGBA=, RGB= or A=";
- goto error;
- }
- state = PARSER_STATE_EXPECT_FUNCTION_NAME;
- continue;
-
- case PARSER_STATE_EXPECT_FUNCTION_NAME:
- mark = p;
- state = PARSER_STATE_SCRAPING_FUNCTION_NAME;
-
- /* fall through */
- case PARSER_STATE_SCRAPING_FUNCTION_NAME:
- if (*p != '(')
- {
- if (!is_alphanum_char (*p))
- {
- error_string = "non alpha numeric character in function"
- "name";
- goto error;
- }
- continue;
- }
- statement->function = get_function_info (mark, p, context);
- if (!statement->function)
- {
- error_string = "Unknown function name";
- goto error;
- }
- remaining_argc = statement->function->argc;
- current_arg = 0;
- state = PARSER_STATE_EXPECT_ARG_START;
-
- /* fall through */
- case PARSER_STATE_EXPECT_ARG_START:
- if (*p != '(' && *p != ',')
- continue;
- if (remaining_argc)
- {
- p++; /* parse_argument expects to see the first char of the arg */
- if (!parse_argument (string, &p, statement,
- current_arg, &statement->args[current_arg],
- context, error))
- return 0;
- current_arg++;
- remaining_argc--;
- }
- if (!remaining_argc)
- state = PARSER_STATE_EXPECT_STATEMENT_END;
- continue;
-
- case PARSER_STATE_EXPECT_STATEMENT_END:
- if (*p != ')')
- {
- error_string = "Expected end of statement";
- goto error;
- }
- state = PARSER_STATE_EXPECT_DEST_CHANNELS;
- if (current_statement++ == 1)
- goto finished;
- statement = &statements[current_statement];
- }
- }
- while (p++);
-
-finished:
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- if (current_statement > 0)
- print_statement (0, &statements[0]);
- if (current_statement > 1)
- print_statement (1, &statements[1]);
- }
-
- if (!validate_statements_for_context (statements,
- current_statement,
- context,
- error))
- return 0;
-
- return current_statement;
-
-error:
- {
- int offset = p - string;
- g_set_error (error,
- COGL_BLEND_STRING_ERROR,
- COGL_BLEND_STRING_ERROR_PARSE_ERROR,
- "Syntax error at offset %d: %s",
- offset,
- error_string);
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_BLEND_STRINGS))
- {
- g_debug ("Syntax error at offset %d: %s",
- offset, error_string);
- }
- return 0;
- }
-}
-
-/*
- * INTERNAL TESTING CODE ...
- */
-
-struct _TestString
-{
- const char *string;
- CoglBlendStringContext context;
-};
-
-int
-_cogl_blend_string_test (void)
-{
- struct _TestString strings[] = {
- {" A = MODULATE ( TEXTURE[RGB], PREVIOUS[A], PREVIOUS[A] ) ",
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
- {" RGB = MODULATE ( TEXTURE[RGB], PREVIOUS[A] ) ",
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
- {"A=ADD(TEXTURE[A],PREVIOUS[RGB])",
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
- {"A=ADD(TEXTURE[A],PREVIOUS[RGB])",
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE },
-
- {"RGBA = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))",
- COGL_BLEND_STRING_CONTEXT_BLENDING },
- {"RGB = ADD(SRC_COLOR, DST_COLOR*(0))",
- COGL_BLEND_STRING_CONTEXT_BLENDING },
- {"RGB = ADD(SRC_COLOR, 0)",
- COGL_BLEND_STRING_CONTEXT_BLENDING },
- {"RGB = ADD()",
- COGL_BLEND_STRING_CONTEXT_BLENDING },
- {"RGB = ADD(SRC_COLOR, 0, DST_COLOR)",
- COGL_BLEND_STRING_CONTEXT_BLENDING },
- {NULL}
- };
- int i;
-
- GError *error = NULL;
- for (i = 0; strings[i].string; i++)
- {
- CoglBlendStringStatement statements[2];
- int count = _cogl_blend_string_compile (strings[i].string,
- strings[i].context,
- statements,
- &error);
- if (!count)
- {
- g_print ("Failed to parse string:\n%s\n%s\n",
- strings[i].string,
- error->message);
- g_error_free (error);
- error = NULL;
- continue;
- }
- g_print ("Original:\n");
- g_print ("%s\n", strings[i].string);
- if (count > 0)
- print_statement (0, &statements[0]);
- if (count > 1)
- print_statement (1, &statements[1]);
- }
-
- return 0;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef COGL_BLEND_STRING_H
-#define COGL_BLEND_STRING_H
-
-#include <stdlib.h>
-#include <glib.h>
-
-typedef enum _CoglBlendStringContext
-{
- COGL_BLEND_STRING_CONTEXT_BLENDING,
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE
-} CoglBlendStringContext;
-
-/* NB: debug stringify code will get upset if these
- * are re-ordered */
-typedef enum _CoglBlendStringChannelMask
-{
- COGL_BLEND_STRING_CHANNEL_MASK_RGB,
- COGL_BLEND_STRING_CHANNEL_MASK_ALPHA,
- COGL_BLEND_STRING_CHANNEL_MASK_RGBA
-} CoglBlendStringChannelMask;
-
-typedef enum _CoglBlendStringColorSourceType
-{
- /* blending */
- COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR,
- COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR,
-
- /* shared */
- COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT,
-
- /* texture combining */
- COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE,
- COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N,
- COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY,
- COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS
-} CoglBlendStringColorSourceType;
-
-typedef struct _CoglBlendStringColorSourceInfo
-{
- CoglBlendStringColorSourceType type;
- const char *name;
- gsize name_len;
-} CoglBlendStringColorSourceInfo;
-
-typedef struct _CoglBlendStringColorSource
-{
- gboolean is_zero;
- const CoglBlendStringColorSourceInfo *info;
- int texture; /* for the TEXTURE_N color source */
- gboolean one_minus;
- CoglBlendStringChannelMask mask;
-} CoglBlendStringColorSource;
-
-typedef struct _CoglBlendStringFactor
-{
- gboolean is_one;
- gboolean is_src_alpha_saturate;
- gboolean is_color;
- CoglBlendStringColorSource source;
-} CoglBlendStringFactor;
-
-typedef struct _CoglBlendStringArgument
-{
- CoglBlendStringColorSource source;
- CoglBlendStringFactor factor;
-} CoglBlendStringArgument;
-
-typedef enum _CoglBlendStringFunctionType
-{
- /* shared */
- COGL_BLEND_STRING_FUNCTION_ADD,
-
- /* texture combine only */
- COGL_BLEND_STRING_FUNCTION_REPLACE,
- COGL_BLEND_STRING_FUNCTION_MODULATE,
- COGL_BLEND_STRING_FUNCTION_ADD_SIGNED,
- COGL_BLEND_STRING_FUNCTION_INTERPOLATE,
- COGL_BLEND_STRING_FUNCTION_SUBTRACT,
- COGL_BLEND_STRING_FUNCTION_DOT3_RGB,
- COGL_BLEND_STRING_FUNCTION_DOT3_RGBA
-} CoglBlendStringFunctionType;
-
-typedef struct _CoglBlendStringFunctionInfo
-{
- enum _CoglBlendStringFunctionType type;
- const char *name;
- gsize name_len;
- int argc;
-} CoglBlendStringFunctionInfo;
-
-typedef struct _CoglBlendStringStatement
-{
- CoglBlendStringChannelMask mask;
- const CoglBlendStringFunctionInfo *function;
- CoglBlendStringArgument args[3];
-} CoglBlendStringStatement;
-
-
-gboolean
-_cogl_blend_string_compile (const char *string,
- CoglBlendStringContext context,
- CoglBlendStringStatement *statements,
- GError **error);
-
-void
-_cogl_blend_string_split_rgba_statement (CoglBlendStringStatement *statement,
- CoglBlendStringStatement *rgb,
- CoglBlendStringStatement *a);
-
-#endif /* COGL_BLEND_STRING_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl.h"
-#include "cogl-blit.h"
-#include "cogl-context-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-texture-2d-private.h"
-
-static const CoglBlitMode *_cogl_blit_default_mode = NULL;
-
-static gboolean
-_cogl_blit_texture_render_begin (CoglBlitData *data)
-{
- CoglHandle fbo;
- CoglPipeline *pipeline;
- unsigned int dst_width, dst_height;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- fbo = _cogl_offscreen_new_to_texture_full
- (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- if (fbo == COGL_INVALID_HANDLE)
- return FALSE;
-
- cogl_push_framebuffer (fbo);
- cogl_handle_unref (fbo);
-
- dst_width = cogl_texture_get_width (data->dst_tex);
- dst_height = cogl_texture_get_height (data->dst_tex);
-
- /* Set up an orthographic projection so we can use pixel
- coordinates to render to the texture */
- cogl_ortho (0, /* left */
- dst_width, /* right */
- dst_height, /* bottom */
- 0, /* top */
- -1, /* near */
- 1 /* far */);
-
- /* We cache a pipeline used for migrating on to the context so
- that it doesn't have to continuously regenerate a shader
- program */
- if (ctx->blit_texture_pipeline == NULL)
- {
- ctx->blit_texture_pipeline = cogl_pipeline_new ();
-
- cogl_pipeline_set_layer_filters (ctx->blit_texture_pipeline, 0,
- COGL_PIPELINE_FILTER_NEAREST,
- COGL_PIPELINE_FILTER_NEAREST);
-
- /* Disable blending by just directly taking the contents of the
- source texture */
- cogl_pipeline_set_blend (ctx->blit_texture_pipeline,
- "RGBA = ADD(SRC_COLOR, 0)",
- NULL);
- }
-
- pipeline = ctx->blit_texture_pipeline;
-
- cogl_pipeline_set_layer_texture (pipeline, 0, data->src_tex);
-
- cogl_push_source (pipeline);
-
- return TRUE;
-}
-
-static void
-_cogl_blit_texture_render_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- cogl_rectangle_with_texture_coords (dst_x, dst_y,
- dst_x + width,
- dst_y + height,
- src_x / (float) data->src_width,
- src_y / (float) data->src_height,
- (src_x + width) /
- (float) data->src_width,
- (src_y + height) /
- (float) data->src_height);
-}
-
-static void
-_cogl_blit_texture_render_end (CoglBlitData *data)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_pop_source ();
- cogl_pop_framebuffer ();
-
- /* Attach the target texture to the texture render pipeline so that
- we don't keep a reference to the source texture forever. This is
- assuming that the destination texture will live for a long time
- which is currently the case when cogl_blit_* is used from the
- atlas code. It may be better in future to keep around a set of
- dummy 1x1 textures for each texture target that we could bind
- instead. This would also be useful when using a pipeline as a
- hash table key such as for the ARBfp program cache. */
- cogl_pipeline_set_layer_texture (ctx->blit_texture_pipeline, 0,
- data->dst_tex);
-}
-
-static gboolean
-_cogl_blit_framebuffer_begin (CoglBlitData *data)
-{
- CoglHandle dst_fbo, src_fbo;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* We can only blit between FBOs if both textures are the same
- format and the blit framebuffer extension is supported */
- if ((cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) !=
- (cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) ||
- !cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT))
- return FALSE;
-
- dst_fbo = _cogl_offscreen_new_to_texture_full
- (data->dst_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- if (dst_fbo == COGL_INVALID_HANDLE)
- return FALSE;
-
- src_fbo = _cogl_offscreen_new_to_texture_full
- (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- if (src_fbo == COGL_INVALID_HANDLE)
- {
- cogl_handle_unref (dst_fbo);
- return FALSE;
- }
-
- _cogl_push_framebuffers (dst_fbo, src_fbo);
- cogl_handle_unref (src_fbo);
- cogl_handle_unref (dst_fbo);
-
- return TRUE;
-}
-
-static void
-_cogl_blit_framebuffer_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- _cogl_blit_framebuffer (src_x, src_y,
- dst_x, dst_y,
- width, height);
-}
-
-static void
-_cogl_blit_framebuffer_end (CoglBlitData *data)
-{
- cogl_pop_framebuffer ();
-}
-
-static gboolean
-_cogl_blit_copy_tex_sub_image_begin (CoglBlitData *data)
-{
- CoglHandle fbo;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* This will only work if the target texture is a CoglTexture2D */
- if (!_cogl_is_texture_2d (data->dst_tex))
- return FALSE;
-
- fbo = _cogl_offscreen_new_to_texture_full
- (data->src_tex, COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL, 0 /* level */);
-
- if (fbo == COGL_INVALID_HANDLE)
- return FALSE;
-
- cogl_push_framebuffer (fbo);
- cogl_handle_unref (fbo);
-
- return TRUE;
-}
-
-static void
-_cogl_blit_copy_tex_sub_image_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- _cogl_texture_2d_copy_from_framebuffer (data->dst_tex,
- dst_x, dst_y,
- src_x, src_y,
- width, height);
-}
-
-static void
-_cogl_blit_copy_tex_sub_image_end (CoglBlitData *data)
-{
- cogl_pop_framebuffer ();
-}
-
-static gboolean
-_cogl_blit_get_tex_data_begin (CoglBlitData *data)
-{
- data->format = cogl_texture_get_format (data->src_tex);
- data->bpp = _cogl_get_format_bpp (data->format);
-
- data->image_data = g_malloc (data->bpp * data->src_width *
- data->src_height);
- cogl_texture_get_data (data->src_tex, data->format,
- data->src_width * data->bpp, data->image_data);
-
- return TRUE;
-}
-
-static void
-_cogl_blit_get_tex_data_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- cogl_texture_set_region (data->dst_tex,
- src_x, src_y,
- dst_x, dst_y,
- width, height,
- data->src_width, data->src_height,
- data->format,
- data->src_width * data->bpp,
- data->image_data);
-}
-
-static void
-_cogl_blit_get_tex_data_end (CoglBlitData *data)
-{
- g_free (data->image_data);
-}
-
-/* These should be specified in order of preference */
-static const CoglBlitMode
-_cogl_blit_modes[] =
- {
- {
- "texture-render",
- _cogl_blit_texture_render_begin,
- _cogl_blit_texture_render_blit,
- _cogl_blit_texture_render_end
- },
- {
- "framebuffer",
- _cogl_blit_framebuffer_begin,
- _cogl_blit_framebuffer_blit,
- _cogl_blit_framebuffer_end
- },
- {
- "copy-tex-sub-image",
- _cogl_blit_copy_tex_sub_image_begin,
- _cogl_blit_copy_tex_sub_image_blit,
- _cogl_blit_copy_tex_sub_image_end
- },
- {
- "get-tex-data",
- _cogl_blit_get_tex_data_begin,
- _cogl_blit_get_tex_data_blit,
- _cogl_blit_get_tex_data_end
- }
- };
-
-void
-_cogl_blit_begin (CoglBlitData *data,
- CoglHandle dst_tex,
- CoglHandle src_tex)
-{
- int i;
-
- if (_cogl_blit_default_mode == NULL)
- {
- const char *default_mode_string;
-
- /* Allow the default to be specified with an environment
- variable. For the time being these functions are only used
- when blitting between atlas textures so the environment
- variable is named to be specific to the atlas code. If we
- want to use the code in other places we should create another
- environment variable for each specific use case */
- if ((default_mode_string = g_getenv ("COGL_ATLAS_DEFAULT_BLIT_MODE")))
- {
- for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++)
- if (!strcmp (_cogl_blit_modes[i].name, default_mode_string))
- {
- _cogl_blit_default_mode = _cogl_blit_modes + i;
- break;
- }
-
- if (i >= G_N_ELEMENTS (_cogl_blit_modes))
- {
- g_warning ("Unknown blit mode %s", default_mode_string);
- _cogl_blit_default_mode = _cogl_blit_modes;
- }
- }
- else
- /* Default to the first blit mode */
- _cogl_blit_default_mode = _cogl_blit_modes;
- }
-
- data->dst_tex = dst_tex;
- data->src_tex = src_tex;
-
- data->src_width = cogl_texture_get_width (src_tex);
- data->src_height = cogl_texture_get_height (src_tex);
-
- /* Try the default blit mode first */
- if (!_cogl_blit_default_mode->begin_func (data))
- {
- COGL_NOTE (ATLAS, "Failed to set up blit mode %s",
- _cogl_blit_default_mode->name);
-
- /* Try all of the other modes in order */
- for (i = 0; i < G_N_ELEMENTS (_cogl_blit_modes); i++)
- if (_cogl_blit_modes + i != _cogl_blit_default_mode &&
- _cogl_blit_modes[i].begin_func (data))
- {
- /* Use this mode as the default from now on */
- _cogl_blit_default_mode = _cogl_blit_modes + i;
- break;
- }
- else
- COGL_NOTE (ATLAS,
- "Failed to set up blit mode %s",
- _cogl_blit_modes[i].name);
-
- /* The last blit mode can't fail so this should never happen */
- g_return_if_fail (i < G_N_ELEMENTS (_cogl_blit_modes));
- }
-
- data->blit_mode = _cogl_blit_default_mode;
-
- COGL_NOTE (ATLAS, "Setup blit using %s", _cogl_blit_default_mode->name);
-}
-
-void
-_cogl_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- data->blit_mode->blit_func (data, src_x, src_y, dst_x, dst_y, width, height);
-}
-
-void
-_cogl_blit_end (CoglBlitData *data)
-{
- data->blit_mode->end_func (data);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __COGL_BLIT_H
-#define __COGL_BLIT_H
-
-#include <glib.h>
-#include "cogl-handle.h"
-
-/* This structures and functions are used when a series of blits needs
- to be performed between two textures. In this case there are
- multiple methods we can use, most of which involve transferring
- between an FBO bound to the texture. */
-
-typedef struct _CoglBlitData CoglBlitData;
-
-typedef gboolean (* CoglBlitBeginFunc) (CoglBlitData *data);
-typedef void (* CoglBlitEndFunc) (CoglBlitData *data);
-
-typedef void (* CoglBlitFunc) (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height);
-
-typedef struct
-{
- const char *name;
- CoglBlitBeginFunc begin_func;
- CoglBlitFunc blit_func;
- CoglBlitEndFunc end_func;
-} CoglBlitMode;
-
-struct _CoglBlitData
-{
- CoglHandle src_tex, dst_tex;
-
- unsigned int src_width;
- unsigned int src_height;
-
- const CoglBlitMode *blit_mode;
-
- /* If we're not using an FBO then we g_malloc a buffer and copy the
- complete texture data in */
- unsigned char *image_data;
- CoglPixelFormat format;
- int bpp;
-};
-
-void
-_cogl_blit_begin (CoglBlitData *data,
- CoglHandle dst_tex,
- CoglHandle src_tex);
-
-void
-_cogl_blit (CoglBlitData *data,
- unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height);
-
-void
-_cogl_blit_end (CoglBlitData *data);
-
-#endif /* __COGL_BLIT_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_BUFFER_PRIVATE_H__
-#define __COGL_BUFFER_PRIVATE_H__
-
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-object-private.h"
-#include "cogl-buffer.h"
-
-G_BEGIN_DECLS
-
-#define COGL_BUFFER(buffer) ((CoglBuffer *)(buffer))
-
-typedef struct _CoglBufferVtable CoglBufferVtable;
-
-struct _CoglBufferVtable
-{
- void * (* map) (CoglBuffer *buffer,
- CoglBufferAccess access,
- CoglBufferMapHint hints);
-
- void (* unmap) (CoglBuffer *buffer);
-
- gboolean (* set_data) (CoglBuffer *buffer,
- unsigned int offset,
- const void *data,
- unsigned int size);
-};
-
-typedef enum _CoglBufferFlags
-{
- COGL_BUFFER_FLAG_NONE = 0,
- COGL_BUFFER_FLAG_BUFFER_OBJECT = 1UL << 0, /* real openGL buffer object */
- COGL_BUFFER_FLAG_MAPPED = 1UL << 1,
- COGL_BUFFER_FLAG_MAPPED_FALLBACK = 1UL << 2
-} CoglBufferFlags;
-
-typedef enum {
- COGL_BUFFER_USAGE_HINT_TEXTURE,
- COGL_BUFFER_USAGE_HINT_VERTEX_ARRAY,
- COGL_BUFFER_USAGE_HINT_INDEX_ARRAY
-} CoglBufferUsageHint;
-
-typedef enum {
- COGL_BUFFER_BIND_TARGET_PIXEL_PACK,
- COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK,
- COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY,
- COGL_BUFFER_BIND_TARGET_INDEX_ARRAY,
-
- COGL_BUFFER_BIND_TARGET_COUNT
-} CoglBufferBindTarget;
-
-struct _CoglBuffer
-{
- CoglObject _parent;
- CoglBufferVtable vtable;
-
- CoglBufferBindTarget last_target;
-
- CoglBufferFlags flags;
-
- GLuint gl_handle; /* OpenGL handle */
- unsigned int size; /* size of the buffer, in bytes */
- CoglBufferUsageHint usage_hint;
- CoglBufferUpdateHint update_hint;
-
- guint8 *data; /* points to the mapped memory when
- * the CoglBuffer is a VBO, PBO, ... or
- * points to allocated memory in the
- * fallback paths */
-
- int immutable_ref;
-
- guint store_created:1;
-};
-
-/* This is used to register a type to the list of handle types that
- will be considered a texture in cogl_is_texture() */
-void
-_cogl_buffer_register_buffer_type (GQuark type);
-
-#define COGL_BUFFER_DEFINE(TypeName, type_name) \
- COGL_OBJECT_DEFINE_WITH_CODE \
- (TypeName, type_name, \
- _cogl_buffer_register_buffer_type (_cogl_object_ \
- ## type_name ## _get_type ()))
-
-void
-_cogl_buffer_initialize (CoglBuffer *buffer,
- unsigned int size,
- gboolean use_malloc,
- CoglBufferBindTarget default_target,
- CoglBufferUsageHint usage_hint,
- CoglBufferUpdateHint update_hint);
-
-void
-_cogl_buffer_fini (CoglBuffer *buffer);
-
-void *
-_cogl_buffer_bind (CoglBuffer *buffer,
- CoglBufferBindTarget target);
-
-void
-_cogl_buffer_unbind (CoglBuffer *buffer);
-
-CoglBufferUsageHint
-_cogl_buffer_get_usage_hint (CoglBuffer *buffer);
-
-GLenum
-_cogl_buffer_access_to_gl_enum (CoglBufferAccess access);
-
-GLenum
-_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
- CoglBufferUpdateHint update_hint);
-
-CoglBuffer *
-_cogl_buffer_immutable_ref (CoglBuffer *buffer);
-
-void
-_cogl_buffer_immutable_unref (CoglBuffer *buffer);
-
-/* This is a wrapper around cogl_buffer_map for internal use when we
- want to map the buffer for write only to replace the entire
- contents. If the map fails then it will fallback to writing to a
- temporary buffer. When _cogl_buffer_unmap_for_fill_or_fallback is
- called the temporary buffer will be copied into the array. Note
- that these calls share a global array so they can not be nested. */
-void *
-_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer);
-
-void
-_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer);
-
-G_END_DECLS
-
-#endif /* __COGL_BUFFER_PRIVATE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-/* For an overview of the functionality implemented here, please see
- * cogl-buffer.h, which contains the gtk-doc section overview for the
- * Pixel Buffers API.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-pixel-array-private.h"
-
-/*
- * GL/GLES compatibility defines for the buffer API:
- */
-
-#if defined (HAVE_COGL_GL)
-
-#define glGenBuffers ctx->drv.pf_glGenBuffers
-#define glBindBuffer ctx->drv.pf_glBindBuffer
-#define glBufferData ctx->drv.pf_glBufferData
-#define glBufferSubData ctx->drv.pf_glBufferSubData
-#define glGetBufferSubData ctx->drv.pf_glGetBufferSubData
-#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
-
-#endif
-
-/* These two are always accessed through an extension, even on GLES */
-#define glMapBuffer ctx->drv.pf_glMapBuffer
-#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
-
-#ifndef GL_PIXEL_PACK_BUFFER
-#define GL_PIXEL_PACK_BUFFER 0x88EB
-#endif
-#ifndef GL_PIXEL_UNPACK_BUFFER
-#define GL_PIXEL_UNPACK_BUFFER 0x88EC
-#endif
-#ifndef GL_ARRAY_BUFFER
-#define GL_ARRAY_BUFFER 0x8892
-#endif
-#ifndef GL_ELEMENT_ARRAY_BUFFER
-#define GL_ARRAY_BUFFER 0x8893
-#endif
-#ifndef GL_READ_ONLY
-#define GL_READ_ONLY 0x88B8
-#endif
-#ifndef GL_WRITE_ONLY
-#define GL_WRITE_ONLY 0x88B9
-#endif
-#ifndef GL_READ_WRITE
-#define GL_READ_WRITE 0x88BA
-#endif
-
-/* XXX:
- * The CoglHandle macros don't support any form of inheritance, so for
- * now we implement the CoglObject support for the CoglBuffer
- * abstract class manually.
- */
-
-void
-_cogl_buffer_register_buffer_type (GQuark type)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- ctx->buffer_types = g_slist_prepend (ctx->buffer_types,
- GINT_TO_POINTER (type));
-}
-
-gboolean
-cogl_is_buffer (const void *object)
-{
- const CoglHandleObject *obj = object;
- GSList *l;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (object == NULL)
- return FALSE;
-
- for (l = ctx->buffer_types; l; l = l->next)
- if (GPOINTER_TO_INT (l->data) == obj->klass->type)
- return TRUE;
-
- return FALSE;
-}
-
-static GLenum
-convert_bind_target_to_gl_target (CoglBufferBindTarget target)
-{
- switch (target)
- {
- case COGL_BUFFER_BIND_TARGET_PIXEL_PACK:
- return GL_PIXEL_PACK_BUFFER;
- case COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK:
- return GL_PIXEL_UNPACK_BUFFER;
- case COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY:
- return GL_ARRAY_BUFFER;
- case COGL_BUFFER_BIND_TARGET_INDEX_ARRAY:
- return GL_ELEMENT_ARRAY_BUFFER;
- default:
- g_return_val_if_reached (COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK);
- }
-}
-
-static void *
-bo_map (CoglBuffer *buffer,
- CoglBufferAccess access,
- CoglBufferMapHint hints)
-{
- guint8 *data;
- CoglBufferBindTarget target;
- GLenum gl_target;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- if ((access & COGL_BUFFER_ACCESS_READ) &&
- !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_READ))
- return NULL;
- if ((access & COGL_BUFFER_ACCESS_WRITE) &&
- !cogl_features_available (COGL_FEATURE_MAP_BUFFER_FOR_WRITE))
- return NULL;
-
- target = buffer->last_target;
- _cogl_buffer_bind (buffer, target);
-
- gl_target = convert_bind_target_to_gl_target (target);
-
- /* create an empty store if we don't have one yet. creating the store
- * lazily allows the user of the CoglBuffer to set a hint before the
- * store is created. */
- if (!buffer->store_created || (hints & COGL_BUFFER_MAP_HINT_DISCARD))
- {
- GE( glBufferData (gl_target,
- buffer->size,
- NULL,
- _cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
- buffer->update_hint)) );
- buffer->store_created = TRUE;
- }
-
- GE_RET( data, glMapBuffer (gl_target,
- _cogl_buffer_access_to_gl_enum (access)) );
- if (data)
- buffer->flags |= COGL_BUFFER_FLAG_MAPPED;
-
- _cogl_buffer_unbind (buffer);
-
- return data;
-}
-
-static void
-bo_unmap (CoglBuffer *buffer)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_buffer_bind (buffer, buffer->last_target);
-
- GE( glUnmapBuffer (convert_bind_target_to_gl_target (buffer->last_target)) );
- buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED;
-
- _cogl_buffer_unbind (buffer);
-}
-
-static gboolean
-bo_set_data (CoglBuffer *buffer,
- unsigned int offset,
- const void *data,
- unsigned int size)
-{
- CoglBufferBindTarget target;
- GLenum gl_target;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- target = buffer->last_target;
- _cogl_buffer_bind (buffer, target);
-
- gl_target = convert_bind_target_to_gl_target (target);
-
- /* create an empty store if we don't have one yet. creating the store
- * lazily allows the user of the CoglBuffer to set a hint before the
- * store is created. */
- if (!buffer->store_created)
- {
- GE( glBufferData (gl_target,
- buffer->size,
- NULL,
- _cogl_buffer_hints_to_gl_enum (buffer->usage_hint,
- buffer->update_hint)) );
- buffer->store_created = TRUE;
- }
-
- GE( glBufferSubData (gl_target, offset, size, data) );
-
- _cogl_buffer_unbind (buffer);
-
- return TRUE;
-}
-
-/*
- * Fallback path, buffer->data points to a malloc'ed buffer.
- */
-
-static void *
-malloc_map (CoglBuffer *buffer,
- CoglBufferAccess access,
- CoglBufferMapHint hints)
-{
- buffer->flags |= COGL_BUFFER_FLAG_MAPPED;
- return buffer->data;
-}
-
-static void
-malloc_unmap (CoglBuffer *buffer)
-{
- buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED;
-}
-
-static gboolean
-malloc_set_data (CoglBuffer *buffer,
- unsigned int offset,
- const void *data,
- unsigned int size)
-{
- memcpy (buffer->data + offset, data, size);
- return TRUE;
-}
-
-void
-_cogl_buffer_initialize (CoglBuffer *buffer,
- unsigned int size,
- gboolean use_malloc,
- CoglBufferBindTarget default_target,
- CoglBufferUsageHint usage_hint,
- CoglBufferUpdateHint update_hint)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- buffer->flags = COGL_BUFFER_FLAG_NONE;
- buffer->store_created = FALSE;
- buffer->size = size;
- buffer->last_target = default_target;
- buffer->usage_hint = usage_hint;
- buffer->update_hint = update_hint;
- buffer->data = NULL;
- buffer->immutable_ref = 0;
-
- if (use_malloc)
- {
- buffer->vtable.map = malloc_map;
- buffer->vtable.unmap = malloc_unmap;
- buffer->vtable.set_data = malloc_set_data;
-
- buffer->data = g_malloc (size);
- }
- else
- {
- buffer->vtable.map = bo_map;
- buffer->vtable.unmap = bo_unmap;
- buffer->vtable.set_data = bo_set_data;
-
- GE( glGenBuffers (1, &buffer->gl_handle) );
- buffer->flags |= COGL_BUFFER_FLAG_BUFFER_OBJECT;
- }
-}
-
-void
-_cogl_buffer_fini (CoglBuffer *buffer)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (!(buffer->flags & COGL_BUFFER_FLAG_MAPPED));
- g_return_if_fail (buffer->immutable_ref == 0);
-
- if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
- GE( glDeleteBuffers (1, &buffer->gl_handle) );
- else
- g_free (buffer->data);
-}
-
-GLenum
-_cogl_buffer_access_to_gl_enum (CoglBufferAccess access)
-{
- if ((access & COGL_BUFFER_ACCESS_READ_WRITE) == COGL_BUFFER_ACCESS_READ_WRITE)
- return GL_READ_WRITE;
- else if (access & COGL_BUFFER_ACCESS_WRITE)
- return GL_WRITE_ONLY;
- else
- return GL_READ_ONLY;
-}
-
-/* OpenGL ES 1.1 and 2 only know about STATIC_DRAW and DYNAMIC_DRAW */
-#if defined (COGL_HAS_GLES)
-GLenum
-_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
- CoglBufferUpdateHint update_hint)
-{
- /* usage hint is always TEXTURE for now */
- if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC)
- return GL_STATIC_DRAW;
- return GL_DYNAMIC_DRAW;
-}
-#else
-GLenum
-_cogl_buffer_hints_to_gl_enum (CoglBufferUsageHint usage_hint,
- CoglBufferUpdateHint update_hint)
-{
- /* usage hint is always TEXTURE for now */
- if (update_hint == COGL_BUFFER_UPDATE_HINT_STATIC)
- return GL_STATIC_DRAW;
- if (update_hint == COGL_BUFFER_UPDATE_HINT_DYNAMIC)
- return GL_DYNAMIC_DRAW;
- if (update_hint == COGL_BUFFER_UPDATE_HINT_STREAM)
- return GL_STREAM_DRAW;
-
- return GL_STATIC_DRAW;
-}
-#endif
-
-void *
-_cogl_buffer_bind (CoglBuffer *buffer, CoglBufferBindTarget target)
-{
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_return_val_if_fail (buffer != NULL, NULL);
-
- /* Don't allow binding the buffer to multiple targets at the same time */
- g_return_val_if_fail (ctx->current_buffer[buffer->last_target] != buffer,
- NULL);
-
- /* Don't allow nesting binds to the same target */
- g_return_val_if_fail (ctx->current_buffer[target] == NULL, NULL);
-
- buffer->last_target = target;
- ctx->current_buffer[target] = buffer;
-
- if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
- {
- GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target);
- GE( glBindBuffer (gl_target, buffer->gl_handle) );
- return NULL;
- }
- else
- return buffer->data;
-}
-
-void
-_cogl_buffer_unbind (CoglBuffer *buffer)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (buffer != NULL);
-
- /* the unbind should pair up with a previous bind */
- g_return_if_fail (ctx->current_buffer[buffer->last_target] == buffer);
-
- if (buffer->flags & COGL_BUFFER_FLAG_BUFFER_OBJECT)
- {
- GLenum gl_target = convert_bind_target_to_gl_target (buffer->last_target);
- GE( glBindBuffer (gl_target, 0) );
- }
-
- ctx->current_buffer[buffer->last_target] = NULL;
-}
-
-unsigned int
-cogl_buffer_get_size (CoglBuffer *buffer)
-{
- if (!cogl_is_buffer (buffer))
- return 0;
-
- return COGL_BUFFER (buffer)->size;
-}
-
-void
-cogl_buffer_set_update_hint (CoglBuffer *buffer,
- CoglBufferUpdateHint hint)
-{
- if (!cogl_is_buffer (buffer))
- return;
-
- if (G_UNLIKELY (hint > COGL_BUFFER_UPDATE_HINT_STREAM))
- hint = COGL_BUFFER_UPDATE_HINT_STATIC;
-
- buffer->update_hint = hint;
-}
-
-CoglBufferUpdateHint
-cogl_buffer_get_update_hint (CoglBuffer *buffer)
-{
- if (!cogl_is_buffer (buffer))
- return FALSE;
-
- return buffer->update_hint;
-}
-
-static void
-warn_about_midscene_changes (void)
-{
- static gboolean seen = FALSE;
- if (!seen)
- {
- g_warning ("Mid-scene modification of buffers has "
- "undefined results\n");
- seen = TRUE;
- }
-}
-
-void *
-cogl_buffer_map (CoglBuffer *buffer,
- CoglBufferAccess access,
- CoglBufferMapHint hints)
-{
- g_return_val_if_fail (cogl_is_buffer (buffer), NULL);
-
- if (G_UNLIKELY (buffer->immutable_ref))
- warn_about_midscene_changes ();
-
- if (buffer->flags & COGL_BUFFER_FLAG_MAPPED)
- return buffer->data;
-
- buffer->data = buffer->vtable.map (buffer, access, hints);
- return buffer->data;
-}
-
-void
-cogl_buffer_unmap (CoglBuffer *buffer)
-{
- if (!cogl_is_buffer (buffer))
- return;
-
- if (!(buffer->flags & COGL_BUFFER_FLAG_MAPPED))
- return;
-
- buffer->vtable.unmap (buffer);
-}
-
-void *
-_cogl_buffer_map_for_fill_or_fallback (CoglBuffer *buffer)
-{
- void *ret;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_return_val_if_fail (!ctx->buffer_map_fallback_in_use, NULL);
-
- ctx->buffer_map_fallback_in_use = TRUE;
-
- ret = cogl_buffer_map (buffer,
- COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
-
- if (ret)
- return ret;
- else
- {
- /* If the map fails then we'll use a temporary buffer to fill
- the data and then upload it using cogl_buffer_set_data when
- the buffer is unmapped. The temporary buffer is shared to
- avoid reallocating it every time */
- g_byte_array_set_size (ctx->buffer_map_fallback_array, buffer->size);
-
- buffer->flags |= COGL_BUFFER_FLAG_MAPPED_FALLBACK;
-
- return ctx->buffer_map_fallback_array->data;
- }
-}
-
-void
-_cogl_buffer_unmap_for_fill_or_fallback (CoglBuffer *buffer)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (ctx->buffer_map_fallback_in_use);
-
- ctx->buffer_map_fallback_in_use = FALSE;
-
- if ((buffer->flags & COGL_BUFFER_FLAG_MAPPED_FALLBACK))
- {
- cogl_buffer_set_data (buffer, 0,
- ctx->buffer_map_fallback_array->data,
- buffer->size);
- buffer->flags &= ~COGL_BUFFER_FLAG_MAPPED_FALLBACK;
- }
- else
- cogl_buffer_unmap (buffer);
-}
-
-gboolean
-cogl_buffer_set_data (CoglBuffer *buffer,
- gsize offset,
- const void *data,
- gsize size)
-{
- g_return_val_if_fail (cogl_is_buffer (buffer), FALSE);
- g_return_val_if_fail ((offset + size) <= buffer->size, FALSE);
-
- if (G_UNLIKELY (buffer->immutable_ref))
- warn_about_midscene_changes ();
-
- return buffer->vtable.set_data (buffer, offset, data, size);
-}
-
-CoglBuffer *
-_cogl_buffer_immutable_ref (CoglBuffer *buffer)
-{
- g_return_val_if_fail (cogl_is_buffer (buffer), NULL);
-
- buffer->immutable_ref++;
- return buffer;
-}
-
-void
-_cogl_buffer_immutable_unref (CoglBuffer *buffer)
-{
- g_return_if_fail (cogl_is_buffer (buffer));
- g_return_if_fail (buffer->immutable_ref > 0);
-
- buffer->immutable_ref--;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C)2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_BUFFER_H__
-#define __COGL_BUFFER_H__
-
-#include <glib.h>
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-buffer
- * @short_description: Buffer creation and manipulation
- * @stability: Unstable
- *
- * COGL allows the creation and the manipulation of buffers. If the underlying
- * OpenGL implementation allows it, COGL will use Pixel Buffer Objects.
- */
-
-/* All of the cogl-buffer API is currently experimental so we suffix
- * the actual symbols with _EXP so if somone is monitoring for ABI
- * changes it will hopefully be clearer to them what's going on if any
- * of the symbols dissapear at a later date.
- */
-#define cogl_is_buffer cogl_is_buffer_EXP
-#define cogl_buffer_get_size cogl_buffer_get_size_EXP
-#define cogl_buffer_set_usage_hint cogl_buffer_set_usage_hint_EXP
-#define cogl_buffer_get_usage_hint cogl_buffer_get_usage_hint_EXP
-#define cogl_buffer_set_update_hint cogl_buffer_set_update_hint_EXP
-#define cogl_buffer_get_update_hint cogl_buffer_get_update_hint_EXP
-#define cogl_buffer_map cogl_buffer_map_EXP
-#define cogl_buffer_unmap cogl_buffer_unmap_EXP
-#define cogl_buffer_set_data cogl_buffer_set_data_EXP
-
-typedef struct _CoglBuffer CoglBuffer;
-
-/**
- * cogl_is_buffer:
- * @buffer: a buffer object
- *
- * Checks whether @buffer is a buffer object.
- *
- * Return value: %TRUE if the handle is a CoglBuffer, and %FALSE otherwise
- *
- * Since: 1.2
- * Stability: Unstable
- */
-gboolean
-cogl_is_buffer (const void *object);
-
-/**
- * cogl_buffer_get_size:
- * @buffer: a buffer object
- *
- * Retrieves the size of buffer
- *
- * Return value: the size of the buffer in bytes
- *
- * Since: 1.2
- * Stability: Unstable
- */
-unsigned int
-cogl_buffer_get_size (CoglBuffer *buffer);
-
-/**
- * CoglBufferUpdateHint:
- * @COGL_BUFFER_UPDATE_HINT_STATIC: the buffer will not change over time
- * @COGL_BUFFER_UPDATE_HINT_DYNAMIC: the buffer will change from time to time
- * @COGL_BUFFER_UPDATE_HINT_STREAM: the buffer will be used once or a couple of
- * times
- *
- * The update hint on a buffer allows the user to give some detail on how often
- * the buffer data is going to be updated.
- *
- * Since: 1.2
- * Stability: Unstable
- */
-typedef enum { /*< prefix=COGL_BUFFER_UPDATE_HINT >*/
- COGL_BUFFER_UPDATE_HINT_STATIC,
- COGL_BUFFER_UPDATE_HINT_DYNAMIC,
- COGL_BUFFER_UPDATE_HINT_STREAM
-} CoglBufferUpdateHint;
-
-/**
- * cogl_buffer_set_update_hint:
- * @buffer: a buffer object
- * @hint: the new hint
- *
- * Sets the update hint on a buffer. See #CoglBufferUpdateHint for a description
- * of the available hints.
- *
- * Since: 1.2
- * Stability: Unstable
- */
-void
-cogl_buffer_set_update_hint (CoglBuffer *buffer,
- CoglBufferUpdateHint hint);
-
-/**
- * cogl_buffer_get_update_hint:
- * @buffer: a buffer object
- *
- * Retrieves the update hints set using cogl_buffer_set_update_hint()
- *
- * Return value: the #CoglBufferUpdateHint currently used by the buffer
- *
- * Since: 1.2
- * Stability: Unstable
- */
-CoglBufferUpdateHint
-cogl_buffer_get_update_hint (CoglBuffer *buffer);
-
-/**
- * CoglBufferAccess:
- * @COGL_BUFFER_ACCESS_READ: the buffer will be read
- * @COGL_BUFFER_ACCESS_WRITE: the buffer will written to
- * @COGL_BUFFER_ACCESS_READ_WRITE: the buffer will be used for both reading and
- * writing
- *
- * The access hints for cogl_buffer_set_update_hint()
- *
- * Since: 1.2
- * Stability: Unstable
- */
-typedef enum { /*< prefix=COGL_BUFFER_ACCESS >*/
- COGL_BUFFER_ACCESS_READ = 1 << 0,
- COGL_BUFFER_ACCESS_WRITE = 1 << 1,
- COGL_BUFFER_ACCESS_READ_WRITE = COGL_BUFFER_ACCESS_READ | COGL_BUFFER_ACCESS_WRITE
-} CoglBufferAccess;
-
-
-/**
- * CoglBufferMapHint:
- * @COGL_BUFFER_MAP_HINT_DISCARD: Tells Cogl that you plan to replace
- * all the buffer's contents.
- *
- * Hints to Cogl about how you are planning to modify the data once it
- * is mapped.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-typedef enum { /*< prefix=COGL_BUFFER_MAP_HINT >*/
- COGL_BUFFER_MAP_HINT_DISCARD = 1 << 0
-} CoglBufferMapHint;
-
-/**
- * cogl_buffer_map:
- * @buffer: a buffer object
- * @access: how the mapped buffer will be used by the application
- * @hints: A mask of #CoglBufferMapHint<!-- -->s that tell Cogl how
- * the data will be modified once mapped.
- *
- * Maps the buffer into the application address space for direct access.
- *
- * It is strongly recommended that you pass
- * %COGL_BUFFER_MAP_HINT_DISCARD as a hint if you are going to replace
- * all the buffer's data. This way if the buffer is currently being
- * used by the GPU then the driver won't have to stall the CPU and
- * wait for the hardware to finish because it can instead allocate a
- * new buffer to map.
- *
- * The behaviour is undefined if you access the buffer in a way
- * conflicting with the @access mask you pass. It is also an error to
- * release your last reference while the buffer is mapped.
- *
- * Return value: A pointer to the mapped memory or %NULL is the call fails
- *
- * Since: 1.2
- * Stability: Unstable
- */
-void *
-cogl_buffer_map (CoglBuffer *buffer,
- CoglBufferAccess access,
- CoglBufferMapHint hints);
-
-/**
- * cogl_buffer_unmap:
- * @buffer: a buffer object
- *
- * Unmaps a buffer previously mapped by cogl_buffer_map().
- *
- * Since: 1.2
- * Stability: Unstable
- */
-void
-cogl_buffer_unmap (CoglBuffer *buffer);
-
-/**
- * cogl_buffer_set_data:
- * @buffer: a buffer object
- * @offset: destination offset (in bytes) in the buffer
- * @data: a pointer to the data to be copied into the buffer
- * @size: number of bytes to copy
- *
- * Updates part of the buffer with new data from @data. Where to put this new
- * data is controlled by @offset and @offset + @data should be less than the
- * buffer size.
- *
- * Return value: %TRUE is the operation succeeded, %FALSE otherwise
- *
- * Since: 1.2
- * Stability: Unstable
- */
-gboolean
-cogl_buffer_set_data (CoglBuffer *buffer,
- gsize offset,
- const void *data,
- gsize size);
-
-G_END_DECLS
-
-#endif /* __COGL_BUFFER_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <math.h>
-
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-clip-stack.h"
-#include "cogl-primitives.h"
-#include "cogl-context-private.h"
-#include "cogl-internal.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-util.h"
-#include "cogl-path-private.h"
-#include "cogl-matrix-private.h"
-#include "cogl-primitives-private.h"
-
-#ifndef GL_CLIP_PLANE0
-#define GL_CLIP_PLANE0 0x3000
-#define GL_CLIP_PLANE1 0x3001
-#define GL_CLIP_PLANE2 0x3002
-#define GL_CLIP_PLANE3 0x3003
-#define GL_CLIP_PLANE4 0x3004
-#define GL_CLIP_PLANE5 0x3005
-#endif
-
-static void
-project_vertex (const CoglMatrix *modelview_projection,
- float *vertex)
-{
- int i;
-
- cogl_matrix_transform_point (modelview_projection,
- &vertex[0], &vertex[1],
- &vertex[2], &vertex[3]);
-
- /* Convert from homogenized coordinates */
- for (i = 0; i < 4; i++)
- vertex[i] /= vertex[3];
-}
-
-static void
-set_clip_plane (GLint plane_num,
- const float *vertex_a,
- const float *vertex_b)
-{
-#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
- GLfloat plane[4];
-#else
- GLdouble plane[4];
-#endif
- GLfloat angle;
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (framebuffer);
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (framebuffer);
- CoglMatrix inverse_projection;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_matrix_stack_get_inverse (projection_stack, &inverse_projection);
-
- /* Calculate the angle between the axes and the line crossing the
- two points */
- angle = atan2f (vertex_b[1] - vertex_a[1],
- vertex_b[0] - vertex_a[0]) * (180.0/G_PI);
-
- _cogl_matrix_stack_push (modelview_stack);
-
- /* Load the inverse of the projection matrix so we can specify the plane
- * in screen coordinates */
- _cogl_matrix_stack_set (modelview_stack, &inverse_projection);
-
- /* Rotate about point a */
- _cogl_matrix_stack_translate (modelview_stack,
- vertex_a[0], vertex_a[1], vertex_a[2]);
- /* Rotate the plane by the calculated angle so that it will connect
- the two points */
- _cogl_matrix_stack_rotate (modelview_stack, angle, 0.0f, 0.0f, 1.0f);
- _cogl_matrix_stack_translate (modelview_stack,
- -vertex_a[0], -vertex_a[1], -vertex_a[2]);
-
- _cogl_matrix_stack_flush_to_gl (modelview_stack, COGL_MATRIX_MODELVIEW);
-
- plane[0] = 0;
- plane[1] = -1.0;
- plane[2] = 0;
- plane[3] = vertex_a[1];
-#if defined (HAVE_COGL_GLES2)
- g_assert_not_reached ();
-#elif defined (HAVE_COGL_GLES)
- GE( glClipPlanef (plane_num, plane) );
-#else
- GE( glClipPlane (plane_num, plane) );
-#endif
-
- _cogl_matrix_stack_pop (modelview_stack);
-}
-
-static void
-set_clip_planes (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (framebuffer);
- CoglMatrix modelview_matrix;
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (framebuffer);
- CoglMatrix projection_matrix;
- CoglMatrix modelview_projection;
- float signed_area;
-
- float vertex_tl[4] = { x_1, y_1, 0, 1.0 };
- float vertex_tr[4] = { x_2, y_1, 0, 1.0 };
- float vertex_bl[4] = { x_1, y_2, 0, 1.0 };
- float vertex_br[4] = { x_2, y_2, 0, 1.0 };
-
- _cogl_matrix_stack_get (projection_stack, &projection_matrix);
- _cogl_matrix_stack_get (modelview_stack, &modelview_matrix);
-
- cogl_matrix_multiply (&modelview_projection,
- &projection_matrix,
- &modelview_matrix);
-
- project_vertex (&modelview_projection, vertex_tl);
- project_vertex (&modelview_projection, vertex_tr);
- project_vertex (&modelview_projection, vertex_bl);
- project_vertex (&modelview_projection, vertex_br);
-
- /* Calculate the signed area of the polygon formed by the four
- vertices so that we can know its orientation */
- signed_area = (vertex_tl[0] * (vertex_tr[1] - vertex_bl[1])
- + vertex_tr[0] * (vertex_br[1] - vertex_tl[1])
- + vertex_br[0] * (vertex_bl[1] - vertex_tr[1])
- + vertex_bl[0] * (vertex_tl[1] - vertex_br[1]));
-
- /* Set the clip planes to form lines between all of the vertices
- using the same orientation as we calculated */
- if (signed_area > 0.0f)
- {
- /* counter-clockwise */
- set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_bl);
- set_clip_plane (GL_CLIP_PLANE1, vertex_bl, vertex_br);
- set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_tr);
- set_clip_plane (GL_CLIP_PLANE3, vertex_tr, vertex_tl);
- }
- else
- {
- /* clockwise */
- set_clip_plane (GL_CLIP_PLANE0, vertex_tl, vertex_tr);
- set_clip_plane (GL_CLIP_PLANE1, vertex_tr, vertex_br);
- set_clip_plane (GL_CLIP_PLANE2, vertex_br, vertex_bl);
- set_clip_plane (GL_CLIP_PLANE3, vertex_bl, vertex_tl);
- }
-}
-
-static void
-add_stencil_clip_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2,
- gboolean first)
-{
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (framebuffer);
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (framebuffer);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* temporarily swap in our special stenciling pipeline */
- cogl_push_source (ctx->stencil_pipeline);
-
- /* This can be called from the journal code which doesn't flush
- the matrix stacks between calls so we need to ensure they're
- flushed now */
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- if (first)
- {
- GE( glEnable (GL_STENCIL_TEST) );
-
- /* Initially disallow everything */
- GE( glClearStencil (0) );
- GE( glClear (GL_STENCIL_BUFFER_BIT) );
-
- /* Punch out a hole to allow the rectangle */
- GE( glStencilFunc (GL_NEVER, 0x1, 0x1) );
- GE( glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE) );
-
- _cogl_rectangle_immediate (x_1, y_1, x_2, y_2);
- }
- else
- {
- /* Add one to every pixel of the stencil buffer in the
- rectangle */
- GE( glStencilFunc (GL_NEVER, 0x1, 0x3) );
- GE( glStencilOp (GL_INCR, GL_INCR, GL_INCR) );
- _cogl_rectangle_immediate (x_1, y_1, x_2, y_2);
-
- /* Subtract one from all pixels in the stencil buffer so that
- only pixels where both the original stencil buffer and the
- rectangle are set will be valid */
- GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
-
- _cogl_matrix_stack_push (projection_stack);
- _cogl_matrix_stack_load_identity (projection_stack);
-
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_load_identity (modelview_stack);
-
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
-
- _cogl_matrix_stack_pop (modelview_stack);
- _cogl_matrix_stack_pop (projection_stack);
- }
-
- /* Restore the stencil mode */
- GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
- GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
-
- /* restore the original source pipeline */
- cogl_pop_source ();
-}
-
-static void
-disable_stencil_buffer (void)
-{
- GE( glDisable (GL_STENCIL_TEST) );
-}
-
-static void
-enable_clip_planes (void)
-{
- GE( glEnable (GL_CLIP_PLANE0) );
- GE( glEnable (GL_CLIP_PLANE1) );
- GE( glEnable (GL_CLIP_PLANE2) );
- GE( glEnable (GL_CLIP_PLANE3) );
-}
-
-static void
-disable_clip_planes (void)
-{
- GE( glDisable (GL_CLIP_PLANE3) );
- GE( glDisable (GL_CLIP_PLANE2) );
- GE( glDisable (GL_CLIP_PLANE1) );
- GE( glDisable (GL_CLIP_PLANE0) );
-}
-
-static gpointer
-_cogl_clip_stack_push_entry (CoglClipStack *clip_stack,
- size_t size,
- CoglClipStackType type)
-{
- CoglClipStack *entry = g_slice_alloc (size);
-
- /* The new entry starts with a ref count of 1 because the stack
- holds a reference to it as it is the top entry */
- entry->ref_count = 1;
- entry->type = type;
- entry->parent = clip_stack;
-
- /* We don't need to take a reference to the parent from the entry
- because the we are stealing the ref in the new stack top */
-
- return entry;
-}
-
-/* Sets the window-space bounds of the entry based on the projected
- coordinates of the given rectangle */
-static void
-_cogl_clip_stack_entry_set_bounds (CoglClipStack *entry,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- const CoglMatrix *modelview)
-{
- CoglMatrix projection;
- float viewport[4];
- float verts[4 * 2] = { x_1, y_1, x_2, y_1, x_2, y_2, x_1, y_2 };
- float min_x = G_MAXFLOAT, min_y = G_MAXFLOAT;
- float max_x = -G_MAXFLOAT, max_y = -G_MAXFLOAT;
- int i;
-
- cogl_get_projection_matrix (&projection);
- cogl_get_viewport (viewport);
-
- for (i = 0; i < 4; i++)
- {
- float *v = verts + i * 2;
-
- /* Project the coordinates to window space coordinates */
- _cogl_transform_point (modelview, &projection, viewport, v, v + 1);
-
- if (v[0] > max_x)
- max_x = v[0];
- if (v[0] < min_x)
- min_x = v[0];
- if (v[1] > max_y)
- max_y = v[1];
- if (v[1] < min_y)
- min_y = v[1];
- }
-
- entry->bounds_x0 = floorf (min_x);
- entry->bounds_x1 = ceilf (max_x);
- entry->bounds_y0 = floorf (min_y);
- entry->bounds_y1 = ceilf (max_y);
-}
-
-CoglClipStack *
-_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
- int x_offset,
- int y_offset,
- int width,
- int height)
-{
- CoglClipStack *entry;
-
- entry = _cogl_clip_stack_push_entry (stack,
- sizeof (CoglClipStackWindowRect),
- COGL_CLIP_STACK_WINDOW_RECT);
-
- entry->bounds_x0 = x_offset;
- entry->bounds_x1 = x_offset + width;
- entry->bounds_y0 = y_offset;
- entry->bounds_y1 = y_offset + height;
-
- return entry;
-}
-
-CoglClipStack *
-_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- const CoglMatrix *modelview_matrix)
-{
- CoglClipStackRect *entry;
- CoglMatrix matrix_p;
- float v[4];
-
- /* Make a new entry */
- entry = _cogl_clip_stack_push_entry (stack,
- sizeof (CoglClipStackRect),
- COGL_CLIP_STACK_RECT);
-
- entry->x0 = x_1;
- entry->y0 = y_1;
- entry->x1 = x_2;
- entry->y1 = y_2;
-
- entry->matrix = *modelview_matrix;
-
- /* If the modelview meets these constraints then a transformed rectangle
- * should still be a rectangle when it reaches screen coordinates.
- *
- * FIXME: we are are making certain assumptions about the projection
- * matrix a.t.m and should really be looking at the combined modelview
- * and projection matrix.
- * FIXME: we don't consider rotations that are a multiple of 90 degrees
- * which could be quite common.
- */
- if (modelview_matrix->xy != 0 || modelview_matrix->xz != 0 ||
- modelview_matrix->yx != 0 || modelview_matrix->yz != 0 ||
- modelview_matrix->zx != 0 || modelview_matrix->zy != 0)
- {
- entry->can_be_scissor = FALSE;
- _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
- x_1, y_1, x_2, y_2, modelview_matrix);
- }
- else
- {
- CoglClipStack *base_entry = (CoglClipStack *) entry;
-
- cogl_get_projection_matrix (&matrix_p);
- cogl_get_viewport (v);
-
- _cogl_transform_point (modelview_matrix, &matrix_p, v, &x_1, &y_1);
- _cogl_transform_point (modelview_matrix, &matrix_p, v, &x_2, &y_2);
-
- /* Consider that the modelview matrix may flip the rectangle
- * along the x or y axis... */
-#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
- if (x_1 > x_2)
- SWAP (x_1, x_2);
- if (y_1 > y_2)
- SWAP (y_1, y_2);
-#undef SWAP
-
- base_entry->bounds_x0 = COGL_UTIL_NEARBYINT (x_1);
- base_entry->bounds_y0 = COGL_UTIL_NEARBYINT (y_1);
- base_entry->bounds_x1 = COGL_UTIL_NEARBYINT (x_2);
- base_entry->bounds_y1 = COGL_UTIL_NEARBYINT (y_2);
- entry->can_be_scissor = TRUE;
- }
-
- return (CoglClipStack *) entry;
-}
-
-CoglClipStack *
-_cogl_clip_stack_push_from_path (CoglClipStack *stack,
- CoglPath *path,
- const CoglMatrix *modelview_matrix)
-{
- float x_1, y_1, x_2, y_2;
-
- _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
-
- /* If the path is a simple rectangle then we can divert to pushing a
- rectangle clip instead which usually won't involve the stencil
- buffer */
- if (_cogl_path_is_rectangle (path))
- return _cogl_clip_stack_push_rectangle (stack,
- x_1, y_1,
- x_2, y_2,
- modelview_matrix);
- else
- {
- CoglClipStackPath *entry;
-
- entry = _cogl_clip_stack_push_entry (stack,
- sizeof (CoglClipStackPath),
- COGL_CLIP_STACK_PATH);
-
- entry->path = cogl_path_copy (path);
-
- entry->matrix = *modelview_matrix;
-
- _cogl_clip_stack_entry_set_bounds ((CoglClipStack *) entry,
- x_1, y_1, x_2, y_2, modelview_matrix);
-
- return (CoglClipStack *) entry;
- }
-}
-
-CoglClipStack *
-_cogl_clip_stack_ref (CoglClipStack *entry)
-{
- /* A NULL pointer is considered a valid stack so we should accept
- that as an argument */
- if (entry)
- entry->ref_count++;
-
- return entry;
-}
-
-void
-_cogl_clip_stack_unref (CoglClipStack *entry)
-{
- /* Unref all of the entries until we hit the root of the list or the
- entry still has a remaining reference */
- while (entry && --entry->ref_count <= 0)
- {
- CoglClipStack *parent = entry->parent;
-
- switch (entry->type)
- {
- case COGL_CLIP_STACK_RECT:
- g_slice_free1 (sizeof (CoglClipStackRect), entry);
- break;
-
- case COGL_CLIP_STACK_WINDOW_RECT:
- g_slice_free1 (sizeof (CoglClipStackWindowRect), entry);
- break;
-
- case COGL_CLIP_STACK_PATH:
- cogl_object_unref (((CoglClipStackPath *) entry)->path);
- g_slice_free1 (sizeof (CoglClipStackPath), entry);
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- entry = parent;
- }
-}
-
-CoglClipStack *
-_cogl_clip_stack_pop (CoglClipStack *stack)
-{
- CoglClipStack *new_top;
-
- g_return_val_if_fail (stack != NULL, NULL);
-
- /* To pop we are moving the top of the stack to the old top's parent
- node. The stack always needs to have a reference to the top entry
- so we must take a reference to the new top. The stack would have
- previously had a reference to the old top so we need to decrease
- the ref count on that. We need to ref the new head first in case
- this stack was the only thing referencing the old top. In that
- case the call to _cogl_clip_stack_entry_unref will unref the
- parent. */
- new_top = stack->parent;
-
- _cogl_clip_stack_ref (new_top);
-
- _cogl_clip_stack_unref (stack);
-
- return new_top;
-}
-
-void
-_cogl_clip_stack_get_bounds (CoglClipStack *stack,
- int *scissor_x0,
- int *scissor_y0,
- int *scissor_x1,
- int *scissor_y1)
-{
- CoglClipStack *entry;
-
- *scissor_x0 = 0;
- *scissor_y0 = 0;
- *scissor_x1 = G_MAXINT;
- *scissor_y1 = G_MAXINT;
-
- for (entry = stack; entry; entry = entry->parent)
- {
- /* Get the intersection of the current scissor and the bounding
- box of this clip */
- *scissor_x0 = MAX (*scissor_x0, entry->bounds_x0);
- *scissor_y0 = MAX (*scissor_y0, entry->bounds_y0);
- *scissor_x1 = MIN (*scissor_x1, entry->bounds_x1);
- *scissor_y1 = MIN (*scissor_y1, entry->bounds_y1);
- }
-}
-
-void
-_cogl_clip_stack_flush (CoglClipStack *stack)
-{
- int has_clip_planes;
- gboolean using_clip_planes = FALSE;
- gboolean using_stencil_buffer = FALSE;
- int scissor_x0;
- int scissor_y0;
- int scissor_x1;
- int scissor_y1;
- CoglMatrixStack *modelview_stack;
- CoglClipStack *entry;
- int scissor_y_start;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If we have already flushed this state then we don't need to do
- anything */
- if (ctx->current_clip_stack_valid)
- {
- if (ctx->current_clip_stack == stack)
- return;
-
- _cogl_clip_stack_unref (ctx->current_clip_stack);
- }
-
- ctx->current_clip_stack_valid = TRUE;
- ctx->current_clip_stack = _cogl_clip_stack_ref (stack);
-
- modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
-
- has_clip_planes = cogl_features_available (COGL_FEATURE_FOUR_CLIP_PLANES);
-
- if (has_clip_planes)
- disable_clip_planes ();
- disable_stencil_buffer ();
-
- /* If the stack is empty then there's nothing else to do */
- if (stack == NULL)
- {
- COGL_NOTE (CLIPPING, "Flushed empty clip stack");
-
- ctx->current_clip_stack_uses_stencil = FALSE;
- GE (glDisable (GL_SCISSOR_TEST));
- return;
- }
-
- /* Calculate the scissor rect first so that if we eventually have to
- clear the stencil buffer then the clear will be clipped to the
- intersection of all of the bounding boxes. This saves having to
- clear the whole stencil buffer */
- _cogl_clip_stack_get_bounds (stack,
- &scissor_x0, &scissor_y0,
- &scissor_x1, &scissor_y1);
-
- /* Enable scissoring as soon as possible */
- if (scissor_x0 >= scissor_x1 || scissor_y0 >= scissor_y1)
- scissor_x0 = scissor_y0 = scissor_x1 = scissor_y1 = scissor_y_start = 0;
- else
- {
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
-
- /* We store the entry coordinates in Cogl coordinate space
- * but OpenGL requires the window origin to be the bottom
- * left so we may need to convert the incoming coordinates.
- *
- * NB: Cogl forces all offscreen rendering to be done upside
- * down so in this case no conversion is needed.
- */
-
- if (cogl_is_offscreen (framebuffer))
- scissor_y_start = scissor_y0;
- else
- {
- int framebuffer_height =
- cogl_framebuffer_get_height (framebuffer);
-
- scissor_y_start = framebuffer_height - scissor_y1;
- }
- }
-
- COGL_NOTE (CLIPPING, "Flushing scissor to (%i, %i, %i, %i)",
- scissor_x0, scissor_y0,
- scissor_x1, scissor_y1);
-
- GE (glEnable (GL_SCISSOR_TEST));
- GE (glScissor (scissor_x0, scissor_y_start,
- scissor_x1 - scissor_x0,
- scissor_y1 - scissor_y0));
-
- /* Add all of the entries. This will end up adding them in the
- reverse order that they were specified but as all of the clips
- are intersecting it should work out the same regardless of the
- order */
- for (entry = stack; entry; entry = entry->parent)
- {
- if (entry->type == COGL_CLIP_STACK_PATH)
- {
- CoglClipStackPath *path_entry = (CoglClipStackPath *) entry;
-
- COGL_NOTE (CLIPPING, "Adding stencil clip for path");
-
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_set (modelview_stack, &path_entry->matrix);
-
- _cogl_add_path_to_stencil_buffer (path_entry->path,
- using_stencil_buffer,
- TRUE);
-
- _cogl_matrix_stack_pop (modelview_stack);
-
- using_stencil_buffer = TRUE;
- }
- else if (entry->type == COGL_CLIP_STACK_RECT)
- {
- CoglClipStackRect *rect = (CoglClipStackRect *) entry;
-
- /* We don't need to do anything extra if the clip for this
- rectangle was entirely described by its scissor bounds */
- if (!rect->can_be_scissor)
- {
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_set (modelview_stack, &rect->matrix);
-
- /* If we support clip planes and we haven't already used
- them then use that instead */
- if (has_clip_planes)
- {
- COGL_NOTE (CLIPPING, "Adding clip planes clip for rectangle");
-
- set_clip_planes (rect->x0,
- rect->y0,
- rect->x1,
- rect->y1);
- using_clip_planes = TRUE;
- /* We can't use clip planes a second time */
- has_clip_planes = FALSE;
- }
- else
- {
- COGL_NOTE (CLIPPING, "Adding stencil clip for rectangle");
-
- add_stencil_clip_rectangle (rect->x0,
- rect->y0,
- rect->x1,
- rect->y1,
- !using_stencil_buffer);
- using_stencil_buffer = TRUE;
- }
-
- _cogl_matrix_stack_pop (modelview_stack);
- }
- }
- /* We don't need to do anything for window space rectangles
- because their functionality is entirely implemented by the
- entry bounding box */
- }
-
- /* Enabling clip planes is delayed to now so that they won't affect
- setting up the stencil buffer */
- if (using_clip_planes)
- enable_clip_planes ();
-
- ctx->current_clip_stack_uses_stencil = using_stencil_buffer;
-}
-
-void
-_cogl_clip_stack_dirty (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->current_clip_stack_valid)
- {
- ctx->current_clip_stack_valid = FALSE;
- _cogl_clip_stack_unref (ctx->current_clip_stack);
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_CLIP_STACK_H
-#define __COGL_CLIP_STACK_H
-
-#include "cogl2-path.h"
-#include "cogl-matrix.h"
-
-/* The clip stack works like a GSList where only a pointer to the top
- of the stack is stored. The empty clip stack is represented simply
- by the NULL pointer. When an entry is added to or removed from the
- stack the new top of the stack is returned. When an entry is pushed
- a new clip stack entry is created which effectively takes ownership
- of the reference on the old entry. Therefore unrefing the top entry
- effectively loses ownership of all entries in the stack */
-
-typedef struct _CoglClipStack CoglClipStack;
-typedef struct _CoglClipStackRect CoglClipStackRect;
-typedef struct _CoglClipStackWindowRect CoglClipStackWindowRect;
-typedef struct _CoglClipStackPath CoglClipStackPath;
-
-typedef enum
- {
- COGL_CLIP_STACK_RECT,
- COGL_CLIP_STACK_WINDOW_RECT,
- COGL_CLIP_STACK_PATH
- } CoglClipStackType;
-
-/* A clip stack consists a list of entries. Each entry has a reference
- * count and a link to its parent node. The child takes a reference on
- * the parent and the CoglClipStack holds a reference to the top of
- * the stack. There are no links back from the parent to the
- * children. This allows stacks that have common ancestry to share the
- * entries.
- *
- * For example, the following sequence of operations would generate
- * the tree below:
- *
- * CoglClipStack *stack_a = NULL;
- * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...);
- * stack_a = _cogl_clip_stack_push_rectangle (stack_a, ...);
- * stack_a = _cogl_clip_stack_push_from_path (stack_a, ...);
- * CoglClipStack *stack_b = NULL;
- * stack_b = cogl_clip_stack_push_window_rectangle (stack_b, ...);
- *
- * stack_a
- * \ holds a ref to
- * +-----------+
- * | path node |
- * |ref count 1|
- * +-----------+
- * \
- * +-----------+ +-----------+
- * both tops hold | rect node | | rect node |
- * a ref to the |ref count 2|--|ref count 1|
- * same rect node +-----------+ +-----------+
- * /
- * +-----------+
- * | win. rect |
- * |ref count 1|
- * +-----------+
- * / holds a ref to
- * stack_b
- *
- */
-
-struct _CoglClipStack
-{
- CoglClipStackType type;
-
- /* This will be null if there is no parent. If it is not null then
- this node must be holding a reference to the parent */
- CoglClipStack *parent;
-
- /* All clip entries have a window-space bounding box which we can
- use to calculate a scissor. The scissor limits the clip so that
- we don't need to do a full stencil clear if the stencil buffer is
- needed. This is stored in Cogl's coordinate space (ie, 0,0 is the
- top left) */
- int bounds_x0;
- int bounds_y0;
- int bounds_x1;
- int bounds_y1;
-
- unsigned int ref_count;
-};
-
-struct _CoglClipStackRect
-{
- CoglClipStack _parent_data;
-
- /* The rectangle for this clip */
- float x0;
- float y0;
- float x1;
- float y1;
-
- /* If this is true then the clip for this rectangle is entirely
- described by the scissor bounds. This implies that the rectangle
- is screen aligned and we don't need to use the stencil buffer to
- set the clip. We keep the entry as a rect entry rather than a
- window rect entry so that it will be easier to detect if the
- modelview matrix is that same as when a rectangle is added to the
- journal. In that case we can use the original clip coordinates
- and modify the rectangle instead. */
- gboolean can_be_scissor;
-
- /* The matrix that was current when the clip was set */
- CoglMatrix matrix;
-};
-
-struct _CoglClipStackWindowRect
-{
- CoglClipStack _parent_data;
-
- /* The window rect clip doesn't need any specific data because it
- just adds to the scissor clip */
-};
-
-struct _CoglClipStackPath
-{
- CoglClipStack _parent_data;
-
- /* The matrix that was current when the clip was set */
- CoglMatrix matrix;
-
- CoglPath *path;
-};
-
-CoglClipStack *
-_cogl_clip_stack_push_window_rectangle (CoglClipStack *stack,
- int x_offset,
- int y_offset,
- int width,
- int height);
-
-CoglClipStack *
-_cogl_clip_stack_push_rectangle (CoglClipStack *stack,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- const CoglMatrix *modelview_matrix);
-
-CoglClipStack *
-_cogl_clip_stack_push_from_path (CoglClipStack *stack,
- CoglPath *path,
- const CoglMatrix *modelview_matrix);
-CoglClipStack *
-_cogl_clip_stack_pop (CoglClipStack *stack);
-
-void
-_cogl_clip_stack_get_bounds (CoglClipStack *stack,
- int *scissor_x0,
- int *scissor_y0,
- int *scissor_x1,
- int *scissor_y1);
-
-void
-_cogl_clip_stack_flush (CoglClipStack *stack);
-
-CoglClipStack *
-_cogl_clip_stack_ref (CoglClipStack *stack);
-
-void
-_cogl_clip_stack_unref (CoglClipStack *stack);
-
-void
-_cogl_clip_stack_dirty (void);
-
-#endif /* __COGL_CLIP_STACK_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_CLIP_STATE_PRIVATE_H
-#define __COGL_CLIP_STATE_PRIVATE_H
-
-#include "cogl-clip-stack.h"
-
-typedef struct _CoglClipState CoglClipState;
-
-struct _CoglClipState
-{
- /* Stack of CoglClipStacks */
- GSList *stacks;
-};
-
-void
-_cogl_clip_state_init (CoglClipState *state);
-
-void
-_cogl_clip_state_destroy (CoglClipState *state);
-
-void
-_cogl_clip_state_flush (CoglClipState *clip_state);
-
-CoglClipStack *
-_cogl_clip_state_get_stack (CoglClipState *clip_state);
-
-void
-_cogl_clip_state_set_stack (CoglClipState *clip_state,
- CoglClipStack *clip_stack);
-
-#endif /* __COGL_CLIP_STATE_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-#include <math.h>
-
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-clip-stack.h"
-#include "cogl-clip-state-private.h"
-#include "cogl-context-private.h"
-#include "cogl-internal.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-util.h"
-#include "cogl-matrix-private.h"
-
-void
-cogl_clip_push_window_rectangle (int x_offset,
- int y_offset,
- int width,
- int height)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- clip_state->stacks->data =
- _cogl_clip_stack_push_window_rectangle (clip_state->stacks->data,
- x_offset, y_offset,
- width, height);
-}
-
-/* XXX: This is deprecated API */
-void
-cogl_clip_push_window_rect (float x_offset,
- float y_offset,
- float width,
- float height)
-{
- cogl_clip_push_window_rectangle (x_offset, y_offset, width, height);
-}
-
-void
-cogl_clip_push_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
- CoglMatrix modelview_matrix;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- cogl_get_modelview_matrix (&modelview_matrix);
-
- clip_state->stacks->data =
- _cogl_clip_stack_push_rectangle (clip_state->stacks->data,
- x_1, y_1, x_2, y_2,
- &modelview_matrix);
-}
-
-/* XXX: Deprecated API */
-void
-cogl_clip_push (float x_offset,
- float y_offset,
- float width,
- float height)
-{
- cogl_clip_push_rectangle (x_offset,
- y_offset,
- x_offset + width,
- y_offset + height);
-}
-
-void
-cogl_clip_push_from_path_preserve (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl2_clip_push_from_path (ctx->current_path);
-}
-
-#undef cogl_clip_push_from_path
-void
-cogl_clip_push_from_path (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_clip_push_from_path (ctx->current_path);
-
- cogl_object_unref (ctx->current_path);
- ctx->current_path = cogl2_path_new ();
-}
-
-static void
-_cogl_clip_pop_real (CoglClipState *clip_state)
-{
- clip_state->stacks->data = _cogl_clip_stack_pop (clip_state->stacks->data);
-}
-
-void
-cogl_clip_pop (void)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_pop_real (clip_state);
-}
-
-void
-_cogl_clip_state_flush (CoglClipState *clip_state)
-{
- /* Flush the topmost stack. The clip stack code will bail out early
- if this is already flushed */
- _cogl_clip_stack_flush (clip_state->stacks->data);
-}
-
-/* XXX: This should never have been made public API! */
-void
-cogl_clip_ensure (void)
-{
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglClipState *clip_state;
-
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
- /* Flushing the clip state doesn't cause the journal to be
- flushed. This function may be being called by an external
- application however so it makes sense to flush the journal
- here */
- _cogl_framebuffer_flush_journal (framebuffer);
- _cogl_clip_state_flush (clip_state);
-}
-
-static void
-_cogl_clip_stack_save_real (CoglClipState *clip_state)
-{
- clip_state->stacks = g_slist_prepend (clip_state->stacks, NULL);
-}
-
-void
-cogl_clip_stack_save (void)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_stack_save_real (clip_state);
-}
-
-static void
-_cogl_clip_stack_restore_real (CoglClipState *clip_state)
-{
- CoglHandle stack;
-
- g_return_if_fail (clip_state->stacks != NULL);
-
- stack = clip_state->stacks->data;
-
- _cogl_clip_stack_unref (stack);
-
- /* Revert to an old stack */
- clip_state->stacks = g_slist_delete_link (clip_state->stacks,
- clip_state->stacks);
-}
-
-void
-cogl_clip_stack_restore (void)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_stack_restore_real (clip_state);
-}
-
-void
-_cogl_clip_state_init (CoglClipState *clip_state)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- clip_state->stacks = NULL;
-
- /* Add an intial stack */
- _cogl_clip_stack_save_real (clip_state);
-}
-
-void
-_cogl_clip_state_destroy (CoglClipState *clip_state)
-{
- /* Destroy all of the stacks */
- while (clip_state->stacks)
- _cogl_clip_stack_restore_real (clip_state);
-}
-
-CoglClipStack *
-_cogl_clip_state_get_stack (CoglClipState *clip_state)
-{
- return clip_state->stacks->data;
-}
-
-void
-_cogl_clip_state_set_stack (CoglClipState *clip_state,
- CoglClipStack *stack)
-{
- /* Replace the top of the stack of stacks */
- _cogl_clip_stack_ref (stack);
- _cogl_clip_stack_unref (clip_state->stacks->data);
- clip_state->stacks->data = stack;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_CLIP_STATE_H
-#define __COGL_CLIP_STATE_H
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * cogl_clip_push_from_path:
- *
- * Sets a new clipping area using the current path. The current path
- * is then cleared. The clipping area is intersected with the previous
- * clipping area. To restore the previous clipping area, call
- * cogl_clip_pop().
- *
- * Since: 1.0
- */
-void
-cogl_clip_push_from_path (void);
-
-G_END_DECLS
-
-#endif /* __COGL_CLIP_STATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-types.h"
-#include "cogl-private.h"
-#include "cogl-context-private.h"
-#include "cogl-winsys-private.h"
-#include "cogl-framebuffer-private.h"
-
-gboolean
-cogl_clutter_check_extension (const char *name, const char *ext)
-{
- return _cogl_check_extension (name, ext);
-}
-
-gboolean
-cogl_clutter_winsys_has_feature (CoglWinsysFeature feature)
-{
- return _cogl_winsys_has_feature (feature);
-}
-
-void
-cogl_onscreen_clutter_backend_set_size (int width, int height)
-{
- CoglFramebuffer *framebuffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!ctx->stub_winsys)
- return;
-
- framebuffer = COGL_FRAMEBUFFER (ctx->window_buffer);
-
- _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
-}
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-XVisualInfo *
-cogl_clutter_winsys_xlib_get_visual_info (void)
-{
- const CoglWinsysVtable *winsys;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- winsys = _cogl_context_get_winsys (ctx);
-
- return winsys->xlib_get_visual_info ();
-}
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_CLUTTER_H__
-#define __COGL_CLUTTER_H__
-
-#ifdef COGL_HAS_XLIB
-#include <X11/Xutil.h>
-#endif
-
-G_BEGIN_DECLS
-
-#define cogl_clutter_check_extension cogl_clutter_check_extension_CLUTTER
-gboolean
-cogl_clutter_check_extension (const char *name, const char *ext);
-
-#define cogl_clutter_winsys_has_feature cogl_clutter_winsys_has_feature_CLUTTER
-gboolean
-cogl_clutter_winsys_has_feature (CoglWinsysFeature feature);
-
-#define cogl_onscreen_clutter_backend_set_size cogl_onscreen_clutter_backend_set_size_CLUTTER
-void
-cogl_onscreen_clutter_backend_set_size (int width, int height);
-
-#ifdef COGL_HAS_XLIB
-#define cogl_clutter_winsys_xlib_get_visual_info cogl_clutter_winsys_xlib_get_visual_info_CLUTTER
-XVisualInfo *
-cogl_clutter_winsys_xlib_get_visual_info (void);
-#endif
-
-G_END_DECLS
-
-#endif /* __COGL_CLUTTER_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_COLOR_PRIVATE_PRIVATE_H
-#define __COGL_COLOR_PRIVATE_PRIVATE_H
-
-#include "cogl-color.h"
-
-#include <glib.h>
-
-/* cogl-pipeline.c wants to be able to hash CoglColor data so it needs
- * the exact data size to be able to avoid reading the padding bytes.
- */
-#define _COGL_COLOR_DATA_SIZE 4
-
-void
-_cogl_color_get_rgba_4ubv (const CoglColor *color,
- guint8 *dest);
-
-#endif /* __COGL_COLOR_PRIVATE_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl.h"
-#include "cogl-color.h"
-#include "cogl-fixed.h"
-
-CoglColor *
-cogl_color_new (void)
-{
- return g_slice_new (CoglColor);
-}
-
-CoglColor *
-cogl_color_copy (const CoglColor *color)
-{
- if (G_LIKELY (color))
- return g_slice_dup (CoglColor, color);
-
- return NULL;
-}
-
-void
-cogl_color_free (CoglColor *color)
-{
- if (G_LIKELY (color))
- g_slice_free (CoglColor, color);
-}
-
-void
-cogl_color_init_from_4ub (CoglColor *color,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha)
-{
- g_return_if_fail (color != NULL);
-
- color->red = red;
- color->green = green;
- color->blue = blue;
- color->alpha = alpha;
-}
-
-/* XXX: deprecated, use cogl_color_init_from_4ub */
-void
-cogl_color_set_from_4ub (CoglColor *dest,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha)
-{
- cogl_color_init_from_4ub (dest, red, green, blue, alpha);
-}
-
-void
-cogl_color_init_from_4f (CoglColor *color,
- float red,
- float green,
- float blue,
- float alpha)
-{
- g_return_if_fail (color != NULL);
-
- color->red = (red * 255);
- color->green = (green * 255);
- color->blue = (blue * 255);
- color->alpha = (alpha * 255);
-}
-
-/* XXX: deprecated, use cogl_color_init_from_4f */
-void
-cogl_color_set_from_4f (CoglColor *color,
- float red,
- float green,
- float blue,
- float alpha)
-{
- cogl_color_init_from_4f (color, red, green, blue, alpha);
-}
-
-void
-cogl_color_init_from_4fv (CoglColor *color,
- float *color_array)
-{
- g_return_if_fail (color != NULL);
-
- color->red = (color_array[0] * 255);
- color->green = (color_array[1] * 255);
- color->blue = (color_array[2] * 255);
- color->alpha = (color_array[3] * 255);
-}
-
-unsigned char
-cogl_color_get_red_byte (const CoglColor *color)
-{
- return color->red;
-}
-
-float
-cogl_color_get_red_float (const CoglColor *color)
-{
- return (float) color->red / 255.0;
-}
-
-float
-cogl_color_get_red (const CoglColor *color)
-{
- return ((float) color->red / 255.0);
-}
-
-unsigned char
-cogl_color_get_green_byte (const CoglColor *color)
-{
- return color->green;
-}
-
-float
-cogl_color_get_green_float (const CoglColor *color)
-{
- return (float) color->green / 255.0;
-}
-
-float
-cogl_color_get_green (const CoglColor *color)
-{
- return ((float) color->green / 255.0);
-}
-
-unsigned char
-cogl_color_get_blue_byte (const CoglColor *color)
-{
- return color->blue;
-}
-
-float
-cogl_color_get_blue_float (const CoglColor *color)
-{
- return (float) color->blue / 255.0;
-}
-
-float
-cogl_color_get_blue (const CoglColor *color)
-{
- return ((float) color->blue / 255.0);
-}
-
-unsigned char
-cogl_color_get_alpha_byte (const CoglColor *color)
-{
- return color->alpha;
-}
-
-float
-cogl_color_get_alpha_float (const CoglColor *color)
-{
- return (float) color->alpha / 255.0;
-}
-
-float
-cogl_color_get_alpha (const CoglColor *color)
-{
- return ((float) color->alpha / 255.0);
-}
-
-void
-cogl_color_set_red_byte (CoglColor *color,
- unsigned char red)
-{
- color->red = red;
-}
-
-void
-cogl_color_set_red_float (CoglColor *color,
- float red)
-{
- color->red = red * 255.0;
-}
-
-void
-cogl_color_set_red (CoglColor *color,
- float red)
-{
- color->red = red * 255.0;
-}
-
-void
-cogl_color_set_green_byte (CoglColor *color,
- unsigned char green)
-{
- color->green = green;
-}
-
-void
-cogl_color_set_green_float (CoglColor *color,
- float green)
-{
- color->green = green * 255.0;
-}
-
-void
-cogl_color_set_green (CoglColor *color,
- float green)
-{
- color->green = green * 255.0;
-}
-
-void
-cogl_color_set_blue_byte (CoglColor *color,
- unsigned char blue)
-{
- color->blue = blue;
-}
-
-void
-cogl_color_set_blue_float (CoglColor *color,
- float blue)
-{
- color->blue = blue * 255.0;
-}
-
-void
-cogl_color_set_blue (CoglColor *color,
- float blue)
-{
- color->blue = blue * 255.0;
-}
-
-void
-cogl_color_set_alpha_byte (CoglColor *color,
- unsigned char alpha)
-{
- color->alpha = alpha;
-}
-
-void
-cogl_color_set_alpha_float (CoglColor *color,
- float alpha)
-{
- color->alpha = alpha * 255.0;
-}
-
-void
-cogl_color_set_alpha (CoglColor *color,
- float alpha)
-{
- color->alpha = alpha * 255.0;
-}
-
-void
-cogl_color_premultiply (CoglColor *color)
-{
- color->red = (color->red * color->alpha + 128) / 255;
- color->green = (color->green * color->alpha + 128) / 255;
- color->blue = (color->blue * color->alpha + 128) / 255;
-}
-
-void
-cogl_color_unpremultiply (CoglColor *color)
-{
- if (color->alpha != 0)
- {
- color->red = (color->red * 255) / color->alpha;
- color->green = (color->green * 255) / color->alpha;
- color->blue = (color->blue * 255) / color->alpha;
- }
-}
-
-gboolean
-cogl_color_equal (gconstpointer v1, gconstpointer v2)
-{
- const guint32 *c1 = v1, *c2 = v2;
-
- g_return_val_if_fail (v1 != NULL, FALSE);
- g_return_val_if_fail (v2 != NULL, FALSE);
-
- /* XXX: We don't compare the padding */
- return *c1 == *c2 ? TRUE : FALSE;
-}
-
-void
-_cogl_color_get_rgba_4ubv (const CoglColor *color,
- guint8 *dest)
-{
- memcpy (dest, color, 4);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/**
- * SECTION:cogl-color
- * @short_description: A generic color definition
- *
- * #CoglColor is a simple structure holding the definition of a color such
- * that it can be efficiently used by GL
- *
- * Since: 1.0
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_COLOR_H__
-#define __COGL_COLOR_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * cogl_color_new:
- *
- * Creates a new (empty) color
- *
- * Return value: a newly-allocated #CoglColor. Use cogl_color_free()
- * to free the allocated resources
- *
- * Since: 1.0
- */
-CoglColor *
-cogl_color_new (void);
-
-/**
- * cogl_color_copy:
- * @color: the color to copy
- *
- * Creates a copy of @color
- *
- * Return value: a newly-allocated #CoglColor. Use cogl_color_free()
- * to free the allocate resources
- *
- * Since: 1.0
- */
-CoglColor *
-cogl_color_copy (const CoglColor *color);
-
-/**
- * cogl_color_free:
- * @color: the color to free
- *
- * Frees the resources allocated by cogl_color_new() and cogl_color_copy()
- *
- * Since: 1.0
- */
-void
-cogl_color_free (CoglColor *color);
-
-/**
- * cogl_color_init_from_4ub:
- * @color: A pointer to a #CoglColor to initialize
- * @red: value of the red channel, between 0 and 255
- * @green: value of the green channel, between 0 and 255
- * @blue: value of the blue channel, between 0 and 255
- * @alpha: value of the alpha channel, between 0 and 255
- *
- * Sets the values of the passed channels into a #CoglColor.
- *
- * Since: 1.4
- */
-void
-cogl_color_init_from_4ub (CoglColor *color,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha);
-
-/**
- * cogl_color_set_from_4ub:
- * @color: A pointer to a #CoglColor to initialize
- * @red: value of the red channel, between 0 and 255
- * @green: value of the green channel, between 0 and 255
- * @blue: value of the blue channel, between 0 and 255
- * @alpha: value of the alpha channel, between 0 and 255
- *
- * Sets the values of the passed channels into a #CoglColor.
- *
- * Since: 1.0
- * Deprecated: 1.4: Use cogl_color_init_from_4ub instead.
- */
-void
-cogl_color_set_from_4ub (CoglColor *color,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha);
-
-/**
- * cogl_color_init_from_4f:
- * @color: A pointer to a #CoglColor to initialize
- * @red: value of the red channel, between 0 and %1.0
- * @green: value of the green channel, between 0 and %1.0
- * @blue: value of the blue channel, between 0 and %1.0
- * @alpha: value of the alpha channel, between 0 and %1.0
- *
- * Sets the values of the passed channels into a #CoglColor
- *
- * Since: 1.4
- */
-void
-cogl_color_init_from_4f (CoglColor *color,
- float red,
- float green,
- float blue,
- float alpha);
-
-/**
- * cogl_color_set_from_4f:
- * @color: A pointer to a #CoglColor to initialize
- * @red: value of the red channel, between 0 and %1.0
- * @green: value of the green channel, between 0 and %1.0
- * @blue: value of the blue channel, between 0 and %1.0
- * @alpha: value of the alpha channel, between 0 and %1.0
- *
- * Sets the values of the passed channels into a #CoglColor
- *
- * Since: 1.0
- * Deprecated: 1.4: Use cogl_color_init_from_4f instead.
- */
-void
-cogl_color_set_from_4f (CoglColor *color,
- float red,
- float green,
- float blue,
- float alpha);
-
-/**
- * cogl_color_init_from_4fv:
- * @color: A pointer to a #CoglColor to initialize
- * @color_array: a pointer to an array of 4 float color components
- *
- * Sets the values of the passed channels into a #CoglColor
- *
- * Since: 1.4
- */
-void
-cogl_color_init_from_4fv (CoglColor *color,
- float *color_array);
-
-/**
- * cogl_color_get_red_byte:
- * @color: a #CoglColor
- *
- * Retrieves the red channel of @color as a byte value
- * between 0 and 255
- *
- * Return value: the red channel of the passed color
- *
- * Since: 1.0
- */
-unsigned char
-cogl_color_get_red_byte (const CoglColor *color);
-
-/**
- * cogl_color_get_green_byte:
- * @color: a #CoglColor
- *
- * Retrieves the green channel of @color as a byte value
- * between 0 and 255
- *
- * Return value: the green channel of the passed color
- *
- * Since: 1.0
- */
-unsigned char
-cogl_color_get_green_byte (const CoglColor *color);
-
-/**
- * cogl_color_get_blue_byte:
- * @color: a #CoglColor
- *
- * Retrieves the blue channel of @color as a byte value
- * between 0 and 255
- *
- * Return value: the blue channel of the passed color
- *
- * Since: 1.0
- */
-unsigned char
-cogl_color_get_blue_byte (const CoglColor *color);
-
-/**
- * cogl_color_get_alpha_byte:
- * @color: a #CoglColor
- *
- * Retrieves the alpha channel of @color as a byte value
- * between 0 and 255
- *
- * Return value: the alpha channel of the passed color
- *
- * Since: 1.0
- */
-unsigned char
-cogl_color_get_alpha_byte (const CoglColor *color);
-
-/**
- * cogl_color_get_red_float:
- * @color: a #CoglColor
- *
- * Retrieves the red channel of @color as a floating point
- * value between 0.0 and 1.0
- *
- * Return value: the red channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_red_float (const CoglColor *color);
-
-/**
- * cogl_color_get_green_float:
- * @color: a #CoglColor
- *
- * Retrieves the green channel of @color as a floating point
- * value between 0.0 and 1.0
- *
- * Return value: the green channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_green_float (const CoglColor *color);
-
-/**
- * cogl_color_get_blue_float:
- * @color: a #CoglColor
- *
- * Retrieves the blue channel of @color as a floating point
- * value between 0.0 and 1.0
- *
- * Return value: the blue channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_blue_float (const CoglColor *color);
-
-/**
- * cogl_color_get_alpha_float:
- * @color: a #CoglColor
- *
- * Retrieves the alpha channel of @color as a floating point
- * value between 0.0 and 1.0
- *
- * Return value: the alpha channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_alpha_float (const CoglColor *color);
-
-/**
- * cogl_color_get_red:
- * @color: a #CoglColor
- *
- * Retrieves the red channel of @color as a fixed point
- * value between 0 and %1.0.
- *
- * Return value: the red channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_red (const CoglColor *color);
-
-/**
- * cogl_color_get_green:
- * @color: a #CoglColor
- *
- * Retrieves the green channel of @color as a fixed point
- * value between 0 and %1.0.
- *
- * Return value: the green channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_green (const CoglColor *color);
-
-/**
- * cogl_color_get_blue:
- * @color: a #CoglColor
- *
- * Retrieves the blue channel of @color as a fixed point
- * value between 0 and %1.0.
- *
- * Return value: the blue channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_blue (const CoglColor *color);
-
-/**
- * cogl_color_get_alpha:
- * @color: a #CoglColor
- *
- * Retrieves the alpha channel of @color as a fixed point
- * value between 0 and %1.0.
- *
- * Return value: the alpha channel of the passed color
- *
- * Since: 1.0
- */
-float
-cogl_color_get_alpha (const CoglColor *color);
-
-/**
- * cogl_color_set_red_byte:
- * @color: a #CoglColor
- * @red: a byte value between 0 and 255
- *
- * Sets the red channel of @color to @red.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_red_byte (CoglColor *color,
- unsigned char red);
-
-/**
- * cogl_color_set_green_byte:
- * @color: a #CoglColor
- * @green: a byte value between 0 and 255
- *
- * Sets the green channel of @color to @green.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_green_byte (CoglColor *color,
- unsigned char green);
-
-/**
- * cogl_color_set_blue_byte:
- * @color: a #CoglColor
- * @blue: a byte value between 0 and 255
- *
- * Sets the blue channel of @color to @blue.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_blue_byte (CoglColor *color,
- unsigned char blue);
-
-/**
- * cogl_color_set_alpha_byte:
- * @color: a #CoglColor
- * @alpha: a byte value between 0 and 255
- *
- * Sets the alpha channel of @color to @alpha.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_alpha_byte (CoglColor *color,
- unsigned char alpha);
-
-/**
- * cogl_color_set_red_float:
- * @color: a #CoglColor
- * @red: a float value between 0.0f and 1.0f
- *
- * Sets the red channel of @color to @red.
- *
- * since: 1.4
- */
-void
-cogl_color_set_red_float (CoglColor *color,
- float red);
-
-/**
- * cogl_color_set_green_float:
- * @color: a #CoglColor
- * @green: a float value between 0.0f and 1.0f
- *
- * Sets the green channel of @color to @green.
- *
- * since: 1.4
- */
-void
-cogl_color_set_green_float (CoglColor *color,
- float green);
-
-/**
- * cogl_color_set_blue_float:
- * @color: a #CoglColor
- * @blue: a float value between 0.0f and 1.0f
- *
- * Sets the blue channel of @color to @blue.
- *
- * since: 1.4
- */
-void
-cogl_color_set_blue_float (CoglColor *color,
- float blue);
-
-/**
- * cogl_color_set_alpha_float:
- * @color: a #CoglColor
- * @alpha: a float value between 0.0f and 1.0f
- *
- * Sets the alpha channel of @color to @alpha.
- *
- * since: 1.4
- */
-void
-cogl_color_set_alpha_float (CoglColor *color,
- float alpha);
-
-/**
- * cogl_color_set_red:
- * @color: a #CoglColor
- * @red: a float value between 0.0f and 1.0f
- *
- * Sets the red channel of @color to @red.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_red (CoglColor *color,
- float red);
-
-/**
- * cogl_color_set_green:
- * @color: a #CoglColor
- * @green: a float value between 0.0f and 1.0f
- *
- * Sets the green channel of @color to @green.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_green (CoglColor *color,
- float green);
-
-/**
- * cogl_color_set_blue:
- * @color: a #CoglColor
- * @blue: a float value between 0.0f and 1.0f
- *
- * Sets the blue channel of @color to @blue.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_blue (CoglColor *color,
- float blue);
-
-/**
- * cogl_color_set_alpha:
- * @color: a #CoglColor
- * @alpha: a float value between 0.0f and 1.0f
- *
- * Sets the alpha channel of @color to @alpha.
- *
- * Since: 1.4
- */
-void
-cogl_color_set_alpha (CoglColor *color,
- float alpha);
-
-/**
- * cogl_color_premultiply:
- * @color: the color to premultiply
- *
- * Converts a non-premultiplied color to a pre-multiplied color. For
- * example, semi-transparent red is (1.0, 0, 0, 0.5) when non-premultiplied
- * and (0.5, 0, 0, 0.5) when premultiplied.
- *
- * Since: 1.0
- */
-void
-cogl_color_premultiply (CoglColor *color);
-
-/**
- * cogl_color_unpremultiply:
- * @color: the color to unpremultiply
- *
- * Converts a pre-multiplied color to a non-premultiplied color. For
- * example, semi-transparent red is (0.5, 0, 0, 0.5) when premultiplied
- * and (1.0, 0, 0, 0.5) when non-premultiplied.
- *
- * Since: 1.4
- */
-void
-cogl_color_unpremultiply (CoglColor *color);
-
-/**
- * cogl_color_equal:
- * @v1: a #CoglColor
- * @v2: a #CoglColor
- *
- * Compares two #CoglColor<!-- -->s and checks if they are the same.
- *
- * This function can be passed to g_hash_table_new() as the @key_equal_func
- * parameter, when using #CoglColor<!-- -->s as keys in a #GHashTable.
- *
- * Return value: %TRUE if the two colors are the same.
- *
- * Since: 1.0
- */
-gboolean
-cogl_color_equal (gconstpointer v1,
- gconstpointer v2);
-
-G_END_DECLS
-
-#endif /* __COGL_COLOR_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_CONTEXT_PRIVATE_H
-#define __COGL_CONTEXT_PRIVATE_H
-
-#include "cogl-internal.h"
-#include "cogl-context.h"
-#include "cogl-winsys-private.h"
-#include "cogl-flags.h"
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include "cogl-xlib-private.h"
-#endif
-
-#if HAVE_COGL_GL
-#include "cogl-context-driver-gl.h"
-#endif
-
-#if HAVE_COGL_GLES || HAVE_COGL_GLES2
-#include "cogl-context-driver-gles.h"
-#endif
-
-#include "cogl-display-private.h"
-#include "cogl-primitives.h"
-#include "cogl-clip-stack.h"
-#include "cogl-matrix-stack.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-buffer-private.h"
-#include "cogl-bitmask.h"
-#include "cogl-atlas.h"
-
-typedef struct
-{
- GLfloat v[3];
- GLfloat t[2];
- GLubyte c[4];
-} CoglTextureGLVertex;
-
-struct _CoglContext
-{
- CoglObject _parent;
-
- CoglDisplay *display;
-
- /* Features cache */
- CoglFeatureFlags feature_flags;
-
- CoglHandle default_pipeline;
- CoglHandle default_layer_0;
- CoglHandle default_layer_n;
- CoglHandle dummy_layer_dependant;
-
- /* Enable cache */
- unsigned long enable_flags;
-
- gboolean enable_backface_culling;
- CoglFrontWinding flushed_front_winding;
-
- /* A few handy matrix constants */
- CoglMatrix identity_matrix;
- CoglMatrix y_flip_matrix;
-
- /* Client-side matrix stack or NULL if none */
- CoglMatrixMode flushed_matrix_mode;
-
- /* On GLES2 we need to track the matrices separately because the are
- stored in GLSL uniforms rather than using the fixed function
- API. We keep track of the matrix stack that Cogl is trying to
- flush so we can flush it later after the program is generated. A
- reference is taken on the stacks. */
-#ifdef HAVE_COGL_GLES2
- CoglMatrixStack *flushed_modelview_stack;
- CoglMatrixStack *flushed_projection_stack;
-#endif /* HAVE_COGL_GLES2 */
-
- GArray *texture_units;
- int active_texture_unit;
-
- CoglPipelineFogState legacy_fog_state;
-
- /* Pipelines */
- CoglPipeline *opaque_color_pipeline; /* used for set_source_color */
- CoglPipeline *blended_color_pipeline; /* used for set_source_color */
- CoglPipeline *texture_pipeline; /* used for set_source_texture */
- GString *codegen_header_buffer;
- GString *codegen_source_buffer;
- GList *source_stack;
-
- int legacy_state_set;
-
-#ifdef HAVE_COGL_GL
- GHashTable *arbfp_cache;
-#endif
-
- /* Textures */
- CoglHandle default_gl_texture_2d_tex;
- CoglHandle default_gl_texture_rect_tex;
-
- /* Central list of all framebuffers so all journals can be flushed
- * at any time. */
- GList *framebuffers;
-
- /* Global journal buffers */
- GArray *journal_flush_attributes_array;
- GArray *journal_clip_bounds;
-
- GArray *polygon_vertices;
-
- /* Some simple caching, to minimize state changes... */
- CoglPipeline *current_pipeline;
- unsigned long current_pipeline_changes_since_flush;
- gboolean current_pipeline_skip_gl_color;
- unsigned long current_pipeline_age;
-
- GArray *pipeline0_nodes;
- GArray *pipeline1_nodes;
-
- /* Bitmask of attributes enabled. On GLES2 these are the vertex
- attribute numbers and on regular GL these are only used for the
- texture coordinate arrays */
- CoglBitmask arrays_enabled;
- /* These are temporary bitmasks that are used when disabling
- texcoord arrays. They are here just to avoid allocating new ones
- each time */
- CoglBitmask arrays_to_change;
- CoglBitmask temp_bitmask;
-
- gboolean gl_blend_enable_cache;
-
- gboolean depth_test_enabled_cache;
- CoglDepthTestFunction depth_test_function_cache;
- gboolean depth_writing_enabled_cache;
- float depth_range_near_cache;
- float depth_range_far_cache;
-
- gboolean legacy_depth_test_enabled;
-
- float point_size_cache;
-
- CoglBuffer *current_buffer[COGL_BUFFER_BIND_TARGET_COUNT];
-
- /* Framebuffers */
- GSList *framebuffer_stack;
- CoglHandle window_buffer;
- gboolean dirty_bound_framebuffer;
- gboolean dirty_gl_viewport;
-
- /* Primitives */
- CoglPath *current_path;
- CoglPipeline *stencil_pipeline;
-
- /* Pre-generated VBOs containing indices to generate GL_TRIANGLES
- out of a vertex array of quads */
- CoglHandle quad_buffer_indices_byte;
- unsigned int quad_buffer_indices_len;
- CoglHandle quad_buffer_indices;
-
- CoglIndices *rectangle_byte_indices;
- CoglIndices *rectangle_short_indices;
- int rectangle_short_indices_len;
-
- gboolean in_begin_gl_block;
-
- CoglPipeline *texture_download_pipeline;
- CoglPipeline *blit_texture_pipeline;
-
- GSList *atlases;
- GHookList atlas_reorganize_callbacks;
-
- /* This debugging variable is used to pick a colour for visually
- displaying the quad batches. It needs to be global so that it can
- be reset by cogl_clear. It needs to be reset to increase the
- chances of getting the same colour during an animation */
- guint8 journal_rectangles_color;
-
- /* Cached values for GL_MAX_TEXTURE_[IMAGE_]UNITS to avoid calling
- glGetInteger too often */
- GLint max_texture_units;
- GLint max_texture_image_units;
- GLint max_activateable_texture_units;
-
- /* Fragment processing programs */
- CoglHandle current_program;
-
- CoglPipelineProgramType current_fragment_program_type;
- CoglPipelineProgramType current_vertex_program_type;
- GLuint current_gl_program;
-
- /* List of types that will be considered a subclass of CoglTexture in
- cogl_is_texture */
- GSList *texture_types;
-
- /* List of types that will be considered a subclass of CoglBuffer in
- cogl_is_buffer */
- GSList *buffer_types;
-
- /* Clipping */
- /* TRUE if we have a valid clipping stack flushed. In that case
- current_clip_stack will describe what the current state is. If
- this is FALSE then the current clip stack is completely unknown
- so it will need to be reflushed. In that case current_clip_stack
- doesn't need to be a valid pointer. We can't just use NULL in
- current_clip_stack to mark a dirty state because NULL is a valid
- stack (meaning no clipping) */
- gboolean current_clip_stack_valid;
- /* The clip state that was flushed. This isn't intended to be used
- as a stack to push and pop new entries. Instead the current stack
- that the user wants is part of the framebuffer state. This is
- just used to record the flush state so we can avoid flushing the
- same state multiple times. When the clip state is flushed this
- will hold a reference */
- CoglClipStack *current_clip_stack;
- /* Whether the stencil buffer was used as part of the current clip
- state. If TRUE then any further use of the stencil buffer (such
- as for drawing paths) would need to be merged with the existing
- stencil buffer */
- gboolean current_clip_stack_uses_stencil;
-
- /* This is used as a temporary buffer to fill a CoglBuffer when
- cogl_buffer_map fails and we only want to map to fill it with new
- data */
- GByteArray *buffer_map_fallback_array;
- gboolean buffer_map_fallback_in_use;
-
- CoglWinsysRectangleState rectangle_state;
-
- /* FIXME: remove these when we remove the last xlib based clutter
- * backend. they should be tracked as part of the renderer but e.g.
- * the eglx backend doesn't yet have a corresponding Cogl winsys
- * and so we wont have a renderer in that case. */
-#ifdef COGL_HAS_XLIB_SUPPORT
- int damage_base;
- /* List of callback functions that will be given every Xlib event */
- GSList *event_filters;
- /* Current top of the XError trap state stack. The actual memory for
- these is expected to be allocated on the stack by the caller */
- CoglXlibTrapState *trap_state;
-#endif
-
- CoglContextDriver drv;
-
- unsigned int winsys_features
- [COGL_FLAGS_N_INTS_FOR_SIZE (COGL_WINSYS_FEATURE_N_FEATURES)];
- void *winsys;
- gboolean stub_winsys;
-};
-
-CoglContext *
-_cogl_context_get_default ();
-
-const CoglWinsysVtable *
-_cogl_context_get_winsys (CoglContext *context);
-
-/* Obtains the context and returns retval if NULL */
-#define _COGL_GET_CONTEXT(ctxvar, retval) \
-CoglContext *ctxvar = _cogl_context_get_default (); \
-if (ctxvar == NULL) return retval;
-
-#define NO_RETVAL
-
-#endif /* __COGL_CONTEXT_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-object.h"
-#include "cogl-internal.h"
-#include "cogl-private.h"
-#include "cogl-winsys-private.h"
-#include "cogl-profile.h"
-#include "cogl-util.h"
-#include "cogl-context-private.h"
-#include "cogl-display-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl2-path.h"
-
-#include <string.h>
-
-#ifdef HAVE_COGL_GL
-#include "cogl-pipeline-fragend-arbfp-private.h"
-#define glActiveTexture _context->drv.pf_glActiveTexture
-#endif
-
-/* This isn't defined in the GLES headers */
-#ifndef GL_POINT_SPRITE
-#define GL_POINT_SPRITE 0x8861
-#endif
-
-static void _cogl_context_free (CoglContext *context);
-
-COGL_OBJECT_DEFINE (Context, context);
-
-extern void
-_cogl_create_context_driver (CoglContext *context);
-
-static CoglContext *_context = NULL;
-
-static void
-_cogl_init_feature_overrides (CoglContext *ctx)
-{
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_VBOS)))
- ctx->feature_flags &= ~COGL_FEATURE_VBOS;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PBOS)))
- ctx->feature_flags &= ~COGL_FEATURE_PBOS;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_ARBFP)))
- ctx->feature_flags &= ~COGL_FEATURE_SHADERS_ARBFP;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_GLSL)))
- ctx->feature_flags &= ~COGL_FEATURE_SHADERS_GLSL;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_NPOT_TEXTURES)))
- ctx->feature_flags &= ~(COGL_FEATURE_TEXTURE_NPOT |
- COGL_FEATURE_TEXTURE_NPOT_BASIC |
- COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
- COGL_FEATURE_TEXTURE_NPOT_REPEAT);
-}
-
-const CoglWinsysVtable *
-_cogl_context_get_winsys (CoglContext *context)
-{
- return context->display->renderer->winsys_vtable;
-}
-
-/* For reference: There was some deliberation over whether to have a
- * constructor that could throw an exception but looking at standard
- * practices with several high level OO languages including python, C++,
- * C# Java and Ruby they all support exceptions in constructors and the
- * general consensus appears to be that throwing an exception is neater
- * than successfully constructing with an internal error status that
- * would then have to be explicitly checked via some form of ::is_ok()
- * method.
- */
-CoglContext *
-cogl_context_new (CoglDisplay *display,
- GError **error)
-{
- CoglContext *context;
- GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
- unsigned long enable_flags = 0;
- const CoglWinsysVtable *winsys;
- int i;
-
-#ifdef CLUTTER_ENABLE_PROFILE
- /* We need to be absolutely sure that uprof has been initialized
- * before calling _cogl_uprof_init. uprof_init (NULL, NULL)
- * will be a NOP if it has been initialized but it will also
- * mean subsequent parsing of the UProf GOptionGroup will have no
- * affect.
- *
- * Sadly GOptionGroup based library initialization is extremely
- * fragile by design because GOptionGroups have no notion of
- * dependencies and so the order things are initialized isn't
- * currently under tight control.
- */
- uprof_init (NULL, NULL);
- _cogl_uprof_init ();
-#endif
-
- /* Allocate context memory */
- context = g_malloc (sizeof (CoglContext));
-
- /* XXX: Gross hack!
- * Currently everything in Cogl just assumes there is a default
- * context which it can access via _COGL_GET_CONTEXT() including
- * code used to construct a CoglContext. Until all of that code
- * has been updated to take an explicit context argument we have
- * to immediately make our pointer the default context.
- */
- _context = context;
-
- /* Init default values */
- context->feature_flags = 0;
-
- context->texture_types = NULL;
- context->buffer_types = NULL;
-
- context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN;
-
- memset (context->winsys_features, 0, sizeof (context->winsys_features));
-
- if (!display)
- display = cogl_display_new (NULL, NULL);
- else
- cogl_object_ref (display);
-
- if (!cogl_display_setup (display, error))
- {
- cogl_object_unref (display);
- g_free (context);
- return NULL;
- }
-
- context->display = display;
-
-#ifdef COGL_HAS_FULL_WINSYS
- context->stub_winsys = FALSE;
- winsys = _cogl_context_get_winsys (context);
- if (!winsys->context_init (context, error))
- {
- cogl_object_unref (display);
- g_free (context);
- return NULL;
- }
-#else
- /* In this case Clutter is still responsible for creating a GL
- * context. */
- context->stub_winsys = TRUE;
- if (!_cogl_gl_check_version (error))
- {
- g_free (context);
- return NULL;
- }
- _cogl_gl_update_features (context);
-#ifdef COGL_HAS_XLIB_SUPPORT
- _cogl_xlib_query_damage_extension ();
-#endif
-#endif
-
- /* Initialise the driver specific state */
- _cogl_init_feature_overrides (context);
-
- _cogl_pipeline_init_default_pipeline ();
- _cogl_pipeline_init_default_layers ();
- _cogl_pipeline_init_state_hash_functions ();
- _cogl_pipeline_init_layer_state_hash_functions ();
-
- context->enable_flags = 0;
-
- context->enable_backface_culling = FALSE;
- context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
-
- cogl_matrix_init_identity (&context->identity_matrix);
- cogl_matrix_init_identity (&context->y_flip_matrix);
- cogl_matrix_scale (&context->y_flip_matrix, 1, -1, 1);
-
- context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;
-
- context->texture_units =
- g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit));
-
- /* See cogl-pipeline.c for more details about why we leave texture unit 1
- * active by default... */
- context->active_texture_unit = 1;
- GE (glActiveTexture (GL_TEXTURE1));
-
- context->legacy_fog_state.enabled = FALSE;
-
- context->opaque_color_pipeline = cogl_pipeline_new ();
- context->blended_color_pipeline = cogl_pipeline_new ();
- context->texture_pipeline = cogl_pipeline_new ();
- context->codegen_header_buffer = g_string_new ("");
- context->codegen_source_buffer = g_string_new ("");
- context->source_stack = NULL;
-
- context->legacy_state_set = 0;
-
- context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
- context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;
-
- context->framebuffers = NULL;
-
- context->journal_flush_attributes_array =
- g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
- context->journal_clip_bounds = NULL;
-
- context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (float));
-
- context->current_pipeline = NULL;
- context->current_pipeline_changes_since_flush = 0;
- context->current_pipeline_skip_gl_color = FALSE;
-
- context->pipeline0_nodes =
- g_array_sized_new (FALSE, FALSE, sizeof (CoglHandle), 20);
- context->pipeline1_nodes =
- g_array_sized_new (FALSE, FALSE, sizeof (CoglHandle), 20);
-
- _cogl_bitmask_init (&context->arrays_enabled);
- _cogl_bitmask_init (&context->temp_bitmask);
- _cogl_bitmask_init (&context->arrays_to_change);
-
- context->max_texture_units = -1;
- context->max_texture_image_units = -1;
- context->max_activateable_texture_units = -1;
-
- context->current_program = COGL_INVALID_HANDLE;
-
- context->current_fragment_program_type = COGL_PIPELINE_PROGRAM_TYPE_FIXED;
- context->current_vertex_program_type = COGL_PIPELINE_PROGRAM_TYPE_FIXED;
- context->current_gl_program = 0;
-
- context->gl_blend_enable_cache = FALSE;
-
- context->depth_test_enabled_cache = FALSE;
- context->depth_test_function_cache = COGL_DEPTH_TEST_FUNCTION_LESS;
- context->depth_writing_enabled_cache = TRUE;
- context->depth_range_near_cache = 0;
- context->depth_range_far_cache = 1;
-
- context->point_size_cache = 1.0f;
-
- context->legacy_depth_test_enabled = FALSE;
-
-#ifdef HAVE_COGL_GL
- _context->arbfp_cache = g_hash_table_new (_cogl_pipeline_fragend_arbfp_hash,
- _cogl_pipeline_fragend_arbfp_equal);
-#endif
-
- for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++)
- context->current_buffer[i] = NULL;
-
- context->framebuffer_stack = _cogl_create_framebuffer_stack ();
-
- /* XXX: In this case the Clutter backend is still responsible for
- * the OpenGL binding API and for creating onscreen framebuffers and
- * so we have to add a dummy framebuffer to represent the backend
- * owned window... */
- if (context->stub_winsys)
- {
- CoglOnscreen *window = _cogl_onscreen_new ();
- cogl_set_framebuffer (COGL_FRAMEBUFFER (window));
- cogl_object_unref (COGL_FRAMEBUFFER (window));
- }
-
- _context->current_clip_stack_valid = FALSE;
-
- context->dirty_bound_framebuffer = TRUE;
- context->dirty_gl_viewport = TRUE;
-
- context->current_path = cogl2_path_new ();
- context->stencil_pipeline = cogl_pipeline_new ();
-
- context->in_begin_gl_block = FALSE;
-
- context->quad_buffer_indices_byte = COGL_INVALID_HANDLE;
- context->quad_buffer_indices = COGL_INVALID_HANDLE;
- context->quad_buffer_indices_len = 0;
-
- context->rectangle_byte_indices = NULL;
- context->rectangle_short_indices = NULL;
- context->rectangle_short_indices_len = 0;
-
- context->texture_download_pipeline = COGL_INVALID_HANDLE;
- context->blit_texture_pipeline = COGL_INVALID_HANDLE;
-
-#ifndef HAVE_COGL_GLES2
- /* The default for GL_ALPHA_TEST is to always pass which is equivalent to
- * the test being disabled therefore we assume that for all drivers there
- * will be no performance impact if we always leave the test enabled which
- * makes things a bit simpler for us. Under GLES2 the alpha test is
- * implemented in the fragment shader so there is no enable for it
- */
- GE (glEnable (GL_ALPHA_TEST));
-#endif
-
-#ifdef HAVE_COGL_GLES2
- _context->flushed_modelview_stack = NULL;
- _context->flushed_projection_stack = NULL;
-#endif
-
- /* Create default textures used for fall backs */
- context->default_gl_texture_2d_tex =
- cogl_texture_new_from_data (1, /* width */
- 1, /* height */
- COGL_TEXTURE_NO_SLICING,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
- /* internal format */
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- 0, /* auto calc row stride */
- default_texture_data);
- context->default_gl_texture_rect_tex =
- cogl_texture_new_from_data (1, /* width */
- 1, /* height */
- COGL_TEXTURE_NO_SLICING,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
- /* internal format */
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- 0, /* auto calc row stride */
- default_texture_data);
-
- cogl_push_source (context->opaque_color_pipeline);
- _cogl_pipeline_flush_gl_state (context->opaque_color_pipeline, FALSE, 0);
- _cogl_enable (enable_flags);
- _cogl_flush_face_winding ();
-
- context->atlases = NULL;
- g_hook_list_init (&context->atlas_reorganize_callbacks, sizeof (GHook));
-
- _context->buffer_map_fallback_array = g_byte_array_new ();
- _context->buffer_map_fallback_in_use = FALSE;
-
- /* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
- unless GL_COORD_REPLACE is enabled for an individual
- layer. Therefore it seems like it should be ok to just leave it
- enabled all the time instead of having to have a set property on
- each pipeline to track whether any layers have point sprite
- coords enabled. We don't need to do this for GLES2 because point
- sprites are handled using a builtin varying in the shader. */
-#ifndef HAVE_COGL_GLES2
- if (cogl_features_available (COGL_FEATURE_POINT_SPRITE))
- GE (glEnable (GL_POINT_SPRITE));
-#endif
-
- return _cogl_context_object_new (context);
-}
-
-static void
-_cogl_context_free (CoglContext *context)
-{
- const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
-
- winsys->context_deinit (context);
-
- _cogl_destroy_texture_units ();
-
- _cogl_free_framebuffer_stack (context->framebuffer_stack);
-
- if (context->current_path)
- cogl_handle_unref (context->current_path);
-
- if (context->default_gl_texture_2d_tex)
- cogl_handle_unref (context->default_gl_texture_2d_tex);
- if (context->default_gl_texture_rect_tex)
- cogl_handle_unref (context->default_gl_texture_rect_tex);
-
- if (context->opaque_color_pipeline)
- cogl_handle_unref (context->opaque_color_pipeline);
- if (context->blended_color_pipeline)
- cogl_handle_unref (context->blended_color_pipeline);
- if (context->texture_pipeline)
- cogl_handle_unref (context->texture_pipeline);
-
- if (context->blit_texture_pipeline)
- cogl_handle_unref (context->blit_texture_pipeline);
-
- if (context->journal_flush_attributes_array)
- g_array_free (context->journal_flush_attributes_array, TRUE);
- if (context->journal_clip_bounds)
- g_array_free (context->journal_clip_bounds, TRUE);
-
- if (context->polygon_vertices)
- g_array_free (context->polygon_vertices, TRUE);
-
- if (context->quad_buffer_indices_byte)
- cogl_handle_unref (context->quad_buffer_indices_byte);
- if (context->quad_buffer_indices)
- cogl_handle_unref (context->quad_buffer_indices);
-
- if (context->rectangle_byte_indices)
- cogl_object_unref (context->rectangle_byte_indices);
- if (context->rectangle_short_indices)
- cogl_object_unref (context->rectangle_short_indices);
-
- if (context->default_pipeline)
- cogl_handle_unref (context->default_pipeline);
-
- if (context->dummy_layer_dependant)
- cogl_handle_unref (context->dummy_layer_dependant);
- if (context->default_layer_n)
- cogl_handle_unref (context->default_layer_n);
- if (context->default_layer_0)
- cogl_handle_unref (context->default_layer_0);
-
- if (context->current_clip_stack_valid)
- _cogl_clip_stack_unref (context->current_clip_stack);
-
- g_slist_free (context->atlases);
- g_hook_list_clear (&context->atlas_reorganize_callbacks);
-
- _cogl_bitmask_destroy (&context->arrays_enabled);
- _cogl_bitmask_destroy (&context->temp_bitmask);
- _cogl_bitmask_destroy (&context->arrays_to_change);
-
- g_slist_free (context->texture_types);
- g_slist_free (context->buffer_types);
-
-#ifdef HAVE_COGL_GLES2
- if (_context->flushed_modelview_stack)
- cogl_object_unref (_context->flushed_modelview_stack);
- if (_context->flushed_projection_stack)
- cogl_object_unref (_context->flushed_projection_stack);
-#endif
-
-#ifdef HAVE_COGL_GL
- g_hash_table_unref (context->arbfp_cache);
-#endif
-
- g_byte_array_free (context->buffer_map_fallback_array, TRUE);
-
- cogl_object_unref (context->display);
-
- g_free (context);
-}
-
-CoglContext *
-_cogl_context_get_default (void)
-{
- GError *error = NULL;
- /* Create if doesn't exist yet */
- if (_context == NULL)
- {
- _context = cogl_context_new (NULL, &error);
- if (!_context)
- {
- g_warning ("Failed to create default context: %s",
- error->message);
- g_error_free (error);
- }
- }
-
- return _context;
-}
-
-void
-cogl_set_default_context (CoglContext *context)
-{
- cogl_object_ref (context);
-
- if (_context)
- cogl_object_unref (_context);
- _context = context;
-}
-
-#ifdef COGL_HAS_EGL_SUPPORT
-EGLDisplay
-cogl_context_egl_get_egl_display (CoglContext *context)
-{
- const CoglWinsysVtable *winsys = _cogl_context_get_winsys (context);
- return winsys->context_egl_get_egl_display (context);
-}
-#endif
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_CONTEXT_H__
-#define __COGL_CONTEXT_H__
-
-#include <cogl/cogl-display.h>
-
-#ifdef COGL_HAS_EGL_SUPPORT
-#ifdef COGL_HAS_GLES1
-#include <GLES/gl.h>
-#include <GLES/egl.h>
-#else
-#include <EGL/egl.h>
-#define NativeDisplayType EGLNativeDisplayType
-#define NativeWindowType EGLNativeWindowType
-#endif
-#endif
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-context
- * @short_description: The top level application context.
- *
- * A CoglContext is the topmost sandbox of Cogl state for an
- * application or toolkit. Its main purpose is to bind together the
- * key state objects at any one time; with the most significant being
- * the current framebuffer being drawn too (See #CoglFramebuffer for
- * more details) and the current GPU pipeline configuration (See
- * #CoglPipeline for more details).
- */
-
-typedef struct _CoglContext CoglContext;
-
-#define COGL_CONTEXT(OBJECT) ((CoglContext *)OBJECT)
-
-#define cogl_context_new cogl_context_new_EXP
-
-CoglContext *
-cogl_context_new (CoglDisplay *display,
- GError **error);
-
-#define cogl_set_default_context cogl_set_default_context_EXP
-void
-cogl_set_default_context (CoglContext *context);
-
-#ifdef COGL_HAS_EGL_SUPPORT
-#define cogl_context_egl_get_egl_display cogl_context_egl_get_egl_display_EXP
-EGLDisplay
-cogl_context_egl_get_egl_display (CoglContext *context);
-#endif
-
-G_END_DECLS
-
-#endif /* __COGL_CONTEXT_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-OPT (HANDLE,
- "Cogl Tracing",
- "ref-counts",
- "CoglObject references",
- "Debug ref counting issues for CoglObjects")
-OPT (SLICING,
- "Cogl Tracing",
- "slicing",
- "Trace Texture Slicing",
- "debug the creation of texture slices")
-OPT (ATLAS,
- "Cogl Tracing",
- "atlas",
- "Trace Atlas Textures",
- "Debug texture atlas management")
-OPT (BLEND_STRINGS,
- "Cogl Tracing",
- "blend-strings",
- "Trace Blend Strings",
- "Debug CoglBlendString parsing")
-OPT (JOURNAL,
- "Cogl Tracing",
- "journal",
- "Trace Journal",
- "View all the geometry passing through the journal")
-OPT (BATCHING,
- "Cogl Tracing",
- "batching",
- "Trace Batching",
- "Show how geometry is being batched in the journal")
-OPT (MATRICES,
- "Cogl Tracing",
- "matrices",
- "Trace matrices",
- "Trace all matrix manipulation")
-/* XXX we should replace the "draw" option its very hand wavy... */
-OPT (DRAW,
- "Cogl Tracing",
- "draw",
- "Trace Misc Drawing",
- "Trace some misc drawing operations")
-OPT (PANGO,
- "Cogl Tracing",
- "pango",
- "Trace Pango Renderer",
- "Trace the Cogl Pango renderer")
-OPT (TEXTURE_PIXMAP,
- "Cogl Tracing",
- "texture-pixmap",
- "Trace CoglTexturePixmap backend",
- "Trace the Cogl texture pixmap backend")
-OPT (RECTANGLES,
- "Visualize",
- "rectangles",
- "Outline rectangles",
- "Add wire outlines for all rectangular geometry")
-OPT (WIREFRAME,
- "Visualize",
- "wireframe",
- "Show wireframes",
- "Add wire outlines for all geometry")
-OPT (DISABLE_BATCHING,
- "Root Cause",
- "disable-batching",
- "Disable Journal batching",
- "Disable batching of geometry in the Cogl Journal.")
-OPT (DISABLE_VBOS,
- "Root Cause",
- "disable-vbos",
- "Disable GL Vertex Buffers",
- "Disable use of OpenGL vertex buffer objects")
-OPT (DISABLE_PBOS,
- "Root Cause",
- "disable-pbos",
- "Disable GL Pixel Buffers",
- "Disable use of OpenGL pixel buffer objects")
-OPT (DISABLE_SOFTWARE_TRANSFORM,
- "Root Cause",
- "disable-software-transform",
- "Disable software rect transform",
- "Use the GPU to transform rectangular geometry")
-OPT (DUMP_ATLAS_IMAGE,
- "Cogl Specialist",
- "dump-atlas-image",
- "Dump atlas images",
- "Dump texture atlas changes to an image file")
-OPT (DISABLE_ATLAS,
- "Root Cause",
- "disable-atlas",
- "Disable texture atlasing",
- "Disable use of texture atlasing")
-OPT (DISABLE_SHARED_ATLAS,
- "Root Cause",
- "disable-shared-atlas",
- "Disable sharing the texture atlas between text and images",
- "When this is set the glyph cache will always use a separate texture "
- "for its atlas. Otherwise it will try to share the atlas with images.")
-OPT (DISABLE_TEXTURING,
- "Root Cause",
- "disable-texturing",
- "Disable texturing",
- "Disable texturing any primitives")
-OPT (DISABLE_ARBFP,
- "Root Cause",
- "disable-arbfp",
- "Disable arbfp",
- "Disable use of ARB fragment programs")
-OPT (DISABLE_FIXED,
- "Root Cause",
- "disable-fixed",
- "Disable fixed",
- "Disable use of the fixed function pipeline backend")
-OPT (DISABLE_GLSL,
- "Root Cause",
- "disable-glsl",
- "Disable GLSL",
- "Disable use of GLSL")
-OPT (DISABLE_BLENDING,
- "Root Cause",
- "disable-blending",
- "Disable blending",
- "Disable use of blending")
-OPT (DISABLE_NPOT_TEXTURES,
- "Root Cause",
- "disable-npot-textures",
- "Disable non-power-of-two textures",
- "Makes Cogl think that the GL driver doesn't support NPOT textures "
- "so that it will create sliced textures or textures with waste instead.")
-OPT (DISABLE_SOFTWARE_CLIP,
- "Root Cause",
- "disable-software-clip",
- "Disable software clipping",
- "Disables Cogl's attempts to clip some rectangles in software.")
-OPT (SHOW_SOURCE,
- "Cogl Tracing",
- "show-source",
- "Show source",
- "Show generated ARBfp/GLSL source code")
-OPT (OPENGL,
- "Cogl Tracing",
- "opengl",
- "Trace some OpenGL",
- "Traces some select OpenGL calls")
-OPT (OFFSCREEN,
- "Cogl Tracing",
- "offscreen",
- "Trace offscreen support",
- "Debug offscreen support")
-OPT (DISABLE_BLENDING,
- "Root Cause",
- "disable-program-caches",
- "Disable program caches",
- "Disable fallback caches for arbfp and glsl programs")
-OPT (DISABLE_FAST_READ_PIXEL,
- "Root Cause",
- "disable-fast-read-pixel",
- "Disable read pixel optimization",
- "Disable optimization for reading 1px for simple "
- "scenes of opaque rectangles")
-OPT (CLIPPING,
- "Cogl Tracing",
- "clipping",
- "Trace clipping",
- "Logs information about how Cogl is implementing clipping")
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <glib/gi18n-lib.h>
-
-#include "cogl-debug.h"
-
-#ifdef COGL_ENABLE_DEBUG
-
-/* XXX: If you add a debug option, please also add an option
- * definition to cogl-debug-options.h. This will enable us - for
- * example - to emit a "help" description for the option.
- */
-
-/* NB: Only these options get enabled if COGL_DEBUG=all is
- * used since they don't affect the behaviour of Cogl they
- * simply print out verbose information */
-static const GDebugKey cogl_log_debug_keys[] = {
- { "handle", COGL_DEBUG_HANDLE },
- { "slicing", COGL_DEBUG_SLICING },
- { "atlas", COGL_DEBUG_ATLAS },
- { "blend-strings", COGL_DEBUG_BLEND_STRINGS },
- { "journal", COGL_DEBUG_JOURNAL },
- { "batching", COGL_DEBUG_BATCHING },
- { "matrices", COGL_DEBUG_MATRICES },
- { "draw", COGL_DEBUG_DRAW },
- { "opengl", COGL_DEBUG_OPENGL },
- { "pango", COGL_DEBUG_PANGO },
- { "show-source", COGL_DEBUG_SHOW_SOURCE},
- { "offscreen", COGL_DEBUG_OFFSCREEN },
- { "texture-pixmap", COGL_DEBUG_TEXTURE_PIXMAP },
- { "bitmap", COGL_DEBUG_BITMAP },
- { "clipping", COGL_DEBUG_CLIPPING }
-};
-static const int n_cogl_log_debug_keys =
- G_N_ELEMENTS (cogl_log_debug_keys);
-
-static const GDebugKey cogl_behavioural_debug_keys[] = {
- { "rectangles", COGL_DEBUG_RECTANGLES },
- { "disable-batching", COGL_DEBUG_DISABLE_BATCHING },
- { "disable-vbos", COGL_DEBUG_DISABLE_VBOS },
- { "disable-pbos", COGL_DEBUG_DISABLE_PBOS },
- { "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM },
- { "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE },
- { "disable-atlas", COGL_DEBUG_DISABLE_ATLAS },
- { "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS },
- { "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING},
- { "disable-arbfp", COGL_DEBUG_DISABLE_ARBFP},
- { "disable-fixed", COGL_DEBUG_DISABLE_FIXED},
- { "disable-glsl", COGL_DEBUG_DISABLE_GLSL},
- { "disable-blending", COGL_DEBUG_DISABLE_BLENDING},
- { "disable-npot-textures", COGL_DEBUG_DISABLE_NPOT_TEXTURES},
- { "wireframe", COGL_DEBUG_WIREFRAME},
- { "disable-software-clip", COGL_DEBUG_DISABLE_SOFTWARE_CLIP},
- { "disable-program-caches", COGL_DEBUG_DISABLE_PROGRAM_CACHES},
- { "disable-fast-read-pixel", COGL_DEBUG_DISABLE_FAST_READ_PIXEL}
-};
-static const int n_cogl_behavioural_debug_keys =
- G_N_ELEMENTS (cogl_behavioural_debug_keys);
-
-unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
-
-static void
-_cogl_parse_debug_string_for_keys (const char *value,
- gboolean enable,
- const GDebugKey *keys,
- unsigned int nkeys)
-{
- int int_num, key_num;
-
- /* g_parse_debug_string expects the value field in GDebugKey to be a
- mask in a guint but we may have multiple guints so we need to
- build a separate array for each possible guint */
-
- for (int_num = 0; int_num < COGL_DEBUG_N_INTS; int_num++)
- {
- GDebugKey keys_for_int[sizeof (unsigned int) * 8];
- unsigned int mask_for_int;
- int nkeys_for_int = 0;
-
- for (key_num = 0; key_num < nkeys; key_num++)
- if (COGL_FLAGS_GET_INDEX (keys[key_num].value) == int_num)
- {
- keys_for_int[nkeys_for_int] = keys[key_num];
- keys_for_int[nkeys_for_int].value =
- COGL_FLAGS_GET_MASK (keys[key_num].value);
- nkeys_for_int++;
- }
-
- if (nkeys_for_int > 0)
- {
- mask_for_int = g_parse_debug_string (value,
- keys_for_int,
- nkeys_for_int);
- if (enable)
- _cogl_debug_flags[int_num] |= mask_for_int;
- else
- _cogl_debug_flags[int_num] &= ~mask_for_int;
- }
- }
-}
-
-static void
-_cogl_parse_debug_string (const char *value,
- gboolean enable,
- gboolean ignore_help)
-{
- if (ignore_help && strcmp (value, "help") == 0)
- return;
-
- /* We don't want to let g_parse_debug_string handle "all" because
- * literally enabling all the debug options wouldn't be useful to
- * anyone; instead the all option enables all non behavioural
- * options.
- */
- if (strcmp (value, "all") == 0 ||
- strcmp (value, "verbose") == 0)
- {
- int i;
- for (i = 0; i < n_cogl_log_debug_keys; i++)
- if (enable)
- COGL_DEBUG_SET_FLAG (cogl_log_debug_keys[i].value);
- else
- COGL_DEBUG_CLEAR_FLAG (cogl_log_debug_keys[i].value);
- }
- else if (strcmp (value, "help") == 0)
- {
- g_printerr ("\n\n%28s\n", "Supported debug values:");
-#define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \
- g_printerr ("%28s %s\n", NAME ":", DESCRIPTION);
-#include "cogl-debug-options.h"
- g_printerr ("\n%28s\n", "Special debug values:");
- OPT (IGNORED, "ignored", "all", "ignored", \
- "Enables all non-behavioural debug options");
- OPT (IGNORED, "ignored", "verbose", "ignored", \
- "Enables all non-behavioural debug options");
-#undef OPT
- exit (1);
- }
- else
- {
- _cogl_parse_debug_string_for_keys (value,
- enable,
- cogl_log_debug_keys,
- n_cogl_log_debug_keys);
- _cogl_parse_debug_string_for_keys (value,
- enable,
- cogl_behavioural_debug_keys,
- n_cogl_behavioural_debug_keys);
- }
-}
-
-static gboolean
-cogl_arg_debug_cb (const char *key,
- const char *value,
- gpointer user_data)
-{
- _cogl_parse_debug_string (value,
- TRUE /* enable the flags */,
- FALSE /* don't ignore help */);
- return TRUE;
-}
-
-static gboolean
-cogl_arg_no_debug_cb (const char *key,
- const char *value,
- gpointer user_data)
-{
- _cogl_parse_debug_string (value,
- FALSE, /* disable the flags */
- TRUE /* ignore help */);
- return TRUE;
-}
-#endif /* COGL_ENABLE_DEBUG */
-
-static GOptionEntry cogl_args[] = {
-#ifdef COGL_ENABLE_DEBUG
- { "cogl-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_debug_cb,
- N_("Cogl debugging flags to set"), "FLAGS" },
- { "cogl-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_no_debug_cb,
- N_("Cogl debugging flags to unset"), "FLAGS" },
-#endif /* COGL_ENABLE_DEBUG */
- { NULL, },
-};
-
-static gboolean
-pre_parse_hook (GOptionContext *context,
- GOptionGroup *group,
- gpointer data,
- GError **error)
-{
-#ifdef COGL_ENABLE_DEBUG
- const char *env_string;
-
- env_string = g_getenv ("COGL_DEBUG");
- if (env_string != NULL)
- {
- _cogl_parse_debug_string (env_string,
- TRUE /* enable the flags */,
- FALSE /* don't ignore help */);
- env_string = NULL;
- }
-#endif /* COGL_ENABLE_DEBUG */
-
- return TRUE;
-}
-
-GOptionGroup *
-cogl_get_option_group (void)
-{
- GOptionGroup *group;
-
- group = g_option_group_new ("cogl",
- _("Cogl Options"),
- _("Show Cogl options"),
- NULL, NULL);
-
- g_option_group_set_parse_hooks (group, pre_parse_hook, NULL);
- g_option_group_add_entries (group, cogl_args);
- g_option_group_set_translation_domain (group, GETTEXT_PACKAGE);
-
- return group;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_DEBUG_H__
-#define __COGL_DEBUG_H__
-
-#include "cogl-profile.h"
-#include "cogl-flags.h"
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-typedef enum {
- COGL_DEBUG_SLICING,
- COGL_DEBUG_OFFSCREEN,
- COGL_DEBUG_DRAW,
- COGL_DEBUG_PANGO,
- COGL_DEBUG_RECTANGLES,
- COGL_DEBUG_HANDLE,
- COGL_DEBUG_BLEND_STRINGS,
- COGL_DEBUG_DISABLE_BATCHING,
- COGL_DEBUG_DISABLE_VBOS,
- COGL_DEBUG_DISABLE_PBOS,
- COGL_DEBUG_JOURNAL,
- COGL_DEBUG_BATCHING,
- COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM,
- COGL_DEBUG_MATRICES,
- COGL_DEBUG_ATLAS,
- COGL_DEBUG_DUMP_ATLAS_IMAGE,
- COGL_DEBUG_DISABLE_ATLAS,
- COGL_DEBUG_DISABLE_SHARED_ATLAS,
- COGL_DEBUG_OPENGL,
- COGL_DEBUG_DISABLE_TEXTURING,
- COGL_DEBUG_DISABLE_ARBFP,
- COGL_DEBUG_DISABLE_FIXED,
- COGL_DEBUG_DISABLE_GLSL,
- COGL_DEBUG_SHOW_SOURCE,
- COGL_DEBUG_DISABLE_BLENDING,
- COGL_DEBUG_TEXTURE_PIXMAP,
- COGL_DEBUG_BITMAP,
- COGL_DEBUG_DISABLE_NPOT_TEXTURES,
- COGL_DEBUG_WIREFRAME,
- COGL_DEBUG_DISABLE_SOFTWARE_CLIP,
- COGL_DEBUG_DISABLE_PROGRAM_CACHES,
- COGL_DEBUG_DISABLE_FAST_READ_PIXEL,
- COGL_DEBUG_CLIPPING,
- COGL_DEBUG_WINSYS,
-
- COGL_DEBUG_N_FLAGS
-} CoglDebugFlags;
-
-#ifdef COGL_ENABLE_DEBUG
-
-#define COGL_DEBUG_N_INTS COGL_FLAGS_N_INTS_FOR_SIZE (COGL_DEBUG_N_FLAGS)
-
-extern unsigned int _cogl_debug_flags[COGL_DEBUG_N_INTS];
-
-#define COGL_DEBUG_ENABLED(flag) \
- COGL_FLAGS_GET (_cogl_debug_flags, flag)
-
-#define COGL_DEBUG_SET_FLAG(flag) \
- COGL_FLAGS_SET (_cogl_debug_flags, flag, TRUE)
-
-#define COGL_DEBUG_CLEAR_FLAG(flag) \
- COGL_FLAGS_SET (_cogl_debug_flags, flag, FALSE)
-
-#ifdef __GNUC__
-#define COGL_NOTE(type,x,a...) G_STMT_START { \
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type))) { \
- _cogl_profile_trace_message ("[" #type "] " G_STRLOC " & " x, ##a); \
- } } G_STMT_END
-
-#else
-#define COGL_NOTE(type,...) G_STMT_START { \
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_##type)) { \
- char *_fmt = g_strdup_printf (__VA_ARGS__); \
- _cogl_profile_trace_message ("[" #type "] " G_STRLOC " & %s", _fmt);\
- g_free (_fmt); \
- } } G_STMT_END
-
-#endif /* __GNUC__ */
-
-#else /* !COGL_ENABLE_DEBUG */
-
-#define COGL_NOTE(type,...) G_STMT_START {} G_STMT_END
-
-#define COGL_DEBUG_ENABLED(flag) FALSE
-
-#define COGL_DEBUG_SET_FLAG(flag) \
- G_STMT_START { } G_STMT_END
-
-#define COGL_DEBUG_CLEAR_FLAG(flag) \
- G_STMT_START { } G_STMT_END
-
-#endif /* COGL_ENABLE_DEBUG */
-
-G_END_DECLS
-
-#endif /* __COGL_DEBUG_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_DEFINES_H__
-#define __COGL_DEFINES_H__
-
-#include <glib.h>
-@COGL_GL_HEADER_INCLUDES@
-
-G_BEGIN_DECLS
-
-@COGL_DEFINES@
-
-G_END_DECLS
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef COGL_DEPRECATED_H
-
-#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color
-#define cogl_enable_depth_test cogl_enable_depth_test_RENAMED_TO_cogl_set_depth_test_enabled
-#define cogl_enable_backface_culling cogl_enable_backface_culling_RENAMED_TO_cogl_set_backface_culling_enabled
-
-#define cogl_texture_rectangle cogl_texture_rectangle_REPLACE_BY_cogl_set_source_texture_AND_cogl_rectangle_with_texture_coords
-
-#define cogl_texture_multiple_rectangles cogl_texture_multiple_rectangles_REPLACED_BY_cogl_set_source_texture_AND_cogl_rectangles_with_texture_coords
-
-#define cogl_texture_polygon cogl_texture_polygon_REPLACED_BY_cogl_set_source_texture_AND_cogl_polygon
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_DISPLAY_GLX_PRIVATE_H
-#define __COGL_DISPLAY_GLX_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-display-xlib-private.h"
-
-typedef struct _CoglGLXCachedConfig
-{
- /* This will be -1 if there is no cached config in this slot */
- int depth;
- gboolean found;
- GLXFBConfig fb_config;
- gboolean can_mipmap;
-} CoglGLXCachedConfig;
-
-#define COGL_GLX_N_CACHED_CONFIGS 3
-
-typedef struct _CoglDisplayGLX
-{
- CoglDisplayXlib _parent;
-
- CoglGLXCachedConfig glx_cached_configs[COGL_GLX_N_CACHED_CONFIGS];
-
- gboolean found_fbconfig;
- gboolean fbconfig_has_rgba_visual;
- GLXFBConfig fbconfig;
-
- /* Single context for all wins */
- GLXContext glx_context;
- GLXWindow dummy_glxwin;
-} CoglDisplayGLX;
-
-#endif /* __COGL_DISPLAY_GLX_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_DISPLAY_PRIVATE_H
-#define __COGL_DISPLAY_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-display.h"
-#include "cogl-renderer.h"
-#include "cogl-onscreen-template.h"
-
-struct _CoglDisplay
-{
- CoglObject _parent;
-
- gboolean setup;
- CoglRenderer *renderer;
- CoglOnscreenTemplate *onscreen_template;
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- struct gdl_plane *gdl_plane;
-#endif
-
- void *winsys;
-};
-
-#endif /* __COGL_DISPLAY_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_DISPLAY_XLIB_PRIVATE_H
-#define __COGL_DISPLAY_XLIB_PRIVATE_H
-
-#include <X11/Xlib.h>
-
-typedef struct _CoglDisplayXlib
-{
- Window dummy_xwin;
-} CoglDisplayXlib;
-
-#endif /* __COGL_DISPLAY_XLIB_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-object.h"
-
-#include "cogl-display-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-winsys-private.h"
-
-static void _cogl_display_free (CoglDisplay *display);
-
-COGL_OBJECT_DEFINE (Display, display);
-
-GQuark
-cogl_display_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-display-error-quark");
-}
-
-static void
-_cogl_display_free (CoglDisplay *display)
-{
- if (display->renderer)
- {
- cogl_object_unref (display->renderer);
- display->renderer = NULL;
- }
-
- if (display->onscreen_template)
- {
- cogl_object_unref (display->onscreen_template);
- display->onscreen_template = NULL;
- }
-
- g_slice_free (CoglDisplay, display);
-}
-
-CoglDisplay *
-cogl_display_new (CoglRenderer *renderer,
- CoglOnscreenTemplate *onscreen_template)
-{
- CoglDisplay *display = g_slice_new0 (CoglDisplay);
- GError *error = NULL;
-
- display->renderer = renderer;
- if (renderer)
- cogl_object_ref (renderer);
- else
- display->renderer = cogl_renderer_new ();
-
- if (!cogl_renderer_connect (display->renderer, &error))
- {
- g_warning ("Failed to connect renderer: %s\n", error->message);
- g_error_free (error);
- g_object_unref (display->renderer);
- g_slice_free (CoglDisplay, display);
- return NULL;
- }
-
- display->onscreen_template = onscreen_template;
- if (onscreen_template)
- cogl_object_ref (onscreen_template);
-
- display->setup = FALSE;
-
- return _cogl_display_object_new (display);
-}
-
-static const CoglWinsysVtable *
-_cogl_display_get_winsys (CoglDisplay *display)
-{
- return display->renderer->winsys_vtable;
-}
-
-gboolean
-cogl_display_setup (CoglDisplay *display,
- GError **error)
-{
-#ifdef COGL_HAS_FULL_WINSYS
- const CoglWinsysVtable *winsys;
-#endif
-
- if (display->setup)
- return TRUE;
-
-#ifdef COGL_HAS_FULL_WINSYS
- winsys = _cogl_display_get_winsys (display);
- if (!winsys->display_setup (display, error))
- return FALSE;
-#endif
-
- display->setup = TRUE;
-
- return TRUE;
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
-void
-cogl_gdl_display_set_plane (CoglDisplay *display,
- struct gdl_plane *plane)
-{
- g_return_if_fail (display->setup == FALSE);
-
- display->gdl_plane = plane;
-}
-#endif
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_DISPLAY_H__
-#define __COGL_DISPLAY_H__
-
-#include <cogl/cogl-renderer.h>
-#include <cogl/cogl-onscreen-template.h>
-
-G_BEGIN_DECLS
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
-#include <@CLUTTER_CEX100_LIBGDL_PREFIX@libgdl.h>
-#endif
-
-/**
- * SECTION:cogl-display
- * @short_description: Represents a display pipeline
- *
- * TODO: We still need to decide if we really need this object or if
- * it's enough to just have the CoglSwapChain CoglOnscreenTemplate
- * objects.
- *
- * The basic intention is for this object to let the application
- * specify its display preferences before creating a context, and
- * there are a few different aspects to this...
- *
- * Firstly there is the physical display pipeline that is currently
- * being used including the digital to analogue conversion hardware
- * and the screen the user sees. Although we don't have a plan to
- * expose all the advanced features of arbitrary display hardware with
- * a Cogl API, some backends may want to expose limited control over
- * this hardware via Cogl and simpler features like providing a list
- * of modes to choose from in a UI could be nice too.
- *
- * Another aspect is that the display configuration may be tightly
- * related to how onscreen framebuffers should be configured. In fact
- * one of the early rationals for this object was to let us handle
- * GLX's requirement that framebuffers must be "compatible" with the
- * fbconfig associated with the current context meaning we have to
- * force the user to describe how they would like to create their
- * onscreen windows before we can choose a suitable fbconfig and
- * create a GLContext.
- *
- * TODO: continue this thought process and come to a decision...
- */
-
-typedef struct _CoglDisplay CoglDisplay;
-
-#define COGL_DISPLAY(OBJECT) ((CoglDisplay *)OBJECT)
-
-#define cogl_display_new cogl_display_new_EXP
-CoglDisplay *
-cogl_display_new (CoglRenderer *renderer,
- CoglOnscreenTemplate *onscreen_template);
-
-#define cogl_display_setup cogl_display_setup_EXP
-gboolean
-cogl_display_setup (CoglDisplay *display,
- GError **error);
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
-#define cogl_gdl_display_set_plane \
- cogl_gdl_display_set_plane_EXP
-void
-cogl_gdl_display_set_plane (CoglDisplay *display,
- struct gdl_plane *plane);
-#endif
-
-G_END_DECLS
-
-#endif /* __COGL_DISPLAY_H__ */
-
+++ /dev/null
-/*** BEGIN file-header ***/
-#include "cogl-enum-types.h"
-#include "cogl.h"
-/*** END file-header ***/
-
-/*** BEGIN file-production ***/
-
-/* enumerations from "@filename@" */
-#include "@filename@"
-
-/*** END file-production ***/
-
-/*** BEGIN value-header ***/
-GType
-@enum_name@_get_type (void)
-{
- static volatile gsize g_enum_type_id__volatile = 0;
-
- if (g_once_init_enter (&g_enum_type_id__volatile))
- {
- static const G@Type@Value values[] = {
-/*** END value-header ***/
-
-/*** BEGIN value-production ***/
- { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
-/*** END value-production ***/
-
-/*** BEGIN value-tail ***/
- { 0, NULL, NULL }
- };
- GType g_enum_type_id;
-
- g_enum_type_id =
- g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
-
- g_once_init_leave (&g_enum_type_id__volatile, g_enum_type_id);
- }
-
- return g_enum_type_id__volatile;
-}
-/*** END value-tail ***/
+++ /dev/null
-/*** BEGIN file-header ***/
-#ifndef __COGL_ENUM_TYPES_H__
-#define __COGL_ENUM_TYPES_H__
-
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-/*** END file-header ***/
-
-/*** BEGIN file-production ***/
-/* enumerations from "@filename@" */
-/*** END file-production ***/
-
-/*** BEGIN file-tail ***/
-G_END_DECLS
-
-#endif /* !__CLUTTER_ENUM_TYPES_H__ */
-/*** END file-tail ***/
-
-/*** BEGIN value-header ***/
-GType @enum_name@_get_type (void) G_GNUC_CONST;
-#define COGL_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
-
-/*** END value-header ***/
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl.h"
-#include "cogl-context-private.h"
-
-#include "cogl-feature-private.h"
-
-gboolean
-_cogl_feature_check (const char *driver_prefix,
- const CoglFeatureData *data,
- unsigned int gl_major,
- unsigned int gl_minor,
- const char *extensions_string,
- void *function_table)
-
-{
- const char *suffix = NULL;
- int func_num;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* First check whether the functions should be directly provided by
- GL */
- if (COGL_CHECK_GL_VERSION (gl_major, gl_minor,
- data->min_gl_major, data->min_gl_minor))
- suffix = "";
- else
- {
- /* Otherwise try all of the extensions */
- const char *namespace, *namespace_suffix;
- unsigned int namespace_len;
-
- for (namespace = data->namespaces;
- *namespace;
- namespace += strlen (namespace) + 1)
- {
- const char *extension;
- GString *full_extension_name = g_string_new ("");
-
- /* If the namespace part contains a ':' then the suffix for
- the function names is different from the name space */
- if ((namespace_suffix = strchr (namespace, ':')))
- {
- namespace_len = namespace_suffix - namespace;
- namespace_suffix++;
- }
- else
- {
- namespace_len = strlen (namespace);
- namespace_suffix = namespace;
- }
-
- for (extension = data->extension_names;
- *extension;
- extension += strlen (extension) + 1)
- {
- g_string_assign (full_extension_name, driver_prefix);
- g_string_append_c (full_extension_name, '_');
- g_string_append_len (full_extension_name,
- namespace, namespace_len);
- g_string_append_c (full_extension_name, '_');
- g_string_append (full_extension_name, extension);
- if (!_cogl_check_extension (full_extension_name->str,
- extensions_string))
- break;
- }
-
- g_string_free (full_extension_name, TRUE);
-
- /* If we found all of the extensions with this namespace
- then use it as the suffix */
- if (*extension == '\0')
- {
- suffix = namespace_suffix;
- break;
- }
- }
- }
-
- /* If we couldn't find anything that provides the functions then
- give up */
- if (suffix == NULL)
- return FALSE;
-
- /* Try to get all of the entry points */
- for (func_num = 0; data->functions[func_num].name; func_num++)
- {
- void *func;
- char *full_function_name;
-
- full_function_name = g_strconcat (data->functions[func_num].name,
- suffix, NULL);
- func = cogl_get_proc_address (full_function_name);
- g_free (full_function_name);
-
- if (func == NULL)
- break;
-
- /* Set the function pointer in the context */
- *(void **) ((guint8 *) function_table +
- data->functions[func_num].pointer_offset) = func;
- }
-
- /* If one of the functions wasn't found then we should set all of
- the function pointers back to NULL so that the rest of Cogl can
- safely do feature testing by just looking at the function
- pointers */
- if (data->functions[func_num].name)
- {
- while (func_num-- > 0)
- *(void **) ((guint8 *) ctx +
- data->functions[func_num].pointer_offset) = NULL;
- return FALSE;
- }
- else
- return TRUE;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_FEATURE_PRIVATE_H
-#define __COGL_FEATURE_PRIVATE_H
-
-#include <glib.h>
-
-#include "cogl-internal.h"
-
-#define COGL_CHECK_GL_VERSION(driver_major, driver_minor, \
- target_major, target_minor) \
- ((driver_major) > (target_major) || \
- ((driver_major) == (target_major) && (driver_minor) >= (target_minor)))
-
-typedef struct _CoglFeatureFunction CoglFeatureFunction;
-
-struct _CoglFeatureFunction
-{
- /* The name of the function without the "EXT" or "ARB" suffix */
- const char *name;
- /* The offset in the context of where to store the function pointer */
- unsigned int pointer_offset;
-};
-
-typedef struct _CoglFeatureData CoglFeatureData;
-
-struct _CoglFeatureData
-{
- /* A minimum GL version which the functions should be defined in
- without needing an extension. Set to 255,255 if it's only
- provided in an extension */
- guint8 min_gl_major, min_gl_minor;
- /* \0 separated list of namespaces to try. Eg "EXT\0ARB\0" */
- const char *namespaces;
- /* \0 separated list of required extension names without the GL_EXT
- or GL_ARB prefix. All of the extensions must be available for the
- feature to be considered available. If the suffix for an
- extension is different from the namespace, you can specify it
- with a ':' after the namespace */
- const char *extension_names;
- /* A set of feature flags to enable if the extension is available */
- CoglFeatureFlags feature_flags;
- /* FIXME: This is now unused */
- int padding_feature_flags_private;
- /* An optional corresponding winsys feature. */
- CoglWinsysFeature winsys_feature;
- /* A list of functions required for this feature. Terminated with a
- NULL name */
- const CoglFeatureFunction *functions;
-};
-
-gboolean
-_cogl_feature_check (const char *driver_prefix,
- const CoglFeatureData *data,
- unsigned int gl_major,
- unsigned int gl_minor,
- const char *extensions_string,
- void *function_table);
-
-#endif /* __COGL_FEATURE_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#define G_IMPLEMENT_INLINES
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-fixed.h"
-
-/* pre-computed sin table for 1st quadrant
- *
- * Currently contains 257 entries.
- *
- * The current maximum absolute error is about 1.9e-0.5
- * and is greatest around pi/2 where the second derivative
- * of sin(x) is greatest. If greater accuracy is needed,
- * modestly increasing the table size, or maybe using
- * quadratic interpolation would drop the interpolation
- * error below the precision limits of CoglFixed.
- */
-static const CoglFixed sin_tbl[] =
-{
- 0x00000000L, 0x00000192L, 0x00000324L, 0x000004B6L,
- 0x00000648L, 0x000007DAL, 0x0000096CL, 0x00000AFEL,
- 0x00000C90L, 0x00000E21L, 0x00000FB3L, 0x00001144L,
- 0x000012D5L, 0x00001466L, 0x000015F7L, 0x00001787L,
- 0x00001918L, 0x00001AA8L, 0x00001C38L, 0x00001DC7L,
- 0x00001F56L, 0x000020E5L, 0x00002274L, 0x00002402L,
- 0x00002590L, 0x0000271EL, 0x000028ABL, 0x00002A38L,
- 0x00002BC4L, 0x00002D50L, 0x00002EDCL, 0x00003067L,
- 0x000031F1L, 0x0000337CL, 0x00003505L, 0x0000368EL,
- 0x00003817L, 0x0000399FL, 0x00003B27L, 0x00003CAEL,
- 0x00003E34L, 0x00003FBAL, 0x0000413FL, 0x000042C3L,
- 0x00004447L, 0x000045CBL, 0x0000474DL, 0x000048CFL,
- 0x00004A50L, 0x00004BD1L, 0x00004D50L, 0x00004ECFL,
- 0x0000504DL, 0x000051CBL, 0x00005348L, 0x000054C3L,
- 0x0000563EL, 0x000057B9L, 0x00005932L, 0x00005AAAL,
- 0x00005C22L, 0x00005D99L, 0x00005F0FL, 0x00006084L,
- 0x000061F8L, 0x0000636BL, 0x000064DDL, 0x0000664EL,
- 0x000067BEL, 0x0000692DL, 0x00006A9BL, 0x00006C08L,
- 0x00006D74L, 0x00006EDFL, 0x00007049L, 0x000071B2L,
- 0x0000731AL, 0x00007480L, 0x000075E6L, 0x0000774AL,
- 0x000078ADL, 0x00007A10L, 0x00007B70L, 0x00007CD0L,
- 0x00007E2FL, 0x00007F8CL, 0x000080E8L, 0x00008243L,
- 0x0000839CL, 0x000084F5L, 0x0000864CL, 0x000087A1L,
- 0x000088F6L, 0x00008A49L, 0x00008B9AL, 0x00008CEBL,
- 0x00008E3AL, 0x00008F88L, 0x000090D4L, 0x0000921FL,
- 0x00009368L, 0x000094B0L, 0x000095F7L, 0x0000973CL,
- 0x00009880L, 0x000099C2L, 0x00009B03L, 0x00009C42L,
- 0x00009D80L, 0x00009EBCL, 0x00009FF7L, 0x0000A130L,
- 0x0000A268L, 0x0000A39EL, 0x0000A4D2L, 0x0000A605L,
- 0x0000A736L, 0x0000A866L, 0x0000A994L, 0x0000AAC1L,
- 0x0000ABEBL, 0x0000AD14L, 0x0000AE3CL, 0x0000AF62L,
- 0x0000B086L, 0x0000B1A8L, 0x0000B2C9L, 0x0000B3E8L,
- 0x0000B505L, 0x0000B620L, 0x0000B73AL, 0x0000B852L,
- 0x0000B968L, 0x0000BA7DL, 0x0000BB8FL, 0x0000BCA0L,
- 0x0000BDAFL, 0x0000BEBCL, 0x0000BFC7L, 0x0000C0D1L,
- 0x0000C1D8L, 0x0000C2DEL, 0x0000C3E2L, 0x0000C4E4L,
- 0x0000C5E4L, 0x0000C6E2L, 0x0000C7DEL, 0x0000C8D9L,
- 0x0000C9D1L, 0x0000CAC7L, 0x0000CBBCL, 0x0000CCAEL,
- 0x0000CD9FL, 0x0000CE8EL, 0x0000CF7AL, 0x0000D065L,
- 0x0000D14DL, 0x0000D234L, 0x0000D318L, 0x0000D3FBL,
- 0x0000D4DBL, 0x0000D5BAL, 0x0000D696L, 0x0000D770L,
- 0x0000D848L, 0x0000D91EL, 0x0000D9F2L, 0x0000DAC4L,
- 0x0000DB94L, 0x0000DC62L, 0x0000DD2DL, 0x0000DDF7L,
- 0x0000DEBEL, 0x0000DF83L, 0x0000E046L, 0x0000E107L,
- 0x0000E1C6L, 0x0000E282L, 0x0000E33CL, 0x0000E3F4L,
- 0x0000E4AAL, 0x0000E55EL, 0x0000E610L, 0x0000E6BFL,
- 0x0000E76CL, 0x0000E817L, 0x0000E8BFL, 0x0000E966L,
- 0x0000EA0AL, 0x0000EAABL, 0x0000EB4BL, 0x0000EBE8L,
- 0x0000EC83L, 0x0000ED1CL, 0x0000EDB3L, 0x0000EE47L,
- 0x0000EED9L, 0x0000EF68L, 0x0000EFF5L, 0x0000F080L,
- 0x0000F109L, 0x0000F18FL, 0x0000F213L, 0x0000F295L,
- 0x0000F314L, 0x0000F391L, 0x0000F40CL, 0x0000F484L,
- 0x0000F4FAL, 0x0000F56EL, 0x0000F5DFL, 0x0000F64EL,
- 0x0000F6BAL, 0x0000F724L, 0x0000F78CL, 0x0000F7F1L,
- 0x0000F854L, 0x0000F8B4L, 0x0000F913L, 0x0000F96EL,
- 0x0000F9C8L, 0x0000FA1FL, 0x0000FA73L, 0x0000FAC5L,
- 0x0000FB15L, 0x0000FB62L, 0x0000FBADL, 0x0000FBF5L,
- 0x0000FC3BL, 0x0000FC7FL, 0x0000FCC0L, 0x0000FCFEL,
- 0x0000FD3BL, 0x0000FD74L, 0x0000FDACL, 0x0000FDE1L,
- 0x0000FE13L, 0x0000FE43L, 0x0000FE71L, 0x0000FE9CL,
- 0x0000FEC4L, 0x0000FEEBL, 0x0000FF0EL, 0x0000FF30L,
- 0x0000FF4EL, 0x0000FF6BL, 0x0000FF85L, 0x0000FF9CL,
- 0x0000FFB1L, 0x0000FFC4L, 0x0000FFD4L, 0x0000FFE1L,
- 0x0000FFECL, 0x0000FFF5L, 0x0000FFFBL, 0x0000FFFFL,
- 0x00010000L,
-};
-
-/* pre-computed tan table for 1st quadrant */
-static const CoglFixed tan_tbl[] =
-{
- 0x00000000L, 0x00000192L, 0x00000324L, 0x000004b7L,
- 0x00000649L, 0x000007dbL, 0x0000096eL, 0x00000b01L,
- 0x00000c94L, 0x00000e27L, 0x00000fbaL, 0x0000114eL,
- 0x000012e2L, 0x00001477L, 0x0000160cL, 0x000017a1L,
- 0x00001937L, 0x00001acdL, 0x00001c64L, 0x00001dfbL,
- 0x00001f93L, 0x0000212cL, 0x000022c5L, 0x0000245fL,
- 0x000025f9L, 0x00002795L, 0x00002931L, 0x00002aceL,
- 0x00002c6cL, 0x00002e0aL, 0x00002faaL, 0x0000314aL,
- 0x000032ecL, 0x0000348eL, 0x00003632L, 0x000037d7L,
- 0x0000397dL, 0x00003b24L, 0x00003cccL, 0x00003e75L,
- 0x00004020L, 0x000041ccL, 0x00004379L, 0x00004528L,
- 0x000046d8L, 0x0000488aL, 0x00004a3dL, 0x00004bf2L,
- 0x00004da8L, 0x00004f60L, 0x0000511aL, 0x000052d5L,
- 0x00005492L, 0x00005651L, 0x00005812L, 0x000059d5L,
- 0x00005b99L, 0x00005d60L, 0x00005f28L, 0x000060f3L,
- 0x000062c0L, 0x0000648fL, 0x00006660L, 0x00006834L,
- 0x00006a0aL, 0x00006be2L, 0x00006dbdL, 0x00006f9aL,
- 0x0000717aL, 0x0000735dL, 0x00007542L, 0x0000772aL,
- 0x00007914L, 0x00007b02L, 0x00007cf2L, 0x00007ee6L,
- 0x000080dcL, 0x000082d6L, 0x000084d2L, 0x000086d2L,
- 0x000088d6L, 0x00008adcL, 0x00008ce7L, 0x00008ef4L,
- 0x00009106L, 0x0000931bL, 0x00009534L, 0x00009750L,
- 0x00009971L, 0x00009b95L, 0x00009dbeL, 0x00009febL,
- 0x0000a21cL, 0x0000a452L, 0x0000a68cL, 0x0000a8caL,
- 0x0000ab0eL, 0x0000ad56L, 0x0000afa3L, 0x0000b1f5L,
- 0x0000b44cL, 0x0000b6a8L, 0x0000b909L, 0x0000bb70L,
- 0x0000bdddL, 0x0000c04fL, 0x0000c2c7L, 0x0000c545L,
- 0x0000c7c9L, 0x0000ca53L, 0x0000cce3L, 0x0000cf7aL,
- 0x0000d218L, 0x0000d4bcL, 0x0000d768L, 0x0000da1aL,
- 0x0000dcd4L, 0x0000df95L, 0x0000e25eL, 0x0000e52eL,
- 0x0000e806L, 0x0000eae7L, 0x0000edd0L, 0x0000f0c1L,
- 0x0000f3bbL, 0x0000f6bfL, 0x0000f9cbL, 0x0000fce1L,
- 0x00010000L, 0x00010329L, 0x0001065dL, 0x0001099aL,
- 0x00010ce3L, 0x00011036L, 0x00011394L, 0x000116feL,
- 0x00011a74L, 0x00011df6L, 0x00012184L, 0x0001251fL,
- 0x000128c6L, 0x00012c7cL, 0x0001303fL, 0x00013410L,
- 0x000137f0L, 0x00013bdfL, 0x00013fddL, 0x000143ebL,
- 0x00014809L, 0x00014c37L, 0x00015077L, 0x000154c9L,
- 0x0001592dL, 0x00015da4L, 0x0001622eL, 0x000166ccL,
- 0x00016b7eL, 0x00017045L, 0x00017523L, 0x00017a17L,
- 0x00017f22L, 0x00018444L, 0x00018980L, 0x00018ed5L,
- 0x00019445L, 0x000199cfL, 0x00019f76L, 0x0001a53aL,
- 0x0001ab1cL, 0x0001b11dL, 0x0001b73fL, 0x0001bd82L,
- 0x0001c3e7L, 0x0001ca71L, 0x0001d11fL, 0x0001d7f4L,
- 0x0001def1L, 0x0001e618L, 0x0001ed6aL, 0x0001f4e8L,
- 0x0001fc96L, 0x00020473L, 0x00020c84L, 0x000214c9L,
- 0x00021d44L, 0x000225f9L, 0x00022ee9L, 0x00023818L,
- 0x00024187L, 0x00024b3aL, 0x00025534L, 0x00025f78L,
- 0x00026a0aL, 0x000274edL, 0x00028026L, 0x00028bb8L,
- 0x000297a8L, 0x0002a3fbL, 0x0002b0b5L, 0x0002bdddL,
- 0x0002cb79L, 0x0002d98eL, 0x0002e823L, 0x0002f740L,
- 0x000306ecL, 0x00031730L, 0x00032816L, 0x000339a6L,
- 0x00034bebL, 0x00035ef2L, 0x000372c6L, 0x00038776L,
- 0x00039d11L, 0x0003b3a6L, 0x0003cb48L, 0x0003e40aL,
- 0x0003fe02L, 0x00041949L, 0x000435f7L, 0x0004542bL,
- 0x00047405L, 0x000495a9L, 0x0004b940L, 0x0004def6L,
- 0x00050700L, 0x00053196L, 0x00055ef9L, 0x00058f75L,
- 0x0005c35dL, 0x0005fb14L, 0x00063709L, 0x000677c0L,
- 0x0006bdd0L, 0x000709ecL, 0x00075ce6L, 0x0007b7bbL,
- 0x00081b98L, 0x000889e9L, 0x0009046eL, 0x00098d4dL,
- 0x000a2736L, 0x000ad593L, 0x000b9cc6L, 0x000c828aL,
- 0x000d8e82L, 0x000ecb1bL, 0x001046eaL, 0x00121703L,
- 0x00145b00L, 0x0017448dL, 0x001b2672L, 0x002095afL,
- 0x0028bc49L, 0x0036519aL, 0x00517bb6L, 0x00a2f8fdL,
- 0x46d3eab2L,
-};
-
-/* 257-value table of atan.
- *
- * atan_tbl[0] is atan(0.0) and atan_tbl[256] is atan(1).
- * The angles are radians in CoglFixed truncated to 16-bit (they're
- * all less than one)
- */
-static const guint16 atan_tbl[] =
-{
- 0x0000, 0x00FF, 0x01FF, 0x02FF, 0x03FF, 0x04FF, 0x05FF, 0x06FF,
- 0x07FF, 0x08FF, 0x09FE, 0x0AFE, 0x0BFD, 0x0CFD, 0x0DFC, 0x0EFB,
- 0x0FFA, 0x10F9, 0x11F8, 0x12F7, 0x13F5, 0x14F3, 0x15F2, 0x16F0,
- 0x17EE, 0x18EB, 0x19E9, 0x1AE6, 0x1BE3, 0x1CE0, 0x1DDD, 0x1ED9,
- 0x1FD5, 0x20D1, 0x21CD, 0x22C8, 0x23C3, 0x24BE, 0x25B9, 0x26B3,
- 0x27AD, 0x28A7, 0x29A1, 0x2A9A, 0x2B93, 0x2C8B, 0x2D83, 0x2E7B,
- 0x2F72, 0x306A, 0x3160, 0x3257, 0x334D, 0x3442, 0x3538, 0x362D,
- 0x3721, 0x3815, 0x3909, 0x39FC, 0x3AEF, 0x3BE2, 0x3CD4, 0x3DC5,
- 0x3EB6, 0x3FA7, 0x4097, 0x4187, 0x4277, 0x4365, 0x4454, 0x4542,
- 0x462F, 0x471C, 0x4809, 0x48F5, 0x49E0, 0x4ACB, 0x4BB6, 0x4CA0,
- 0x4D89, 0x4E72, 0x4F5B, 0x5043, 0x512A, 0x5211, 0x52F7, 0x53DD,
- 0x54C2, 0x55A7, 0x568B, 0x576F, 0x5852, 0x5934, 0x5A16, 0x5AF7,
- 0x5BD8, 0x5CB8, 0x5D98, 0x5E77, 0x5F55, 0x6033, 0x6110, 0x61ED,
- 0x62C9, 0x63A4, 0x647F, 0x6559, 0x6633, 0x670C, 0x67E4, 0x68BC,
- 0x6993, 0x6A6A, 0x6B40, 0x6C15, 0x6CEA, 0x6DBE, 0x6E91, 0x6F64,
- 0x7036, 0x7108, 0x71D9, 0x72A9, 0x7379, 0x7448, 0x7516, 0x75E4,
- 0x76B1, 0x777E, 0x7849, 0x7915, 0x79DF, 0x7AA9, 0x7B72, 0x7C3B,
- 0x7D03, 0x7DCA, 0x7E91, 0x7F57, 0x801C, 0x80E1, 0x81A5, 0x8269,
- 0x832B, 0x83EE, 0x84AF, 0x8570, 0x8630, 0x86F0, 0x87AF, 0x886D,
- 0x892A, 0x89E7, 0x8AA4, 0x8B5F, 0x8C1A, 0x8CD5, 0x8D8E, 0x8E47,
- 0x8F00, 0x8FB8, 0x906F, 0x9125, 0x91DB, 0x9290, 0x9345, 0x93F9,
- 0x94AC, 0x955F, 0x9611, 0x96C2, 0x9773, 0x9823, 0x98D2, 0x9981,
- 0x9A2F, 0x9ADD, 0x9B89, 0x9C36, 0x9CE1, 0x9D8C, 0x9E37, 0x9EE0,
- 0x9F89, 0xA032, 0xA0DA, 0xA181, 0xA228, 0xA2CE, 0xA373, 0xA418,
- 0xA4BC, 0xA560, 0xA602, 0xA6A5, 0xA746, 0xA7E8, 0xA888, 0xA928,
- 0xA9C7, 0xAA66, 0xAB04, 0xABA1, 0xAC3E, 0xACDB, 0xAD76, 0xAE11,
- 0xAEAC, 0xAF46, 0xAFDF, 0xB078, 0xB110, 0xB1A7, 0xB23E, 0xB2D5,
- 0xB36B, 0xB400, 0xB495, 0xB529, 0xB5BC, 0xB64F, 0xB6E2, 0xB773,
- 0xB805, 0xB895, 0xB926, 0xB9B5, 0xBA44, 0xBAD3, 0xBB61, 0xBBEE,
- 0xBC7B, 0xBD07, 0xBD93, 0xBE1E, 0xBEA9, 0xBF33, 0xBFBC, 0xC046,
- 0xC0CE, 0xC156, 0xC1DD, 0xC264, 0xC2EB, 0xC371, 0xC3F6, 0xC47B,
- 0xC4FF, 0xC583, 0xC606, 0xC689, 0xC70B, 0xC78D, 0xC80E, 0xC88F,
- 0xC90F
-};
-
-/* look up table for square root */
-static const CoglFixed sqrt_tbl[] =
-{
- 0x00000000L, 0x00010000L, 0x00016A0AL, 0x0001BB68L,
- 0x00020000L, 0x00023C6FL, 0x00027312L, 0x0002A550L,
- 0x0002D414L, 0x00030000L, 0x0003298BL, 0x0003510EL,
- 0x000376CFL, 0x00039B05L, 0x0003BDDDL, 0x0003DF7CL,
- 0x00040000L, 0x00041F84L, 0x00043E1EL, 0x00045BE1L,
- 0x000478DEL, 0x00049524L, 0x0004B0BFL, 0x0004CBBCL,
- 0x0004E624L, 0x00050000L, 0x00051959L, 0x00053237L,
- 0x00054AA0L, 0x0005629AL, 0x00057A2BL, 0x00059159L,
- 0x0005A828L, 0x0005BE9CL, 0x0005D4B9L, 0x0005EA84L,
- 0x00060000L, 0x00061530L, 0x00062A17L, 0x00063EB8L,
- 0x00065316L, 0x00066733L, 0x00067B12L, 0x00068EB4L,
- 0x0006A21DL, 0x0006B54DL, 0x0006C847L, 0x0006DB0CL,
- 0x0006ED9FL, 0x00070000L, 0x00071232L, 0x00072435L,
- 0x0007360BL, 0x000747B5L, 0x00075935L, 0x00076A8CL,
- 0x00077BBBL, 0x00078CC2L, 0x00079DA3L, 0x0007AE60L,
- 0x0007BEF8L, 0x0007CF6DL, 0x0007DFBFL, 0x0007EFF0L,
- 0x00080000L, 0x00080FF0L, 0x00081FC1L, 0x00082F73L,
- 0x00083F08L, 0x00084E7FL, 0x00085DDAL, 0x00086D18L,
- 0x00087C3BL, 0x00088B44L, 0x00089A32L, 0x0008A906L,
- 0x0008B7C2L, 0x0008C664L, 0x0008D4EEL, 0x0008E361L,
- 0x0008F1BCL, 0x00090000L, 0x00090E2EL, 0x00091C45L,
- 0x00092A47L, 0x00093834L, 0x0009460CL, 0x000953CFL,
- 0x0009617EL, 0x00096F19L, 0x00097CA1L, 0x00098A16L,
- 0x00099777L, 0x0009A4C6L, 0x0009B203L, 0x0009BF2EL,
- 0x0009CC47L, 0x0009D94FL, 0x0009E645L, 0x0009F32BL,
- 0x000A0000L, 0x000A0CC5L, 0x000A1979L, 0x000A261EL,
- 0x000A32B3L, 0x000A3F38L, 0x000A4BAEL, 0x000A5816L,
- 0x000A646EL, 0x000A70B8L, 0x000A7CF3L, 0x000A8921L,
- 0x000A9540L, 0x000AA151L, 0x000AAD55L, 0x000AB94BL,
- 0x000AC534L, 0x000AD110L, 0x000ADCDFL, 0x000AE8A1L,
- 0x000AF457L, 0x000B0000L, 0x000B0B9DL, 0x000B172DL,
- 0x000B22B2L, 0x000B2E2BL, 0x000B3998L, 0x000B44F9L,
- 0x000B504FL, 0x000B5B9AL, 0x000B66D9L, 0x000B720EL,
- 0x000B7D37L, 0x000B8856L, 0x000B936AL, 0x000B9E74L,
- 0x000BA973L, 0x000BB467L, 0x000BBF52L, 0x000BCA32L,
- 0x000BD508L, 0x000BDFD5L, 0x000BEA98L, 0x000BF551L,
- 0x000C0000L, 0x000C0AA6L, 0x000C1543L, 0x000C1FD6L,
- 0x000C2A60L, 0x000C34E1L, 0x000C3F59L, 0x000C49C8L,
- 0x000C542EL, 0x000C5E8CL, 0x000C68E0L, 0x000C732DL,
- 0x000C7D70L, 0x000C87ACL, 0x000C91DFL, 0x000C9C0AL,
- 0x000CA62CL, 0x000CB047L, 0x000CBA59L, 0x000CC464L,
- 0x000CCE66L, 0x000CD861L, 0x000CE254L, 0x000CEC40L,
- 0x000CF624L, 0x000D0000L, 0x000D09D5L, 0x000D13A2L,
- 0x000D1D69L, 0x000D2727L, 0x000D30DFL, 0x000D3A90L,
- 0x000D4439L, 0x000D4DDCL, 0x000D5777L, 0x000D610CL,
- 0x000D6A9AL, 0x000D7421L, 0x000D7DA1L, 0x000D871BL,
- 0x000D908EL, 0x000D99FAL, 0x000DA360L, 0x000DACBFL,
- 0x000DB618L, 0x000DBF6BL, 0x000DC8B7L, 0x000DD1FEL,
- 0x000DDB3DL, 0x000DE477L, 0x000DEDABL, 0x000DF6D8L,
- 0x000E0000L, 0x000E0922L, 0x000E123DL, 0x000E1B53L,
- 0x000E2463L, 0x000E2D6DL, 0x000E3672L, 0x000E3F70L,
- 0x000E4869L, 0x000E515DL, 0x000E5A4BL, 0x000E6333L,
- 0x000E6C16L, 0x000E74F3L, 0x000E7DCBL, 0x000E869DL,
- 0x000E8F6BL, 0x000E9832L, 0x000EA0F5L, 0x000EA9B2L,
- 0x000EB26BL, 0x000EBB1EL, 0x000EC3CBL, 0x000ECC74L,
- 0x000ED518L, 0x000EDDB7L, 0x000EE650L, 0x000EEEE5L,
- 0x000EF775L, 0x000F0000L, 0x000F0886L, 0x000F1107L,
- 0x000F1984L, 0x000F21FCL, 0x000F2A6FL, 0x000F32DDL,
- 0x000F3B47L, 0x000F43ACL, 0x000F4C0CL, 0x000F5468L,
- 0x000F5CBFL, 0x000F6512L, 0x000F6D60L, 0x000F75AAL,
- 0x000F7DEFL, 0x000F8630L, 0x000F8E6DL, 0x000F96A5L,
- 0x000F9ED9L, 0x000FA709L, 0x000FAF34L, 0x000FB75BL,
- 0x000FBF7EL, 0x000FC79DL, 0x000FCFB7L, 0x000FD7CEL,
- 0x000FDFE0L, 0x000FE7EEL, 0x000FEFF8L, 0x000FF7FEL,
- 0x00100000L,
-};
-
-/* the difference of the angle for two adjacent values in the
- * sin_tbl table, expressed as CoglFixed number
- */
-static const int sin_tbl_size = G_N_ELEMENTS (sin_tbl) - 1;
-
-static const double _magic = 68719476736.0 * 1.5;
-
-/* Where in the 64 bits of double is the mantissa.
- *
- * FIXME - this should go inside the configure.ac
- */
-#if (__FLOAT_WORD_ORDER == 1234)
-#define _COGL_MAN 0
-#elif (__FLOAT_WORD_ORDER == 4321)
-#define _COGL_MAN 1
-#else
-#define COGL_NO_FAST_CONVERSIONS
-#endif
-
-/*
- * cogl_double_to_fixed :
- * @value: value to be converted
- *
- * A fast conversion from double precision floating to fixed point
- *
- * Return value: Fixed point representation of the value
- */
-CoglFixed
-cogl_double_to_fixed (double val)
-{
-#ifdef COGL_NO_FAST_CONVERSIONS
- return (CoglFixed) (val * (double) COGL_FIXED_1);
-#else
- union {
- double d;
- unsigned int i[2];
- } dbl;
-
- dbl.d = val;
- dbl.d = dbl.d + _magic;
-
- return dbl.i[_COGL_MAN];
-#endif
-}
-
-/*
- * cogl_double_to_int :
- * @value: value to be converted
- *
- * A fast conversion from doulbe precision floatint point to int;
- * used this instead of casting double/float to int.
- *
- * Return value: Integer part of the double
- */
-int
-cogl_double_to_int (double val)
-{
-#ifdef COGL_NO_FAST_CONVERSIONS
- return (int) (val);
-#else
- union {
- double d;
- unsigned int i[2];
- } dbl;
-
- dbl.d = val;
- dbl.d = dbl.d + _magic;
-
- return ((int) dbl.i[_COGL_MAN]) >> 16;
-#endif
-}
-
-unsigned int
-cogl_double_to_uint (double val)
-{
-#ifdef COGL_NO_FAST_CONVERSIONS
- return (unsigned int)(val);
-#else
- union {
- double d;
- unsigned int i[2];
- } dbl;
-
- dbl.d = val;
- dbl.d = dbl.d + _magic;
-
- return (dbl.i[_COGL_MAN]) >> 16;
-#endif
-}
-
-#undef _COGL_MAN
-
-CoglFixed
-cogl_fixed_sin (CoglFixed angle)
-{
- int sign = 1, indx1, indx2;
- CoglFixed low, high;
- CoglFixed p1, p2;
- CoglFixed d1, d2;
-
- /* convert negative angle to positive + sign */
- if ((int) angle < 0)
- {
- sign = -sign;
- angle = -angle;
- }
-
- /* reduce to <0, 2*pi) */
- angle = angle % COGL_FIXED_2_PI;
-
- /* reduce to first quadrant and sign */
- if (angle > COGL_FIXED_PI)
- {
- sign = -sign;
-
- if (angle > COGL_FIXED_PI + COGL_FIXED_PI_2)
- {
- /* fourth qudrant */
- angle = COGL_FIXED_2_PI - angle;
- }
- else
- {
- /* third quadrant */
- angle -= COGL_FIXED_PI;
- }
- }
- else
- {
- if (angle > COGL_FIXED_PI_2)
- {
- /* second quadrant */
- angle = COGL_FIXED_PI - angle;
- }
- }
-
- /* Calculate indices of the two nearest values in our table
- * and return weighted average.
- *
- * We multiple first than divide to preserve precision. Since
- * angle is in the first quadrant, angle * SIN_TBL_SIZE (=256)
- * can't overflow.
- *
- * Handle the end of the table gracefully
- */
- indx1 = (angle * sin_tbl_size) / COGL_FIXED_PI_2;
-
- if (indx1 == sin_tbl_size)
- {
- indx2 = indx1;
- indx1 = indx2 - 1;
- }
- else
- {
- indx2 = indx1 + 1;
- }
-
- low = sin_tbl[indx1];
- high = sin_tbl[indx2];
-
- /* Again multiply the divide; no danger of overflow */
- p1 = (indx1 * COGL_FIXED_PI_2) / sin_tbl_size;
- p2 = (indx2 * COGL_FIXED_PI_2) / sin_tbl_size;
- d1 = angle - p1;
- d2 = p2 - angle;
-
- angle = ((low * d2 + high * d1) / (p2 - p1));
-
- if (sign < 0)
- angle = -angle;
-
- return angle;
-}
-
-CoglFixed
-cogl_angle_sin (CoglAngle angle)
-{
- int sign = 1;
- CoglFixed result;
-
- /* reduce negative angle to positive + sign */
- if (angle < 0)
- {
- sign = -sign;
- angle = -angle;
- }
-
- /* reduce to <0, 2*pi) */
- angle &= 0x3ff;
-
- /* reduce to first quadrant and sign */
- if (angle > 512)
- {
- sign = -sign;
-
- if (angle > 768)
- {
- /* fourth qudrant */
- angle = 1024 - angle;
- }
- else
- {
- /* third quadrant */
- angle -= 512;
- }
- }
- else
- {
- if (angle > 256)
- {
- /* second quadrant */
- angle = 512 - angle;
- }
- }
-
- result = sin_tbl[angle];
-
- if (sign < 0)
- result = -result;
-
- return result;
-}
-
-CoglFixed
-cogl_fixed_tan (CoglFixed angle)
-{
- return cogl_angle_tan (COGL_ANGLE_FROM_DEGX (angle));
-}
-
-CoglFixed
-cogl_angle_tan (CoglAngle angle)
-{
- int sign = 1;
- CoglFixed result;
-
- /* reduce negative angle to positive + sign */
- if (angle < 0)
- {
- sign = -sign;
- angle = -angle;
- }
-
- /* reduce to <0, pi) */
- angle &= 0x1ff;
-
- /* reduce to first quadrant and sign */
- if (angle > 256)
- {
- sign = -sign;
- angle = 512 - angle;
- }
-
- result = tan_tbl[angle];
-
- if (sign < 0)
- result = -result;
-
- return result;
-}
-
-CoglFixed
-cogl_fixed_atan (CoglFixed x)
-{
- gboolean negative = FALSE;
- CoglFixed angle;
-
- if (x < 0)
- {
- negative = TRUE;
- x = -x;
- }
-
- if (x > COGL_FIXED_1)
- {
- /* if x > 1 then atan(x) = pi/2 - atan(1/x) */
- angle = COGL_FIXED_PI / 2
- - atan_tbl[COGL_FIXED_DIV (COGL_FIXED_1, x) >> 8];
- }
- else
- angle = atan_tbl[x >> 8];
-
- return negative ? -angle : angle;
-}
-
-CoglFixed
-cogl_fixed_atan2 (CoglFixed y, CoglFixed x)
-{
- CoglFixed angle;
-
- if (x == 0)
- angle = y >= 0 ? COGL_FIXED_PI_2 : -COGL_FIXED_PI_2;
- else
- {
- angle = cogl_fixed_atan (COGL_FIXED_DIV (y, x));
-
- if (x < 0)
- angle += y >= 0 ? COGL_FIXED_PI : -COGL_FIXED_PI;
- }
-
- return angle;
-}
-
-CoglFixed
-cogl_fixed_sqrt (CoglFixed x)
-{
- /* The idea for this comes from the Alegro library, exploiting the
- * fact that,
- * sqrt (x) = sqrt (x/d) * sqrt (d);
- *
- * For d == 2^(n):
- *
- * sqrt (x) = sqrt (x/2^(2n)) * 2^n
- *
- * By locating suitable n for given x such that x >> 2n is in <0,255>
- * we can use a LUT of precomputed values.
- *
- * This algorithm provides both good performance and precision;
- * on ARM this function is about 5 times faster than c-lib sqrt,
- * whilst producing errors < 1%.
- */
- int t = 0;
- int sh = 0;
- unsigned int mask = 0x40000000;
- unsigned fract = x & 0x0000ffff;
- unsigned int d1, d2;
- CoglFixed v1, v2;
-
- if (x <= 0)
- return 0;
-
- if (x > COGL_FIXED_255 || x < COGL_FIXED_1)
- {
- /*
- * Find the highest bit set
- */
-#if __arm__
- /* This actually requires at least arm v5, but gcc does not seem
- * to set the architecture defines correctly, and it is I think
- * very unlikely that anyone will want to use clutter on anything
- * less than v5.
- */
- int bit;
- __asm__ ("clz %0, %1\n"
- "rsb %0, %0, #31\n"
- :"=r"(bit)
- :"r" (x));
-
- /* make even (2n) */
- bit &= 0xfffffffe;
-#else
- /* TODO -- add i386 branch using bshr
- *
- * NB: it's been said that the bshr instruction is poorly implemented
- * and that it is possible to write a faster code in C using binary
- * search -- at some point we should explore this
- */
- int bit = 30;
- while (bit >= 0)
- {
- if (x & mask)
- break;
-
- mask = (mask >> 1 | mask >> 2);
- bit -= 2;
- }
-#endif
-
- /* now bit indicates the highest bit set; there are two scenarios
- *
- * 1) bit < 23: Our number is smaller so we shift it left to maximase
- * precision (< 16 really, since <16,23> never goes
- * through here.
- *
- * 2) bit > 23: our number is above the table, so we shift right
- */
-
- sh = ((bit - 22) >> 1);
- if (bit >= 8)
- t = (x >> (16 - 22 + bit));
- else
- t = (x << (22 - 16 - bit));
- }
- else
- {
- t = COGL_FIXED_TO_INT (x);
- }
-
- /* Do a weighted average of the two nearest values */
- v1 = sqrt_tbl[t];
- v2 = sqrt_tbl[t+1];
-
- /*
- * 12 is fairly arbitrary -- we want integer that is not too big to cost
- * us precision
- */
- d1 = (unsigned)(fract) >> 12;
- d2 = ((unsigned)COGL_FIXED_1 >> 12) - d1;
-
- x = ((v1*d2) + (v2*d1))/(COGL_FIXED_1 >> 12);
-
- if (sh > 0)
- x = x << sh;
- else if (sh < 0)
- x = x >> -sh;
-
- return x;
-}
-
-/**
- * cogl_sqrti:
- * @x: integer value
- *
- * Very fast fixed point implementation of square root for integers.
- *
- * This function is at least 6x faster than clib sqrt() on x86, and (this is
- * not a typo!) about 500x faster on ARM without FPU. It's error is < 5%
- * for arguments < %COGL_SQRTI_ARG_5_PERCENT and < 10% for arguments <
- * %COGL_SQRTI_ARG_10_PERCENT. The maximum argument that can be passed to
- * this function is COGL_SQRTI_ARG_MAX.
- *
- * Return value: integer square root.
- *
- *
- * Since: 0.2
- */
-int
-cogl_sqrti (int number)
-{
-#if defined __SSE2__
- /* The GCC built-in with SSE2 (sqrtsd) is up to twice as fast as
- * the pure integer code below. It is also more accurate.
- */
- return __builtin_sqrt (number);
-#else
- /* This is a fixed point implementation of the Quake III sqrt algorithm,
- * described, for example, at
- * http://www.codemaestro.com/reviews/review00000105.html
- *
- * While the original QIII is extremely fast, the use of floating division
- * and multiplication makes it perform very on arm processors without FPU.
- *
- * The key to successfully replacing the floating point operations with
- * fixed point is in the choice of the fixed point format. The QIII
- * algorithm does not calculate the square root, but its reciprocal ('y'
- * below), which is only at the end turned to the inverse value. In order
- * for the algorithm to produce satisfactory results, the reciprocal value
- * must be represented with sufficient precission; the 16.16 we use
- * elsewhere in clutter is not good enough, and 10.22 is used instead.
- */
- CoglFixed x;
- guint32 y_1; /* 10.22 fixed point */
- guint32 f = 0x600000; /* '1.5' as 10.22 fixed */
-
- union
- {
- float f;
- guint32 i;
- } flt, flt2;
-
- flt.f = number;
-
- x = COGL_FIXED_FROM_INT (number) / 2;
-
- /* The QIII initial estimate */
- flt.i = 0x5f3759df - ( flt.i >> 1 );
-
- /* Now, we convert the float to 10.22 fixed. We exploit the mechanism
- * described at http://www.d6.com/users/checker/pdfs/gdmfp.pdf.
- *
- * We want 22 bit fraction; a single precission float uses 23 bit
- * mantisa, so we only need to add 2^(23-22) (no need for the 1.5
- * multiplier as we are only dealing with positive numbers).
- *
- * Note: we have to use two separate variables here -- for some reason,
- * if we try to use just the flt variable, gcc on ARM optimises the whole
- * addition out, and it all goes pear shape, since without it, the bits
- * in the float will not be correctly aligned.
- */
- flt2.f = flt.f + 2.0;
- flt2.i &= 0x7FFFFF;
-
- /* Now we correct the estimate */
- y_1 = (flt2.i >> 11) * (flt2.i >> 11);
- y_1 = (y_1 >> 8) * (x >> 8);
-
- y_1 = f - y_1;
- flt2.i = (flt2.i >> 11) * (y_1 >> 11);
-
- /* If the original argument is less than 342, we do another
- * iteration to improve precission (for arguments >= 342, the single
- * iteration produces generally better results).
- */
- if (x < 171)
- {
- y_1 = (flt2.i >> 11) * (flt2.i >> 11);
- y_1 = (y_1 >> 8) * (x >> 8);
-
- y_1 = f - y_1;
- flt2.i = (flt2.i >> 11) * (y_1 >> 11);
- }
-
- /* Invert, round and convert from 10.22 to an integer
- * 0x1e3c68 is a magical rounding constant that produces slightly
- * better results than 0x200000.
- */
- return (number * flt2.i + 0x1e3c68) >> 22;
-#endif
-}
-
-CoglFixed
-cogl_fixed_mul (CoglFixed a,
- CoglFixed b)
-{
-#ifdef __arm__
- /* This provides about 12% speedeup on the gcc -O2 optimised
- * C version
- *
- * Based on code found in the following thread:
- * http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2006-August/014405.html
- */
- int res_low, res_hi;
-
- __asm__ ("smull %0, %1, %2, %3 \n"
- "mov %0, %0, lsr %4 \n"
- "add %1, %0, %1, lsl %5 \n"
- : "=r"(res_hi), "=r"(res_low) \
- : "r"(a), "r"(b), "i"(COGL_FIXED_Q), "i"(32 - COGL_FIXED_Q));
-
- return (CoglFixed) res_low;
-#else
- gint64 r = (gint64) a * (gint64) b;
-
- return (CoglFixed) (r >> COGL_FIXED_Q);
-#endif
-}
-
-CoglFixed
-cogl_fixed_div (CoglFixed a,
- CoglFixed b)
-{
- return (CoglFixed) ((((gint64) a) << COGL_FIXED_Q) / b);
-}
-
-CoglFixed
-cogl_fixed_mul_div (CoglFixed a,
- CoglFixed b,
- CoglFixed c)
-{
- CoglFixed ab = cogl_fixed_mul (a, b);
- CoglFixed quo = cogl_fixed_div (ab, c);
-
- return quo;
-}
-
-/*
- * The log2x() and pow2x() functions
- *
- * The implementation of the log2x() and pow2x() exploits the
- * well-documented fact that the exponent part of IEEE floating
- * number provides a good estimate of log2 of that number, while
- * the mantissa serves as a good error-correction.
- *
- * The implementation here uses a quadratic error correction as
- * described by Ian Stephenson at:
- * http://www.dctsystems.co.uk/Software/power.html.
- */
-
-CoglFixed
-cogl_fixed_log2 (unsigned int x)
-{
- /* Note: we could easily have a version for CoglFixed x, but the int
- * precision is enough for the current purposes.
- */
- union
- {
- float f;
- CoglFixed i;
- } flt;
-
- CoglFixed magic = 0x58bb;
- CoglFixed y;
-
- /*
- * Convert x to float, then extract exponent.
- *
- * We want the result to be 16.16 fixed, so we shift (23-16) bits only
- */
- flt.f = x;
- flt.i >>= 7;
- flt.i -= COGL_FIXED_FROM_INT (127);
-
- y = COGL_FIXED_FRACTION (flt.i);
-
- y = COGL_FIXED_MUL ((y - COGL_FIXED_MUL (y, y)), magic);
-
- return flt.i + y;
-}
-
-unsigned int
-cogl_fixed_pow2 (CoglFixed x)
-{
- /* Note: we could easily have a version that produces CoglFixed result,
- * but the range would be limited to x < 15, and the int precision
- * is enough for the current purposes.
- */
-
- union
- {
- float f;
- guint32 i;
- } flt;
-
- CoglFixed magic = 0x56f7;
- CoglFixed y;
-
- flt.i = x;
-
- /*
- * Reverse of the log2x function -- convert the fixed value to a suitable
- * floating point exponent, and mantisa adjusted with quadratic error
- * correction y.
- */
- y = COGL_FIXED_FRACTION (x);
- y = COGL_FIXED_MUL ((y - COGL_FIXED_MUL (y, y)), magic);
-
- /* Shift the exponent into it's position in the floating point
- * representation; as our number is not int but 16.16 fixed, shift only
- * by (23 - 16)
- */
- flt.i += (COGL_FIXED_FROM_INT (127) - y);
- flt.i <<= 7;
-
- return COGL_FLOAT_TO_UINT (flt.f);
-}
-
-unsigned int
-cogl_fixed_pow (unsigned int x,
- CoglFixed y)
-{
- return cogl_fixed_pow2 (COGL_FIXED_MUL (y, cogl_fixed_log2 (x)));
-}
-
-CoglFixed
-cogl_angle_cos (CoglAngle angle)
-{
- CoglAngle a = angle + 256;
-
- return cogl_angle_sin (a);
-}
-
-CoglFixed
-cogl_fixed_cos (CoglFixed angle)
-{
- CoglFixed a = angle + COGL_FIXED_PI_2;
-
- return cogl_fixed_sin (a);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_FIXED_H__
-#define __COGL_FIXED_H__
-
-#include <cogl/cogl-types.h>
-
-/**
- * SECTION:cogl-fixed
- * @short_description: Fixed Point API
- *
- * COGL has a fixed point API targeted at platforms without a floating
- * point unit, such as embedded devices. On such platforms this API should
- * be preferred to the floating point one as it does not trigger the slow
- * path of software emulation, relying on integer math for fixed-to-floating
- * and floating-to-fixed notations conversion.
- *
- * It is not recommened for use on platforms with a floating point unit
- * (e.g. desktop systems), nor for use in language bindings.
- *
- * Basic rules of Fixed Point arithmethic:
- * <itemizedlist>
- * <listitem>
- * <para>Two fixed point numbers can be directly added, subtracted and
- * have their modulus taken.</para>
- * </listitem>
- * <listitem>
- * <para>To add other numerical type to a fixed point number it has to
- * be first converted to fixed point.</para>
- * </listitem>
- * <listitem>
- * <para>A fixed point number can be directly multiplied or divided by
- * an integer.</para>
- * </listitem>
- * <listitem>
- * <para>Two fixed point numbers can only be multiplied and divided by
- * the provided %COGL_FIXED_MUL and %COGL_FIXED_DIV macros.</para>
- * </listitem>
- * </itemizedlist>
- *
- * The fixed point API is available since COGL 1.0.
- */
-
-G_BEGIN_DECLS
-
-/**
- * COGL_FIXED_BITS:
- *
- * Evaluates to the number of bits used by the #CoglFixed type.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_BITS (32)
-
-/**
- * COGL_FIXED_Q:
- *
- * Evaluates to the number of bits used for the non-integer part
- * of the #CoglFixed type.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_Q (COGL_FIXED_BITS - 16)
-
-/**
- * COGL_FIXED_1:
- *
- * The number 1 expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_1 (1 << COGL_FIXED_Q)
-
-/**
- * COGL_FIXED_0_5:
- *
- * The number 0.5 expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_0_5 (32768)
-
-/**
- * COGL_FIXED_EPSILON:
- *
- * A very small number expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_EPSILON (1)
-
-/**
- * COGL_FIXED_MAX:
- *
- * The biggest number representable using #CoglFixed
- *
- * Since: 1.0
- */
-#define COGL_FIXED_MAX (0x7fffffff)
-
-/**
- * COGL_FIXED_MIN:
- *
- * The smallest number representable using #CoglFixed
- *
- * Since: 1.0
- */
-#define COGL_FIXED_MIN (0x80000000)
-
-/**
- * COGL_FIXED_PI:
- *
- * The number pi, expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_PI (0x0003243f)
-
-/**
- * COGL_FIXED_2_PI:
- *
- * Two times pi, expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_2_PI (0x0006487f)
-
-/**
- * COGL_FIXED_PI_2:
- *
- * Half pi, expressed as a #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_PI_2 (0x00019220)
-
-/**
- * COGL_FIXED_PI_4:
- *
- * pi / 4, expressed as #CoglFixed number.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_PI_4 (0x0000c910)
-
-/**
- * COGL_FIXED_360:
- *
- * Evaluates to the number 360 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_360 (COGL_FIXED_FROM_INT (360))
-
-/**
- * COGL_FIXED_270:
- *
- * Evaluates to the number 270 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_270 (COGL_FIXED_FROM_INT (270))
-
-/**
- * COGL_FIXED_255:
- *
- * Evaluates to the number 255 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_255 (COGL_FIXED_FROM_INT (255))
-
-/**
- * COGL_FIXED_240:
- *
- * Evaluates to the number 240 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_240 (COGL_FIXED_FROM_INT (240))
-
-/**
- * COGL_FIXED_180:
- *
- * Evaluates to the number 180 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_180 (COGL_FIXED_FROM_INT (180))
-
-/**
- * COGL_FIXED_120:
- *
- * Evaluates to the number 120 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_120 (COGL_FIXED_FROM_INT (120))
-
-/**
- * COGL_FIXED_90:
- *
- * Evaluates to the number 90 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_90 (COGL_FIXED_FROM_INT (90))
-
-/**
- * COGL_FIXED_60:
- *
- * Evaluates to the number 60 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_60 (COGL_FIXED_FROM_INT (60))
-
-/**
- * COGL_FIXED_45:
- *
- * Evaluates to the number 45 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_45 (COGL_FIXED_FROM_INT (45))
-
-/**
- * COGL_FIXED_30:
- *
- * Evaluates to the number 30 in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_30 (COGL_FIXED_FROM_INT (30))
-
-/**
- * COGL_RADIANS_TO_DEGREES:
- *
- * Evaluates to 180 / pi in fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_RADIANS_TO_DEGREES (0x394bb8)
-
-/*
- * conversion macros
- */
-
-/**
- * COGL_FIXED_FROM_FLOAT:
- * @x: a floating point number
- *
- * Converts @x from a floating point to a fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FROM_FLOAT(x) ((float) cogl_double_to_fixed (x))
-
-/**
- * COGL_FIXED_TO_FLOAT:
- * @x: a #CoglFixed number
- *
- * Converts @x from a fixed point to a floating point notation, in
- * single precision.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_TO_FLOAT(x) ((float) ((int)(x) / 65536.0))
-
-/**
- * COGL_FIXED_FROM_DOUBLE:
- * @x: a floating point number
- *
- * Converts @x from a double precision, floating point to a fixed
- * point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FROM_DOUBLE(x) (cogl_double_to_fixed (x))
-
-/**
- * COGL_FIXED_TO_DOUBLE:
- * @x: a #CoglFixed number
- *
- * Converts @x from a fixed point to a floating point notation, in
- * double precision.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_TO_DOUBLE(x) ((double) ((int)(x) / 65536.0))
-
-/**
- * COGL_FIXED_FROM_INT:
- * @x: an integer number
- *
- * Converts @x from an integer to a fixed point notation.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FROM_INT(x) ((x) << COGL_FIXED_Q)
-
-/**
- * COGL_FIXED_TO_INT:
- * @x: a #CoglFixed number
- *
- * Converts @x from a fixed point notation to an integer, dropping
- * the fractional part without rounding.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_TO_INT(x) ((x) >> COGL_FIXED_Q)
-
-/**
- * COGL_FLOAT_TO_INT:
- * @x: a floatint point number
- *
- * Converts @x from a floating point notation to a signed integer.
- *
- * Since: 1.0
- */
-#define COGL_FLOAT_TO_INT(x) (cogl_double_to_int ((x)))
-
-/**
- * COGL_FLOAT_TO_UINT:
- * @x: a floatint point number
- *
- * Converts @x from a floating point notation to an unsigned integer.
- *
- * Since: 1.0
- */
-#define COGL_FLOAT_TO_UINT(x) (cogl_double_to_uint ((x)))
-
-/*
- * fixed point math functions
- */
-
-/**
- * COGL_FIXED_FRACTION:
- * @x: a #CoglFixed number
- *
- * Retrieves the fractionary part of @x.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FRACTION(x) ((x) & ((1 << COGL_FIXED_Q) - 1))
-
-/**
- * COGL_FIXED_FLOOR:
- * @x: a #CoglFixed number
- *
- * Rounds down a fixed point number to the previous integer.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FLOOR(x) (((x) >= 0) ? ((x) >> COGL_FIXED_Q) \
- : ~((~(x)) >> COGL_FIXED_Q))
-
-/**
- * COGL_FIXED_CEIL:
- * @x: a #CoglFixed number
- *
- * Rounds up a fixed point number to the next integer.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_CEIL(x) (COGL_FIXED_FLOOR ((x) + 0xffff))
-
-/**
- * COGL_FIXED_MUL:
- * @a: a #CoglFixed number
- * @b: a #CoglFixed number
- *
- * Computes (a * b).
- *
- * Since: 1.0
- */
-#define COGL_FIXED_MUL(a,b) (cogl_fixed_mul ((a), (b)))
-
-/**
- * COGL_FIXED_DIV:
- * @a: a #CoglFixed number
- * @b: a #CoglFixed number
- *
- * Computes (a / b).
- *
- * Since: 1.0
- */
-#define COGL_FIXED_DIV(a,b) (cogl_fixed_div ((a), (b)))
-
-/**
- * COGL_FIXED_MUL_DIV:
- * @a: a #CoglFixed number
- * @b: a #CoglFixed number
- * @c: a #CoglFixed number
- *
- * Computes ((a * b) / c). It is logically equivalent to:
- *
- * |[
- * res = COGL_FIXED_DIV (COGL_FIXED_MUL (a, b), c);
- * ]|
- *
- * But it is shorter to type.
- *
- * Since: 1.0
- */
-#define COGL_FIXED_MUL_DIV(a,b,c) (cogl_fixed_mul_div ((a), (b), (c)))
-
-/**
- * COGL_FIXED_FAST_MUL:
- * @a: a #CoglFixed number
- * @b: a #CoglFixed number
- *
- * Fast version of %COGL_FIXED_MUL, implemented as a macro.
- *
- * <note>This macro might lose precision. If the precision of the result
- * is important use %COGL_FIXED_MUL instead.</note>
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FAST_MUL(a,b) ((a) >> 8) * ((b) >> 8)
-
-/**
- * COGL_FIXED_FAST_DIV:
- * @a: a #CoglFixed number
- * @b: a #CoglFixed number
- *
- * Fast version of %COGL_FIXED_DIV, implemented as a macro.
- *
- * <note>This macro might lose precision. If the precision of the result
- * is important use %COGL_FIXED_DIV instead.</note>
- *
- * Since: 1.0
- */
-#define COGL_FIXED_FAST_DIV(a,b) ((((a) << 8) / (b)) << 8)
-
-/**
- * cogl_fixed_sin:
- * @angle: a #CoglFixed number
- *
- * Computes the sine of @angle.
- *
- * Return value: the sine of the passed angle, in fixed point notation
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_sin (CoglFixed angle);
-
-/**
- * cogl_fixed_tan:
- * @angle: a #CoglFixed number
- *
- * Computes the tangent of @angle.
- *
- * Return value: the tangent of the passed angle, in fixed point notation
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_tan (CoglFixed angle);
-
-/**
- * cogl_fixed_cos:
- * @angle: a #CoglFixed number
- *
- * Computes the cosine of @angle.
- *
- * Return value: the cosine of the passed angle, in fixed point notation
- *
- * Since: 1.0
- */
-CoglFixed cogl_fixed_cos (CoglFixed angle);
-
-/**
- * cogl_fixed_atan:
- * @a: a #CoglFixed number
- *
- * Computes the arc tangent of @a.
- *
- * Return value: the arc tangent of the passed value, in fixed point notation
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_atan (CoglFixed a);
-
-/**
- * cogl_fixed_atan2:
- * @a: the numerator as a #CoglFixed number
- * @b: the denominator as a #CoglFixed number
- *
- * Computes the arc tangent of @a / @b but uses the sign of both
- * arguments to return the angle in right quadrant.
- *
- * Return value: the arc tangent of the passed fraction, in fixed point
- * notation
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_atan2 (CoglFixed a,
- CoglFixed b);
-
-/*< public >*/
-
-/* Fixed point math routines */
-G_INLINE_FUNC CoglFixed
-cogl_fixed_mul (CoglFixed a,
- CoglFixed b);
-
-G_INLINE_FUNC CoglFixed
-cogl_fixed_div (CoglFixed a,
- CoglFixed b);
-
-G_INLINE_FUNC CoglFixed
-cogl_fixed_mul_div (CoglFixed a,
- CoglFixed b,
- CoglFixed c);
-
-/**
- * COGL_SQRTI_ARG_MAX:
- *
- * Maximum argument that can be passed to cogl_sqrti() function.
- *
- * Since: 1.0
- */
-#ifndef __SSE2__
-#define COGL_SQRTI_ARG_MAX 0x3fffff
-#else
-#define COGL_SQRTI_ARG_MAX INT_MAX
-#endif
-
-/**
- * COGL_SQRTI_ARG_5_PERCENT:
- *
- * Maximum argument that can be passed to cogl_sqrti() for which the
- * resulting error is < 5%
- *
- * Since: 1.0
- */
-#ifndef __SSE2__
-#define COGL_SQRTI_ARG_5_PERCENT 210
-#else
-#define COGL_SQRTI_ARG_5_PERCENT INT_MAX
-#endif
-
-/**
- * COGL_SQRTI_ARG_10_PERCENT:
- *
- * Maximum argument that can be passed to cogl_sqrti() for which the
- * resulting error is < 10%
- *
- * Since: 1.0
- */
-#ifndef __SSE2__
-#define COGL_SQRTI_ARG_10_PERCENT 5590
-#else
-#define COGL_SQRTI_ARG_10_PERCENT INT_MAX
-#endif
-
-/**
- * cogl_fixed_sqrt:
- * @x: a #CoglFixed number
- *
- * Computes the square root of @x.
- *
- * Return value: the square root of the passed value, in floating point
- * notation
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_sqrt (CoglFixed x);
-
-/**
- * cogl_fixed_log2:
- * @x: value to calculate base 2 logarithm from
- *
- * Calculates base 2 logarithm.
- *
- * This function is some 2.5 times faster on x86, and over 12 times faster on
- * fpu-less arm, than using libc log().
- *
- * Return value: base 2 logarithm.
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_fixed_log2 (unsigned int x);
-
-/**
- * cogl_fixed_pow2:
- * @x: a #CoglFixed number
- *
- * Calculates 2 to the @x power.
- *
- * This function is around 11 times faster on x86, and around 22 times faster
- * on fpu-less arm than libc pow(2, x).
- *
- * Return value: the power of 2 to the passed value
- *
- * Since: 1.0
- */
-unsigned int
-cogl_fixed_pow2 (CoglFixed x);
-
-/**
- * cogl_fixed_pow:
- * @x: base
- * @y: #CoglFixed exponent
- *
- * Calculates @x to the @y power.
- *
- * Return value: the power of @x to the @y
- *
- * Since: 1.0
- */
-unsigned int
-cogl_fixed_pow (unsigned int x,
- CoglFixed y);
-
-/**
- * cogl_sqrti:
- * @x: integer value
- *
- * Very fast fixed point implementation of square root for integers.
- *
- * This function is at least 6x faster than clib sqrt() on x86, and (this is
- * not a typo!) about 500x faster on ARM without FPU. It's error is less than
- * 5% for arguments smaller than %COGL_SQRTI_ARG_5_PERCENT and less than 10%
- * for narguments smaller than %COGL_SQRTI_ARG_10_PERCENT. The maximum
- * argument that can be passed to this function is %COGL_SQRTI_ARG_MAX.
- *
- * Return value: integer square root.
- *
- * Since: 1.0
- */
-int
-cogl_sqrti (int x);
-
-/**
- * COGL_ANGLE_FROM_DEG:
- * @x: an angle in degrees in floating point notation
- *
- * Converts an angle in degrees into a #CoglAngle.
- *
- * Since: 1.0
- */
-#define COGL_ANGLE_FROM_DEG(x) (COGL_FLOAT_TO_INT (((float)(x) * 1024.0f) / 360.0f))
-
-/**
- * COGL_ANGLE_TO_DEG:
- * @x: a #CoglAngle
- *
- * Converts a #CoglAngle into an angle in degrees, using floatint point
- * notation.
- *
- * Since: 1.0
- */
-#define COGL_ANGLE_TO_DEG(x) (((float)(x) * 360.0) / 1024.0)
-
-/**
- * COGL_ANGLE_FROM_DEGX:
- * @x: an angle in degrees in fixed point notation
- *
- * Converts an angle in degrees into a #CoglAngle.
- *
- * Since: 1.0
- */
-#define COGL_ANGLE_FROM_DEGX(x) (COGL_FIXED_TO_INT ((((x) / 360) * 1024) + COGL_FIXED_0_5))
-
-/**
- * COGL_ANGLE_TO_DEGX:
- * @x: a #CoglAngle
- *
- * Converts a #CoglAngle into an angle in degrees, using fixed point notation
- *
- * Since: 1.0
- */
-#define COGL_ANGLE_TO_DEGX(x) (COGL_FIXED_FROM_INT ((x) * 45) / 128)
-
-/**
- * cogl_angle_sin:
- * @angle: an angle expressed using #CoglAngle
- *
- * Computes the sine of @angle
- *
- * Return value: the sine of the passed angle
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_angle_sin (CoglAngle angle);
-
-/**
- * cogl_angle_tan:
- * @angle: an angle expressed using #CoglAngle
- *
- * Computes the tangent of @angle
- *
- * Return value: the tangent of the passed angle
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_angle_tan (CoglAngle angle);
-
-/**
- * cogl_angle_cos:
- * @angle: an angle expressed using #CoglAngle
- *
- * Computes the cosine of @angle
- *
- * Return value: the cosine of the passed angle
- *
- * Since: 1.0
- */
-CoglFixed
-cogl_angle_cos (CoglAngle angle);
-
-/*< private >*/
-
-#if defined (G_CAN_INLINE)
-G_INLINE_FUNC CoglFixed
-cogl_fixed_mul (CoglFixed a,
- CoglFixed b)
-{
-# ifdef __arm__
- int res_low, res_hi;
-
- __asm__ ("smull %0, %1, %2, %3 \n"
- "mov %0, %0, lsr %4 \n"
- "add %1, %0, %1, lsl %5 \n"
- : "=r"(res_hi), "=r"(res_low)\
- : "r"(a), "r"(b), "i"(COGL_FIXED_Q), "i"(32 - COGL_FIXED_Q));
-
- return (CoglFixed) res_low;
-# else
- long long r = (long long) a * (long long) b;
-
- return (unsigned int)(r >> COGL_FIXED_Q);
-# endif
-}
-#endif
-
-#if defined (G_CAN_INLINE)
-G_INLINE_FUNC CoglFixed
-cogl_fixed_div (CoglFixed a,
- CoglFixed b)
-{
- return (CoglFixed) ((((gint64) a) << COGL_FIXED_Q) / b);
-}
-#endif
-
-#if defined(G_CAN_INLINE)
-G_INLINE_FUNC CoglFixed
-cogl_fixed_mul_div (CoglFixed a,
- CoglFixed b,
- CoglFixed c)
-{
- CoglFixed ab = cogl_fixed_mul (a, b);
- CoglFixed quo = cogl_fixed_div (ab, c);
-
- return quo;
-}
-#endif
-
-CoglFixed
-cogl_double_to_fixed (double value);
-
-int
-cogl_double_to_int (double value);
-
-unsigned int
-cogl_double_to_uint (double value);
-
-G_END_DECLS
-
-#endif /* __COGL_FIXED_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_FLAGS_H
-#define __COGL_FLAGS_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/* These are macros used to implement a fixed-size array of bits. This
- should be used instead of CoglBitmask when the maximum bit number
- that will be set is known at compile time, for example when setting
- for recording a set of known available features */
-
-/* The bits are stored in an array of unsigned ints. It would probably
- make sense to use unsigned long instead because then on 64-bit
- systems where it can handle 64-bits just as easily and it can test
- more bits. However GDebugKey uses a guint for the mask and we need
- to fit the masks into this */
-
-/* To use these macros, you would typically have an enum defining the
- available bits with an extra last enum to define the maximum
- value. Then to store the flags you would declare an array of
- unsigned ints sized using COGL_FLAGS_N_INTS_FOR_SIZE, eg:
-
- typedef enum { FEATURE_A, FEATURE_B, FEATURE_C, N_FEATURES } Features;
-
- unsigned int feature_flags[COGL_FLAGS_N_INTS_FOR_SIZE (N_FEATURES)];
-*/
-
-#define COGL_FLAGS_N_INTS_FOR_SIZE(size) \
- (((size) + \
- (sizeof (unsigned int) * 8 - 1)) \
- / (sizeof (unsigned int) * 8))
-
-/* @flag is expected to be constant so these should result in a
- constant expression. This means that setting a flag is equivalent
- to just setting in a bit in a global variable at a known
- location */
-#define COGL_FLAGS_GET_INDEX(flag) \
- ((flag) / (sizeof (unsigned int) * 8))
-#define COGL_FLAGS_GET_MASK(flag) \
- (1U << ((unsigned int) (flag) & \
- (sizeof (unsigned int) * 8 - 1)))
-
-#define COGL_FLAGS_GET(array, flag) \
- (!!((array)[COGL_FLAGS_GET_INDEX (flag)] & \
- COGL_FLAGS_GET_MASK (flag)))
-
-/* The expectation here is that @value will be constant so the if
- statement will be optimised out */
-#define COGL_FLAGS_SET(array, flag, value) \
- G_STMT_START { \
- if (value) \
- ((array)[COGL_FLAGS_GET_INDEX (flag)] |= \
- COGL_FLAGS_GET_MASK (flag)); \
- else \
- ((array)[COGL_FLAGS_GET_INDEX (flag)] &= \
- ~COGL_FLAGS_GET_MASK (flag)); \
- } G_STMT_END
-
-G_END_DECLS
-
-#endif /* __COGL_FLAGS_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_FRAMEBUFFER_PRIVATE_H
-#define __COGL_FRAMEBUFFER_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-matrix-stack.h"
-#include "cogl-clip-state-private.h"
-#include "cogl-journal-private.h"
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include <X11/Xlib.h>
-#endif
-
-#ifdef COGL_HAS_GLX_SUPPORT
-#include <GL/glx.h>
-#include <GL/glxext.h>
-#endif
-
-typedef enum _CoglFramebufferType {
- COGL_FRAMEBUFFER_TYPE_ONSCREEN,
- COGL_FRAMEBUFFER_TYPE_OFFSCREEN
-} CoglFramebufferType;
-
-struct _CoglFramebuffer
-{
- CoglObject _parent;
- CoglContext *context;
- CoglFramebufferType type;
- int width;
- int height;
- /* Format of the pixels in the framebuffer (including the expected
- premult state) */
- CoglPixelFormat format;
- gboolean allocated;
-
- CoglMatrixStack *modelview_stack;
- CoglMatrixStack *projection_stack;
- float viewport_x;
- float viewport_y;
- float viewport_width;
- float viewport_height;
-
- CoglClipState clip_state;
-
- gboolean dirty_bitmasks;
- int red_bits;
- int blue_bits;
- int green_bits;
- int alpha_bits;
-
- /* We journal the textured rectangles we want to submit to OpenGL so
- * we have an oppertunity to batch them together into less draw
- * calls. */
- CoglJournal *journal;
-
- /* The scene of a given framebuffer may depend on images in other
- * framebuffers... */
- GList *deps;
-
- /* As part of an optimization for reading-back single pixels from a
- * framebuffer in some simple cases where the geometry is still
- * available in the journal we need to track the bounds of the last
- * region cleared, its color and we need to track when something
- * does in fact draw to that region so it is no longer clear.
- */
- float clear_color_red;
- float clear_color_green;
- float clear_color_blue;
- float clear_color_alpha;
- int clear_clip_x0;
- int clear_clip_y0;
- int clear_clip_x1;
- int clear_clip_y1;
- gboolean clear_clip_dirty;
-};
-
-typedef struct _CoglOffscreen
-{
- CoglFramebuffer _parent;
- GLuint fbo_handle;
- GSList *renderbuffers;
- CoglHandle texture;
-} CoglOffscreen;
-
-/* Flags to pass to _cogl_offscreen_new_to_texture_full */
-typedef enum
-{
- COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL = 1
-} CoglOffscreenFlags;
-
-#define COGL_OFFSCREEN(X) ((CoglOffscreen *)(X))
-
-struct _CoglOnscreen
-{
- CoglFramebuffer _parent;
-
-#ifdef COGL_HAS_X11_SUPPORT
- guint32 foreign_xid;
- CoglOnscreenX11MaskCallback foreign_update_mask_callback;
- void *foreign_update_mask_data;
-#endif
-
- gboolean swap_throttled;
-
- void *winsys;
-};
-
-void
-_cogl_framebuffer_state_init (void);
-
-void
-_cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
- int width, int height);
-
-void
-_cogl_clear4f (unsigned long buffers,
- float red,
- float green,
- float blue,
- float alpha);
-
-void
-_cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
- unsigned long buffers,
- const CoglColor *color);
-
-void
-_cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
- unsigned long buffers,
- float red,
- float green,
- float blue,
- float alpha);
-
-void
-_cogl_framebuffer_dirty (CoglFramebuffer *framebuffer);
-
-CoglClipState *
-_cogl_framebuffer_get_clip_state (CoglFramebuffer *framebuffer);
-
-/*
- * _cogl_framebuffer_get_clip_stack:
- * @framebuffer: A #CoglFramebuffer
- *
- * Gets a pointer to the current clip stack. This can be used to later
- * return to the same clip stack state with
- * _cogl_framebuffer_set_clip_stack(). A reference is not taken on the
- * stack so if you want to keep it you should call
- * _cogl_clip_stack_ref().
- *
- * Return value: a pointer to the @framebuffer clip stack.
- */
-CoglClipStack *
-_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer);
-
-/*
- * _cogl_framebuffer_set_clip_stack:
- * @framebuffer: A #CoglFramebuffer
- * @stack: a pointer to the replacement clip stack
- *
- * Replaces the @framebuffer clip stack with @stack.
- */
-void
-_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
- CoglClipStack *stack);
-
-void
-_cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
- float x,
- float y,
- float width,
- float height);
-float
-_cogl_framebuffer_get_viewport_x (CoglFramebuffer *framebuffer);
-
-float
-_cogl_framebuffer_get_viewport_y (CoglFramebuffer *framebuffer);
-
-float
-_cogl_framebuffer_get_viewport_width (CoglFramebuffer *framebuffer);
-
-float
-_cogl_framebuffer_get_viewport_height (CoglFramebuffer *framebuffer);
-
-void
-_cogl_framebuffer_get_viewport4fv (CoglFramebuffer *framebuffer,
- float *viewport);
-
-CoglMatrixStack *
-_cogl_framebuffer_get_modelview_stack (CoglFramebuffer *framebuffer);
-
-CoglMatrixStack *
-_cogl_framebuffer_get_projection_stack (CoglFramebuffer *framebuffer);
-
-void
-_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer,
- CoglFramebuffer *dependency);
-
-void
-_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer);
-
-void
-_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer);
-
-void
-_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer);
-
-gboolean
-_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
- int x,
- int y,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixel);
-
-typedef enum _CoglFramebufferFlushFlags
-{
- /* XXX: When using this, that imples you are going to manually load the
- * modelview matrix (via glLoadMatrix). _cogl_matrix_stack_flush_to_gl wont
- * be called for framebuffer->modelview_stack, and the modelview_stack will
- * also be marked as dirty. */
- COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW = 1L<<0,
- /* Similarly this flag implies you are going to flush the clip state
- yourself */
- COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE = 1L<<1,
- /* When using this all that will be updated is the glBindFramebuffer
- * state and corresponding winsys state to make the framebuffer
- * current if it is a CoglOnscreen framebuffer. */
- COGL_FRAMEBUFFER_FLUSH_BIND_ONLY = 1L<<2
-} CoglFramebufferFlushFlags;
-
-void
-_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer,
- CoglFramebufferFlushFlags flags);
-
-CoglFramebuffer *
-_cogl_get_read_framebuffer (void);
-
-GSList *
-_cogl_create_framebuffer_stack (void);
-
-void
-_cogl_free_framebuffer_stack (GSList *stack);
-
-/*
- * _cogl_offscreen_new_to_texture_full:
- * @texhandle: A handle to the texture to target
- * @create_flags: Flags specifying how to create the FBO
- * @level: The mipmap level within the texture to target
- *
- * Creates a new offscreen buffer which will target the given
- * texture. By default the buffer will have a depth and stencil
- * buffer. This can be disabled by passing
- * %COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL in @create_flags.
- *
- * Return value: the new CoglOffscreen object.
- */
-CoglHandle
-_cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
- CoglOffscreenFlags create_flags,
- unsigned int level);
-
-/*
- * _cogl_push_framebuffers:
- * @draw_buffer: A pointer to the buffer used for drawing
- * @read_buffer: A pointer to the buffer used for reading back pixels
- *
- * Redirects drawing and reading to the specified framebuffers as in
- * cogl_push_framebuffer() except that it allows the draw and read
- * buffer to be different. The buffers are pushed as a pair so that
- * they can later both be restored with a single call to
- * cogl_pop_framebuffer().
- */
-void
-_cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer);
-
-/*
- * _cogl_blit_framebuffer:
- * @src_x: Source x position
- * @src_y: Source y position
- * @dst_x: Destination x position
- * @dst_y: Destination y position
- * @width: Width of region to copy
- * @height: Height of region to copy
- *
- * This blits a region of the color buffer of the current draw buffer
- * to the current read buffer. The draw and read buffers can be set up
- * using _cogl_push_framebuffers(). This function should only be
- * called if the COGL_FEATURE_OFFSCREEN_BLIT feature is
- * advertised. The two buffers must both be offscreen and have the
- * same format.
- *
- * Note that this function differs a lot from the glBlitFramebuffer
- * function provided by the GL_EXT_framebuffer_blit extension. Notably
- * it doesn't support having different sizes for the source and
- * destination rectangle. This isn't supported by the corresponding
- * GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem
- * like a particularly useful feature. If the application wanted to
- * scale the results it may make more sense to draw a primitive
- * instead.
- *
- * We can only really support blitting between two offscreen buffers
- * for this function on GLES2.0. This is because we effectively render
- * upside down to offscreen buffers to maintain Cogl's representation
- * of the texture coordinate system where 0,0 is the top left of the
- * texture. If we were to blit from an offscreen to an onscreen buffer
- * then we would need to mirror the blit along the x-axis but the GLES
- * extension does not support this.
- *
- * The GL function is documented to be affected by the scissor. This
- * function therefore ensure that an empty clip stack is flushed
- * before performing the blit which means the scissor is effectively
- * ignored.
- *
- * The function also doesn't support specifying the buffers to copy
- * and instead only the color buffer is copied. When copying the depth
- * or stencil buffers the extension on GLES2.0 only supports copying
- * the full buffer which would be awkward to document with this
- * API. If we wanted to support that feature it may be better to have
- * a separate function to copy the entire buffer for a given mask.
- */
-void
-_cogl_blit_framebuffer (unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height);
-
-CoglOnscreen *
-_cogl_onscreen_new (void);
-
-#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-display-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-handle.h"
-#include "cogl-object-private.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-clip-stack.h"
-#include "cogl-journal-private.h"
-#include "cogl-winsys-private.h"
-
-#ifndef HAVE_COGL_GLES2
-
-#define glGenRenderbuffers ctx->drv.pf_glGenRenderbuffers
-#define glDeleteRenderbuffers ctx->drv.pf_glDeleteRenderbuffers
-#define glBindRenderbuffer ctx->drv.pf_glBindRenderbuffer
-#define glRenderbufferStorage ctx->drv.pf_glRenderbufferStorage
-#define glGenFramebuffers ctx->drv.pf_glGenFramebuffers
-#define glBindFramebuffer ctx->drv.pf_glBindFramebuffer
-#define glFramebufferTexture2D ctx->drv.pf_glFramebufferTexture2D
-#define glFramebufferRenderbuffer ctx->drv.pf_glFramebufferRenderbuffer
-#define glCheckFramebufferStatus ctx->drv.pf_glCheckFramebufferStatus
-#define glDeleteFramebuffers ctx->drv.pf_glDeleteFramebuffers
-#define glGetFramebufferAttachmentParameteriv \
- ctx->drv.pf_glGetFramebufferAttachmentParameteriv
-
-#endif
-
-#define glBlitFramebuffer ctx->drv.pf_glBlitFramebuffer
-
-#ifndef GL_FRAMEBUFFER
-#define GL_FRAMEBUFFER 0x8D40
-#endif
-#ifndef GL_RENDERBUFFER
-#define GL_RENDERBUFFER 0x8D41
-#endif
-#ifndef GL_STENCIL_ATTACHMENT
-#define GL_STENCIL_ATTACHMENT 0x8D00
-#endif
-#ifndef GL_COLOR_ATTACHMENT0
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#endif
-#ifndef GL_FRAMEBUFFER_COMPLETE
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#endif
-#ifndef GL_STENCIL_INDEX8
-#define GL_STENCIL_INDEX8 0x8D48
-#endif
-#ifndef GL_DEPTH_STENCIL
-#define GL_DEPTH_STENCIL 0x84F9
-#endif
-#ifndef GL_DEPTH_ATTACHMENT
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#endif
-#ifndef GL_DEPTH_COMPONENT16
-#define GL_DEPTH_COMPONENT16 0x81A5
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
-#endif
-#ifndef GL_FRAMEBUFFER_ATTCHMENT_DEPTH_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
-#endif
-#ifndef GL_READ_FRAMEBUFFER
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#endif
-#ifndef GL_DRAW_FRAMEBUFFER
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#endif
-
-typedef enum {
- _TRY_DEPTH_STENCIL = 1L<<0,
- _TRY_DEPTH = 1L<<1,
- _TRY_STENCIL = 1L<<2
-} TryFBOFlags;
-
-typedef struct _CoglFramebufferStackEntry
-{
- CoglFramebuffer *draw_buffer;
- CoglFramebuffer *read_buffer;
-} CoglFramebufferStackEntry;
-
-static void _cogl_framebuffer_free (CoglFramebuffer *framebuffer);
-static void _cogl_onscreen_free (CoglOnscreen *onscreen);
-static void _cogl_offscreen_free (CoglOffscreen *offscreen);
-
-COGL_OBJECT_INTERNAL_DEFINE (Onscreen, onscreen);
-COGL_OBJECT_DEFINE (Offscreen, offscreen);
-COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (offscreen);
-
-/* XXX:
- * The CoglObject macros don't support any form of inheritance, so for
- * now we implement the CoglObject support for the CoglFramebuffer
- * abstract class manually.
- */
-
-gboolean
-_cogl_is_framebuffer (void *object)
-{
- CoglHandleObject *obj = object;
-
- if (obj == NULL)
- return FALSE;
-
- return obj->klass->type == _cogl_handle_onscreen_get_type ()
- || obj->klass->type == _cogl_handle_offscreen_get_type ();
-}
-
-static void
-_cogl_framebuffer_init (CoglFramebuffer *framebuffer,
- CoglContext *ctx,
- CoglFramebufferType type,
- CoglPixelFormat format,
- int width,
- int height)
-{
- framebuffer->context = cogl_object_ref (ctx);
-
- framebuffer->type = type;
- framebuffer->width = width;
- framebuffer->height = height;
- framebuffer->format = format;
- framebuffer->viewport_x = 0;
- framebuffer->viewport_y = 0;
- framebuffer->viewport_width = width;
- framebuffer->viewport_height = height;
-
- framebuffer->modelview_stack = _cogl_matrix_stack_new ();
- framebuffer->projection_stack = _cogl_matrix_stack_new ();
-
- framebuffer->dirty_bitmasks = TRUE;
-
- /* Initialise the clip stack */
- _cogl_clip_state_init (&framebuffer->clip_state);
-
- framebuffer->journal = _cogl_journal_new ();
-
- /* Ensure we know the framebuffer->clear_color* members can't be
- * referenced for our fast-path read-pixel optimization (see
- * _cogl_journal_try_read_pixel()) until some region of the
- * framebuffer is initialized.
- */
- framebuffer->clear_clip_dirty = TRUE;
-
- /* XXX: We have to maintain a central list of all framebuffers
- * because at times we need to be able to flush all known journals.
- *
- * Examples where we need to flush all journals are:
- * - because journal entries can reference OpenGL texture
- * coordinates that may not survive texture-atlas reorganization
- * so we need the ability to flush those entries.
- * - because although we generally advise against modifying
- * pipelines after construction we have to handle that possibility
- * and since pipelines may be referenced in journal entries we
- * need to be able to flush them before allowing the pipelines to
- * be changed.
- *
- * Note we don't maintain a list of journals and associate
- * framebuffers with journals by e.g. having a journal->framebuffer
- * reference since that would introduce a circular reference.
- *
- * Note: As a future change to try and remove the need to index all
- * journals it might be possible to defer resolving of OpenGL
- * texture coordinates for rectangle primitives until we come to
- * flush a journal. This would mean for instance that a single
- * rectangle entry in a journal could later be expanded into
- * multiple quad primitives to handle sliced textures but would mean
- * we don't have to worry about retaining references to OpenGL
- * texture coordinates that may later become invalid.
- */
- ctx->framebuffers = g_list_prepend (ctx->framebuffers, framebuffer);
-}
-
-void
-_cogl_framebuffer_free (CoglFramebuffer *framebuffer)
-{
- CoglContext *ctx = framebuffer->context;
-
- _cogl_clip_state_destroy (&framebuffer->clip_state);
-
- cogl_object_unref (framebuffer->modelview_stack);
- framebuffer->modelview_stack = NULL;
-
- cogl_object_unref (framebuffer->projection_stack);
- framebuffer->projection_stack = NULL;
-
- cogl_object_unref (framebuffer->journal);
-
- ctx->framebuffers = g_list_remove (ctx->framebuffers, framebuffer);
- cogl_object_unref (ctx);
-}
-
-static const CoglWinsysVtable *
-_cogl_framebuffer_get_winsys (CoglFramebuffer *framebuffer)
-{
- return framebuffer->context->display->renderer->winsys_vtable;
-}
-
-/* This version of cogl_clear can be used internally as an alternative
- * to avoid flushing the journal or the framebuffer state. This is
- * needed when doing operations that may be called whiling flushing
- * the journal */
-void
-_cogl_clear4f (unsigned long buffers,
- float red,
- float green,
- float blue,
- float alpha)
-{
- GLbitfield gl_buffers = 0;
-
- if (buffers & COGL_BUFFER_BIT_COLOR)
- {
- GE( glClearColor (red, green, blue, alpha) );
- gl_buffers |= GL_COLOR_BUFFER_BIT;
- }
-
- if (buffers & COGL_BUFFER_BIT_DEPTH)
- gl_buffers |= GL_DEPTH_BUFFER_BIT;
-
- if (buffers & COGL_BUFFER_BIT_STENCIL)
- gl_buffers |= GL_STENCIL_BUFFER_BIT;
-
- if (!gl_buffers)
- {
- static gboolean shown = FALSE;
-
- if (!shown)
- {
- g_warning ("You should specify at least one auxiliary buffer "
- "when calling cogl_clear");
- }
-
- return;
- }
-
- GE (glClear (gl_buffers));
-}
-
-void
-_cogl_framebuffer_dirty (CoglFramebuffer *framebuffer)
-{
- framebuffer->clear_clip_dirty = TRUE;
-}
-
-void
-_cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
- unsigned long buffers,
- float red,
- float green,
- float blue,
- float alpha)
-{
- CoglClipStack *clip_stack = _cogl_framebuffer_get_clip_stack (framebuffer);
- int scissor_x0;
- int scissor_y0;
- int scissor_x1;
- int scissor_y1;
-
- g_return_if_fail (framebuffer->allocated);
-
- _cogl_clip_stack_get_bounds (clip_stack,
- &scissor_x0, &scissor_y0,
- &scissor_x1, &scissor_y1);
-
- /* NB: the previous clear could have had an arbitrary clip.
- * NB: everything for the last frame might still be in the journal
- * but we can't assume anything about how each entry was
- * clipped.
- * NB: Clutter will scissor its pick renders which would mean all
- * journal entries have a common ClipStack entry, but without
- * a layering violation Cogl has to explicitly walk the journal
- * entries to determine if this is the case.
- * NB: We have a software only read-pixel optimization in the
- * journal that determines the color at a given framebuffer
- * coordinate for simple scenes without rendering with the GPU.
- * When Clutter is hitting this fast-path we can expect to
- * receive calls to clear the framebuffer with an un-flushed
- * journal.
- * NB: To fully support software based picking for Clutter we
- * need to be able to reliably detect when the contents of a
- * journal can be discarded and when we can skip the call to
- * glClear because it matches the previous clear request.
- */
-
- /* Note: we don't check for the stencil buffer being cleared here
- * since there isn't any public cogl api to manipulate the stencil
- * buffer.
- *
- * Note: we check for an exact clip match here because
- * 1) a smaller clip could mean existing journal entries may
- * need to contribute to regions outside the new clear-clip
- * 2) a larger clip would mean we need to issue a real
- * glClear and we only care about cases avoiding a
- * glClear.
- *
- * Note: Comparing without an epsilon is considered
- * appropriate here.
- */
- if (buffers & COGL_BUFFER_BIT_COLOR &&
- buffers & COGL_BUFFER_BIT_DEPTH &&
- !framebuffer->clear_clip_dirty &&
- framebuffer->clear_color_red == red &&
- framebuffer->clear_color_green == green &&
- framebuffer->clear_color_blue == blue &&
- framebuffer->clear_color_alpha == alpha &&
- scissor_x0 == framebuffer->clear_clip_x0 &&
- scissor_y0 == framebuffer->clear_clip_y0 &&
- scissor_x1 == framebuffer->clear_clip_x1 &&
- scissor_y1 == framebuffer->clear_clip_y1)
- {
- /* NB: We only have to consider the clip state of journal
- * entries if the current clear is clipped since otherwise we
- * know every pixel of the framebuffer is affected by the clear
- * and so all journal entries become redundant and can simply be
- * discarded.
- */
- if (clip_stack)
- {
- /*
- * Note: the function for checking the journal entries is
- * quite strict. It avoids detailed checking of all entry
- * clip_stacks by only checking the details of the first
- * entry and then it only verifies that the remaining
- * entries share the same clip_stack ancestry. This means
- * it's possible for some false negatives here but that will
- * just result in us falling back to a real clear.
- */
- if (_cogl_journal_all_entries_within_bounds (framebuffer->journal,
- scissor_x0, scissor_y0,
- scissor_x1, scissor_y1))
- {
- _cogl_journal_discard (framebuffer->journal);
- goto cleared;
- }
- }
- else
- {
- _cogl_journal_discard (framebuffer->journal);
- goto cleared;
- }
- }
-
- COGL_NOTE (DRAW, "Clear begin");
-
- _cogl_framebuffer_flush_journal (framebuffer);
-
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. */
- _cogl_framebuffer_flush_state (framebuffer, framebuffer, 0);
-
- _cogl_clear4f (buffers, red, green, blue, alpha);;
-
- /* This is a debugging variable used to visually display the quad
- * batches from the journal. It is reset here to increase the
- * chances of getting the same colours for each frame during an
- * animation */
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_RECTANGLES)) &&
- buffers & COGL_BUFFER_BIT_COLOR)
- {
- framebuffer->context->journal_rectangles_color = 1;
- }
-
- COGL_NOTE (DRAW, "Clear end");
-
-cleared:
-
- if (buffers & COGL_BUFFER_BIT_COLOR && buffers & COGL_BUFFER_BIT_DEPTH)
- {
- /* For our fast-path for reading back a single pixel of simple
- * scenes where the whole frame is in the journal we need to
- * track the cleared color of the framebuffer in case the point
- * read doesn't intersect any of the journal rectangles. */
- framebuffer->clear_clip_dirty = FALSE;
- framebuffer->clear_color_red = red;
- framebuffer->clear_color_green = green;
- framebuffer->clear_color_blue = blue;
- framebuffer->clear_color_alpha = alpha;
-
- /* NB: A clear may be scissored so we need to track the extents
- * that the clear is applicable too... */
- if (clip_stack)
- {
- _cogl_clip_stack_get_bounds (clip_stack,
- &framebuffer->clear_clip_x0,
- &framebuffer->clear_clip_y0,
- &framebuffer->clear_clip_x1,
- &framebuffer->clear_clip_y1);
- }
- else
- {
- /* FIXME: set degenerate clip */
- }
- }
- else
- _cogl_framebuffer_dirty (framebuffer);
-}
-
-/* XXX: We'll need to consider if this API is a good approach for the
- * planned, public, CoglFramebuffer API. A framebuffer may have
- * multiple color buffers associated with it and the user may want to
- * only clear a subset of those buffers. Flags aren't a great
- * mechanism for handling this, but I don't think it would be very
- * convenient if you had to explicitly enumerate the individual
- * ancillary buffers to clear them.
- *
- * My current expectation is that we'll keep this flag based API but
- * also add a way to enumerate the individual color buffers for
- * clearing individually.
- *
- * Note: the 'buffers' and 'color' arguments were switched around on
- * purpose compared to the original cogl_clear API since it was odd
- * that you would be expected to specify a color before even
- * necessarily choosing to clear the color buffer.
- */
-void
-_cogl_framebuffer_clear (CoglFramebuffer *framebuffer,
- unsigned long buffers,
- const CoglColor *color)
-{
- g_return_if_fail (framebuffer->allocated);
-
- _cogl_framebuffer_clear4f (framebuffer, buffers,
- cogl_color_get_red_float (color),
- cogl_color_get_green_float (color),
- cogl_color_get_blue_float (color),
- cogl_color_get_alpha_float (color));
-}
-
-int
-cogl_framebuffer_get_width (CoglFramebuffer *framebuffer)
-{
- return framebuffer->width;
-}
-
-int
-cogl_framebuffer_get_height (CoglFramebuffer *framebuffer)
-{
- return framebuffer->height;
-}
-
-CoglClipState *
-_cogl_framebuffer_get_clip_state (CoglFramebuffer *framebuffer)
-{
- return &framebuffer->clip_state;
-}
-
-CoglClipStack *
-_cogl_framebuffer_get_clip_stack (CoglFramebuffer *framebuffer)
-{
- CoglClipState *clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- return _cogl_clip_state_get_stack (clip_state);
-}
-
-void
-_cogl_framebuffer_set_clip_stack (CoglFramebuffer *framebuffer,
- CoglClipStack *stack)
-{
- CoglClipState *clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- _cogl_clip_state_set_stack (clip_state, stack);
-}
-
-void
-_cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
- float x,
- float y,
- float width,
- float height)
-{
- if (framebuffer->viewport_x == x &&
- framebuffer->viewport_y == y &&
- framebuffer->viewport_width == width &&
- framebuffer->viewport_height == height)
- return;
-
- _cogl_framebuffer_flush_journal (framebuffer);
-
- framebuffer->viewport_x = x;
- framebuffer->viewport_y = y;
- framebuffer->viewport_width = width;
- framebuffer->viewport_height = height;
-
- if (framebuffer->context && cogl_get_draw_framebuffer () == framebuffer)
- framebuffer->context->dirty_gl_viewport = TRUE;
-}
-
-float
-_cogl_framebuffer_get_viewport_x (CoglFramebuffer *framebuffer)
-{
- return framebuffer->viewport_x;
-}
-
-float
-_cogl_framebuffer_get_viewport_y (CoglFramebuffer *framebuffer)
-{
- return framebuffer->viewport_y;
-}
-
-float
-_cogl_framebuffer_get_viewport_width (CoglFramebuffer *framebuffer)
-{
- return framebuffer->viewport_width;
-}
-
-float
-_cogl_framebuffer_get_viewport_height (CoglFramebuffer *framebuffer)
-{
- return framebuffer->viewport_height;
-}
-
-void
-_cogl_framebuffer_get_viewport4fv (CoglFramebuffer *framebuffer,
- float *viewport)
-{
- viewport[0] = framebuffer->viewport_x;
- viewport[1] = framebuffer->viewport_y;
- viewport[2] = framebuffer->viewport_width;
- viewport[3] = framebuffer->viewport_height;
-}
-
-CoglMatrixStack *
-_cogl_framebuffer_get_modelview_stack (CoglFramebuffer *framebuffer)
-{
- return framebuffer->modelview_stack;
-}
-
-CoglMatrixStack *
-_cogl_framebuffer_get_projection_stack (CoglFramebuffer *framebuffer)
-{
- return framebuffer->projection_stack;
-}
-
-void
-_cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer,
- CoglFramebuffer *dependency)
-{
- GList *l;
-
- for (l = framebuffer->deps; l; l = l->next)
- {
- CoglFramebuffer *existing_dep = l->data;
- if (existing_dep == dependency)
- return;
- }
-
- /* TODO: generalize the primed-array type structure we e.g. use for
- * cogl_object_set_user_data or for pipeline children as a way to
- * avoid quite a lot of mid-scene micro allocations here... */
- framebuffer->deps =
- g_list_prepend (framebuffer->deps, cogl_object_ref (dependency));
-}
-
-void
-_cogl_framebuffer_remove_all_dependencies (CoglFramebuffer *framebuffer)
-{
- GList *l;
- for (l = framebuffer->deps; l; l = l->next)
- cogl_object_unref (l->data);
- g_list_free (framebuffer->deps);
- framebuffer->deps = NULL;
-}
-
-void
-_cogl_framebuffer_flush_journal (CoglFramebuffer *framebuffer)
-{
- _cogl_journal_flush (framebuffer->journal, framebuffer);
-}
-
-void
-_cogl_framebuffer_flush_dependency_journals (CoglFramebuffer *framebuffer)
-{
- GList *l;
- for (l = framebuffer->deps; l; l = l->next)
- _cogl_framebuffer_flush_journal (l->data);
- _cogl_framebuffer_remove_all_dependencies (framebuffer);
-}
-
-static inline void
-_cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
-{
-#ifdef HAVE_COGL_GL
- CoglContext *ctx = framebuffer->context;
-#endif
-
- if (G_LIKELY (!framebuffer->dirty_bitmasks))
- return;
-
-#ifdef HAVE_COGL_GL
- if (cogl_features_available (COGL_FEATURE_OFFSCREEN)
- && framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
- {
- GLenum attachment, pname;
-
- attachment = GL_COLOR_ATTACHMENT0;
-
- pname = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE;
- GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- attachment,
- pname,
- &framebuffer->red_bits) );
-
- pname = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE;
- GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- attachment,
- pname,
- &framebuffer->green_bits) );
-
- pname = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE;
- GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- attachment,
- pname,
- &framebuffer->blue_bits) );
-
- pname = GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE;
- GE( glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- attachment,
- pname,
- &framebuffer->alpha_bits) );
- }
- else
-#endif /* HAVE_COGL_GL */
- {
- GE( glGetIntegerv (GL_RED_BITS, &framebuffer->red_bits) );
- GE( glGetIntegerv (GL_GREEN_BITS, &framebuffer->green_bits) );
- GE( glGetIntegerv (GL_BLUE_BITS, &framebuffer->blue_bits) );
- GE( glGetIntegerv (GL_ALPHA_BITS, &framebuffer->alpha_bits) );
- }
-
-
- COGL_NOTE (OFFSCREEN,
- "RGBA Bits for framebuffer[%p, %s]: %d, %d, %d, %d",
- framebuffer,
- framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN
- ? "offscreen"
- : "onscreen",
- framebuffer->red_bits,
- framebuffer->blue_bits,
- framebuffer->green_bits,
- framebuffer->alpha_bits);
-
- framebuffer->dirty_bitmasks = FALSE;
-}
-
-typedef struct
-{
- CoglHandle texture;
- unsigned int level;
- unsigned int level_width;
- unsigned int level_height;
-} CoglFramebufferTryFBOData;
-
-static gboolean
-try_creating_fbo (CoglOffscreen *offscreen,
- TryFBOFlags flags,
- CoglFramebufferTryFBOData *data)
-{
- GLuint gl_depth_stencil_handle;
- GLuint gl_depth_handle;
- GLuint gl_stencil_handle;
- GLuint tex_gl_handle;
- GLenum tex_gl_target;
- GLuint fbo_gl_handle;
- GLenum status;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!cogl_texture_get_gl_texture (data->texture,
- &tex_gl_handle, &tex_gl_target))
- return FALSE;
-
- if (tex_gl_target != GL_TEXTURE_2D
-#ifdef HAVE_COGL_GL
- && tex_gl_target != GL_TEXTURE_RECTANGLE_ARB
-#endif
- )
- return FALSE;
-
- /* We are about to generate and bind a new fbo, so we pretend to
- * change framebuffer state so that the old framebuffer will be
- * rebound again before drawing. */
- ctx->dirty_bound_framebuffer = 1;
-
- /* Generate framebuffer */
- glGenFramebuffers (1, &fbo_gl_handle);
- GE (glBindFramebuffer (GL_FRAMEBUFFER, fbo_gl_handle));
- offscreen->fbo_handle = fbo_gl_handle;
-
- GE (glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- tex_gl_target, tex_gl_handle, data->level));
-
- if (flags & _TRY_DEPTH_STENCIL)
- {
- /* Create a renderbuffer for depth and stenciling */
- GE (glGenRenderbuffers (1, &gl_depth_stencil_handle));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle));
- GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_STENCIL,
- data->level_width,
- data->level_height));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
- GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, gl_depth_stencil_handle));
- GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, gl_depth_stencil_handle));
- offscreen->renderbuffers =
- g_slist_prepend (offscreen->renderbuffers,
- GUINT_TO_POINTER (gl_depth_stencil_handle));
- }
-
- if (flags & _TRY_DEPTH)
- {
- GE (glGenRenderbuffers (1, &gl_depth_handle));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_handle));
- /* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's
- * available under GLES */
- GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
- data->level_width,
- data->level_height));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
- GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, gl_depth_handle));
- offscreen->renderbuffers =
- g_slist_prepend (offscreen->renderbuffers,
- GUINT_TO_POINTER (gl_depth_handle));
- }
-
- if (flags & _TRY_STENCIL)
- {
- GE (glGenRenderbuffers (1, &gl_stencil_handle));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
- GE (glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
- data->level_width,
- data->level_height));
- GE (glBindRenderbuffer (GL_RENDERBUFFER, 0));
- GE (glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, gl_stencil_handle));
- offscreen->renderbuffers =
- g_slist_prepend (offscreen->renderbuffers,
- GUINT_TO_POINTER (gl_stencil_handle));
- }
-
- /* Make sure it's complete */
- status = glCheckFramebufferStatus (GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- GSList *l;
-
- GE (glDeleteFramebuffers (1, &fbo_gl_handle));
-
- for (l = offscreen->renderbuffers; l; l = l->next)
- {
- GLuint renderbuffer = GPOINTER_TO_UINT (l->data);
- GE (glDeleteRenderbuffers (1, &renderbuffer));
- }
-
- g_slist_free (offscreen->renderbuffers);
- offscreen->renderbuffers = NULL;
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-CoglHandle
-_cogl_offscreen_new_to_texture_full (CoglHandle texhandle,
- CoglOffscreenFlags create_flags,
- unsigned int level)
-{
- CoglOffscreen *offscreen;
- static TryFBOFlags flags;
- static gboolean have_working_flags = FALSE;
- unsigned int i;
- CoglFramebufferTryFBOData data;
- gboolean fbo_created;
-
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
- return COGL_INVALID_HANDLE;
-
- /* Make texhandle is a valid texture object */
- if (!cogl_is_texture (texhandle))
- return COGL_INVALID_HANDLE;
-
- /* The texture must not be sliced */
- if (cogl_texture_is_sliced (texhandle))
- return COGL_INVALID_HANDLE;
-
- data.texture = texhandle;
- data.level = level;
-
- /* Calculate the size of the texture at this mipmap level to ensure
- that it's a valid level */
- data.level_width = cogl_texture_get_width (texhandle);
- data.level_height = cogl_texture_get_height (texhandle);
-
- for (i = 0; i < level; i++)
- {
- /* If neither dimension can be further divided then the level is
- invalid */
- if (data.level_width == 1 && data.level_height == 1)
- return COGL_INVALID_HANDLE;
-
- if (data.level_width > 1)
- data.level_width >>= 1;
- if (data.level_height > 1)
- data.level_height >>= 1;
- }
-
- /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
- * a texture as a renderbuffer with mipmap filtering enabled while the
- * mipmaps have not been uploaded should result in an incomplete framebuffer
- * object. (different drivers make different decisions)
- *
- * To avoid an error with drivers that do consider this a problem we
- * explicitly set non mipmapped filters here. These will later be reset when
- * the texture is actually used for rendering according to the filters set on
- * the corresponding CoglPipeline.
- */
- _cogl_texture_set_filters (texhandle, GL_NEAREST, GL_NEAREST);
-
- offscreen = g_new0 (CoglOffscreen, 1);
- offscreen->texture = texhandle;
-
- if ((create_flags & COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL))
- fbo_created = try_creating_fbo (offscreen, 0, &data);
- else
- {
- if ((have_working_flags &&
- try_creating_fbo (offscreen, flags, &data)) ||
-#ifdef HAVE_COGL_GL
- try_creating_fbo (offscreen, flags = _TRY_DEPTH_STENCIL, &data) ||
-#endif
- try_creating_fbo (offscreen, flags = _TRY_DEPTH | _TRY_STENCIL,
- &data) ||
- try_creating_fbo (offscreen, flags = _TRY_STENCIL, &data) ||
- try_creating_fbo (offscreen, flags = _TRY_DEPTH, &data) ||
- try_creating_fbo (offscreen, flags = 0, &data))
- {
- /* Record that the last set of flags succeeded so that we can
- try that set first next time */
- have_working_flags = TRUE;
- fbo_created = TRUE;
- }
- else
- fbo_created = FALSE;
- }
-
- if (fbo_created)
- {
- CoglOffscreen *ret;
- CoglFramebuffer *fb = COGL_FRAMEBUFFER (offscreen);
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- _cogl_framebuffer_init (fb,
- ctx,
- COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
- cogl_texture_get_format (texhandle),
- data.level_width,
- data.level_height);
-
- /* take a reference on the texture */
- cogl_handle_ref (offscreen->texture);
-
- ret = _cogl_offscreen_object_new (offscreen);
- _cogl_texture_associate_framebuffer (texhandle, COGL_FRAMEBUFFER (ret));
-
- fb->allocated = TRUE;
-
- return ret;
- }
- else
- {
- g_free (offscreen);
- /* XXX: This API should probably have been defined to take a GError */
- g_warning ("%s: Failed to create an OpenGL framebuffer", G_STRLOC);
-
- return COGL_INVALID_HANDLE;
- }
-}
-
-CoglHandle
-cogl_offscreen_new_to_texture (CoglHandle texhandle)
-{
- return _cogl_offscreen_new_to_texture_full (texhandle, 0, 0);
-}
-
-static void
-_cogl_offscreen_free (CoglOffscreen *offscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen);
-#ifndef HAVE_COGL_GLES2
- CoglContext *ctx = framebuffer->context;
-#endif
- GSList *l;
-
- /* Chain up to parent */
- _cogl_framebuffer_free (framebuffer);
-
- for (l = offscreen->renderbuffers; l; l = l->next)
- {
- GLuint renderbuffer = GPOINTER_TO_UINT (l->data);
- GE (glDeleteRenderbuffers (1, &renderbuffer));
- }
- g_slist_free (offscreen->renderbuffers);
-
- GE (glDeleteFramebuffers (1, &offscreen->fbo_handle));
-
- if (offscreen->texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (offscreen->texture);
-
- g_free (offscreen);
-}
-
-/* XXX: While we still have backend in Clutter we need a dummy object
- * to represent the CoglOnscreen framebuffer that the backend
- * creates... */
-CoglOnscreen *
-_cogl_onscreen_new (void)
-{
- CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
- ctx,
- COGL_FRAMEBUFFER_TYPE_ONSCREEN,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- 0xdeadbeef, /* width */
- 0xdeadbeef); /* height */
-
- COGL_FRAMEBUFFER (onscreen)->allocated = TRUE;
-
- /* XXX: Note we don't initialize onscreen->winsys in this case. */
-
- return _cogl_onscreen_object_new (onscreen);
-}
-
-CoglOnscreen *
-cogl_onscreen_new (CoglContext *ctx, int width, int height)
-{
- CoglOnscreen *onscreen;
-
- /* FIXME: We are assuming onscreen buffers will always be
- premultiplied so we'll set the premult flag on the bitmap
- format. This will usually be correct because the result of the
- default blending operations for Cogl ends up with premultiplied
- data in the framebuffer. However it is possible for the
- framebuffer to be in whatever format depending on what
- CoglPipeline is used to render to it. Eventually we may want to
- add a way for an application to inform Cogl that the framebuffer
- is not premultiplied in case it is being used for some special
- purpose. */
-
- onscreen = g_new0 (CoglOnscreen, 1);
- _cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
- ctx,
- COGL_FRAMEBUFFER_TYPE_ONSCREEN,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- width, /* width */
- height); /* height */
-
- onscreen->swap_throttled = TRUE;
-
- return _cogl_onscreen_object_new (onscreen);
-}
-
-gboolean
-cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
- GError **error)
-{
- CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
-
- if (framebuffer->allocated)
- return TRUE;
-
- /* XXX: with the current cogl_offscreen_new_to_texture() API the
- * framebuffer is implicitly allocated before returning. */
- g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN,
- TRUE);
-
- if (!winsys->onscreen_init (onscreen, error))
- return FALSE;
-
- framebuffer->allocated = TRUE;
-
- return TRUE;
-}
-
-static void
-_cogl_onscreen_free (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
-
- winsys->onscreen_deinit (onscreen);
- g_return_if_fail (onscreen->winsys == NULL);
-
- /* Chain up to parent */
- _cogl_framebuffer_free (framebuffer);
-
- g_free (onscreen);
-}
-
-void
-_cogl_framebuffer_winsys_update_size (CoglFramebuffer *framebuffer,
- int width, int height)
-{
- CoglContext *ctx = framebuffer->context;
-
- if (framebuffer->width == width && framebuffer->height == height)
- return;
-
- framebuffer->width = width;
- framebuffer->height = height;
-
- /* We'll need to recalculate the GL viewport state derived
- * from the Cogl viewport */
- ctx->dirty_gl_viewport = 1;
-}
-
-static CoglFramebufferStackEntry *
-create_stack_entry (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer)
-{
- CoglFramebufferStackEntry *entry = g_slice_new (CoglFramebufferStackEntry);
-
- entry->draw_buffer = draw_buffer;
- entry->read_buffer = read_buffer;
-
- return entry;
-}
-
-GSList *
-_cogl_create_framebuffer_stack (void)
-{
- CoglFramebufferStackEntry *entry;
- GSList *stack = NULL;
-
- entry = create_stack_entry (COGL_INVALID_HANDLE, COGL_INVALID_HANDLE);
-
- return g_slist_prepend (stack, entry);
-}
-
-void
-_cogl_free_framebuffer_stack (GSList *stack)
-{
- GSList *l;
-
- for (l = stack; l != NULL; l = l->next)
- {
- CoglFramebufferStackEntry *entry = l->data;
-
- if (entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
- _cogl_offscreen_free (COGL_OFFSCREEN (entry->draw_buffer));
- else
- _cogl_onscreen_free (COGL_ONSCREEN (entry->draw_buffer));
-
- if (entry->read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
- _cogl_offscreen_free (COGL_OFFSCREEN (entry->read_buffer));
- else
- _cogl_onscreen_free (COGL_ONSCREEN (entry->read_buffer));
-
- g_slice_free (CoglFramebufferStackEntry, entry);
- }
- g_slist_free (stack);
-}
-
-/* Set the current framebuffer without checking if it's already the
- * current framebuffer. This is used by cogl_pop_framebuffer while
- * the top of the stack is currently not up to date. */
-static void
-_cogl_set_framebuffers_real (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer)
-{
- CoglFramebufferStackEntry *entry;
- GSList *l;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (ctx != NULL);
- g_return_if_fail (draw_buffer && read_buffer ?
- draw_buffer->context == read_buffer->context : TRUE);
-
- entry = ctx->framebuffer_stack->data;
-
- ctx->dirty_bound_framebuffer = 1;
- ctx->dirty_gl_viewport = 1;
-
- if (draw_buffer)
- cogl_object_ref (draw_buffer);
- if (entry->draw_buffer)
- cogl_object_unref (entry->draw_buffer);
-
- if (read_buffer)
- cogl_object_ref (read_buffer);
- if (entry->read_buffer)
- cogl_object_unref (entry->read_buffer);
-
- entry->draw_buffer = draw_buffer;
- entry->read_buffer = read_buffer;
-
- /* We've effectively just switched the current modelview and
- * projection matrix stacks and clip state so we need to dirty
- * them to ensure they get flushed for the next batch of geometry
- * we flush */
- if (draw_buffer)
- {
- _cogl_matrix_stack_dirty (draw_buffer->modelview_stack);
- _cogl_matrix_stack_dirty (draw_buffer->projection_stack);
- }
-
- _cogl_clip_stack_dirty ();
-
- /* XXX:
- * To support the deprecated cogl_set_draw_buffer API we keep track
- * of the last onscreen framebuffer that was pushed so that it can
- * be restored if the COGL_WINDOW_BUFFER enum is used. */
- ctx->window_buffer = NULL;
- for (l = ctx->framebuffer_stack; l; l = l->next)
- {
- entry = l->data;
- if (entry->draw_buffer &&
- entry->draw_buffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
- ctx->window_buffer = entry->draw_buffer;
- }
-}
-
-static void
-_cogl_set_framebuffers (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer)
-{
- CoglFramebuffer *current_draw_buffer;
- CoglFramebuffer *current_read_buffer;
-
- g_return_if_fail (_cogl_is_framebuffer (draw_buffer));
- g_return_if_fail (_cogl_is_framebuffer (read_buffer));
-
- current_draw_buffer = cogl_get_draw_framebuffer ();
- current_read_buffer = _cogl_get_read_framebuffer ();
-
- if (current_draw_buffer != draw_buffer ||
- current_read_buffer != read_buffer)
- {
- /* XXX: eventually we want to remove this implicit journal flush
- * so we can log into the journal beyond framebuffer changes to
- * support batching scenes that depend on the results of
- * mid-scene renders to textures. Current will be NULL when the
- * framebuffer stack is first created so we need to guard
- * against that here */
- if (current_draw_buffer)
- _cogl_framebuffer_flush_journal (current_draw_buffer);
- if (current_read_buffer)
- _cogl_framebuffer_flush_journal (current_read_buffer);
- _cogl_set_framebuffers_real (draw_buffer, read_buffer);
- }
-}
-
-void
-cogl_set_framebuffer (CoglFramebuffer *framebuffer)
-{
- _cogl_set_framebuffers (framebuffer, framebuffer);
-}
-
-/* XXX: deprecated API */
-void
-cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (target == COGL_WINDOW_BUFFER)
- handle = ctx->window_buffer;
-
- /* This is deprecated public API. The public API doesn't currently
- really expose the concept of separate draw and read buffers so
- for the time being this actually just sets both buffers */
- cogl_set_framebuffer (handle);
-}
-
-CoglFramebuffer *
-cogl_get_draw_framebuffer (void)
-{
- CoglFramebufferStackEntry *entry;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_assert (ctx->framebuffer_stack);
-
- entry = ctx->framebuffer_stack->data;
-
- return entry->draw_buffer;
-}
-
-CoglFramebuffer *
-_cogl_get_read_framebuffer (void)
-{
- CoglFramebufferStackEntry *entry;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_assert (ctx->framebuffer_stack);
-
- entry = ctx->framebuffer_stack->data;
-
- return entry->read_buffer;
-}
-
-void
-_cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer)
-{
- CoglContext *ctx;
- CoglFramebuffer *old_draw_buffer, *old_read_buffer;
-
- g_return_if_fail (_cogl_is_framebuffer (draw_buffer));
- g_return_if_fail (_cogl_is_framebuffer (read_buffer));
-
- ctx = draw_buffer->context;
- g_return_if_fail (ctx != NULL);
- g_return_if_fail (draw_buffer->context == read_buffer->context);
-
- g_return_if_fail (ctx->framebuffer_stack != NULL);
-
- /* Copy the top of the stack so that when we call cogl_set_framebuffer
- it will still know what the old framebuffer was */
- old_draw_buffer = cogl_get_draw_framebuffer ();
- if (old_draw_buffer)
- cogl_object_ref (old_draw_buffer);
- old_read_buffer = _cogl_get_read_framebuffer ();
- if (old_read_buffer)
- cogl_object_ref (old_read_buffer);
- ctx->framebuffer_stack =
- g_slist_prepend (ctx->framebuffer_stack,
- create_stack_entry (old_draw_buffer,
- old_read_buffer));
-
- _cogl_set_framebuffers (draw_buffer, read_buffer);
-}
-
-void
-cogl_push_framebuffer (CoglFramebuffer *buffer)
-{
- _cogl_push_framebuffers (buffer, buffer);
-}
-
-/* XXX: deprecated API */
-void
-cogl_push_draw_buffer (void)
-{
- cogl_push_framebuffer (cogl_get_draw_framebuffer ());
-}
-
-void
-cogl_pop_framebuffer (void)
-{
- CoglFramebufferStackEntry *to_pop;
- CoglFramebufferStackEntry *to_restore;
- gboolean changed = FALSE;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->framebuffer_stack != NULL);
- g_assert (ctx->framebuffer_stack->next != NULL);
-
- to_pop = ctx->framebuffer_stack->data;
- to_restore = ctx->framebuffer_stack->next->data;
-
- if (to_pop->draw_buffer != to_restore->draw_buffer ||
- to_pop->read_buffer != to_restore->read_buffer)
- {
- /* XXX: eventually we want to remove this implicit journal flush
- * so we can log into the journal beyond framebuffer changes to
- * support batching scenes that depend on the results of
- * mid-scene renders to textures. */
- _cogl_framebuffer_flush_journal (to_pop->draw_buffer);
- _cogl_framebuffer_flush_journal (to_pop->read_buffer);
-
- changed = TRUE;
- }
-
- cogl_object_unref (to_pop->draw_buffer);
- cogl_object_unref (to_pop->read_buffer);
- g_slice_free (CoglFramebufferStackEntry, to_pop);
-
- ctx->framebuffer_stack =
- g_slist_delete_link (ctx->framebuffer_stack,
- ctx->framebuffer_stack);
-
- /* If the framebuffer has changed as a result of popping the top
- * then re-assert the current buffer so as to dirty state as
- * necessary. */
- if (changed)
- _cogl_set_framebuffers_real (to_restore->draw_buffer,
- to_restore->read_buffer);
-}
-
-/* XXX: deprecated API */
-void
-cogl_pop_draw_buffer (void)
-{
- cogl_pop_framebuffer ();
-}
-
-static void
-bind_gl_framebuffer (CoglContext *ctx,
- GLenum target,
- CoglFramebuffer *framebuffer)
-{
- if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
- GE (glBindFramebuffer (target,
- COGL_OFFSCREEN (framebuffer)->fbo_handle));
- else
- {
-#ifdef COGL_HAS_FULL_WINSYS
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
-#endif
- GE (glBindFramebuffer (target, 0));
- }
-}
-
-void
-_cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
- CoglFramebuffer *read_buffer,
- CoglFramebufferFlushFlags flags)
-{
- CoglContext *ctx = draw_buffer->context;
-
- if (ctx->dirty_bound_framebuffer)
- {
- if (draw_buffer == read_buffer)
- bind_gl_framebuffer (ctx, GL_FRAMEBUFFER, draw_buffer);
- else
- {
- /* NB: Currently we only take advantage of binding separate
- * read/write buffers for offscreen framebuffer blit
- * purposes. */
- g_return_if_fail (cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT));
- g_return_if_fail (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
- g_return_if_fail (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
-
- bind_gl_framebuffer (ctx, GL_DRAW_FRAMEBUFFER, draw_buffer);
- bind_gl_framebuffer (ctx, GL_READ_FRAMEBUFFER, read_buffer);
- }
- }
-
- ctx->dirty_bound_framebuffer = FALSE;
-
- if (flags & COGL_FRAMEBUFFER_FLUSH_BIND_ONLY)
- return;
-
- if (ctx->dirty_gl_viewport)
- {
- float gl_viewport_y;
-
- /* Convert the Cogl viewport y offset to an OpenGL viewport y offset
- * NB: OpenGL defines its window and viewport origins to be bottom
- * left, while Cogl defines them to be top left.
- * NB: We render upside down to offscreen framebuffers so we don't
- * need to convert the y offset in this case. */
- if (cogl_is_offscreen (draw_buffer))
- gl_viewport_y = draw_buffer->viewport_y;
- else
- gl_viewport_y = draw_buffer->height -
- (draw_buffer->viewport_y + draw_buffer->viewport_height);
-
- COGL_NOTE (OPENGL, "Calling glViewport(%f, %f, %f, %f)",
- draw_buffer->viewport_x,
- gl_viewport_y,
- draw_buffer->viewport_width,
- draw_buffer->viewport_height);
-
- GE (glViewport (draw_buffer->viewport_x,
- gl_viewport_y,
- draw_buffer->viewport_width,
- draw_buffer->viewport_height));
- ctx->dirty_gl_viewport = FALSE;
- }
-
- /* since we might have changed the framebuffer, we should initialize
- * the bits; this is a no-op if they have already been initialized
- */
- _cogl_framebuffer_init_bits (draw_buffer);
- _cogl_framebuffer_init_bits (read_buffer);
-
- /* XXX: Flushing clip state may trash the modelview and projection
- * matrices so we must do it before flushing the matrices...
- */
- if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE))
- _cogl_clip_state_flush (&draw_buffer->clip_state);
-
- if (!(flags & COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW))
- _cogl_matrix_stack_flush_to_gl (draw_buffer->modelview_stack,
- COGL_MATRIX_MODELVIEW);
-
- _cogl_matrix_stack_flush_to_gl (draw_buffer->projection_stack,
- COGL_MATRIX_PROJECTION);
-}
-
-int
-_cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer)
-{
- _cogl_framebuffer_init_bits (framebuffer);
-
- return framebuffer->red_bits;
-}
-
-int
-_cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer)
-{
- _cogl_framebuffer_init_bits (framebuffer);
-
- return framebuffer->green_bits;
-}
-
-int
-_cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer)
-{
- _cogl_framebuffer_init_bits (framebuffer);
-
- return framebuffer->blue_bits;
-}
-
-int
-_cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer)
-{
- _cogl_framebuffer_init_bits (framebuffer);
-
- return framebuffer->alpha_bits;
-}
-
-gboolean
-_cogl_framebuffer_try_fast_read_pixel (CoglFramebuffer *framebuffer,
- int x,
- int y,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixel)
-{
- gboolean found_intersection;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FAST_READ_PIXEL)))
- return FALSE;
-
- if (source != COGL_READ_PIXELS_COLOR_BUFFER)
- return FALSE;
-
- if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
- format != COGL_PIXEL_FORMAT_RGBA_8888)
- return FALSE;
-
- if (!_cogl_journal_try_read_pixel (framebuffer->journal,
- x, y, format, pixel,
- &found_intersection))
- return FALSE;
-
- /* If we can't determine the color from the primitives in the
- * journal then see if we can use the last recorded clear color
- */
-
- /* If _cogl_journal_try_read_pixel() failed even though there was an
- * intersection of the given point with a primitive in the journal
- * then we can't fallback to the framebuffer's last clear color...
- * */
- if (found_intersection)
- return TRUE;
-
- /* If the framebuffer has been rendered too since it was last
- * cleared then we can't return the last known clear color. */
- if (framebuffer->clear_clip_dirty)
- return FALSE;
-
- if (x >= framebuffer->clear_clip_x0 &&
- x < framebuffer->clear_clip_x1 &&
- y >= framebuffer->clear_clip_y0 &&
- y < framebuffer->clear_clip_y1)
- {
-
- /* we currently only care about cases where the premultiplied or
- * unpremultipled colors are equivalent... */
- if (framebuffer->clear_color_alpha != 1.0)
- return FALSE;
-
- pixel[0] = framebuffer->clear_color_red * 255.0;
- pixel[1] = framebuffer->clear_color_green * 255.0;
- pixel[2] = framebuffer->clear_color_blue * 255.0;
- pixel[3] = framebuffer->clear_color_alpha * 255.0;
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-_cogl_blit_framebuffer (unsigned int src_x,
- unsigned int src_y,
- unsigned int dst_x,
- unsigned int dst_y,
- unsigned int width,
- unsigned int height)
-{
- CoglFramebuffer *draw_buffer;
- CoglFramebuffer *read_buffer;
- CoglContext *ctx;
-
- /* FIXME: this function should take explit src and dst framebuffer
- * arguments. */
- draw_buffer = cogl_get_draw_framebuffer ();
- read_buffer = _cogl_get_read_framebuffer ();
- ctx = draw_buffer->context;
-
- g_return_if_fail (cogl_features_available (COGL_FEATURE_OFFSCREEN_BLIT));
- /* We can only support blitting between offscreen buffers because
- otherwise we would need to mirror the image and GLES2.0 doesn't
- support this */
- g_return_if_fail (cogl_is_offscreen (draw_buffer));
- g_return_if_fail (cogl_is_offscreen (read_buffer));
- /* The buffers must be the same format */
- g_return_if_fail (draw_buffer->format == read_buffer->format);
-
- /* Make sure the current framebuffers are bound. We explicitly avoid
- flushing the clip state so we can bind our own empty state */
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- _cogl_get_read_framebuffer (),
- COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE);
-
- /* Flush any empty clip stack because glBlitFramebuffer is affected
- by the scissor and we want to hide this feature for the Cogl API
- because it's not obvious to an app how the clip state will affect
- the scissor */
- _cogl_clip_stack_flush (NULL);
-
- glBlitFramebuffer (src_x, src_y,
- src_x + width, src_y + height,
- dst_x, dst_y,
- dst_x + width, dst_y + height,
- GL_COLOR_BUFFER_BIT,
- GL_NEAREST);
-}
-
-void
-cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer)
-{
- /* FIXME: we shouldn't need to flush *all* journals here! */
- cogl_flush ();
- if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
- {
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- winsys->onscreen_swap_buffers (COGL_ONSCREEN (framebuffer));
- }
-}
-
-void
-cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
- int *rectangles,
- int n_rectangles)
-{
- /* FIXME: we shouldn't need to flush *all* journals here! */
- cogl_flush ();
- if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
- {
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- winsys->onscreen_swap_region (COGL_ONSCREEN (framebuffer),
- rectangles,
- n_rectangles);
- }
-}
-
-#ifdef COGL_HAS_X11_SUPPORT
-void
-cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
- guint32 xid,
- CoglOnscreenX11MaskCallback update,
- void *user_data)
-{
- /* We don't wan't applications to get away with being lazy here and not
- * passing an update callback... */
- g_return_if_fail (update);
-
- onscreen->foreign_xid = xid;
- onscreen->foreign_update_mask_callback = update;
- onscreen->foreign_update_mask_data = user_data;
-}
-
-guint32
-cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
-
- return winsys->onscreen_x11_get_window_xid (onscreen);
-}
-
-guint32
-cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
- XVisualInfo *visinfo = winsys->xlib_get_visual_info ();
- guint32 id = (guint32)visinfo->visualid;
-
- XFree (visinfo);
- return id;
-}
-#endif /* COGL_HAS_X11_SUPPORT */
-
-unsigned int
-cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
- CoglSwapBuffersNotify callback,
- void *user_data)
-{
- CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
-
- /* Should this just be cogl_onscreen API instead? */
- g_return_val_if_fail (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN, 0);
-
- return winsys->onscreen_add_swap_buffers_callback (onscreen,
- callback,
- user_data);
-}
-
-void
-cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
- unsigned int id)
-{
- CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
- const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
-
- winsys->onscreen_remove_swap_buffers_callback (onscreen, id);
-}
-
-void
-cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
- gboolean throttled)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- onscreen->swap_throttled = throttled;
- if (framebuffer->allocated)
- {
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- winsys->onscreen_update_swap_throttled (onscreen);
- }
-}
-
-void
-cogl_onscreen_show (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- const CoglWinsysVtable *winsys;
-
- if (!framebuffer->allocated)
- {
- if (!cogl_framebuffer_allocate (framebuffer, NULL))
- return;
- }
-
- winsys = _cogl_framebuffer_get_winsys (framebuffer);
- if (winsys->onscreen_set_visibility)
- winsys->onscreen_set_visibility (onscreen, TRUE);
-}
-
-void
-cogl_onscreen_hide (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-
- if (framebuffer->allocated)
- {
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- if (winsys->onscreen_set_visibility)
- winsys->onscreen_set_visibility (onscreen, FALSE);
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_FRAMEBUFFER_H
-#define __COGL_FRAMEBUFFER_H
-
-#include <glib.h>
-
-
-G_BEGIN_DECLS
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-#define cogl_onscreen_new cogl_onscreen_new_EXP
-
-#define COGL_FRAMEBUFFER(X) ((CoglFramebuffer *)(X))
-
-#define cogl_framebuffer_allocate cogl_framebuffer_allocate_EXP
-gboolean
-cogl_framebuffer_allocate (CoglFramebuffer *framebuffer,
- GError **error);
-
-#define cogl_framebuffer_get_width cogl_framebuffer_get_width_EXP
-int
-cogl_framebuffer_get_width (CoglFramebuffer *framebuffer);
-
-#define cogl_framebuffer_get_height cogl_framebuffer_get_height_EXP
-int
-cogl_framebuffer_get_height (CoglFramebuffer *framebuffer);
-
-#define cogl_framebuffer_swap_buffers cogl_framebuffer_swap_buffers_EXP
-void
-cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
-
-#define cogl_framebuffer_swap_region cogl_framebuffer_swap_region_EXP
-void
-cogl_framebuffer_swap_region (CoglFramebuffer *framebuffer,
- int *rectangles,
- int n_rectangles);
-
-
-typedef void (*CoglSwapBuffersNotify) (CoglFramebuffer *framebuffer,
- void *user_data);
-
-#define cogl_framebuffer_add_swap_buffers_callback \
- cogl_framebuffer_add_swap_buffers_callback_EXP
-unsigned int
-cogl_framebuffer_add_swap_buffers_callback (CoglFramebuffer *framebuffer,
- CoglSwapBuffersNotify callback,
- void *user_data);
-
-#define cogl_framebuffer_remove_swap_buffers_callback \
- cogl_framebuffer_remove_swap_buffers_callback_EXP
-void
-cogl_framebuffer_remove_swap_buffers_callback (CoglFramebuffer *framebuffer,
- unsigned int id);
-
-
-typedef struct _CoglOnscreen CoglOnscreen;
-#define COGL_ONSCREEN(X) ((CoglOnscreen *)(X))
-
-CoglOnscreen *
-cogl_onscreen_new (CoglContext *context, int width, int height);
-
-#ifdef COGL_HAS_X11
-typedef void (*CoglOnscreenX11MaskCallback) (CoglOnscreen *onscreen,
- guint32 event_mask,
- void *user_data);
-
-/**
- * cogl_onscreen_x11_set_foreign_window_xid:
- * @onscreen: The unallocated framebuffer to associated with an X
- * window.
- * @xid: The XID of an existing X window
- * @update: A callback that notifies of updates to what Cogl requires
- * to be in the core X protocol event mask.
- *
- * Ideally we would recommend that you let Cogl be responsible for
- * creating any X window required to back an onscreen framebuffer but
- * if you really need to target a window created manually this
- * function can be called before @onscreen has been allocated to set a
- * foreign XID for your existing X window.
- *
- * Since Cogl needs, for example, to track changes to the size of an X
- * window it requires that certain events be selected for via the core
- * X protocol. This requirement may also be changed asynchronously so
- * you must pass in an @update callback to inform you of Cogl's
- * required event mask.
- *
- * For example if you are using Xlib you could use this API roughly
- * as follows:
- * [{
- * static void
- * my_update_cogl_x11_event_mask (CoglOnscreen *onscreen,
- * guint32 event_mask,
- * void *user_data)
- * {
- * XSetWindowAttributes attrs;
- * MyData *data = user_data;
- * attrs.event_mask = event_mask | data->my_event_mask;
- * XChangeWindowAttributes (data->xdpy,
- * data->xwin,
- * CWEventMask,
- * &attrs);
- * }
- *
- * {
- * *snip*
- * cogl_onscreen_x11_set_foreign_window_xid (onscreen,
- * data->xwin,
- * my_update_cogl_x11_event_mask,
- * data);
- * *snip*
- * }
- * }]
- *
- * Since: 2.0
- * Stability: Unstable
- */
-#define cogl_onscreen_x11_set_foreign_window_xid \
- cogl_onscreen_x11_set_foreign_window_xid_EXP
-void
-cogl_onscreen_x11_set_foreign_window_xid (CoglOnscreen *onscreen,
- guint32 xid,
- CoglOnscreenX11MaskCallback update,
- void *user_data);
-
-#define cogl_onscreen_x11_get_window_xid cogl_onscreen_x11_get_window_xid_EXP
-guint32
-cogl_onscreen_x11_get_window_xid (CoglOnscreen *onscreen);
-
-#define cogl_onscreen_x11_get_visual_xid cogl_onscreen_x11_get_visual_xid_EXP
-guint32
-cogl_onscreen_x11_get_visual_xid (CoglOnscreen *onscreen);
-#endif /* COGL_HAS_X11 */
-
-#define cogl_onscreen_set_swap_throttled cogl_onscreen_set_swap_throttled_EXP
-void
-cogl_onscreen_set_swap_throttled (CoglOnscreen *onscreen,
- gboolean throttled);
-
-/**
- * cogl_onscreen_show:
- * @onscreen: The onscreen framebuffer to make visible
- *
- * This requests to make @onscreen visible to the user.
- *
- * Actually the precise semantics of this function depend on the
- * window system currently in use, and if you don't have a
- * multi-windowining system this function may in-fact do nothing.
- *
- * This function will implicitly allocate the given @onscreen
- * framebuffer before showing it if it hasn't already been allocated.
- *
- * <note>Since Cogl doesn't explicitly track the visibility status of
- * onscreen framebuffers it wont try to avoid redundant window system
- * requests e.g. to show an already visible window. This also means
- * that it's acceptable to alternatively use native APIs to show and
- * hide windows without confusing Cogl.</note>
- *
- * Since: 2.0
- * Stability: Unstable
- */
-#define cogl_onscreen_show cogl_onscreen_show_EXP
-void
-cogl_onscreen_show (CoglOnscreen *onscreen);
-
-/**
- * cogl_onscreen_hide:
- * @onscreen: The onscreen framebuffer to make invisible
- *
- * This requests to make @onscreen invisible to the user.
- *
- * Actually the precise semantics of this function depend on the
- * window system currently in use, and if you don't have a
- * multi-windowining system this function may in-fact do nothing.
- *
- * This function does not implicitly allocate the given @onscreen
- * framebuffer before hiding it.
- *
- * <note>Since Cogl doesn't explicitly track the visibility status of
- * onscreen framebuffers it wont try to avoid redundant window system
- * requests e.g. to show an already visible window. This also means
- * that it's acceptable to alternatively use native APIs to show and
- * hide windows without confusing Cogl.</note>
- *
- * Since: 2.0
- * Stability: Unstable
- */
-#define cogl_onscreen_hide cogl_onscreen_hide_EXP
-void
-cogl_onscreen_hide (CoglOnscreen *onscreen);
-
-#define cogl_get_draw_framebuffer cogl_get_draw_framebuffer_EXP
-CoglFramebuffer *
-cogl_get_draw_framebuffer (void);
-
-#endif /* COGL_ENABLE_EXPERIMENTAL_API */
-
-G_END_DECLS
-
-#endif /* __COGL_FRAMEBUFFER_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#include <glib.h>
-#include <glib-object.h>
-
-#ifndef __COGL_GTYPE_PRIVATE_H__
-#define __COGL_GTYPE_PRIVATE_H__
-
-#define COGL_GTYPE_DEFINE_BOXED(Name, underscore_name, copy_func, free_func) \
-GType \
-cogl_gtype_ ## underscore_name ## _get_type (void) \
-{ \
- static volatile gsize type_volatile = 0; \
- if (g_once_init_enter (&type_volatile)) \
- { \
- GType type = \
- g_boxed_type_register_static (g_intern_static_string ("Cogl" Name), \
- (GBoxedCopyFunc)copy_func, \
- (GBoxedFreeFunc)free_func); \
- g_once_init_leave (&type_volatile, type); \
- } \
- return type_volatile; \
-}
-
-#endif /* __COGL_GTYPE_PRIVATE_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This file is just kept for compatability while we eradicate
- * CoglHandle
- */
-
-#ifndef __COGL_HANDLE_H
-#define __COGL_HANDLE_H
-
-#include "cogl-object-private.h"
-
-#endif /* __COGL_HANDLE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_INDEX_ARRAY_PRIVATE_H
-#define __COGL_INDEX_ARRAY_PRIVATE_H
-
-#include "cogl-buffer-private.h"
-
-struct _CoglIndexArray
-{
- CoglBuffer _parent;
-};
-
-#endif /* __COGL_INDEX_ARRAY_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-object-private.h"
-#include "cogl-indices.h"
-#include "cogl-indices-private.h"
-
-static void _cogl_index_array_free (CoglIndexArray *indices);
-
-COGL_BUFFER_DEFINE (IndexArray, index_array);
-
-/* XXX: Unlike the wiki design this just takes a size. A single
- * indices buffer should be able to contain multiple ranges of indices
- * which the wiki design doesn't currently consider. */
-CoglIndexArray *
-cogl_index_array_new (gsize bytes)
-{
- CoglIndexArray *indices = g_slice_new (CoglIndexArray);
- gboolean use_malloc;
-
- if (!cogl_features_available (COGL_FEATURE_VBOS))
- use_malloc = TRUE;
- else
- use_malloc = FALSE;
-
- /* parent's constructor */
- _cogl_buffer_initialize (COGL_BUFFER (indices),
- bytes,
- use_malloc,
- COGL_BUFFER_BIND_TARGET_INDEX_ARRAY,
- COGL_BUFFER_USAGE_HINT_INDEX_ARRAY,
- COGL_BUFFER_UPDATE_HINT_STATIC);
-
- return _cogl_index_array_object_new (indices);
-}
-
-static void
-_cogl_index_array_free (CoglIndexArray *indices)
-{
- /* parent's destructor */
- _cogl_buffer_fini (COGL_BUFFER (indices));
-
- g_slice_free (CoglIndexArray, indices);
-}
-
-gboolean
-cogl_index_array_allocate (CoglIndexArray *indices,
- GError *error)
-{
- /* TODO */
- return TRUE;
-}
-
-/* XXX: do we want a convenience function like this as an alternative
- * to using cogl_buffer_set_data? The advantage of this is that we can
- * track meta data such as the indices type and max_index_value for a
- * range as part of the indices array. If we just leave people to use
- * cogl_buffer_set_data then we either need a way to specify the type
- * and max index value at draw time or we'll want a separate way to
- * declare the type and max value for a range after uploading the
- * data.
- *
- * XXX: I think in the end it'll be that CoglIndices are to
- * CoglIndexArrays as CoglAttributes are to CoglVertices. I.e
- * a CoglIndexArray is a lite subclass of CoglBuffer that simply
- * implies that the buffer will later be bound as indices but doesn't
- * track more detailed meta data. CoglIndices build on a
- * CoglIndexArray and define the type and max_index_value for some
- * sub-range of a CoglIndexArray.
- *
- * XXX: The double plurel form that "Indices" "Array" implies could be
- * a bit confusing. Also to be a bit more consistent with
- * CoglVertexArray vs CoglAttribute it might be best to rename so
- * we have CoglIndexArray vs CoglIndices? maybe even
- * CoglIndexRange :-/ ?
- *
- * CoglBuffer
- * CoglVertexArray (buffer sub-class)
- * CoglPrimitive (defines meta data for sub-region of array)
- * CoglPixelArray (buffer sub-class)
- * CoglIndexArray (buffer sub-class)
- * CoglIndices (defines meta data for sub-region of array)
- *
- */
-#if 0
-void
-cogl_index_array_set_data (CoglIndexArray *indices,
- CoglIndicesType type,
- int max_index_value,
- gsize write_offset,
- void *user_indices,
- int n_indices)
-{
- GList *l;
-
- for (l = indices->ranges; l; l = l->next)
- {
-
- }
- cogl_buffer_set
-}
-#endif
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_INDEX_ARRAY_H__
-#define __COGL_INDEX_ARRAY_H__
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-vertex-indices
- * @short_description: Functions for creating and manipulating vertex
- * indices.
- *
- * FIXME
- */
-
-typedef struct _CoglIndexArray CoglIndexArray;
-
-/**
- * cogl_index_array_new:
- * @bytes: The number of bytes to allocate for vertex attribute data.
- *
- * Declares a new #CoglIndexArray of @size bytes to contain vertex
- * indices. Once declared, data can be set using
- * cogl_buffer_set_data() or by mapping it into the application's
- * address space using cogl_buffer_map().
- *
- * Since: 1.4
- * Stability: Unstable
- */
-CoglIndexArray *
-cogl_index_array_new (gsize bytes);
-
-/**
- * cogl_is_indices_array:
- * @object: A #CoglObject
- *
- * Gets whether the given object references a #CoglIndexArray.
- *
- * Returns: %TRUE if the handle references a #CoglIndexArray,
- * %FALSE otherwise
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_is_indices_array (void *object);
-
-G_END_DECLS
-
-#endif /* __COGL_INDEX_ARRAY_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_INDICES_PRIVATE_H
-#define __COGL_INDICES_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-index-array-private.h"
-#include "cogl-types.h"
-
-struct _CoglIndices
-{
- CoglObject _parent;
-
- CoglIndexArray *array;
- size_t offset;
-
- CoglIndicesType type;
-
- int immutable_ref;
-};
-
-CoglIndices *
-_cogl_indices_immutable_ref (CoglIndices *indices);
-
-void
-_cogl_indices_immutable_unref (CoglIndices *indices);
-
-#endif /* __COGL_INDICES_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-object-private.h"
-#include "cogl-context-private.h"
-#include "cogl-indices.h"
-#include "cogl-indices-private.h"
-#include "cogl-index-array.h"
-
-#include <stdarg.h>
-
-static void _cogl_indices_free (CoglIndices *indices);
-
-COGL_OBJECT_DEFINE (Indices, indices);
-
-static size_t
-sizeof_indices_type (CoglIndicesType type)
-{
- switch (type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- return 1;
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- return 2;
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- return 4;
- }
- g_return_val_if_reached (0);
-}
-
-CoglIndices *
-cogl_indices_new_for_array (CoglIndicesType type,
- CoglIndexArray *array,
- gsize offset)
-{
- CoglIndices *indices = g_slice_new (CoglIndices);
-
- indices->array = cogl_object_ref (array);
- indices->offset = offset;
-
- indices->type = type;
-
- indices->immutable_ref = 0;
-
- return _cogl_indices_object_new (indices);
-}
-
-CoglIndices *
-cogl_indices_new (CoglIndicesType type,
- const void *indices_data,
- int n_indices)
-{
- size_t array_bytes = sizeof_indices_type (type) * n_indices;
- CoglIndexArray *array = cogl_index_array_new (array_bytes);
- CoglBuffer *buffer = COGL_BUFFER (array);
- CoglIndices *indices;
-
- cogl_buffer_set_data (buffer,
- 0,
- indices_data,
- array_bytes);
-
- indices = cogl_indices_new_for_array (type, array, 0);
- cogl_object_unref (array);
-
- return indices;
-}
-
-CoglIndexArray *
-cogl_indices_get_array (CoglIndices *indices)
-{
- return indices->array;
-}
-
-CoglIndicesType
-cogl_indices_get_type (CoglIndices *indices)
-{
- g_return_val_if_fail (cogl_is_indices (indices),
- COGL_INDICES_TYPE_UNSIGNED_BYTE);
- return indices->type;
-}
-
-gsize
-cogl_indices_get_offset (CoglIndices *indices)
-{
- g_return_val_if_fail (cogl_is_indices (indices), 0);
-
- return indices->offset;
-}
-
-static void
-warn_about_midscene_changes (void)
-{
- static gboolean seen = FALSE;
- if (!seen)
- {
- g_warning ("Mid-scene modification of indices has "
- "undefined results\n");
- seen = TRUE;
- }
-}
-
-void
-cogl_indices_set_offset (CoglIndices *indices,
- gsize offset)
-{
- g_return_if_fail (cogl_is_indices (indices));
-
- if (G_UNLIKELY (indices->immutable_ref))
- warn_about_midscene_changes ();
-
- indices->offset = offset;
-}
-
-static void
-_cogl_indices_free (CoglIndices *indices)
-{
- cogl_object_unref (indices->array);
- g_slice_free (CoglIndices, indices);
-}
-
-CoglIndices *
-_cogl_indices_immutable_ref (CoglIndices *indices)
-{
- g_return_val_if_fail (cogl_is_indices (indices), NULL);
-
- indices->immutable_ref++;
- _cogl_buffer_immutable_ref (COGL_BUFFER (indices->array));
- return indices;
-}
-
-void
-_cogl_indices_immutable_unref (CoglIndices *indices)
-{
- g_return_if_fail (cogl_is_indices (indices));
- g_return_if_fail (indices->immutable_ref > 0);
-
- indices->immutable_ref--;
- _cogl_buffer_immutable_unref (COGL_BUFFER (indices->array));
-}
-
-CoglIndices *
-cogl_get_rectangle_indices (int n_rectangles)
-{
- int n_indices = n_rectangles * 6;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- /* Check if the largest index required will fit in a byte array... */
- if (n_indices <= 256 / 4 * 6)
- {
- /* Generate the byte array if we haven't already */
- if (ctx->rectangle_byte_indices == NULL)
- {
- guint8 *byte_array = g_malloc (256 / 4 * 6 * sizeof (guint8));
- guint8 *p = byte_array;
- int i, vert_num = 0;
-
- for (i = 0; i < 256 / 4; i++)
- {
- *(p++) = vert_num + 0;
- *(p++) = vert_num + 1;
- *(p++) = vert_num + 2;
- *(p++) = vert_num + 0;
- *(p++) = vert_num + 2;
- *(p++) = vert_num + 3;
- vert_num += 4;
- }
-
- ctx->rectangle_byte_indices
- = cogl_indices_new (COGL_INDICES_TYPE_UNSIGNED_BYTE,
- byte_array,
- 256 / 4 * 6);
-
- g_free (byte_array);
- }
-
- return ctx->rectangle_byte_indices;
- }
- else
- {
- if (ctx->rectangle_short_indices_len < n_indices)
- {
- guint16 *short_array;
- guint16 *p;
- int i, vert_num = 0;
-
- if (ctx->rectangle_short_indices != NULL)
- cogl_object_unref (ctx->rectangle_short_indices);
- /* Pick a power of two >= MAX (512, n_indices) */
- if (ctx->rectangle_short_indices_len == 0)
- ctx->rectangle_short_indices_len = 512;
- while (ctx->rectangle_short_indices_len < n_indices)
- ctx->rectangle_short_indices_len *= 2;
-
- /* Over-allocate to generate a whole number of quads */
- p = short_array = g_malloc ((ctx->rectangle_short_indices_len
- + 5) / 6 * 6
- * sizeof (guint16));
-
- /* Fill in the complete quads */
- for (i = 0; i < ctx->rectangle_short_indices_len; i += 6)
- {
- *(p++) = vert_num + 0;
- *(p++) = vert_num + 1;
- *(p++) = vert_num + 2;
- *(p++) = vert_num + 0;
- *(p++) = vert_num + 2;
- *(p++) = vert_num + 3;
- vert_num += 4;
- }
-
- ctx->rectangle_short_indices
- = cogl_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
- short_array,
- ctx->rectangle_short_indices_len);
-
- g_free (short_array);
- }
-
- return ctx->rectangle_short_indices;
- }
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_INDICES_H__
-#define __COGL_INDICES_H__
-
-#include <cogl/cogl-index-array.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-index-range
- * @short_description: Fuctions for declaring a range of vertex indices
- * stored in a #CoglIndexArray.
- *
- * FIXME
- */
-
-typedef struct _CoglIndices CoglIndices;
-
-CoglIndices *
-cogl_indices_new (CoglIndicesType type,
- const void *indices_data,
- int n_indices);
-
-CoglIndices *
-cogl_indices_new_for_array (CoglIndicesType type,
- CoglIndexArray *array,
- gsize offset);
-
-CoglIndexArray *
-cogl_indices_get_array (CoglIndices *indices);
-
-CoglIndicesType
-cogl_indices_get_type (CoglIndices *indices);
-
-gsize
-cogl_indices_get_offset (CoglIndices *indices);
-
-void
-cogl_indices_set_offset (CoglIndices *indices,
- gsize offset);
-
-CoglIndices *
-cogl_get_rectangle_indices (int n_rectangles);
-
-G_END_DECLS
-
-#endif /* __COGL_INDICES_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_INTERNAL_H
-#define __COGL_INTERNAL_H
-
-#include "cogl.h"
-#include "cogl-matrix-stack.h"
-#include "cogl-bitmask.h"
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include <X11/Xutil.h>
-#endif
-
-typedef enum
-{
- COGL_FRONT_WINDING_CLOCKWISE,
- COGL_FRONT_WINDING_COUNTER_CLOCKWISE
-} CoglFrontWinding;
-
-typedef enum {
- COGL_BOXED_NONE,
- COGL_BOXED_INT,
- COGL_BOXED_FLOAT,
- COGL_BOXED_MATRIX
-} CoglBoxedType;
-
-typedef struct _CoglBoxedValue
-{
- CoglBoxedType type;
- int size, count;
- gboolean transpose;
-
- union {
- float float_value[4];
- int int_value[4];
- float matrix[16];
- float *float_array;
- int *int_array;
- void *array;
- } v;
-} CoglBoxedValue;
-
-#ifdef COGL_GL_DEBUG
-
-const char *
-cogl_gl_error_to_string (GLenum error_code);
-
-#define GE(x) G_STMT_START { \
- GLenum __err; \
- (x); \
- while ((__err = glGetError ()) != GL_NO_ERROR) \
- { \
- g_warning ("%s: GL error (%d): %s\n", \
- G_STRLOC, \
- __err, \
- cogl_gl_error_to_string (__err)); \
- } } G_STMT_END
-
-#define GE_RET(ret, x) G_STMT_START { \
- GLenum __err; \
- ret = (x); \
- while ((__err = glGetError ()) != GL_NO_ERROR) \
- { \
- g_warning ("%s: GL error (%d): %s\n", \
- G_STRLOC, \
- __err, \
- cogl_gl_error_to_string (__err)); \
- } } G_STMT_END
-
-#else /* !COGL_GL_DEBUG */
-
-#define GE(x) (x)
-#define GE_RET(ret, x) (ret = (x))
-
-#endif /* COGL_GL_DEBUG */
-
-#define COGL_ENABLE_ALPHA_TEST (1<<1)
-#define COGL_ENABLE_VERTEX_ARRAY (1<<2)
-#define COGL_ENABLE_COLOR_ARRAY (1<<3)
-#define COGL_ENABLE_BACKFACE_CULLING (1<<4)
-
-int
-_cogl_get_format_bpp (CoglPixelFormat format);
-
-void
-_cogl_enable (unsigned long flags);
-
-unsigned long
-_cogl_get_enable (void);
-
-void
-_cogl_flush_face_winding (void);
-
-void
-_cogl_transform_point (const CoglMatrix *matrix_mv,
- const CoglMatrix *matrix_p,
- const float *viewport,
- float *x,
- float *y);
-
-#define COGL_DRIVER_ERROR (_cogl_driver_error_quark ())
-
-typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/
- COGL_DRIVER_ERROR_UNKNOWN_VERSION,
- COGL_DRIVER_ERROR_INVALID_VERSION
-} CoglDriverError;
-
-gboolean
-_cogl_check_extension (const char *name, const char *ext);
-
-GQuark
-_cogl_driver_error_quark (void);
-
-#endif /* __COGL_INTERNAL_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_JOURNAL_PRIVATE_H
-#define __COGL_JOURNAL_PRIVATE_H
-
-#include "cogl.h"
-#include "cogl-handle.h"
-#include "cogl-clip-stack.h"
-
-typedef struct _CoglJournal
-{
- CoglObject _parent;
-
- GArray *entries;
- GArray *vertices;
- size_t needed_vbo_len;
-
- int fast_read_pixel_count;
-
-} CoglJournal;
-
-/* To improve batching of geometry when submitting vertices to OpenGL we
- * log the texture rectangles we want to draw to a journal, so when we
- * later flush the journal we aim to batch data, and gl draw calls. */
-typedef struct _CoglJournalEntry
-{
- CoglPipeline *pipeline;
- int n_layers;
- CoglMatrix model_view;
- CoglClipStack *clip_stack;
- /* Offset into ctx->logged_vertices */
- size_t array_offset;
- /* XXX: These entries are pretty big now considering the padding in
- * CoglPipelineFlushOptions and CoglMatrix, so we might need to optimize this
- * later. */
-} CoglJournalEntry;
-
-CoglJournal *
-_cogl_journal_new (void);
-
-void
-_cogl_journal_log_quad (CoglJournal *journal,
- const float *position,
- CoglPipeline *pipeline,
- int n_layers,
- CoglHandle layer0_override_texture,
- const float *tex_coords,
- unsigned int tex_coords_len);
-
-void
-_cogl_journal_flush (CoglJournal *journal,
- CoglFramebuffer *framebuffer);
-
-void
-_cogl_journal_discard (CoglJournal *journal);
-
-gboolean
-_cogl_journal_all_entries_within_bounds (CoglJournal *journal,
- float clip_x0,
- float clip_y0,
- float clip_x1,
- float clip_y1);
-
-gboolean
-_cogl_journal_try_read_pixel (CoglJournal *journal,
- int x,
- int y,
- CoglPixelFormat format,
- guint8 *pixel,
- gboolean *found_intersection);
-
-#endif /* __COGL_JOURNAL_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-vertex-buffer-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-profile.h"
-#include "cogl-attribute-private.h"
-#include "cogl-point-in-poly-private.h"
-
-#include <string.h>
-#include <gmodule.h>
-#include <math.h>
-
-/* XXX NB:
- * The data logged in logged_vertices is formatted as follows:
- *
- * Per entry:
- * 4 RGBA GLubytes for the color
- * 2 floats for the top left position
- * 2 * n_layers floats for the top left texture coordinates
- * 2 floats for the bottom right position
- * 2 * n_layers floats for the bottom right texture coordinates
- */
-#define GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS(N_LAYERS) \
- (N_LAYERS * 2 + 2)
-
-/* XXX NB:
- * Once in the vertex array, the journal's vertex data is arranged as follows:
- * 4 vertices per quad:
- * 2 or 3 GLfloats per position (3 when doing software transforms)
- * 4 RGBA GLubytes,
- * 2 GLfloats per tex coord * n_layers
- *
- * Where n_layers corresponds to the number of pipeline layers enabled
- *
- * To avoid frequent changes in the stride of our vertex data we always pad
- * n_layers to be >= 2
- *
- * There will be four vertices per quad in the vertex array
- *
- * When we are transforming quads in software we need to also track the z
- * coordinate of transformed vertices.
- *
- * So for a given number of layers this gets the stride in 32bit words:
- */
-#define SW_TRANSFORM (!(COGL_DEBUG_ENABLED \
- (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
-#define POS_STRIDE (SW_TRANSFORM ? 3 : 2) /* number of 32bit words */
-#define N_POS_COMPONENTS POS_STRIDE
-#define COLOR_STRIDE 1 /* number of 32bit words */
-#define TEX_STRIDE 2 /* number of 32bit words */
-#define MIN_LAYER_PADING 2
-#define GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS(N_LAYERS) \
- (POS_STRIDE + COLOR_STRIDE + \
- TEX_STRIDE * (N_LAYERS < MIN_LAYER_PADING ? MIN_LAYER_PADING : N_LAYERS))
-
-/* If a batch is longer than this threshold then we'll assume it's not
- worth doing software clipping and it's cheaper to program the GPU
- to do the clip */
-#define COGL_JOURNAL_HARDWARE_CLIP_THRESHOLD 8
-
-typedef struct _CoglJournalFlushState
-{
- CoglJournal *journal;
-
- CoglVertexArray *vertex_array;
- GArray *attributes;
- int current_attribute;
-
- gsize stride;
- size_t array_offset;
- GLuint current_vertex;
-#ifndef HAVE_COGL_GL
- CoglIndices *indices;
- gsize indices_type_size;
-#endif
- CoglMatrixStack *modelview_stack;
- CoglMatrixStack *projection_stack;
-
- CoglPipeline *source;
-} CoglJournalFlushState;
-
-typedef void (*CoglJournalBatchCallback) (CoglJournalEntry *start,
- int n_entries,
- void *data);
-typedef gboolean (*CoglJournalBatchTest) (CoglJournalEntry *entry0,
- CoglJournalEntry *entry1);
-
-static void _cogl_journal_free (CoglJournal *journal);
-
-COGL_OBJECT_DEFINE (Journal, journal);
-
-static void
-_cogl_journal_free (CoglJournal *journal)
-{
- if (journal->entries)
- g_array_free (journal->entries, TRUE);
- if (journal->vertices)
- g_array_free (journal->vertices, TRUE);
- g_slice_free (CoglJournal, journal);
-}
-
-CoglJournal *
-_cogl_journal_new (void)
-{
- CoglJournal *journal = g_slice_new0 (CoglJournal);
-
- journal->entries = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
- journal->vertices = g_array_new (FALSE, FALSE, sizeof (float));
-
- return _cogl_journal_object_new (journal);
-}
-
-static void
-_cogl_journal_dump_logged_quad (guint8 *data, int n_layers)
-{
- gsize stride = GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (n_layers);
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_print ("n_layers = %d; rgba=0x%02X%02X%02X%02X\n",
- n_layers, data[0], data[1], data[2], data[3]);
-
- data += 4;
-
- for (i = 0; i < 2; i++)
- {
- float *v = (float *)data + (i * stride);
- int j;
-
- g_print ("v%d: x = %f, y = %f", i, v[0], v[1]);
-
- for (j = 0; j < n_layers; j++)
- {
- float *t = v + 2 + TEX_STRIDE * j;
- g_print (", tx%d = %f, ty%d = %f", j, t[0], j, t[1]);
- }
- g_print ("\n");
- }
-}
-
-static void
-_cogl_journal_dump_quad_vertices (guint8 *data, int n_layers)
-{
- gsize stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers);
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_print ("n_layers = %d; stride = %d; pos stride = %d; color stride = %d; "
- "tex stride = %d; stride in bytes = %d\n",
- n_layers, (int)stride, POS_STRIDE, COLOR_STRIDE,
- TEX_STRIDE, (int)stride * 4);
-
- for (i = 0; i < 4; i++)
- {
- float *v = (float *)data + (i * stride);
- guint8 *c = data + (POS_STRIDE * 4) + (i * stride * 4);
- int j;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED
- (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
- g_print ("v%d: x = %f, y = %f, rgba=0x%02X%02X%02X%02X",
- i, v[0], v[1], c[0], c[1], c[2], c[3]);
- else
- g_print ("v%d: x = %f, y = %f, z = %f, rgba=0x%02X%02X%02X%02X",
- i, v[0], v[1], v[2], c[0], c[1], c[2], c[3]);
- for (j = 0; j < n_layers; j++)
- {
- float *t = v + POS_STRIDE + COLOR_STRIDE + TEX_STRIDE * j;
- g_print (", tx%d = %f, ty%d = %f", j, t[0], j, t[1]);
- }
- g_print ("\n");
- }
-}
-
-static void
-_cogl_journal_dump_quad_batch (guint8 *data, int n_layers, int n_quads)
-{
- gsize byte_stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4;
- int i;
-
- g_print ("_cogl_journal_dump_quad_batch: n_layers = %d, n_quads = %d\n",
- n_layers, n_quads);
- for (i = 0; i < n_quads; i++)
- _cogl_journal_dump_quad_vertices (data + byte_stride * 2 * i, n_layers);
-}
-
-static void
-batch_and_call (CoglJournalEntry *entries,
- int n_entries,
- CoglJournalBatchTest can_batch_callback,
- CoglJournalBatchCallback batch_callback,
- void *data)
-{
- int i;
- int batch_len = 1;
- CoglJournalEntry *batch_start = entries;
-
- if (n_entries < 1)
- return;
-
- for (i = 1; i < n_entries; i++)
- {
- CoglJournalEntry *entry0 = &entries[i - 1];
- CoglJournalEntry *entry1 = entry0 + 1;
-
- if (can_batch_callback (entry0, entry1))
- {
- batch_len++;
- continue;
- }
-
- batch_callback (batch_start, batch_len, data);
-
- batch_start = entry1;
- batch_len = 1;
- }
-
- /* The last batch... */
- batch_callback (batch_start, batch_len, data);
-}
-
-static void
-_cogl_journal_flush_modelview_and_entries (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
- CoglAttribute **attributes;
- CoglDrawFlags draw_flags = (COGL_DRAW_SKIP_JOURNAL_FLUSH |
- COGL_DRAW_SKIP_PIPELINE_VALIDATION |
- COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH |
- COGL_DRAW_SKIP_LEGACY_STATE);
-
- COGL_STATIC_TIMER (time_flush_modelview_and_entries,
- "flush: pipeline+entries", /* parent */
- "flush: modelview+entries",
- "The time spent flushing modelview + entries",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context, time_flush_modelview_and_entries);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
- g_print ("BATCHING: modelview batch len = %d\n", batch_len);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
- {
- _cogl_matrix_stack_set (state->modelview_stack,
- &batch_start->model_view);
- _cogl_matrix_stack_flush_to_gl (state->modelview_stack,
- COGL_MATRIX_MODELVIEW);
- }
-
- attributes = (CoglAttribute **)state->attributes->data;
- cogl_push_source (state->source);
-
- if (!_cogl_pipeline_get_real_blend_enabled (state->source))
- draw_flags |= COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE;
-
-#ifdef HAVE_COGL_GL
-
- /* XXX: it's rather evil that we sneak in the GL_QUADS enum here... */
- _cogl_draw_attributes_array (GL_QUADS,
- state->current_vertex, batch_len * 4,
- attributes,
- draw_flags);
-
-#else /* HAVE_COGL_GL */
- if (batch_len > 1)
- {
- _cogl_draw_indexed_attributes_array (COGL_VERTICES_MODE_TRIANGLES,
- state->current_vertex * 6 / 4,
- batch_len * 6,
- state->indices,
- attributes,
- draw_flags);
-
- }
- else
- {
- _cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
- state->current_vertex, 4,
- attributes,
- draw_flags);
- }
-#endif
-
- /* DEBUGGING CODE XXX: This path will cause all rectangles to be
- * drawn with a coloured outline. Each batch will be rendered with
- * the same color. This may e.g. help with debugging texture slicing
- * issues, visually seeing what is batched and debugging blending
- * issues, plus it looks quite cool.
- */
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_RECTANGLES)))
- {
- static CoglPipeline *outline = NULL;
- guint8 color_intensity;
- int i;
- CoglAttribute *loop_attributes[2];
-
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- if (outline == NULL)
- outline = cogl_pipeline_new ();
-
- /* The least significant three bits represent the three
- components so that the order of colours goes red, green,
- yellow, blue, magenta, cyan. Black and white are skipped. The
- next two bits give four scales of intensity for those colours
- in the order 0xff, 0xcc, 0x99, and 0x66. This gives a total
- of 24 colours. If there are more than 24 batches on the stage
- then it will wrap around */
- color_intensity = 0xff - 0x33 * (ctxt->journal_rectangles_color >> 3);
- cogl_pipeline_set_color4ub (outline,
- (ctxt->journal_rectangles_color & 1) ?
- color_intensity : 0,
- (ctxt->journal_rectangles_color & 2) ?
- color_intensity : 0,
- (ctxt->journal_rectangles_color & 4) ?
- color_intensity : 0,
- 0xff);
- cogl_set_source (outline);
-
- loop_attributes[0] = attributes[0]; /* we just want the position */
- loop_attributes[1] = NULL;
- for (i = 0; i < batch_len; i++)
- _cogl_draw_attributes_array (COGL_VERTICES_MODE_LINE_LOOP,
- 4 * i + state->current_vertex, 4,
- loop_attributes,
- draw_flags);
-
- /* Go to the next color */
- do
- ctxt->journal_rectangles_color = ((ctxt->journal_rectangles_color + 1) &
- ((1 << 5) - 1));
- /* We don't want to use black or white */
- while ((ctxt->journal_rectangles_color & 0x07) == 0
- || (ctxt->journal_rectangles_color & 0x07) == 0x07);
- }
-
- state->current_vertex += (4 * batch_len);
-
- cogl_pop_source ();
-
- COGL_TIMER_STOP (_cogl_uprof_context, time_flush_modelview_and_entries);
-}
-
-static gboolean
-compare_entry_modelviews (CoglJournalEntry *entry0,
- CoglJournalEntry *entry1)
-{
- /* Batch together quads with the same model view matrix */
-
- /* FIXME: this is nasty, there are much nicer ways to track this
- * (at the add_quad_vertices level) without resorting to a memcmp!
- *
- * E.g. If the cogl-current-matrix code maintained an "age" for
- * the modelview matrix we could simply check in add_quad_vertices
- * if the age has increased, and if so record the change as a
- * boolean in the journal.
- */
-
- if (memcmp (&entry0->model_view, &entry1->model_view,
- sizeof (GLfloat) * 16) == 0)
- return TRUE;
- else
- return FALSE;
-}
-
-/* At this point we have a run of quads that we know have compatible
- * pipelines, but they may not all have the same modelview matrix */
-static void
-_cogl_journal_flush_pipeline_and_entries (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
- COGL_STATIC_TIMER (time_flush_pipeline_entries,
- "flush: texcoords+pipeline+entries", /* parent */
- "flush: pipeline+entries",
- "The time spent flushing pipeline + entries",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context, time_flush_pipeline_entries);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
- g_print ("BATCHING: pipeline batch len = %d\n", batch_len);
-
- state->source = batch_start->pipeline;
-
- /* If we haven't transformed the quads in software then we need to also break
- * up batches according to changes in the modelview matrix... */
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
- {
- batch_and_call (batch_start,
- batch_len,
- compare_entry_modelviews,
- _cogl_journal_flush_modelview_and_entries,
- data);
- }
- else
- _cogl_journal_flush_modelview_and_entries (batch_start, batch_len, data);
-
- COGL_TIMER_STOP (_cogl_uprof_context, time_flush_pipeline_entries);
-}
-
-static gboolean
-compare_entry_pipelines (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
-{
- /* batch rectangles using compatible pipelines */
-
- if (_cogl_pipeline_equal (entry0->pipeline,
- entry1->pipeline,
- (COGL_PIPELINE_STATE_ALL &
- ~COGL_PIPELINE_STATE_COLOR),
- COGL_PIPELINE_LAYER_STATE_ALL,
- 0))
- return TRUE;
- else
- return FALSE;
-}
-
-/* Since the stride may not reflect the number of texture layers in use
- * (due to padding) we deal with texture coordinate offsets separately
- * from vertex and color offsets... */
-static void
-_cogl_journal_flush_texcoord_vbo_offsets_and_entries (
- CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
- int i;
- COGL_STATIC_TIMER (time_flush_texcoord_pipeline_entries,
- "flush: vbo+texcoords+pipeline+entries", /* parent */
- "flush: texcoords+pipeline+entries",
- "The time spent flushing texcoord offsets + pipeline "
- "+ entries",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context, time_flush_texcoord_pipeline_entries);
-
- /* NB: attributes 0 and 1 are position and color */
-
- for (i = 2; i < state->attributes->len; i++)
- cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i));
-
- g_array_set_size (state->attributes, batch_start->n_layers + 2);
-
- for (i = 0; i < batch_start->n_layers; i++)
- {
- CoglAttribute **attribute_entry =
- &g_array_index (state->attributes, CoglAttribute *, i + 2);
- const char *names[] = {
- "cogl_tex_coord0_in",
- "cogl_tex_coord1_in",
- "cogl_tex_coord2_in",
- "cogl_tex_coord3_in",
- "cogl_tex_coord4_in",
- "cogl_tex_coord5_in",
- "cogl_tex_coord6_in",
- "cogl_tex_coord7_in"
- };
- char *name;
-
- /* XXX NB:
- * Our journal's vertex data is arranged as follows:
- * 4 vertices per quad:
- * 2 or 3 floats per position (3 when doing software transforms)
- * 4 RGBA bytes,
- * 2 floats per tex coord * n_layers
- * (though n_layers may be padded; see definition of
- * GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details)
- */
- name = i < 8 ? (char *)names[i] :
- g_strdup_printf ("cogl_tex_coord%d_in", i);
-
- /* XXX: it may be worth having some form of static initializer for
- * attributes... */
- *attribute_entry =
- cogl_attribute_new (state->vertex_array,
- name,
- state->stride,
- state->array_offset +
- (POS_STRIDE + COLOR_STRIDE) * 4 +
- TEX_STRIDE * 4 * i,
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
-
- if (i >= 8)
- g_free (name);
- }
-
- batch_and_call (batch_start,
- batch_len,
- compare_entry_pipelines,
- _cogl_journal_flush_pipeline_and_entries,
- data);
- COGL_TIMER_STOP (_cogl_uprof_context, time_flush_texcoord_pipeline_entries);
-}
-
-static gboolean
-compare_entry_n_layers (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
-{
- if (entry0->n_layers == entry1->n_layers)
- return TRUE;
- else
- return FALSE;
-}
-
-/* At this point we know the stride has changed from the previous batch
- * of journal entries */
-static void
-_cogl_journal_flush_vbo_offsets_and_entries (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
- gsize stride;
- int i;
- CoglAttribute **attribute_entry;
- COGL_STATIC_TIMER (time_flush_vbo_texcoord_pipeline_entries,
- "flush: clip+vbo+texcoords+pipeline+entries", /* parent */
- "flush: vbo+texcoords+pipeline+entries",
- "The time spent flushing vbo + texcoord offsets + "
- "pipeline + entries",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context,
- time_flush_vbo_texcoord_pipeline_entries);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
- g_print ("BATCHING: vbo offset batch len = %d\n", batch_len);
-
- /* XXX NB:
- * Our journal's vertex data is arranged as follows:
- * 4 vertices per quad:
- * 2 or 3 GLfloats per position (3 when doing software transforms)
- * 4 RGBA GLubytes,
- * 2 GLfloats per tex coord * n_layers
- * (though n_layers may be padded; see definition of
- * GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS for details)
- */
- stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (batch_start->n_layers);
- stride *= sizeof (float);
- state->stride = stride;
-
- for (i = 0; i < state->attributes->len; i++)
- cogl_object_unref (g_array_index (state->attributes, CoglAttribute *, i));
-
- g_array_set_size (state->attributes, 2);
-
- attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 0);
- *attribute_entry = cogl_attribute_new (state->vertex_array,
- "cogl_position_in",
- stride,
- state->array_offset,
- N_POS_COMPONENTS,
- COGL_ATTRIBUTE_TYPE_FLOAT);
-
- attribute_entry = &g_array_index (state->attributes, CoglAttribute *, 1);
- *attribute_entry =
- cogl_attribute_new (state->vertex_array,
- "cogl_color_in",
- stride,
- state->array_offset + (POS_STRIDE * 4),
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
-
-#ifndef HAVE_COGL_GL
- state->indices = cogl_get_rectangle_indices (batch_len);
-#endif
-
- /* We only create new Attributes when the stride within the
- * VertexArray changes. (due to a change in the number of pipeline
- * layers) While the stride remains constant we walk forward through
- * the above VertexArray using a vertex offset passed to
- * cogl_draw_attributes
- */
- state->current_vertex = 0;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
- {
- guint8 *verts;
-
- /* Mapping a buffer for read is probably a really bad thing to
- do but this will only happen during debugging so it probably
- doesn't matter */
- verts = ((guint8 *) cogl_buffer_map (COGL_BUFFER (state->vertex_array),
- COGL_BUFFER_ACCESS_READ, 0) +
- state->array_offset);
-
- _cogl_journal_dump_quad_batch (verts,
- batch_start->n_layers,
- batch_len);
-
- cogl_buffer_unmap (COGL_BUFFER (state->vertex_array));
- }
-
- batch_and_call (batch_start,
- batch_len,
- compare_entry_n_layers,
- _cogl_journal_flush_texcoord_vbo_offsets_and_entries,
- data);
-
- /* progress forward through the VBO containing all our vertices */
- state->array_offset += (stride * 4 * batch_len);
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
- g_print ("new vbo offset = %lu\n", (unsigned long)state->array_offset);
-
- COGL_TIMER_STOP (_cogl_uprof_context,
- time_flush_vbo_texcoord_pipeline_entries);
-}
-
-static gboolean
-compare_entry_strides (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
-{
- /* Currently the only thing that affects the stride for our vertex arrays
- * is the number of pipeline layers. We need to update our VBO offsets
- * whenever the stride changes. */
- /* TODO: We should be padding the n_layers == 1 case as if it were
- * n_layers == 2 so we can reduce the need to split batches. */
- if (entry0->n_layers == entry1->n_layers ||
- (entry0->n_layers <= MIN_LAYER_PADING &&
- entry1->n_layers <= MIN_LAYER_PADING))
- return TRUE;
- else
- return FALSE;
-}
-
-/* At this point we know the batch has a unique clip stack */
-static void
-_cogl_journal_flush_clip_stacks_and_entries (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
-
- COGL_STATIC_TIMER (time_flush_clip_stack_pipeline_entries,
- "Journal Flush", /* parent */
- "flush: clip+vbo+texcoords+pipeline+entries",
- "The time spent flushing clip + vbo + texcoord offsets + "
- "pipeline + entries",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context,
- time_flush_clip_stack_pipeline_entries);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
- g_print ("BATCHING: clip stack batch len = %d\n", batch_len);
-
- _cogl_clip_stack_flush (batch_start->clip_stack);
-
- _cogl_matrix_stack_push (state->modelview_stack);
-
- /* If we have transformed all our quads at log time then we ensure
- * no further model transform is applied by loading the identity
- * matrix here. We need to do this after flushing the clip stack
- * because the clip stack flushing code can modify the matrix */
- if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM))))
- {
- _cogl_matrix_stack_load_identity (state->modelview_stack);
- _cogl_matrix_stack_flush_to_gl (state->modelview_stack,
- COGL_MATRIX_MODELVIEW);
- }
-
- /* Setting up the clip state can sometimes also flush the projection
- matrix so we should flush it again. This will be a no-op if the
- clip code didn't modify the projection */
- _cogl_matrix_stack_flush_to_gl (state->projection_stack,
- COGL_MATRIX_PROJECTION);
-
- batch_and_call (batch_start,
- batch_len,
- compare_entry_strides,
- _cogl_journal_flush_vbo_offsets_and_entries, /* callback */
- data);
-
- _cogl_matrix_stack_pop (state->modelview_stack);
-
- COGL_TIMER_STOP (_cogl_uprof_context,
- time_flush_clip_stack_pipeline_entries);
-}
-
-static gboolean
-calculate_translation (const CoglMatrix *a,
- const CoglMatrix *b,
- float *tx_p,
- float *ty_p)
-{
- float tx, ty;
- int x, y;
-
- /* Assuming we had the original matrix in this form:
- *
- * [ a₁₁, a₁₂, a₁₃, a₁₄ ]
- * [ a₂₁, a₂₂, a₂₃, a₂₄ ]
- * a = [ a₃₁, a₃₂, a₃₃, a₃₄ ]
- * [ a₄₁, a₄₂, a₄₃, a₄₄ ]
- *
- * then a translation of that matrix would be a multiplication by a
- * matrix of this form:
- *
- * [ 1, 0, 0, x ]
- * [ 0, 1, 0, y ]
- * t = [ 0, 0, 1, 0 ]
- * [ 0, 0, 0, 1 ]
- *
- * That would give us a matrix of this form.
- *
- * [ a₁₁, a₁₂, a₁₃, a₁₁ x + a₁₂ y + a₁₄ ]
- * [ a₂₁, a₂₂, a₂₃, a₂₁ x + a₂₂ y + a₂₄ ]
- * b = a ⋅ t = [ a₃₁, a₃₂, a₃₃, a₃₁ x + a₃₂ y + a₃₄ ]
- * [ a₄₁, a₄₂, a₄₃, a₄₁ x + a₄₂ y + a₄₄ ]
- *
- * We can use the two equations from the top left of the matrix to
- * work out the x and y translation given the two matrices:
- *
- * b₁₄ = a₁₁x + a₁₂y + a₁₄
- * b₂₄ = a₂₁x + a₂₂y + a₂₄
- *
- * Rearranging gives us:
- *
- * a₁₂ b₂₄ - a₂₄ a₁₂
- * ----------------- + a₁₄ - b₁₄
- * a₂₂
- * x = ---------------------------------
- * a₁₂ a₂₁
- * ------- - a₁₁
- * a₂₂
- *
- * b₂₄ - a₂₁x - a₂₄
- * y = ----------------
- * a₂₂
- *
- * Once we've worked out what x and y would be if this was a valid
- * translation then we can simply verify that the rest of the matrix
- * matches up.
- */
-
- /* The leftmost 3x4 part of the matrix shouldn't change by a
- translation so we can just compare it directly */
- for (y = 0; y < 4; y++)
- for (x = 0; x < 3; x++)
- if ((&a->xx)[x * 4 + y] != (&b->xx)[x * 4 + y])
- return FALSE;
-
- tx = (((a->xy * b->yw - a->yw * a->xy) / a->yy + a->xw - b->xw) /
- ((a->xy * a->yx) / a->yy - a->xx));
- ty = (b->yw - a->yx * tx - a->yw) / a->yy;
-
-#define APPROX_EQUAL(a, b) (fabsf ((a) - (b)) < 1e-6f)
-
- /* Check whether the 4th column of the matrices match up to the
- calculation */
- if (!APPROX_EQUAL (b->xw, a->xx * tx + a->xy * ty + a->xw) ||
- !APPROX_EQUAL (b->yw, a->yx * tx + a->yy * ty + a->yw) ||
- !APPROX_EQUAL (b->zw, a->zx * tx + a->zy * ty + a->zw) ||
- !APPROX_EQUAL (b->ww, a->wx * tx + a->wy * ty + a->ww))
- return FALSE;
-
-#undef APPROX_EQUAL
-
- *tx_p = tx;
- *ty_p = ty;
-
- return TRUE;
-}
-
-typedef struct
-{
- float x_1, y_1;
- float x_2, y_2;
-} ClipBounds;
-
-static gboolean
-can_software_clip_entry (CoglJournalEntry *journal_entry,
- CoglJournalEntry *prev_journal_entry,
- CoglClipStack *clip_stack,
- ClipBounds *clip_bounds_out)
-{
- CoglPipeline *pipeline = journal_entry->pipeline;
- CoglClipStack *clip_entry;
- int layer_num;
-
- clip_bounds_out->x_1 = -G_MAXFLOAT;
- clip_bounds_out->y_1 = -G_MAXFLOAT;
- clip_bounds_out->x_2 = G_MAXFLOAT;
- clip_bounds_out->y_2 = G_MAXFLOAT;
-
- /* Check the pipeline is usable. We can short-cut here for
- entries using the same pipeline as the previous entry */
- if (prev_journal_entry == NULL || pipeline != prev_journal_entry->pipeline)
- {
- /* If the pipeline has a user program then we can't reliably modify
- the texture coordinates */
- if (cogl_pipeline_get_user_program (pipeline))
- return FALSE;
-
- /* If any of the pipeline layers have a texture matrix then we can't
- reliably modify the texture coordinates */
- for (layer_num = cogl_pipeline_get_n_layers (pipeline) - 1;
- layer_num >= 0;
- layer_num--)
- if (_cogl_pipeline_layer_has_user_matrix (pipeline, layer_num))
- return FALSE;
- }
-
- /* Now we need to verify that each clip entry's matrix is just a
- translation of the journal entry's modelview matrix. We can
- also work out the bounds of the clip in modelview space using
- this translation */
- for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent)
- {
- float rect_x1, rect_y1, rect_x2, rect_y2;
- CoglClipStackRect *clip_rect;
- float tx, ty;
-
- clip_rect = (CoglClipStackRect *) clip_entry;
-
- if (!calculate_translation (&clip_rect->matrix,
- &journal_entry->model_view,
- &tx, &ty))
- return FALSE;
-
- if (clip_rect->x0 < clip_rect->x1)
- {
- rect_x1 = clip_rect->x0;
- rect_x2 = clip_rect->x1;
- }
- else
- {
- rect_x1 = clip_rect->x1;
- rect_x2 = clip_rect->x0;
- }
- if (clip_rect->y0 < clip_rect->y1)
- {
- rect_y1 = clip_rect->y0;
- rect_y2 = clip_rect->y1;
- }
- else
- {
- rect_y1 = clip_rect->y1;
- rect_y2 = clip_rect->y0;
- }
-
- clip_bounds_out->x_1 = MAX (clip_bounds_out->x_1, rect_x1 - tx);
- clip_bounds_out->y_1 = MAX (clip_bounds_out->y_1, rect_y1 - ty);
- clip_bounds_out->x_2 = MIN (clip_bounds_out->x_2, rect_x2 - tx);
- clip_bounds_out->y_2 = MIN (clip_bounds_out->y_2, rect_y2 - ty);
- }
-
- return TRUE;
-}
-
-static void
-software_clip_entry (CoglJournalEntry *journal_entry,
- float *verts,
- ClipBounds *clip_bounds)
-{
- size_t stride =
- GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (journal_entry->n_layers);
- float rx1, ry1, rx2, ry2;
- float vx1, vy1, vx2, vy2;
- int layer_num;
-
- /* Remove the clip on the entry */
- _cogl_clip_stack_unref (journal_entry->clip_stack);
- journal_entry->clip_stack = NULL;
-
- vx1 = verts[0];
- vy1 = verts[1];
- vx2 = verts[stride];
- vy2 = verts[stride + 1];
-
- if (vx1 < vx2)
- {
- rx1 = vx1;
- rx2 = vx2;
- }
- else
- {
- rx1 = vx2;
- rx2 = vx1;
- }
- if (vy1 < vy2)
- {
- ry1 = vy1;
- ry2 = vy2;
- }
- else
- {
- ry1 = vy2;
- ry2 = vy1;
- }
-
- rx1 = CLAMP (rx1, clip_bounds->x_1, clip_bounds->x_2);
- ry1 = CLAMP (ry1, clip_bounds->y_1, clip_bounds->y_2);
- rx2 = CLAMP (rx2, clip_bounds->x_1, clip_bounds->x_2);
- ry2 = CLAMP (ry2, clip_bounds->y_1, clip_bounds->y_2);
-
- /* Check if the rectangle intersects the clip at all */
- if (rx1 == rx2 || ry1 == ry2)
- /* Will set all of the vertex data to 0 in the hope that this
- will create a degenerate rectangle and the GL driver will
- be able to clip it quickly */
- memset (verts, 0, sizeof (float) * stride * 2);
- else
- {
- if (vx1 > vx2)
- {
- float t = rx1;
- rx1 = rx2;
- rx2 = t;
- }
- if (vy1 > vy2)
- {
- float t = ry1;
- ry1 = ry2;
- ry2 = t;
- }
-
- verts[0] = rx1;
- verts[1] = ry1;
- verts[stride] = rx2;
- verts[stride + 1] = ry2;
-
- /* Convert the rectangle coordinates to a fraction of the original
- rectangle */
- rx1 = (rx1 - vx1) / (vx2 - vx1);
- ry1 = (ry1 - vy1) / (vy2 - vy1);
- rx2 = (rx2 - vx1) / (vx2 - vx1);
- ry2 = (ry2 - vy1) / (vy2 - vy1);
-
- for (layer_num = 0; layer_num < journal_entry->n_layers; layer_num++)
- {
- float *t = verts + 2 + 2 * layer_num;
- float tx1 = t[0], ty1 = t[1];
- float tx2 = t[stride], ty2 = t[stride + 1];
- t[0] = rx1 * (tx2 - tx1) + tx1;
- t[1] = ry1 * (ty2 - ty1) + ty1;
- t[stride] = rx2 * (tx2 - tx1) + tx1;
- t[stride + 1] = ry2 * (ty2 - ty1) + ty1;
- }
- }
-}
-
-static void
-maybe_software_clip_entries (CoglJournalEntry *batch_start,
- int batch_len,
- CoglJournalFlushState *state)
-{
- CoglJournal *journal = state->journal;
- CoglClipStack *clip_stack, *clip_entry;
- int entry_num;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* This tries to find cases where the entry is logged with a clip
- but it would be faster to modify the vertex and texture
- coordinates rather than flush the clip so that it can batch
- better */
-
- /* If the batch is reasonably long then it's worthwhile programming
- the GPU to do the clip */
- if (batch_len >= COGL_JOURNAL_HARDWARE_CLIP_THRESHOLD)
- return;
-
- clip_stack = batch_start->clip_stack;
-
- if (clip_stack == NULL)
- return;
-
- /* Verify that all of the clip stack entries are a simple rectangle
- clip */
- for (clip_entry = clip_stack; clip_entry; clip_entry = clip_entry->parent)
- if (clip_entry->type != COGL_CLIP_STACK_RECT)
- return;
-
- /* This scratch buffer is used to store the translation for each
- entry in the journal. We store it in a separate buffer because
- it's expensive to calculate but at this point we still don't know
- whether we can clip all of the entries so we don't want to do the
- rest of the dependant calculations until we're sure we can. */
- if (ctx->journal_clip_bounds == NULL)
- ctx->journal_clip_bounds = g_array_new (FALSE, FALSE, sizeof (ClipBounds));
- g_array_set_size (ctx->journal_clip_bounds, batch_len);
-
- for (entry_num = 0; entry_num < batch_len; entry_num++)
- {
- CoglJournalEntry *journal_entry = batch_start + entry_num;
- CoglJournalEntry *prev_journal_entry =
- entry_num ? batch_start + (entry_num - 1) : NULL;
- ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds,
- ClipBounds, entry_num);
-
- if (!can_software_clip_entry (journal_entry, prev_journal_entry,
- clip_stack,
- clip_bounds))
- return;
- }
-
- /* If we make it here then we know we can software clip the entire batch */
-
- COGL_NOTE (CLIPPING, "Software clipping a batch of length %i", batch_len);
-
- for (entry_num = 0; entry_num < batch_len; entry_num++)
- {
- CoglJournalEntry *journal_entry = batch_start + entry_num;
- float *verts = &g_array_index (journal->vertices, float,
- journal_entry->array_offset + 1);
- ClipBounds *clip_bounds = &g_array_index (ctx->journal_clip_bounds,
- ClipBounds, entry_num);
-
- software_clip_entry (journal_entry, verts, clip_bounds);
- }
-
- return;
-}
-
-static void
-_cogl_journal_maybe_software_clip_entries (CoglJournalEntry *batch_start,
- int batch_len,
- void *data)
-{
- CoglJournalFlushState *state = data;
-
- COGL_STATIC_TIMER (time_check_software_clip,
- "Journal Flush", /* parent */
- "flush: software clipping",
- "Time spent software clipping",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context,
- time_check_software_clip);
-
- maybe_software_clip_entries (batch_start, batch_len, state);
-
- COGL_TIMER_STOP (_cogl_uprof_context,
- time_check_software_clip);
-}
-
-static gboolean
-compare_entry_clip_stacks (CoglJournalEntry *entry0, CoglJournalEntry *entry1)
-{
- return entry0->clip_stack == entry1->clip_stack;
-}
-
-static CoglVertexArray *
-upload_vertices (const CoglJournalEntry *entries,
- int n_entries,
- size_t needed_vbo_len,
- GArray *vertices)
-{
- CoglVertexArray *array;
- CoglBuffer *buffer;
- const float *vin;
- float *vout;
- int entry_num;
- int i;
-
- g_assert (needed_vbo_len);
-
- array = cogl_vertex_array_new (needed_vbo_len * 4, NULL);
- buffer = COGL_BUFFER (array);
- cogl_buffer_set_update_hint (buffer, COGL_BUFFER_UPDATE_HINT_STATIC);
-
- vout = _cogl_buffer_map_for_fill_or_fallback (buffer);
- vin = &g_array_index (vertices, float, 0);
-
- /* Expand the number of vertices from 2 to 4 while uploading */
- for (entry_num = 0; entry_num < n_entries; entry_num++)
- {
- const CoglJournalEntry *entry = entries + entry_num;
- size_t vb_stride = GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (entry->n_layers);
- size_t array_stride =
- GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (entry->n_layers);
-
- /* Copy the color to all four of the vertices */
- for (i = 0; i < 4; i++)
- memcpy (vout + vb_stride * i + POS_STRIDE, vin, 4);
- vin++;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM)))
- {
- vout[vb_stride * 0] = vin[0];
- vout[vb_stride * 0 + 1] = vin[1];
- vout[vb_stride * 1] = vin[0];
- vout[vb_stride * 1 + 1] = vin[array_stride + 1];
- vout[vb_stride * 2] = vin[array_stride];
- vout[vb_stride * 2 + 1] = vin[array_stride + 1];
- vout[vb_stride * 3] = vin[array_stride];
- vout[vb_stride * 3 + 1] = vin[1];
- }
- else
- {
- float v[8];
-
- v[0] = vin[0];
- v[1] = vin[1];
- v[2] = vin[0];
- v[3] = vin[array_stride + 1];
- v[4] = vin[array_stride];
- v[5] = vin[array_stride + 1];
- v[6] = vin[array_stride];
- v[7] = vin[1];
-
- cogl_matrix_transform_points (&entry->model_view,
- 2, /* n_components */
- sizeof (float) * 2, /* stride_in */
- v, /* points_in */
- /* strideout */
- vb_stride * sizeof (float),
- vout, /* points_out */
- 4 /* n_points */);
- }
-
- for (i = 0; i < entry->n_layers; i++)
- {
- const float *tin = vin + 2;
- float *tout = vout + POS_STRIDE + COLOR_STRIDE;
-
- tout[vb_stride * 0 + i * 2] = tin[i * 2];
- tout[vb_stride * 0 + 1 + i * 2] = tin[i * 2 + 1];
- tout[vb_stride * 1 + i * 2] = tin[i * 2];
- tout[vb_stride * 1 + 1 + i * 2] = tin[array_stride + i * 2 + 1];
- tout[vb_stride * 2 + i * 2] = tin[array_stride + i * 2];
- tout[vb_stride * 2 + 1 + i * 2] = tin[array_stride + i * 2 + 1];
- tout[vb_stride * 3 + i * 2] = tin[array_stride + i * 2];
- tout[vb_stride * 3 + 1 + i * 2] = tin[i * 2 + 1];
- }
-
- vin += array_stride * 2;
- vout += vb_stride * 4;
- }
-
- _cogl_buffer_unmap_for_fill_or_fallback (buffer);
-
- return array;
-}
-
-void
-_cogl_journal_discard (CoglJournal *journal)
-{
- int i;
-
- for (i = 0; i < journal->entries->len; i++)
- {
- CoglJournalEntry *entry =
- &g_array_index (journal->entries, CoglJournalEntry, i);
- _cogl_pipeline_journal_unref (entry->pipeline);
- _cogl_clip_stack_unref (entry->clip_stack);
- }
-
- g_array_set_size (journal->entries, 0);
- g_array_set_size (journal->vertices, 0);
- journal->needed_vbo_len = 0;
- journal->fast_read_pixel_count = 0;
-}
-
-/* Note: A return value of FALSE doesn't mean 'no' it means
- * 'unknown' */
-gboolean
-_cogl_journal_all_entries_within_bounds (CoglJournal *journal,
- float clip_x0,
- float clip_y0,
- float clip_x1,
- float clip_y1)
-{
- CoglJournalEntry *entry = (CoglJournalEntry *)journal->entries->data;
- CoglClipStack *clip_entry;
- CoglClipStack *reference = NULL;
- int bounds_x0;
- int bounds_y0;
- int bounds_x1;
- int bounds_y1;
- int i;
-
- if (journal->entries->len == 0)
- return TRUE;
-
- /* Find the shortest clip_stack ancestry that leaves us in the
- * required bounds */
- for (clip_entry = entry->clip_stack;
- clip_entry;
- clip_entry = clip_entry->parent)
- {
- _cogl_clip_stack_get_bounds (clip_entry,
- &bounds_x0, &bounds_y0,
- &bounds_x1, &bounds_y1);
-
- if (bounds_x0 >= clip_x0 && bounds_y0 >= clip_y0 &&
- bounds_x1 <= clip_x1 && bounds_y1 <= clip_y1)
- reference = clip_entry;
- else
- break;
- }
-
- if (!reference)
- return FALSE;
-
- /* For the remaining journal entries we will only verify they share
- * 'reference' as an ancestor in their clip stack since that's
- * enough to know that they would be within the required bounds.
- */
- for (i = 1; i < journal->entries->len; i++)
- {
- gboolean found_reference = FALSE;
- entry = &g_array_index (journal->entries, CoglJournalEntry, i);
-
- for (clip_entry = entry->clip_stack;
- clip_entry;
- clip_entry = clip_entry->parent)
- {
- if (clip_entry == reference)
- {
- found_reference = TRUE;
- break;
- }
- }
-
- if (!found_reference)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* XXX NB: When _cogl_journal_flush() returns all state relating
- * to pipelines, all glEnable flags and current matrix state
- * is undefined.
- */
-void
-_cogl_journal_flush (CoglJournal *journal,
- CoglFramebuffer *framebuffer)
-{
- CoglJournalFlushState state;
- int i;
- CoglMatrixStack *modelview_stack;
- COGL_STATIC_TIMER (flush_timer,
- "Mainloop", /* parent */
- "Journal Flush",
- "The time spent flushing the Cogl journal",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (journal->entries->len == 0)
- return;
-
- /* The entries in this journal may depend on images in other
- * framebuffers which may require that we flush the journals
- * associated with those framebuffers before we can flush
- * this journal... */
- _cogl_framebuffer_flush_dependency_journals (framebuffer);
-
- /* Note: we start the timer after flushing dependency journals so
- * that the timer isn't started recursively. */
- COGL_TIMER_START (_cogl_uprof_context, flush_timer);
-
- cogl_push_framebuffer (framebuffer);
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_BATCHING)))
- g_print ("BATCHING: journal len = %d\n", journal->entries->len);
-
- /* NB: the journal deals with flushing the modelview stack and clip
- state manually */
- _cogl_framebuffer_flush_state (framebuffer,
- framebuffer,
- COGL_FRAMEBUFFER_FLUSH_SKIP_MODELVIEW |
- COGL_FRAMEBUFFER_FLUSH_SKIP_CLIP_STATE);
-
- state.journal = journal;
-
- state.attributes = ctx->journal_flush_attributes_array;
-
- modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer);
- state.modelview_stack = modelview_stack;
- state.projection_stack = _cogl_framebuffer_get_projection_stack (framebuffer);
-
- if (G_UNLIKELY ((COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SOFTWARE_CLIP)) == 0))
- {
- /* We do an initial walk of the journal to analyse the clip stack
- batches to see if we can do software clipping. We do this as a
- separate walk of the journal because we can modify entries and
- this may end up joining together clip stack batches in the next
- iteration. */
- batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */
- journal->entries->len, /* max number of entries to consider */
- compare_entry_clip_stacks,
- _cogl_journal_maybe_software_clip_entries, /* callback */
- &state); /* data */
- }
-
- /* We upload the vertices after the clip stack pass in case it
- modifies the entries */
- state.vertex_array = upload_vertices (&g_array_index (journal->entries,
- CoglJournalEntry, 0),
- journal->entries->len,
- journal->needed_vbo_len,
- journal->vertices);
- state.array_offset = 0;
-
- /* batch_and_call() batches a list of journal entries according to some
- * given criteria and calls a callback once for each determined batch.
- *
- * The process of flushing the journal is staggered to reduce the amount
- * of driver/GPU state changes necessary:
- * 1) We split the entries according to the clip state.
- * 2) We split the entries according to the stride of the vertices:
- * Each time the stride of our vertex data changes we need to call
- * gl{Vertex,Color}Pointer to inform GL of new VBO offsets.
- * Currently the only thing that affects the stride of our vertex data
- * is the number of pipeline layers.
- * 3) We split the entries explicitly by the number of pipeline layers:
- * We pad our vertex data when the number of layers is < 2 so that we
- * can minimize changes in stride. Each time the number of layers
- * changes we need to call glTexCoordPointer to inform GL of new VBO
- * offsets.
- * 4) We then split according to compatible Cogl pipelines:
- * This is where we flush pipeline state
- * 5) Finally we split according to modelview matrix changes:
- * This is when we finally tell GL to draw something.
- * Note: Splitting by modelview changes is skipped when are doing the
- * vertex transformation in software at log time.
- */
- batch_and_call ((CoglJournalEntry *)journal->entries->data, /* first entry */
- journal->entries->len, /* max number of entries to consider */
- compare_entry_clip_stacks,
- _cogl_journal_flush_clip_stacks_and_entries, /* callback */
- &state); /* data */
-
- for (i = 0; i < state.attributes->len; i++)
- cogl_object_unref (g_array_index (state.attributes, CoglAttribute *, i));
- g_array_set_size (state.attributes, 0);
-
- cogl_object_unref (state.vertex_array);
-
- _cogl_journal_discard (journal);
-
- cogl_pop_framebuffer ();
-
- COGL_TIMER_STOP (_cogl_uprof_context, flush_timer);
-}
-
-static gboolean
-add_framebuffer_deps_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglFramebuffer *framebuffer = user_data;
- CoglHandle texture = _cogl_pipeline_layer_get_texture_real (layer);
- const GList *l;
-
- if (!texture)
- return TRUE;
-
- for (l = _cogl_texture_get_associated_framebuffers (texture); l; l = l->next)
- _cogl_framebuffer_add_dependency (framebuffer, l->data);
-
- return TRUE;
-}
-
-void
-_cogl_journal_log_quad (CoglJournal *journal,
- const float *position,
- CoglPipeline *pipeline,
- int n_layers,
- CoglHandle layer0_override_texture,
- const float *tex_coords,
- unsigned int tex_coords_len)
-{
- gsize stride;
- int next_vert;
- float *v;
- int i;
- int next_entry;
- guint32 disable_layers;
- CoglJournalEntry *entry;
- CoglPipeline *source;
- CoglClipStack *clip_stack;
- CoglPipelineFlushOptions flush_options;
- COGL_STATIC_TIMER (log_timer,
- "Mainloop", /* parent */
- "Journal Log",
- "The time spent logging in the Cogl journal",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context, log_timer);
-
- /* The vertex data is logged into a separate array. The data needs
- to be copied into a vertex array before it's given to GL so we
- only store two vertices per quad and expand it to four while
- uploading. */
-
- /* XXX: See definition of GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS for details
- * about how we pack our vertex data */
- stride = GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (n_layers);
-
- next_vert = journal->vertices->len;
- g_array_set_size (journal->vertices, next_vert + 2 * stride + 1);
- v = &g_array_index (journal->vertices, float, next_vert);
-
- /* We calculate the needed size of the vbo as we go because it
- depends on the number of layers in each entry and it's not easy
- calculate based on the length of the logged vertices array */
- journal->needed_vbo_len += GET_JOURNAL_VB_STRIDE_FOR_N_LAYERS (n_layers) * 4;
-
- /* XXX: All the jumping around to fill in this strided buffer doesn't
- * seem ideal. */
-
- /* FIXME: This is a hacky optimization, since it will break if we
- * change the definition of CoglColor: */
- _cogl_pipeline_get_colorubv (pipeline, (guint8 *) v);
- v++;
-
- memcpy (v, position, sizeof (float) * 2);
- memcpy (v + stride, position + 2, sizeof (float) * 2);
-
- for (i = 0; i < n_layers; i++)
- {
- /* XXX: See definition of GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS
- * for details about how we pack our vertex data */
- GLfloat *t = v + 2 + i * 2;
-
- memcpy (t, tex_coords + i * 4, sizeof (float) * 2);
- memcpy (t + stride, tex_coords + i * 4 + 2, sizeof (float) * 2);
- }
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_JOURNAL)))
- {
- g_print ("Logged new quad:\n");
- v = &g_array_index (journal->vertices, float, next_vert);
- _cogl_journal_dump_logged_quad ((guint8 *)v, n_layers);
- }
-
- next_entry = journal->entries->len;
- g_array_set_size (journal->entries, next_entry + 1);
- entry = &g_array_index (journal->entries, CoglJournalEntry, next_entry);
-
- entry->n_layers = n_layers;
- entry->array_offset = next_vert;
-
- source = pipeline;
-
- if (G_UNLIKELY (ctx->legacy_state_set))
- {
- source = cogl_pipeline_copy (pipeline);
- _cogl_pipeline_apply_legacy_state (source);
- }
-
- flush_options.flags = 0;
- if (G_UNLIKELY (cogl_pipeline_get_n_layers (pipeline) != n_layers))
- {
- disable_layers = (1 << n_layers) - 1;
- disable_layers = ~disable_layers;
- flush_options.disable_layers = disable_layers;
- flush_options.flags |= COGL_PIPELINE_FLUSH_DISABLE_MASK;
- }
- if (G_UNLIKELY (layer0_override_texture))
- {
- flush_options.flags |= COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE;
- flush_options.layer0_override_texture = layer0_override_texture;
- }
-
- if (G_UNLIKELY (flush_options.flags))
- {
- /* If we haven't already created a derived pipeline... */
- if (source == pipeline)
- source = cogl_pipeline_copy (pipeline);
- _cogl_pipeline_apply_overrides (source, &flush_options);
- }
-
- entry->pipeline = _cogl_pipeline_journal_ref (source);
-
- clip_stack = _cogl_framebuffer_get_clip_stack (cogl_get_draw_framebuffer ());
- entry->clip_stack = _cogl_clip_stack_ref (clip_stack);
-
- if (G_UNLIKELY (source != pipeline))
- cogl_handle_unref (source);
-
- cogl_get_modelview_matrix (&entry->model_view);
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- add_framebuffer_deps_cb,
- cogl_get_draw_framebuffer ());
-
- /* XXX: It doesn't feel very nice that in this case we just assume
- * that the journal is associated with the current framebuffer. I
- * think a journal->framebuffer reference would seem nicer here but
- * the reason we don't have that currently is that it would
- * introduce a circular reference. */
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BATCHING)))
- _cogl_framebuffer_flush_journal (cogl_get_draw_framebuffer ());
-
- COGL_TIMER_STOP (_cogl_uprof_context, log_timer);
-}
-
-static void
-entry_to_screen_polygon (const CoglJournalEntry *entry,
- float *vertices,
- float *poly)
-{
- size_t array_stride =
- GET_JOURNAL_ARRAY_STRIDE_FOR_N_LAYERS (entry->n_layers);
- CoglMatrixStack *projection_stack;
- CoglMatrix projection;
- int i;
- float viewport[4];
-
- poly[0] = vertices[0];
- poly[1] = vertices[1];
- poly[2] = 0;
- poly[3] = 1;
-
- poly[4] = vertices[0];
- poly[5] = vertices[array_stride + 1];
- poly[6] = 0;
- poly[7] = 1;
-
- poly[8] = vertices[array_stride];
- poly[9] = vertices[array_stride + 1];
- poly[10] = 0;
- poly[11] = 1;
-
- poly[12] = vertices[array_stride];
- poly[13] = vertices[1];
- poly[14] = 0;
- poly[15] = 1;
-
- /* TODO: perhaps split the following out into a more generalized
- * _cogl_transform_points utility...
- */
-
- cogl_matrix_transform_points (&entry->model_view,
- 2, /* n_components */
- sizeof (float) * 4, /* stride_in */
- poly, /* points_in */
- /* strideout */
- sizeof (float) * 4,
- poly, /* points_out */
- 4 /* n_points */);
-
- projection_stack =
- _cogl_framebuffer_get_projection_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_get (projection_stack, &projection);
-
- cogl_matrix_project_points (&projection,
- 3, /* n_components */
- sizeof (float) * 4, /* stride_in */
- poly, /* points_in */
- /* strideout */
- sizeof (float) * 4,
- poly, /* points_out */
- 4 /* n_points */);
-
- _cogl_framebuffer_get_viewport4fv (cogl_get_draw_framebuffer (),
- viewport);
-
-/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
- * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
- * (0,0) being top left. */
-#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
- ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
-/* Note: for Y we first flip all coordinates around the X axis while in
- * normalized device coodinates */
-#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
- ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
-
- /* Scale from normalized device coordinates (in range [-1,1]) to
- * window coordinates ranging [0,window-size] ... */
- for (i = 0; i < 4; i++)
- {
- float w = poly[4 * i + 3];
-
- /* Perform perspective division */
- poly[4 * i] /= w;
- poly[4 * i + 1] /= w;
-
- /* Apply viewport transform */
- poly[4 * i] = VIEWPORT_TRANSFORM_X (poly[4 * i],
- viewport[0], viewport[2]);
- poly[4 * i + 1] = VIEWPORT_TRANSFORM_Y (poly[4 * i + 1],
- viewport[1], viewport[3]);
- }
-
-#undef VIEWPORT_TRANSFORM_X
-#undef VIEWPORT_TRANSFORM_Y
-}
-
-static gboolean
-try_checking_point_hits_entry_after_clipping (CoglJournalEntry *entry,
- float *vertices,
- float x,
- float y,
- gboolean *hit)
-{
- gboolean can_software_clip = TRUE;
- gboolean needs_software_clip = FALSE;
- CoglClipStack *clip_entry;
-
- *hit = TRUE;
-
- /* Verify that all of the clip stack entries are simple rectangle
- * clips */
- for (clip_entry = entry->clip_stack;
- clip_entry;
- clip_entry = clip_entry->parent)
- {
- if (x < clip_entry->bounds_x0 ||
- x >= clip_entry->bounds_x1 ||
- y < clip_entry->bounds_y0 ||
- y >= clip_entry->bounds_y1)
- {
- *hit = FALSE;
- return TRUE;
- }
-
- if (clip_entry->type == COGL_CLIP_STACK_WINDOW_RECT)
- {
- /* XXX: technically we could still run the software clip in
- * this case because for our purposes we know this clip
- * can be ignored now, but [can_]sofware_clip_entry() doesn't
- * know this and will bail out. */
- can_software_clip = FALSE;
- }
- else if (clip_entry->type == COGL_CLIP_STACK_RECT)
- {
- CoglClipStackRect *rect_entry = (CoglClipStackRect *)entry;
-
- if (rect_entry->can_be_scissor == FALSE)
- needs_software_clip = TRUE;
- /* If can_be_scissor is TRUE then we know it's screen
- * aligned and the hit test we did above has determined
- * that we are inside this clip. */
- }
- else
- return FALSE;
- }
-
- if (needs_software_clip)
- {
- ClipBounds clip_bounds;
- float poly[16];
-
- if (!can_software_clip)
- return FALSE;
-
- if (!can_software_clip_entry (entry, NULL,
- entry->clip_stack, &clip_bounds))
- return FALSE;
-
- software_clip_entry (entry, vertices, &clip_bounds);
- entry_to_screen_polygon (entry, vertices, poly);
-
- *hit = _cogl_util_point_in_screen_poly (x, y, poly, sizeof (float) * 4, 4);
- return TRUE;
- }
-
- return TRUE;
-}
-
-gboolean
-_cogl_journal_try_read_pixel (CoglJournal *journal,
- int x,
- int y,
- CoglPixelFormat format,
- guint8 *pixel,
- gboolean *found_intersection)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* XXX: this number has been plucked out of thin air, but the idea
- * is that if so many pixels are being read from the same un-changed
- * journal than we expect that it will be more efficient to fail
- * here so we end up flushing and rendering the journal so that
- * further reads can directly read from the framebuffer. There will
- * be a bit more lag to flush the render but if there are going to
- * continue being lots of arbitrary single pixel reads they will end
- * up faster in the end. */
- if (journal->fast_read_pixel_count > 50)
- return FALSE;
-
- if (format != COGL_PIXEL_FORMAT_RGBA_8888_PRE &&
- format != COGL_PIXEL_FORMAT_RGBA_8888)
- return FALSE;
-
- *found_intersection = FALSE;
-
- /* NB: The most recently added journal entry is the last entry, and
- * assuming this is a simple scene only comprised of opaque coloured
- * rectangles with no special pipelines involved (e.g. enabling
- * depth testing) then we can assume painter's algorithm for the
- * entries and so our fast read-pixel just needs to walk backwards
- * through the journal entries trying to intersect each entry with
- * the given point of interest. */
- for (i = journal->entries->len - 1; i >= 0; i--)
- {
- CoglJournalEntry *entry =
- &g_array_index (journal->entries, CoglJournalEntry, i);
- guint8 *color = (guint8 *)&g_array_index (journal->vertices, float,
- entry->array_offset);
- float *vertices = (float *)color + 1;
- float poly[16];
-
- entry_to_screen_polygon (entry, vertices, poly);
-
- if (!_cogl_util_point_in_screen_poly (x, y, poly, sizeof (float) * 4, 4))
- continue;
-
- /* FIXME: the journal should have a back pointer to the
- * associated framebuffer, because it should be possible to read
- * a pixel from arbitrary framebuffers without needing to
- * internally call _cogl_push/pop_framebuffer.
- */
- if (entry->clip_stack)
- {
- gboolean hit;
-
- if (!try_checking_point_hits_entry_after_clipping (entry, vertices,
- x, y, &hit))
- return FALSE; /* hit couldn't be determined */
-
- if (!hit)
- continue;
- }
-
- *found_intersection = TRUE;
-
- /* If we find that the rectangle the point of interest
- * intersects has any state more complex than a constant opaque
- * color then we bail out. */
- if (!_cogl_pipeline_equal (ctx->opaque_color_pipeline, entry->pipeline,
- (COGL_PIPELINE_STATE_ALL &
- ~COGL_PIPELINE_STATE_COLOR),
- COGL_PIPELINE_LAYER_STATE_ALL,
- 0))
- return FALSE;
-
-
- /* we currently only care about cases where the premultiplied or
- * unpremultipled colors are equivalent... */
- if (color[3] != 0xff)
- return FALSE;
-
- pixel[0] = color[0];
- pixel[1] = color[1];
- pixel[2] = color[2];
- pixel[3] = color[3];
-
- goto success;
- }
-
-success:
- journal->fast_read_pixel_count++;
- return TRUE;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <cogl.h>
-#include <cogl-material-compat.h>
-#include <cogl-pipeline.h>
-#include <cogl-pipeline-private.h>
-#include <cogl-types.h>
-#include <cogl-matrix.h>
-#include <cogl-context-private.h>
-
-CoglMaterial *
-cogl_material_new (void)
-{
- return COGL_MATERIAL (cogl_pipeline_new ());
-}
-
-CoglMaterial *
-cogl_material_copy (CoglMaterial *source)
-{
- return COGL_MATERIAL (cogl_pipeline_copy (COGL_PIPELINE (source)));
-}
-
-CoglHandle
-cogl_material_ref (CoglHandle handle)
-{
- return cogl_object_ref (handle);
-}
-
-void
-cogl_material_unref (CoglHandle handle)
-{
- cogl_object_unref (handle);
-}
-
-gboolean
-cogl_is_material (CoglHandle handle)
-{
- return cogl_is_pipeline (handle);
-}
-
-void
-cogl_material_set_color (CoglMaterial *material,
- const CoglColor *color)
-{
- cogl_pipeline_set_color (COGL_PIPELINE (material), color);
-}
-
-void
-cogl_material_set_color4ub (CoglMaterial *material,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha)
-{
- cogl_pipeline_set_color4ub (COGL_PIPELINE (material),
- red, green, blue, alpha);
-}
-
-void
-cogl_material_set_color4f (CoglMaterial *material,
- float red,
- float green,
- float blue,
- float alpha)
-{
- cogl_pipeline_set_color4f (COGL_PIPELINE (material),
- red, green, blue, alpha);
-}
-
-void
-cogl_material_get_color (CoglMaterial *material,
- CoglColor *color)
-{
- cogl_pipeline_get_color (COGL_PIPELINE (material), color);
-}
-
-void
-cogl_material_set_ambient (CoglMaterial *material,
- const CoglColor *ambient)
-{
- cogl_pipeline_set_ambient (COGL_PIPELINE (material), ambient);
-}
-
-void
-cogl_material_get_ambient (CoglMaterial *material,
- CoglColor *ambient)
-{
- cogl_pipeline_get_ambient (COGL_PIPELINE (material), ambient);
-}
-
-void
-cogl_material_set_diffuse (CoglMaterial *material,
- const CoglColor *diffuse)
-{
- cogl_pipeline_set_diffuse (COGL_PIPELINE (material), diffuse);
-}
-
-void
-cogl_material_get_diffuse (CoglMaterial *material,
- CoglColor *diffuse)
-{
- cogl_pipeline_get_diffuse (COGL_PIPELINE (material), diffuse);
-}
-
-void
-cogl_material_set_ambient_and_diffuse (CoglMaterial *material,
- const CoglColor *color)
-{
- cogl_pipeline_set_ambient_and_diffuse (COGL_PIPELINE (material), color);
-
-}
-
-void
-cogl_material_set_specular (CoglMaterial *material,
- const CoglColor *specular)
-{
- cogl_pipeline_set_specular (COGL_PIPELINE (material), specular);
-}
-
-void
-cogl_material_get_specular (CoglMaterial *material,
- CoglColor *specular)
-{
- cogl_pipeline_get_specular (COGL_PIPELINE (material), specular);
-}
-
-void
-cogl_material_set_shininess (CoglMaterial *material,
- float shininess)
-{
- cogl_pipeline_set_shininess (COGL_PIPELINE (material), shininess);
-}
-
-float
-cogl_material_get_shininess (CoglMaterial *material)
-{
- return cogl_pipeline_get_shininess (COGL_PIPELINE (material));
-}
-
-void
-cogl_material_set_emission (CoglMaterial *material,
- const CoglColor *emission)
-{
- cogl_pipeline_set_emission (COGL_PIPELINE (material), emission);
-
-}
-
-void
-cogl_material_get_emission (CoglMaterial *material,
- CoglColor *emission)
-{
- cogl_pipeline_get_emission (COGL_PIPELINE (material), emission);
-
-}
-
-void
-cogl_material_set_alpha_test_function (CoglMaterial *material,
- CoglMaterialAlphaFunc alpha_func,
- float alpha_reference)
-{
- cogl_pipeline_set_alpha_test_function (COGL_PIPELINE (material),
- alpha_func,
- alpha_reference);
-}
-
-gboolean
-cogl_material_set_blend (CoglMaterial *material,
- const char *blend_string,
- GError **error)
-{
- return cogl_pipeline_set_blend (COGL_PIPELINE (material),
- blend_string,
- error);
-}
-
-void
-cogl_material_set_blend_constant (CoglMaterial *material,
- const CoglColor *constant_color)
-{
- cogl_pipeline_set_blend_constant (COGL_PIPELINE (material), constant_color);
-}
-
-void
-cogl_material_set_point_size (CoglMaterial *material,
- float point_size)
-{
- cogl_pipeline_set_point_size (COGL_PIPELINE (material), point_size);
-}
-
-float
-cogl_material_get_point_size (CoglMaterial *material)
-{
- return cogl_pipeline_get_point_size (COGL_PIPELINE (material));
-}
-
-CoglHandle
-cogl_material_get_user_program (CoglMaterial *material)
-{
- return cogl_pipeline_get_user_program (COGL_PIPELINE (material));
-}
-
-void
-cogl_material_set_user_program (CoglMaterial *material,
- CoglHandle program)
-{
- cogl_pipeline_set_user_program (COGL_PIPELINE (material), program);
-}
-
-void
-cogl_material_set_layer (CoglMaterial *material,
- int layer_index,
- CoglHandle texture)
-{
- cogl_pipeline_set_layer_texture (COGL_PIPELINE (material),
- layer_index, texture);
-}
-
-void
-cogl_material_remove_layer (CoglMaterial *material,
- int layer_index)
-{
- cogl_pipeline_remove_layer (COGL_PIPELINE (material), layer_index);
-}
-
-gboolean
-cogl_material_set_layer_combine (CoglMaterial *material,
- int layer_index,
- const char *blend_string,
- GError **error)
-{
- return cogl_pipeline_set_layer_combine (COGL_PIPELINE (material),
- layer_index,
- blend_string,
- error);
-}
-
-void
-cogl_material_set_layer_combine_constant (CoglMaterial *material,
- int layer_index,
- const CoglColor *constant)
-{
- cogl_pipeline_set_layer_combine_constant (COGL_PIPELINE (material),
- layer_index,
- constant);
-}
-
-void
-cogl_material_set_layer_matrix (CoglMaterial *material,
- int layer_index,
- const CoglMatrix *matrix)
-{
- cogl_pipeline_set_layer_matrix (COGL_PIPELINE (material),
- layer_index, matrix);
-}
-
-G_CONST_RETURN GList *
-cogl_material_get_layers (CoglMaterial *material)
-{
- return _cogl_pipeline_get_layers (COGL_PIPELINE (material));
-}
-
-int
-cogl_material_get_n_layers (CoglMaterial *material)
-{
- return cogl_pipeline_get_n_layers (COGL_PIPELINE (material));
-}
-
-CoglMaterialLayerType
-cogl_material_layer_get_type (CoglMaterialLayer *layer)
-{
- return COGL_MATERIAL_LAYER_TYPE_TEXTURE;
-}
-
-CoglHandle
-cogl_material_layer_get_texture (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_texture (COGL_PIPELINE_LAYER (layer));
-}
-
-CoglMaterialFilter
-cogl_material_layer_get_min_filter (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_min_filter (COGL_PIPELINE_LAYER (layer));
-}
-
-CoglMaterialFilter
-cogl_material_layer_get_mag_filter (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_mag_filter (COGL_PIPELINE_LAYER (layer));
-}
-
-void
-cogl_material_set_layer_filters (CoglMaterial *material,
- int layer_index,
- CoglMaterialFilter min_filter,
- CoglMaterialFilter mag_filter)
-{
- cogl_pipeline_set_layer_filters (COGL_PIPELINE (material),
- layer_index,
- min_filter,
- mag_filter);
-}
-
-gboolean
-cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material,
- int layer_index,
- gboolean enable,
- GError **error)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (material);
- return cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline,
- layer_index,
- enable,
- error);
-}
-
-gboolean
-cogl_material_get_layer_point_sprite_coords_enabled (CoglMaterial *material,
- int layer_index)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (material);
- return cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline,
- layer_index);
-}
-
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_s (CoglMaterial *material,
- int layer_index)
-{
- return cogl_pipeline_get_layer_wrap_mode_s (COGL_PIPELINE (material),
- layer_index);
-}
-
-void
-cogl_material_set_layer_wrap_mode_s (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode)
-{
- cogl_pipeline_set_layer_wrap_mode_s (COGL_PIPELINE (material), layer_index,
- mode);
-}
-
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_t (CoglMaterial *material,
- int layer_index)
-{
- return cogl_pipeline_get_layer_wrap_mode_t (COGL_PIPELINE (material),
- layer_index);
-}
-
-void
-cogl_material_set_layer_wrap_mode_t (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode)
-{
- cogl_pipeline_set_layer_wrap_mode_t (COGL_PIPELINE (material), layer_index,
- mode);
-}
-
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_p (CoglMaterial *material,
- int layer_index)
-{
- return cogl_pipeline_get_layer_wrap_mode_p (COGL_PIPELINE (material),
- layer_index);
-}
-
-void
-cogl_material_set_layer_wrap_mode_p (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode)
-{
- cogl_pipeline_set_layer_wrap_mode_p (COGL_PIPELINE (material), layer_index,
- mode);
-}
-
-void
-cogl_material_set_layer_wrap_mode (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode)
-{
- cogl_pipeline_set_layer_wrap_mode (COGL_PIPELINE (material), layer_index,
- mode);
-}
-
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_s (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_wrap_mode_s (COGL_PIPELINE_LAYER (layer));
-}
-
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_t (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_wrap_mode_t (COGL_PIPELINE_LAYER (layer));
-}
-
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_p (CoglMaterialLayer *layer)
-{
- return _cogl_pipeline_layer_get_wrap_mode_p (COGL_PIPELINE_LAYER (layer));
-}
-
-void
-cogl_material_set_depth_test_enabled (CoglMaterial *material,
- gboolean enable)
-{
- cogl_pipeline_set_depth_test_enabled (COGL_PIPELINE (material), enable);
-}
-
-gboolean
-cogl_material_get_depth_test_enabled (CoglMaterial *material)
-{
- return cogl_pipeline_get_depth_test_enabled (COGL_PIPELINE (material));
-}
-
-void
-cogl_material_set_depth_writing_enabled (CoglMaterial *material,
- gboolean enable)
-{
- cogl_pipeline_set_depth_writing_enabled (COGL_PIPELINE (material), enable);
-}
-
-gboolean
-cogl_material_get_depth_writing_enabled (CoglMaterial *material)
-{
- return cogl_pipeline_get_depth_writing_enabled (COGL_PIPELINE (material));
-}
-
-void
-cogl_material_set_depth_test_function (CoglMaterial *material,
- CoglDepthTestFunction function)
-{
- cogl_pipeline_set_depth_test_function (COGL_PIPELINE (material), function);
-}
-
-CoglDepthTestFunction
-cogl_material_get_depth_test_function (CoglMaterial *material)
-{
- return cogl_pipeline_get_depth_test_function (COGL_PIPELINE (material));
-}
-
-gboolean
-cogl_material_set_depth_range (CoglMaterial *material,
- float near_val,
- float far_val,
- GError **error)
-{
- return cogl_pipeline_set_depth_range (COGL_PIPELINE (material),
- near_val, far_val, error);
-}
-
-void
-cogl_material_get_depth_range (CoglMaterial *material,
- float *near_val,
- float *far_val)
-{
- cogl_pipeline_get_depth_range (COGL_PIPELINE (material), near_val, far_val);
-}
-
-void
-cogl_material_foreach_layer (CoglMaterial *material,
- CoglMaterialLayerCallback callback,
- void *user_data)
-{
- cogl_pipeline_foreach_layer (COGL_PIPELINE (material),
- (CoglPipelineLayerCallback)callback, user_data);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_MATERIAL_H__
-#define __COGL_MATERIAL_H__
-
-G_BEGIN_DECLS
-
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-matrix.h>
-
-/**
- * SECTION:cogl-material
- * @short_description: Fuctions for creating and manipulating materials
- *
- * COGL allows creating and manipulating materials used to fill in
- * geometry. Materials may simply be lighting attributes (such as an
- * ambient and diffuse colour) or might represent one or more textures
- * blended together.
- */
-
-typedef struct _CoglMaterial CoglMaterial;
-typedef struct _CoglMaterialLayer CoglMaterialLayer;
-
-#define COGL_MATERIAL(OBJECT) ((CoglMaterial *)OBJECT)
-
-/**
- * CoglMaterialFilter:
- * @COGL_MATERIAL_FILTER_NEAREST: Measuring in manhatten distance from the,
- * current pixel center, use the nearest texture texel
- * @COGL_MATERIAL_FILTER_LINEAR: Use the weighted average of the 4 texels
- * nearest the current pixel center
- * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches the current pixel, and use the
- * %COGL_MATERIAL_FILTER_NEAREST criterion
- * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches the current pixel, and use the
- * %COGL_MATERIAL_FILTER_LINEAR criterion
- * @COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely matches the current pixel, use
- * the %COGL_MATERIAL_FILTER_NEAREST criterion on each one and take
- * their weighted average
- * @COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely matches the current pixel, use
- * the %COGL_MATERIAL_FILTER_LINEAR criterion on each one and take
- * their weighted average
- *
- * Texture filtering is used whenever the current pixel maps either to more
- * than one texture element (texel) or less than one. These filter enums
- * correspond to different strategies used to come up with a pixel color, by
- * possibly referring to multiple neighbouring texels and taking a weighted
- * average or simply using the nearest texel.
- */
-typedef enum {
- COGL_MATERIAL_FILTER_NEAREST = 0x2600,
- COGL_MATERIAL_FILTER_LINEAR = 0x2601,
- COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = 0x2700,
- COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = 0x2701,
- COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = 0x2702,
- COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = 0x2703
-} CoglMaterialFilter;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * CoglMaterialWrapMode:
- * @COGL_MATERIAL_WRAP_MODE_REPEAT: The texture will be repeated. This
- * is useful for example to draw a tiled background.
- * @COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE: The coordinates outside the
- * range 0→1 will sample copies of the edge pixels of the
- * texture. This is useful to avoid artifacts if only one copy of
- * the texture is being rendered.
- * @COGL_MATERIAL_WRAP_MODE_AUTOMATIC: Cogl will try to automatically
- * decide which of the above two to use. For cogl_rectangle(), it
- * will use repeat mode if any of the texture coordinates are
- * outside the range 0→1, otherwise it will use clamp to edge. For
- * cogl_polygon() it will always use repeat mode. For
- * cogl_vertex_buffer_draw() it will use repeat mode except for
- * layers that have point sprite coordinate generation enabled. This
- * is the default value.
- *
- * The wrap mode specifies what happens when texture coordinates
- * outside the range 0→1 are used. Note that if the filter mode is
- * anything but %COGL_MATERIAL_FILTER_NEAREST then texels outside the
- * range 0→1 might be used even when the coordinate is exactly 0 or 1
- * because OpenGL will try to sample neighbouring pixels. For example
- * if you are trying to render the full texture then you may get
- * artifacts around the edges when the pixels from the other side are
- * merged in if the wrap mode is set to repeat.
- *
- * Since: 1.4
- */
-/* GL_ALWAYS is just used here as a value that is known not to clash
- * with any valid GL wrap modes
- *
- * XXX: keep the values in sync with the CoglMaterialWrapModeInternal
- * enum so no conversion is actually needed.
- */
-typedef enum {
- COGL_MATERIAL_WRAP_MODE_REPEAT = 0x2901,
- COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE = 0x812F,
- COGL_MATERIAL_WRAP_MODE_AUTOMATIC = 0x0207
-} CoglMaterialWrapMode;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * cogl_material_new:
- *
- * Allocates and initializes a blank white material
- *
- * Return value: a pointer to a new #CoglMaterial
- */
-CoglMaterial *
-cogl_material_new (void);
-
-/**
- * cogl_material_copy:
- * @source: a #CoglMaterial object to copy
- *
- * Creates a new material with the configuration copied from the
- * source material.
- *
- * We would strongly advise developers to always aim to use
- * cogl_material_copy() instead of cogl_material_new() whenever there will
- * be any similarity between two materials. Copying a material helps Cogl
- * keep track of a materials ancestry which we may use to help minimize GPU
- * state changes.
- *
- * Returns: a pointer to the newly allocated #CoglMaterial
- *
- * Since: 1.2
- */
-CoglMaterial *
-cogl_material_copy (CoglMaterial *source);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_material_ref:
- * @material: a #CoglMaterial object.
- *
- * Increment the reference count for a #CoglMaterial.
- *
- * Return value: the @material.
- *
- * Since: 1.0
- *
- * Deprecated: 1.2: Use cogl_object_ref() instead
- */
-CoglHandle
-cogl_material_ref (CoglHandle material) G_GNUC_DEPRECATED;
-
-/**
- * cogl_material_unref:
- * @material: a #CoglMaterial object.
- *
- * Decrement the reference count for a #CoglMaterial.
- *
- * Since: 1.0
- *
- * Deprecated: 1.2: Use cogl_object_unref() instead
- */
-void
-cogl_material_unref (CoglHandle material) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_is_material:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing material object.
- *
- * Return value: %TRUE if the handle references a #CoglMaterial,
- * %FALSE otherwise
- */
-gboolean
-cogl_is_material (CoglHandle handle);
-
-/**
- * cogl_material_set_color:
- * @material: A #CoglMaterial object
- * @color: The components of the color
- *
- * Sets the basic color of the material, used when no lighting is enabled.
- *
- * Note that if you don't add any layers to the material then the color
- * will be blended unmodified with the destination; the default blend
- * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for
- * semi-transparent red. See cogl_color_premultiply().
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_color (CoglMaterial *material,
- const CoglColor *color);
-
-/**
- * cogl_material_set_color4ub:
- * @material: A #CoglMaterial object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the material, used when no lighting is enabled.
- *
- * The default value is (0xff, 0xff, 0xff, 0xff)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_color4ub (CoglMaterial *material,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha);
-
-/**
- * cogl_material_set_color4f:
- * @material: A #CoglMaterial object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the material, used when no lighting is enabled.
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_color4f (CoglMaterial *material,
- float red,
- float green,
- float blue,
- float alpha);
-
-/**
- * cogl_material_get_color:
- * @material: A #CoglMaterial object
- * @color: (out): The location to store the color
- *
- * Retrieves the current material color.
- *
- * Since: 1.0
- */
-void
-cogl_material_get_color (CoglMaterial *material,
- CoglColor *color);
-
-/**
- * cogl_material_set_ambient:
- * @material: A #CoglMaterial object
- * @ambient: The components of the desired ambient color
- *
- * Sets the material's ambient color, in the standard OpenGL lighting
- * model. The ambient color affects the overall color of the object.
- *
- * Since the diffuse color will be intense when the light hits the surface
- * directly, the ambient will be most apparent where the light hits at a
- * slant.
- *
- * The default value is (0.2, 0.2, 0.2, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_ambient (CoglMaterial *material,
- const CoglColor *ambient);
-
-/**
- * cogl_material_get_ambient:
- * @material: A #CoglMaterial object
- * @ambient: The location to store the ambient color
- *
- * Retrieves the current ambient color for @material
- *
- * Since: 1.0
- */
-void
-cogl_material_get_ambient (CoglMaterial *material,
- CoglColor *ambient);
-
-/**
- * cogl_material_set_diffuse:
- * @material: A #CoglMaterial object
- * @diffuse: The components of the desired diffuse color
- *
- * Sets the material's diffuse color, in the standard OpenGL lighting
- * model. The diffuse color is most intense where the light hits the
- * surface directly - perpendicular to the surface.
- *
- * The default value is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_diffuse (CoglMaterial *material,
- const CoglColor *diffuse);
-
-/**
- * cogl_material_get_diffuse:
- * @material: A #CoglMaterial object
- * @diffuse: The location to store the diffuse color
- *
- * Retrieves the current diffuse color for @material
- *
- * Since: 1.0
- */
-void
-cogl_material_get_diffuse (CoglMaterial *material,
- CoglColor *diffuse);
-
-/**
- * cogl_material_set_ambient_and_diffuse:
- * @material: A #CoglMaterial object
- * @color: The components of the desired ambient and diffuse colors
- *
- * Conveniently sets the diffuse and ambient color of @material at the same
- * time. See cogl_material_set_ambient() and cogl_material_set_diffuse().
- *
- * The default ambient color is (0.2, 0.2, 0.2, 1.0)
- *
- * The default diffuse color is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_ambient_and_diffuse (CoglMaterial *material,
- const CoglColor *color);
-
-/**
- * cogl_material_set_specular:
- * @material: A #CoglMaterial object
- * @specular: The components of the desired specular color
- *
- * Sets the material's specular color, in the standard OpenGL lighting
- * model. The intensity of the specular color depends on the viewport
- * position, and is brightest along the lines of reflection.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_specular (CoglMaterial *material,
- const CoglColor *specular);
-
-/**
- * cogl_material_get_specular:
- * @material: A #CoglMaterial object
- * @specular: The location to store the specular color
- *
- * Retrieves the materials current specular color.
- *
- * Since: 1.0
- */
-void
-cogl_material_get_specular (CoglMaterial *material,
- CoglColor *specular);
-
-/**
- * cogl_material_set_shininess:
- * @material: A #CoglMaterial object
- * @shininess: The desired shininess; must be >= 0.0
- *
- * Sets the shininess of the material, in the standard OpenGL lighting
- * model, which determines the size of the specular highlights. A
- * higher @shininess will produce smaller highlights which makes the
- * object appear more shiny.
- *
- * The default value is 0.0
- *
- * Since: 1.0
- */
-void
-cogl_material_set_shininess (CoglMaterial *material,
- float shininess);
-
-/**
- * cogl_material_get_shininess:
- * @material: A #CoglMaterial object
- *
- * Retrieves the materials current emission color.
- *
- * Return value: The materials current shininess value
- *
- * Since: 1.0
- */
-float
-cogl_material_get_shininess (CoglMaterial *material);
-
-/**
- * cogl_material_set_emission:
- * @material: A #CoglMaterial object
- * @emission: The components of the desired emissive color
- *
- * Sets the material's emissive color, in the standard OpenGL lighting
- * model. It will look like the surface is a light source emitting this
- * color.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 1.0
- */
-void
-cogl_material_set_emission (CoglMaterial *material,
- const CoglColor *emission);
-
-/**
- * cogl_material_get_emission:
- * @material: A #CoglMaterial object
- * @emission: The location to store the emission color
- *
- * Retrieves the materials current emission color.
- *
- * Since: 1.0
- */
-void
-cogl_material_get_emission (CoglMaterial *material,
- CoglColor *emission);
-
-/**
- * CoglMaterialAlphaFunc:
- * @COGL_MATERIAL_ALPHA_FUNC_NEVER: Never let the fragment through.
- * @COGL_MATERIAL_ALPHA_FUNC_LESS: Let the fragment through if the incoming
- * alpha value is less than the reference alpha value
- * @COGL_MATERIAL_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming
- * alpha value equals the reference alpha value
- * @COGL_MATERIAL_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming
- * alpha value is less than or equal to the reference alpha value
- * @COGL_MATERIAL_ALPHA_FUNC_GREATER: Let the fragment through if the incoming
- * alpha value is greater than the reference alpha value
- * @COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming
- * alpha value does not equal the reference alpha value
- * @COGL_MATERIAL_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming
- * alpha value is greater than or equal to the reference alpha value.
- * @COGL_MATERIAL_ALPHA_FUNC_ALWAYS: Always let the fragment through.
- *
- * Alpha testing happens before blending primitives with the framebuffer and
- * gives an opportunity to discard fragments based on a comparison with the
- * incoming alpha value and a reference alpha value. The #CoglMaterialAlphaFunc
- * determines how the comparison is done.
- */
-typedef enum {
- COGL_MATERIAL_ALPHA_FUNC_NEVER = 0x0200,
- COGL_MATERIAL_ALPHA_FUNC_LESS = 0x0201,
- COGL_MATERIAL_ALPHA_FUNC_EQUAL = 0x0202,
- COGL_MATERIAL_ALPHA_FUNC_LEQUAL = 0x0203,
- COGL_MATERIAL_ALPHA_FUNC_GREATER = 0x0204,
- COGL_MATERIAL_ALPHA_FUNC_NOTEQUAL = 0x0205,
- COGL_MATERIAL_ALPHA_FUNC_GEQUAL = 0x0206,
- COGL_MATERIAL_ALPHA_FUNC_ALWAYS = 0x0207
-} CoglMaterialAlphaFunc;
-
-/**
- * cogl_material_set_alpha_test_function:
- * @material: A #CoglMaterial object
- * @alpha_func: A @CoglMaterialAlphaFunc constant
- * @alpha_reference: A reference point that the chosen alpha function uses
- * to compare incoming fragments to.
- *
- * Before a primitive is blended with the framebuffer, it goes through an
- * alpha test stage which lets you discard fragments based on the current
- * alpha value. This function lets you change the function used to evaluate
- * the alpha channel, and thus determine which fragments are discarded
- * and which continue on to the blending stage.
- *
- * The default is %COGL_MATERIAL_ALPHA_FUNC_ALWAYS
- *
- * Since: 1.0
- */
-void
-cogl_material_set_alpha_test_function (CoglMaterial *material,
- CoglMaterialAlphaFunc alpha_func,
- float alpha_reference);
-
-/**
- * cogl_material_set_blend:
- * @material: A #CoglMaterial object
- * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
- * describing the desired blend function.
- * @error: return location for a #GError that may report lack of driver
- * support if you give separate blend string statements for the alpha
- * channel and RGB channels since some drivers, or backends such as
- * GLES 1.1, don't support this feature. May be %NULL, in which case a
- * warning will be printed out using GLib's logging facilities if an
- * error is encountered.
- *
- * If not already familiar; please refer <link linkend="cogl-Blend-Strings">here</link>
- * for an overview of what blend strings are, and their syntax.
- *
- * Blending occurs after the alpha test function, and combines fragments with
- * the framebuffer.
-
- * Currently the only blend function Cogl exposes is ADD(). So any valid
- * blend statements will be of the form:
- *
- * |[
- * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>))
- * ]|
- *
- * <warning>The brackets around blend factors are currently not
- * optional!</warning>
- *
- * This is the list of source-names usable as blend factors:
- * <itemizedlist>
- * <listitem><para>SRC_COLOR: The color of the in comming fragment</para></listitem>
- * <listitem><para>DST_COLOR: The color of the framebuffer</para></listitem>
- * <listitem><para>CONSTANT: The constant set via cogl_material_set_blend_constant()</para></listitem>
- * </itemizedlist>
- *
- * The source names can be used according to the
- * <link linkend="cogl-Blend-String-syntax">color-source and factor syntax</link>,
- * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would
- * "(CONSTANT[RGB])"
- *
- * These can also be used as factors:
- * <itemizedlist>
- * <listitem>0: (0, 0, 0, 0)</listitem>
- * <listitem>1: (1, 1, 1, 1)</listitem>
- * <listitem>SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A])</listitem>
- * </itemizedlist>
- *
- * <note>Remember; all color components are normalized to the range [0, 1]
- * before computing the result of blending.</note>
- *
- * <example id="cogl-Blend-Strings-blend-unpremul">
- * <title>Blend Strings/1</title>
- * <para>Blend a non-premultiplied source over a destination with
- * premultiplied alpha:</para>
- * <programlisting>
- * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
- * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- * </programlisting>
- * </example>
- *
- * <example id="cogl-Blend-Strings-blend-premul">
- * <title>Blend Strings/2</title>
- * <para>Blend a premultiplied source over a destination with
- * premultiplied alpha</para>
- * <programlisting>
- * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- * </programlisting>
- * </example>
- *
- * The default blend string is:
- * |[
- * RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))
- * ]|
- *
- * That gives normal alpha-blending when the calculated color for the material
- * is in premultiplied form.
- *
- * Return value: %TRUE if the blend string was successfully parsed, and the
- * described blending is supported by the underlying driver/hardware. If
- * there was an error, %FALSE is returned and @error is set accordingly (if
- * present).
- *
- * Since: 1.0
- */
-gboolean
-cogl_material_set_blend (CoglMaterial *material,
- const char *blend_string,
- GError **error);
-
-/**
- * cogl_material_set_blend_constant:
- * @material: A #CoglMaterial object
- * @constant_color: The constant color you want
- *
- * When blending is setup to reference a CONSTANT blend factor then
- * blending will depend on the constant set with this function.
- *
- * Since: 1.0
- */
-void
-cogl_material_set_blend_constant (CoglMaterial *material,
- const CoglColor *constant_color);
-
-/**
- * cogl_material_set_point_size:
- * @material: a material.
- * @point_size: the new point size.
- *
- * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API. Note that typically the GPU will
- * only support a limited minimum and maximum range of point sizes. If
- * the chosen point size is outside that range then the nearest value
- * within that range will be used instead. The size of a point is in
- * screen space so it will be the same regardless of any
- * transformations. The default point size is 1.0.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_point_size (CoglMaterial *material,
- float point_size);
-
-/**
- * cogl_material_get_point_size:
- * @material: a #CoglHandle to a material.
- *
- * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API.
- *
- * Return value: the point size of the material.
- *
- * Since: 1.4
- */
-float
-cogl_material_get_point_size (CoglMaterial *material);
-
-/**
- * cogl_material_get_user_program:
- * @material: a #CoglMaterial object.
- *
- * Queries what user program has been associated with the given
- * @material using cogl_material_set_user_program().
- *
- * Return value: (transfer none): The current user program
- * or %COGL_INVALID_HANDLE.
- *
- * Since: 1.4
- */
-CoglHandle
-cogl_material_get_user_program (CoglMaterial *material);
-
-/**
- * cogl_material_set_user_program:
- * @material: a #CoglMaterial object.
- * @program: A #CoglHandle to a linked CoglProgram
- *
- * Associates a linked CoglProgram with the given material so that the
- * program can take full control of vertex and/or fragment processing.
- *
- * This is an example of how it can be used to associate an ARBfp
- * program with a #CoglMaterial:
- * |[
- * CoglHandle shader;
- * CoglHandle program;
- * CoglMaterial *material;
- *
- * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
- * cogl_shader_source (shader,
- * "!!ARBfp1.0\n"
- * "MOV result.color,fragment.color;\n"
- * "END\n");
- * cogl_shader_compile (shader);
- *
- * program = cogl_create_program ();
- * cogl_program_attach_shader (program, shader);
- * cogl_program_link (program);
- *
- * material = cogl_material_new ();
- * cogl_material_set_user_program (material, program);
- *
- * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
- * cogl_rectangle (0, 0, 100, 100);
- * ]|
- *
- * It is possibly worth keeping in mind that this API is not part of
- * the long term design for how we want to expose shaders to Cogl
- * developers (We are planning on deprecating the cogl_program and
- * cogl_shader APIs in favour of a "snippet" framework) but in the
- * meantime we hope this will handle most practical GLSL and ARBfp
- * requirements.
- *
- * Also remember you need to check for either the
- * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before
- * using the cogl_program or cogl_shader API.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_user_program (CoglMaterial *material,
- CoglHandle program);
-
-/**
- * cogl_material_set_layer:
- * @material: A #CoglMaterial object
- * @layer_index: the index of the layer
- * @texture: a #CoglHandle for the layer object
- *
- * In addition to the standard OpenGL lighting model a Cogl material may have
- * one or more layers comprised of textures that can be blended together in
- * order, with a number of different texture combine modes. This function
- * defines a new texture layer.
- *
- * The index values of multiple layers do not have to be consecutive; it is
- * only their relative order that is important.
- *
- * <note>In the future, we may define other types of material layers, such
- * as purely GLSL based layers.</note>
- *
- * Since: 1.0
- */
-void
-cogl_material_set_layer (CoglMaterial *material,
- int layer_index,
- CoglHandle texture);
-
-/**
- * cogl_material_remove_layer:
- * @material: A #CoglMaterial object
- * @layer_index: Specifies the layer you want to remove
- *
- * This function removes a layer from your material
- */
-void
-cogl_material_remove_layer (CoglMaterial *material,
- int layer_index);
-
-
-/**
- * cogl_material_set_layer_combine:
- * @material: A #CoglMaterial object
- * @layer_index: Specifies the layer you want define a combine function for
- * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
- * describing the desired texture combine function.
- * @error: A #GError that may report parse errors or lack of GPU/driver
- * support. May be %NULL, in which case a warning will be printed out if an
- * error is encountered.
- *
- * If not already familiar; you can refer
- * <link linkend="cogl-Blend-Strings">here</link> for an overview of what blend
- * strings are and there syntax.
- *
- * These are all the functions available for texture combining:
- * <itemizedlist>
- * <listitem>REPLACE(arg0) = arg0</listitem>
- * <listitem>MODULATE(arg0, arg1) = arg0 x arg1</listitem>
- * <listitem>ADD(arg0, arg1) = arg0 + arg1</listitem>
- * <listitem>ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5</listitem>
- * <listitem>INTERPOLATE(arg0, arg1, arg2) = arg0 x arg2 + arg1 x (1 - arg2)</listitem>
- * <listitem>SUBTRACT(arg0, arg1) = arg0 - arg1</listitem>
- * <listitem>
- * <programlisting>
- * DOT3_RGB(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
- * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
- * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
- * </programlisting>
- * </listitem>
- * <listitem>
- * <programlisting>
- * DOT3_RGBA(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
- * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
- * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
- * </programlisting>
- * </listitem>
- * </itemizedlist>
- *
- * Refer to the
- * <link linkend="cogl-Blend-String-syntax">color-source syntax</link> for
- * describing the arguments. The valid source names for texture combining
- * are:
- * <variablelist>
- * <varlistentry>
- * <term>TEXTURE</term>
- * <listitem>Use the color from the current texture layer</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>TEXTURE_0, TEXTURE_1, etc</term>
- * <listitem>Use the color from the specified texture layer</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>CONSTANT</term>
- * <listitem>Use the color from the constant given with
- * cogl_material_set_layer_constant()</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>PRIMARY</term>
- * <listitem>Use the color of the material as set with
- * cogl_material_set_color()</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>PREVIOUS</term>
- * <listitem>Either use the texture color from the previous layer, or
- * if this is layer 0, use the color of the material as set with
- * cogl_material_set_color()</listitem>
- * </varlistentry>
- * </variablelist>
- *
- * <refsect2 id="cogl-Layer-Combine-Examples">
- * <title>Layer Combine Examples</title>
- * <para>This is effectively what the default blending is:</para>
- * <informalexample><programlisting>
- * RGBA = MODULATE (PREVIOUS, TEXTURE)
- * </programlisting></informalexample>
- * <para>This could be used to cross-fade between two images, using
- * the alpha component of a constant as the interpolator. The constant
- * color is given by calling cogl_material_set_layer_constant.</para>
- * <informalexample><programlisting>
- * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A])
- * </programlisting></informalexample>
- * </refsect2>
- *
- * <note>You can't give a multiplication factor for arguments as you can
- * with blending.</note>
- *
- * Return value: %TRUE if the blend string was successfully parsed, and the
- * described texture combining is supported by the underlying driver and
- * or hardware. On failure, %FALSE is returned and @error is set
- *
- * Since: 1.0
- */
-gboolean
-cogl_material_set_layer_combine (CoglMaterial *material,
- int layer_index,
- const char *blend_string,
- GError **error);
-
-/**
- * cogl_material_set_layer_combine_constant:
- * @material: A #CoglMaterial object
- * @layer_index: Specifies the layer you want to specify a constant used
- * for texture combining
- * @constant: The constant color you want
- *
- * When you are using the 'CONSTANT' color source in a layer combine
- * description then you can use this function to define its value.
- *
- * Since: 1.0
- */
-void
-cogl_material_set_layer_combine_constant (CoglMaterial *material,
- int layer_index,
- const CoglColor *constant);
-
-/**
- * cogl_material_set_layer_matrix:
- * @material: A #CoglMaterial object
- * @layer_index: the index for the layer inside @material
- * @matrix: the transformation matrix for the layer
- *
- * This function lets you set a matrix that can be used to e.g. translate
- * and rotate a single layer of a material used to fill your geometry.
- */
-void
-cogl_material_set_layer_matrix (CoglMaterial *material,
- int layer_index,
- const CoglMatrix *matrix);
-
-/**
- * cogl_material_get_layers:
- * @material: A #CoglMaterial object
- *
- * This function lets you access a material's internal list of layers
- * for iteration.
- *
- * <note>You should avoid using this API if possible since it was only
- * made public by mistake and will be deprecated when we have
- * suitable alternative.</note>
- *
- * <note>It's important to understand that the list returned may not
- * remain valid if you modify the material or any of the layers in any
- * way and so you would have to re-get the list in that
- * situation.</note>
- *
- * Return value: (element-type CoglMaterialLayer) (transfer none): A
- * list of #CoglMaterialLayer<!-- -->'s that can be passed to the
- * cogl_material_layer_* functions. The list is owned by Cogl and it
- * should not be modified or freed
- */
-G_CONST_RETURN GList *
-cogl_material_get_layers (CoglMaterial *material);
-
-/**
- * cogl_material_get_n_layers:
- * @material: A #CoglMaterial object
- *
- * Retrieves the number of layers defined for the given @material
- *
- * Return value: the number of layers
- *
- * Since: 1.0
- */
-int
-cogl_material_get_n_layers (CoglMaterial *material);
-
-/**
- * CoglMaterialLayerType:
- * @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a
- * <link linkend="cogl-Textures">texture</link>
- *
- * Available types of layers for a #CoglMaterial. This enumeration
- * might be expanded in later versions.
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_MATERIAL_LAYER_TYPE_TEXTURE
-} CoglMaterialLayerType;
-
-
-/**
- * cogl_material_layer_get_type:
- * @layer: A #CoglMaterialLayer object
- *
- * Retrieves the type of the layer
- *
- * Currently there is only one type of layer defined:
- * %COGL_MATERIAL_LAYER_TYPE_TEXTURE, but considering we may add purely GLSL
- * based layers in the future, you should write code that checks the type
- * first.
- *
- * Return value: the type of the layer
- */
-CoglMaterialLayerType
-cogl_material_layer_get_type (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_layer_get_texture:
- * @layer: A #CoglMaterialLayer object
- *
- * Extracts a texture handle for a specific layer.
- *
- * <note>In the future Cogl may support purely GLSL based layers; for those
- * layers this function which will likely return %COGL_INVALID_HANDLE if you
- * try to get the texture handle from them. Considering this scenario, you
- * should call cogl_material_layer_get_type() first in order check it is of
- * type %COGL_MATERIAL_LAYER_TYPE_TEXTURE before calling this function.</note>
- *
- * Return value: (transfer none): a #CoglHandle for the texture inside the layer
- */
-CoglHandle
-cogl_material_layer_get_texture (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_layer_get_min_filter:
- * @layer: a #CoglHandle for a material layer
- *
- * Queries the currently set downscaling filter for a material layer
- *
- * Return value: the current downscaling filter
- */
-CoglMaterialFilter
-cogl_material_layer_get_min_filter (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_layer_get_mag_filter:
- * @layer: A #CoglMaterialLayer object
- *
- * Queries the currently set downscaling filter for a material later
- *
- * Return value: the current downscaling filter
- */
-CoglMaterialFilter
-cogl_material_layer_get_mag_filter (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_set_layer_filters:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- * @min_filter: the filter used when scaling a texture down.
- * @mag_filter: the filter used when magnifying a texture.
- *
- * Changes the decimation and interpolation filters used when a texture is
- * drawn at other scales than 100%.
- */
-void
-cogl_material_set_layer_filters (CoglMaterial *material,
- int layer_index,
- CoglMaterialFilter min_filter,
- CoglMaterialFilter mag_filter);
-
-/**
- * cogl_material_set_layer_point_sprite_coords_enabled:
- * @material: a #CoglHandle to a material.
- * @layer_index: the layer number to change.
- * @enable: whether to enable point sprite coord generation.
- * @error: A return location for a GError, or NULL to ignore errors.
- *
- * When rendering points, if @enable is %TRUE then the texture
- * coordinates for this layer will be replaced with coordinates that
- * vary from 0.0 to 1.0 across the primitive. The top left of the
- * point will have the coordinates 0.0,0.0 and the bottom right will
- * have 1.0,1.0. If @enable is %FALSE then the coordinates will be
- * fixed for the entire point.
- *
- * This function will only work if %COGL_FEATURE_POINT_SPRITE is
- * available. If the feature is not available then the function will
- * return %FALSE and set @error.
- *
- * Return value: %TRUE if the function succeeds, %FALSE otherwise.
- * Since: 1.4
- */
-gboolean
-cogl_material_set_layer_point_sprite_coords_enabled (CoglMaterial *material,
- int layer_index,
- gboolean enable,
- GError **error);
-
-/**
- * cogl_material_get_layer_point_sprite_coords_enabled:
- * @material: a #CoglHandle to a material.
- * @layer_index: the layer number to check.
- *
- * Gets whether point sprite coordinate generation is enabled for this
- * texture layer.
- *
- * Return value: whether the texture coordinates will be replaced with
- * point sprite coordinates.
- *
- * Since: 1.4
- */
-gboolean
-cogl_material_get_layer_point_sprite_coords_enabled (CoglMaterial *material,
- int layer_index);
-
-/**
- * cogl_material_get_layer_wrap_mode_s:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 's' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 's' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_s (CoglMaterial *material,
- int layer_index);
-
-/**
- * cogl_material_set_layer_wrap_mode_s:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 's' coordinate of texture lookups on this layer.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_layer_wrap_mode_s (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode);
-
-/**
- * cogl_material_get_layer_wrap_mode_t:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 't' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 't' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_t (CoglMaterial *material,
- int layer_index);
-
-
-/**
- * cogl_material_set_layer_wrap_mode_t:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 't' coordinate of texture lookups on this layer.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_layer_wrap_mode_t (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode);
-
-/**
- * cogl_material_get_layer_wrap_mode_p:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 'p' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 'p' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglMaterialWrapMode
-cogl_material_get_layer_wrap_mode_p (CoglMaterial *material,
- int layer_index);
-
-/**
- * cogl_material_set_layer_wrap_mode_p:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 'p' coordinate of texture lookups on
- * this layer. 'p' is the third coordinate.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_layer_wrap_mode_p (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode);
-
-/**
- * cogl_material_set_layer_wrap_mode:
- * @material: A #CoglMaterial object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for all three coordinates of texture lookups on
- * this layer. This is equivalent to calling
- * cogl_material_set_layer_wrap_mode_s(),
- * cogl_material_set_layer_wrap_mode_t() and
- * cogl_material_set_layer_wrap_mode_p() separately.
- *
- * Since: 1.4
- */
-void
-cogl_material_set_layer_wrap_mode (CoglMaterial *material,
- int layer_index,
- CoglMaterialWrapMode mode);
-
-/**
- * cogl_material_layer_get_wrap_mode_s:
- * @layer: A #CoglMaterialLayer object
- *
- * Gets the wrap mode for the 's' coordinate of texture lookups on this layer.
- *
- * Return value: the wrap mode value for the s coordinate.
- *
- * Since: 1.4
- */
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_s (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_layer_get_wrap_mode_t:
- * @layer: A #CoglMaterialLayer object
- *
- * Gets the wrap mode for the 't' coordinate of texture lookups on this layer.
- *
- * Return value: the wrap mode value for the t coordinate.
- *
- * Since: 1.4
- */
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_t (CoglMaterialLayer *layer);
-
-/**
- * cogl_material_layer_get_wrap_mode_p:
- * @layer: A #CoglMaterialLayer object
- *
- * Gets the wrap mode for the 'p' coordinate of texture lookups on
- * this layer. 'p' is the third coordinate.
- *
- * Return value: the wrap mode value for the p coordinate.
- *
- * Since: 1.4
- */
-CoglMaterialWrapMode
-cogl_material_layer_get_wrap_mode_p (CoglMaterialLayer *layer);
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-
-/**
- * cogl_material_set_depth_test_enabled:
- * @material: A #CoglMaterial object
- * @enable: The enable state you want
- *
- * Enables or disables depth testing according to the value of
- * @enable.
- *
- * If depth testing is enable then the #CoglDepthTestFunction set
- * using cogl_material_set_depth_test_function() us used to evaluate
- * the depth value of incoming fragments against the corresponding
- * value stored in the current depth buffer, and if the test passes
- * then the fragments depth value is used to update the depth buffer.
- * (unless you have disabled depth writing via
- * cogl_material_set_depth_writing_enabled ())
- *
- * By default depth testing is disabled.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_material_set_depth_test_enabled (CoglMaterial *material,
- gboolean enable);
-
-/**
- * cogl_material_get_depth_test_enabled:
- * @material: A #CoglMaterial object
- *
- * Gets the current depth test enabled state as previously set by
- * cogl_material_set_depth_test_enabled().
- *
- * Returns: The material's current depth test enabled state.
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_material_get_depth_test_enabled (CoglMaterial *material);
-
-/**
- * cogl_material_set_depth_writing_enabled:
- * @material: A #CoglMaterial object
- * @enable: The enable state you want
- *
- * Enables or disables depth buffer writing according to the value of
- * @enable. Normally when depth testing is enabled and the comparison
- * between a fragment's depth value and the corresponding depth buffer
- * value passes then the fragment's depth is written to the depth
- * buffer unless writing is disabled here.
- *
- * By default depth writing is enabled
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_material_set_depth_writing_enabled (CoglMaterial *material,
- gboolean enable);
-
-/**
- * cogl_material_get_depth_writing_enabled:
- * @material: A #CoglMaterial object
- *
- * Gets the depth writing enable state as set by the corresponding
- * cogl_material_set_depth_writing_enabled.
- *
- * Returns: The current depth writing enable state
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_material_get_depth_writing_enabled (CoglMaterial *material);
-
-/**
- * cogl_material_set_depth_test_function:
- * @material: A #CoglMaterial object
- * @function: The #CoglDepthTestFunction to set
- *
- * Sets the #CoglDepthTestFunction used to compare the depth value of
- * an incoming fragment against the corresponding value in the current
- * depth buffer.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_material_set_depth_test_function (CoglMaterial *material,
- CoglDepthTestFunction function);
-
-/**
- * cogl_material_get_depth_test_function:
- * @material: A #CoglMaterial object
- *
- * Gets the current depth test enable state as previously set via
- * cogl_material_set_depth_test_enabled().
- *
- * Returns: The current depth test enable state.
- * Since: 1.4
- * Stability: Unstable
- */
-CoglDepthTestFunction
-cogl_material_get_depth_test_function (CoglMaterial *material);
-
-/**
- * cogl_material_set_depth_range:
- * @material: A #CoglMaterial object
- * @near_val: The near component of the desired depth range which will be
- * clamped to the range [0, 1]
- * @far_val: The far component of the desired depth range which will be
- * clamped to the range [0, 1]
- * @error: location to store an error of type #CoglError
- *
- * Sets the range to map depth values in normalized device coordinates
- * to before writing out to a depth buffer.
- *
- * After your geometry has be transformed, clipped and had perspective
- * division applied placing it in normalized device
- * coordinates all depth values between the near and far z clipping
- * planes are in the range -1 to 1. Before writing any depth value to
- * the depth buffer though the value is mapped into the range [0, 1].
- *
- * With this function you can change the range which depth values are
- * mapped too although the range must still lye within the range [0,
- * 1].
- *
- * If your driver does not support this feature (for example you are
- * using GLES 1 drivers) then this will return %FALSE and set an error
- * if @error isn't NULL. You can check ahead of time for the
- * %COGL_FEATURE_DEPTH_RANGE feature with cogl_features_available() to
- * know if this function will succeed.
- *
- * By default normalized device coordinate depth values are mapped to
- * the full range of depth buffer values, [0, 1].
- *
- * Returns: %TRUE if driver support is available else %FALSE.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_material_set_depth_range (CoglMaterial *material,
- float near_val,
- float far_val,
- GError **error);
-
-/**
- * cogl_material_get_depth_range_mapping:
- * @material: A #CoglMaterial object
- * @near_val: A pointer to store the near component of the depth range
- * @far_val: A pointer to store the far component of the depth range
- *
- * Gets the current range to which normalized depth values are mapped
- * before writing to the depth buffer. This corresponds to the range
- * set with cogl_material_set_depth_range().
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_material_get_depth_range (CoglMaterial *material,
- float *near_val,
- float *far_val);
-
-/**
- * CoglMaterialLayerCallback:
- * @material: The #CoglMaterial whos layers are being iterated
- * @layer_index: The current layer index
- * @user_data: The private data passed to cogl_material_foreach_layer()
- *
- * The callback prototype used with cogl_material_foreach_layer() for
- * iterating all the layers of a @material.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-typedef gboolean (*CoglMaterialLayerCallback) (CoglMaterial *material,
- int layer_index,
- void *user_data);
-
-/**
- * cogl_material_foreach_layer:
- * @material: A #CoglMaterial object
- * @callback: A #CoglMaterialLayerCallback to be called for each layer
- * index
- * @user_data: Private data that will be passed to the callback
- *
- * Iterates all the layer indices of the given @material.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_material_foreach_layer (CoglMaterial *material,
- CoglMaterialLayerCallback callback,
- void *user_data);
-
-#endif /* COGL_ENABLE_EXPERIMENTAL_API */
-
-G_END_DECLS
-
-#endif /* __COGL_MATERIAL_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-/*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/*
- * file: cogl-matrix-mesa.c
- * Matrix operations.
- *
- * note
- * -# 4x4 transformation matrices are stored in memory in column major order.
- * -# Points/vertices are to be thought of as column vectors.
- * -# Transformation of a point p by a matrix M is: p' = M * p
- */
-
-/*
- * Changes compared to the original code from Mesa:
- *
- * - instead of allocating matrix->m and matrix->inv using malloc, our
- * public CoglMatrix typedef is large enough to directly contain the
- * matrix, its inverse, a type and a set of flags.
- * - instead of having a _math_matrix_analyse which updates the type,
- * flags and inverse, we have _math_matrix_update_inverse which
- * essentially does the same thing (internally making use of
- * _math_matrix_update_type_and_flags()) but with additional guards in
- * place to bail out when the inverse matrix is still valid.
- * - when initializing a matrix with the identity matrix we don't
- * immediately initialize the inverse matrix; rather we just set the
- * dirty flag for the inverse (since it's likely the user won't request
- * the inverse of the identity matrix)
- */
-
-#include "cogl-matrix-mesa.h"
-
-#include <string.h>
-#include <math.h>
-
-
-#define DEG2RAD (G_PI/180.0)
-
-/* Dot product of two 2-element vectors */
-#define DOT2(A,B) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] )
-
-/* Dot product of two 3-element vectors */
-#define DOT3(A,B) ( (A)[0]*(B)[0] + (A)[1]*(B)[1] + (A)[2]*(B)[2] )
-
-#define CROSS3(N, U, V) \
-do { \
- (N)[0] = (U)[1]*(V)[2] - (U)[2]*(V)[1]; \
- (N)[1] = (U)[2]*(V)[0] - (U)[0]*(V)[2]; \
- (N)[2] = (U)[0]*(V)[1] - (U)[1]*(V)[0]; \
-} while (0)
-
-#define SUB_3V(DST, SRCA, SRCB) \
-do { \
- (DST)[0] = (SRCA)[0] - (SRCB)[0]; \
- (DST)[1] = (SRCA)[1] - (SRCB)[1]; \
- (DST)[2] = (SRCA)[2] - (SRCB)[2]; \
-} while (0)
-
-#define LEN_SQUARED_3FV( V ) ((V)[0]*(V)[0]+(V)[1]*(V)[1]+(V)[2]*(V)[2])
-
-/*
- * \defgroup MatFlags MAT_FLAG_XXX-flags
- *
- * Bitmasks to indicate different kinds of 4x4 matrices in CoglMatrix::flags
- */
-/*@{*/
-#define MAT_FLAG_IDENTITY 0 /*< is an identity matrix flag.
- * (Not actually used - the identity
- * matrix is identified by the absense
- * of all other flags.)
- */
-#define MAT_FLAG_GENERAL 0x1 /*< is a general matrix flag */
-#define MAT_FLAG_ROTATION 0x2 /*< is a rotation matrix flag */
-#define MAT_FLAG_TRANSLATION 0x4 /*< is a translation matrix flag */
-#define MAT_FLAG_UNIFORM_SCALE 0x8 /*< is an uniform scaling matrix flag */
-#define MAT_FLAG_GENERAL_SCALE 0x10 /*< is a general scaling matrix flag */
-#define MAT_FLAG_GENERAL_3D 0x20 /*< general 3D matrix flag */
-#define MAT_FLAG_PERSPECTIVE 0x40 /*< is a perspective proj matrix flag */
-#define MAT_FLAG_SINGULAR 0x80 /*< is a singular matrix flag */
-#define MAT_DIRTY_TYPE 0x100 /*< matrix type is dirty */
-#define MAT_DIRTY_FLAGS 0x200 /*< matrix flags are dirty */
-#define MAT_DIRTY_INVERSE 0x400 /*< matrix inverse is dirty */
-
-/* angle preserving matrix flags mask */
-#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \
- MAT_FLAG_TRANSLATION | \
- MAT_FLAG_UNIFORM_SCALE)
-
-/* geometry related matrix flags mask */
-#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \
- MAT_FLAG_ROTATION | \
- MAT_FLAG_TRANSLATION | \
- MAT_FLAG_UNIFORM_SCALE | \
- MAT_FLAG_GENERAL_SCALE | \
- MAT_FLAG_GENERAL_3D | \
- MAT_FLAG_PERSPECTIVE | \
- MAT_FLAG_SINGULAR)
-
-/* length preserving matrix flags mask */
-#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \
- MAT_FLAG_TRANSLATION)
-
-
-/* 3D (non-perspective) matrix flags mask */
-#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \
- MAT_FLAG_TRANSLATION | \
- MAT_FLAG_UNIFORM_SCALE | \
- MAT_FLAG_GENERAL_SCALE | \
- MAT_FLAG_GENERAL_3D)
-
-/* dirty matrix flags mask */
-#define MAT_DIRTY_ALL (MAT_DIRTY_TYPE | \
- MAT_DIRTY_FLAGS | \
- MAT_DIRTY_INVERSE)
-
-/*@}*/
-
-
-/*
- * Test geometry related matrix flags.
- *
- * \param mat a pointer to a CoglMatrix structure.
- * \param a flags mask.
- *
- * \returns non-zero if all geometry related matrix flags are contained within
- * the mask, or zero otherwise.
- */
-#define TEST_MAT_FLAGS(mat, a) \
- ((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0)
-
-
-
-/*
- * Names of the corresponding CoglMatrixType values.
- */
-static const char *types[] = {
- "COGL_MATRIX_TYPE_GENERAL",
- "COGL_MATRIX_TYPE_IDENTITY",
- "COGL_MATRIX_TYPE_3D_NO_ROT",
- "COGL_MATRIX_TYPE_PERSPECTIVE",
- "COGL_MATRIX_TYPE_2D",
- "COGL_MATRIX_TYPE_2D_NO_ROT",
- "COGL_MATRIX_TYPE_3D"
-};
-
-
-/*
- * Identity matrix.
- */
-static float identity[16] = {
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0
-};
-
-
-
-/**********************************************************************/
-/* \name Matrix multiplication */
-/*@{*/
-
-#define A(row,col) a[(col<<2)+row]
-#define B(row,col) b[(col<<2)+row]
-#define R(row,col) result[(col<<2)+row]
-
-/*
- * Perform a full 4x4 matrix multiplication.
- *
- * \param a matrix.
- * \param b matrix.
- * \param product will receive the product of \p a and \p b.
- *
- * \warning Is assumed that \p product != \p b. \p product == \p a is allowed.
- *
- * \note KW: 4*16 = 64 multiplications
- *
- * \author This \c matmul was contributed by Thomas Malik
- */
-static void
-matrix_multiply4x4 (float *result, const float *a, const float *b)
-{
- int i;
- for (i = 0; i < 4; i++)
- {
- const float ai0 = A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
- R(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
- R(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
- R(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
- R(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
- }
-}
-
-/*
- * Multiply two matrices known to occupy only the top three rows, such
- * as typical model matrices, and orthogonal matrices.
- *
- * \param a matrix.
- * \param b matrix.
- * \param product will receive the product of \p a and \p b.
- */
-static void
-matrix_multiply3x4 (float *result, const float *a, const float *b)
-{
- int i;
- for (i = 0; i < 3; i++)
- {
- const float ai0 = A(i,0), ai1 = A(i,1), ai2 = A(i,2), ai3 = A(i,3);
- R(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
- R(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
- R(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
- R(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3;
- }
- R(3,0) = 0;
- R(3,1) = 0;
- R(3,2) = 0;
- R(3,3) = 1;
-}
-
-#undef A
-#undef B
-#undef R
-
-/*
- * Multiply a matrix by an array of floats with known properties.
- *
- * \param mat pointer to a CoglMatrix structure containing the left multiplication
- * matrix, and that will receive the product result.
- * \param m right multiplication matrix array.
- * \param flags flags of the matrix \p m.
- *
- * Joins both flags and marks the type and inverse as dirty. Calls
- * matrix_multiply3x4() if both matrices are 3D, or matrix_multiply4x4()
- * otherwise.
- */
-static void
-matrix_multiply_array_with_flags (CoglMatrix *result,
- const float *array,
- unsigned int flags)
-{
- result->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
-
- if (TEST_MAT_FLAGS (result, MAT_FLAGS_3D))
- matrix_multiply3x4 ((float *)result, (float *)result, array);
- else
- matrix_multiply4x4 ((float *)result, (float *)result, array);
-}
-
-/*
- * Matrix multiplication.
- *
- * \param dest destination matrix.
- * \param a left matrix.
- * \param b right matrix.
- *
- * Joins both flags and marks the type and inverse as dirty. Calls
- * matrix_multiply3x4() if both matrices are 3D, or matrix_multiply4x4()
- * otherwise.
- */
-void
-_math_matrix_multiply (CoglMatrix *result,
- const CoglMatrix *a,
- const CoglMatrix *b)
-{
- result->flags = (a->flags |
- b->flags |
- MAT_DIRTY_TYPE |
- MAT_DIRTY_INVERSE);
-
- if (TEST_MAT_FLAGS(result, MAT_FLAGS_3D))
- matrix_multiply3x4 ((float *)result, (float *)a, (float *)b);
- else
- matrix_multiply4x4 ((float *)result, (float *)a, (float *)b);
-}
-
-/*
- * Matrix multiplication.
- *
- * \param dest left and destination matrix.
- * \param m right matrix array.
- *
- * Marks the matrix flags with general flag, and type and inverse dirty flags.
- * Calls matrix_multiply4x4() for the multiplication.
- */
-void
-_math_matrix_multiply_array (CoglMatrix *result, const float *array)
-{
- result->flags |= (MAT_FLAG_GENERAL |
- MAT_DIRTY_TYPE |
- MAT_DIRTY_INVERSE |
- MAT_DIRTY_FLAGS);
-
- matrix_multiply4x4 ((float *)result, (float *)result, (float *)array);
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/* \name Matrix output */
-/*@{*/
-
-/*
- * Print a matrix array.
- *
- * \param m matrix array.
- *
- * Called by _math_matrix_print() to print a matrix or its inverse.
- */
-static void
-print_matrix_floats (const float m[16])
-{
- int i;
- for (i = 0;i < 4; i++)
- g_print ("\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
-}
-
-/*
- * Dumps the contents of a CoglMatrix structure.
- *
- * \param m pointer to the CoglMatrix structure.
- */
-void
-_math_matrix_print (const CoglMatrix *matrix)
-{
- g_print ("Matrix type: %s, flags: %x\n",
- types[matrix->type], (int)matrix->flags);
- print_matrix_floats ((float *)matrix);
- g_print ("Inverse: \n");
- if (!(matrix->flags & MAT_DIRTY_INVERSE))
- {
- float prod[16];
- print_matrix_floats (matrix->inv);
- matrix_multiply4x4 (prod, (float *)matrix, matrix->inv);
- g_print ("Mat * Inverse:\n");
- print_matrix_floats (prod);
- }
- else
- g_print (" - not available\n");
-}
-
-/*@}*/
-
-
-/*
- * References an element of 4x4 matrix.
- *
- * \param m matrix array.
- * \param c column of the desired element.
- * \param r row of the desired element.
- *
- * \return value of the desired element.
- *
- * Calculate the linear storage index of the element and references it.
- */
-#define MAT(m,r,c) (m)[(c)*4+(r)]
-
-
-/**********************************************************************/
-/* \name Matrix inversion */
-/*@{*/
-
-/*
- * Swaps the values of two floating pointer variables.
- *
- * Used by invert_matrix_general() to swap the row pointers.
- */
-#define SWAP_ROWS(a, b) { float *_tmp = a; (a)=(b); (b)=_tmp; }
-
-/*
- * Compute inverse of 4x4 transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * \author
- * Code contributed by Jacques Leroy jle@star.be
- *
- * Calculates the inverse matrix by performing the gaussian matrix reduction
- * with partial pivoting followed by back/substitution with the loops manually
- * unrolled.
- */
-static gboolean
-invert_matrix_general (CoglMatrix *matrix)
-{
- const float *m = (float *)matrix;
- float *out = matrix->inv;
- float wtmp[4][8];
- float m0, m1, m2, m3, s;
- float *r0, *r1, *r2, *r3;
-
- r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
-
- r0[0] = MAT (m, 0, 0), r0[1] = MAT (m, 0, 1),
- r0[2] = MAT (m, 0, 2), r0[3] = MAT (m, 0, 3),
- r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
-
- r1[0] = MAT (m, 1, 0), r1[1] = MAT (m, 1, 1),
- r1[2] = MAT (m, 1, 2), r1[3] = MAT (m, 1, 3),
- r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
-
- r2[0] = MAT (m, 2, 0), r2[1] = MAT (m, 2, 1),
- r2[2] = MAT (m, 2, 2), r2[3] = MAT (m, 2, 3),
- r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
-
- r3[0] = MAT (m, 3, 0), r3[1] = MAT (m, 3, 1),
- r3[2] = MAT (m, 3, 2), r3[3] = MAT (m, 3, 3),
- r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
-
- /* choose pivot - or die */
- if (fabsf (r3[0]) > fabsf (r2[0]))
- SWAP_ROWS (r3, r2);
- if (fabsf (r2[0]) > fabsf (r1[0]))
- SWAP_ROWS (r2, r1);
- if (fabsf (r1[0]) > fabsf (r0[0]))
- SWAP_ROWS (r1, r0);
- if (0.0 == r0[0])
- return FALSE;
-
- /* eliminate first variable */
- m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0];
- s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
- s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
- s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
- s = r0[4];
- if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; }
- s = r0[5];
- if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; }
- s = r0[6];
- if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; }
- s = r0[7];
- if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; }
-
- /* choose pivot - or die */
- if (fabsf (r3[1]) > fabsf (r2[1]))
- SWAP_ROWS (r3, r2);
- if (fabsf (r2[1]) > fabsf (r1[1]))
- SWAP_ROWS (r2, r1);
- if (0.0 == r1[1])
- return FALSE;
-
- /* eliminate second variable */
- m2 = r2[1] / r1[1]; m3 = r3[1] / r1[1];
- r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];
- r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];
- s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; }
- s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; }
- s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; }
- s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; }
-
- /* choose pivot - or die */
- if (fabsf (r3[2]) > fabsf (r2[2]))
- SWAP_ROWS (r3, r2);
- if (0.0 == r2[2])
- return FALSE;
-
- /* eliminate third variable */
- m3 = r3[2] / r2[2];
- r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
- r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6],
- r3[7] -= m3 * r2[7];
-
- /* last check */
- if (0.0 == r3[3])
- return FALSE;
-
- s = 1.0f / r3[3]; /* now back substitute row 3 */
- r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s;
-
- m2 = r2[3]; /* now back substitute row 2 */
- s = 1.0f / r2[2];
- r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
- r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
- m1 = r1[3];
- r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
- r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
- m0 = r0[3];
- r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
- r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
-
- m1 = r1[2]; /* now back substitute row 1 */
- s = 1.0f / r1[1];
- r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
- r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
- m0 = r0[2];
- r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
- r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
-
- m0 = r0[1]; /* now back substitute row 0 */
- s = 1.0f / r0[0];
- r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
- r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
-
- MAT (out, 0, 0) = r0[4]; MAT (out, 0, 1) = r0[5],
- MAT (out, 0, 2) = r0[6]; MAT (out, 0, 3) = r0[7],
- MAT (out, 1, 0) = r1[4]; MAT (out, 1, 1) = r1[5],
- MAT (out, 1, 2) = r1[6]; MAT (out, 1, 3) = r1[7],
- MAT (out, 2, 0) = r2[4]; MAT (out, 2, 1) = r2[5],
- MAT (out, 2, 2) = r2[6]; MAT (out, 2, 3) = r2[7],
- MAT (out, 3, 0) = r3[4]; MAT (out, 3, 1) = r3[5],
- MAT (out, 3, 2) = r3[6]; MAT (out, 3, 3) = r3[7];
-
- return TRUE;
-}
-#undef SWAP_ROWS
-
-/*
- * Compute inverse of a general 3d transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * \author Adapted from graphics gems II.
- *
- * Calculates the inverse of the upper left by first calculating its
- * determinant and multiplying it to the symmetric adjust matrix of each
- * element. Finally deals with the translation part by transforming the
- * original translation vector using by the calculated submatrix inverse.
- */
-static gboolean
-invert_matrix_3d_general (CoglMatrix *matrix)
-{
- const float *in = (float *)matrix;
- float *out = matrix->inv;
- float pos, neg, t;
- float det;
-
- /* Calculate the determinant of upper left 3x3 submatrix and
- * determine if the matrix is singular.
- */
- pos = neg = 0.0;
- t = MAT (in,0,0) * MAT (in,1,1) * MAT (in,2,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- t = MAT (in,1,0) * MAT (in,2,1) * MAT (in,0,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- t = MAT (in,2,0) * MAT (in,0,1) * MAT (in,1,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- t = -MAT (in,2,0) * MAT (in,1,1) * MAT (in,0,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- t = -MAT (in,1,0) * MAT (in,0,1) * MAT (in,2,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- t = -MAT (in,0,0) * MAT (in,2,1) * MAT (in,1,2);
- if (t >= 0.0) pos += t; else neg += t;
-
- det = pos + neg;
-
- if (det*det < 1e-25)
- return FALSE;
-
- det = 1.0f / det;
- MAT (out,0,0) =
- ( (MAT (in, 1, 1)*MAT (in, 2, 2) - MAT (in, 2, 1)*MAT (in, 1, 2) )*det);
- MAT (out,0,1) =
- (- (MAT (in, 0, 1)*MAT (in, 2, 2) - MAT (in, 2, 1)*MAT (in, 0, 2) )*det);
- MAT (out,0,2) =
- ( (MAT (in, 0, 1)*MAT (in, 1, 2) - MAT (in, 1, 1)*MAT (in, 0, 2) )*det);
- MAT (out,1,0) =
- (- (MAT (in,1,0)*MAT (in,2,2) - MAT (in,2,0)*MAT (in,1,2) )*det);
- MAT (out,1,1) =
- ( (MAT (in,0,0)*MAT (in,2,2) - MAT (in,2,0)*MAT (in,0,2) )*det);
- MAT (out,1,2) =
- (- (MAT (in,0,0)*MAT (in,1,2) - MAT (in,1,0)*MAT (in,0,2) )*det);
- MAT (out,2,0) =
- ( (MAT (in,1,0)*MAT (in,2,1) - MAT (in,2,0)*MAT (in,1,1) )*det);
- MAT (out,2,1) =
- (- (MAT (in,0,0)*MAT (in,2,1) - MAT (in,2,0)*MAT (in,0,1) )*det);
- MAT (out,2,2) =
- ( (MAT (in,0,0)*MAT (in,1,1) - MAT (in,1,0)*MAT (in,0,1) )*det);
-
- /* Do the translation part */
- MAT (out,0,3) = - (MAT (in, 0, 3) * MAT (out, 0, 0) +
- MAT (in, 1, 3) * MAT (out, 0, 1) +
- MAT (in, 2, 3) * MAT (out, 0, 2) );
- MAT (out,1,3) = - (MAT (in, 0, 3) * MAT (out, 1, 0) +
- MAT (in, 1, 3) * MAT (out, 1, 1) +
- MAT (in, 2, 3) * MAT (out, 1, 2) );
- MAT (out,2,3) = - (MAT (in, 0, 3) * MAT (out, 2 ,0) +
- MAT (in, 1, 3) * MAT (out, 2, 1) +
- MAT (in, 2, 3) * MAT (out, 2, 2) );
-
- return TRUE;
-}
-
-/*
- * Compute inverse of a 3d transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * If the matrix is not an angle preserving matrix then calls
- * invert_matrix_3d_general for the actual calculation. Otherwise calculates
- * the inverse matrix analyzing and inverting each of the scaling, rotation and
- * translation parts.
- */
-static gboolean
-invert_matrix_3d (CoglMatrix *matrix)
-{
- const float *in = (float *)matrix;
- float *out = matrix->inv;
-
- if (!TEST_MAT_FLAGS(matrix, MAT_FLAGS_ANGLE_PRESERVING))
- return invert_matrix_3d_general (matrix);
-
- if (matrix->flags & MAT_FLAG_UNIFORM_SCALE)
- {
- float scale = (MAT (in, 0, 0) * MAT (in, 0, 0) +
- MAT (in, 0, 1) * MAT (in, 0, 1) +
- MAT (in, 0, 2) * MAT (in, 0, 2));
-
- if (scale == 0.0)
- return FALSE;
-
- scale = 1.0f / scale;
-
- /* Transpose and scale the 3 by 3 upper-left submatrix. */
- MAT (out, 0, 0) = scale * MAT (in, 0, 0);
- MAT (out, 1, 0) = scale * MAT (in, 0, 1);
- MAT (out, 2, 0) = scale * MAT (in, 0, 2);
- MAT (out, 0, 1) = scale * MAT (in, 1, 0);
- MAT (out, 1, 1) = scale * MAT (in, 1, 1);
- MAT (out, 2, 1) = scale * MAT (in, 1, 2);
- MAT (out, 0, 2) = scale * MAT (in, 2, 0);
- MAT (out, 1, 2) = scale * MAT (in, 2, 1);
- MAT (out, 2, 2) = scale * MAT (in, 2, 2);
- }
- else if (matrix->flags & MAT_FLAG_ROTATION)
- {
- /* Transpose the 3 by 3 upper-left submatrix. */
- MAT (out, 0, 0) = MAT (in, 0, 0);
- MAT (out, 1, 0) = MAT (in, 0, 1);
- MAT (out, 2, 0) = MAT (in, 0, 2);
- MAT (out, 0, 1) = MAT (in, 1, 0);
- MAT (out, 1, 1) = MAT (in, 1, 1);
- MAT (out, 2, 1) = MAT (in, 1, 2);
- MAT (out, 0, 2) = MAT (in, 2, 0);
- MAT (out, 1, 2) = MAT (in, 2, 1);
- MAT (out, 2, 2) = MAT (in, 2, 2);
- }
- else
- {
- /* pure translation */
- memcpy (out, identity, 16 * sizeof (float));
- MAT (out, 0, 3) = - MAT (in, 0, 3);
- MAT (out, 1, 3) = - MAT (in, 1, 3);
- MAT (out, 2, 3) = - MAT (in, 2, 3);
- return TRUE;
- }
-
- if (matrix->flags & MAT_FLAG_TRANSLATION)
- {
- /* Do the translation part */
- MAT (out,0,3) = - (MAT (in, 0, 3) * MAT (out, 0, 0) +
- MAT (in, 1, 3) * MAT (out, 0, 1) +
- MAT (in, 2, 3) * MAT (out, 0, 2) );
- MAT (out,1,3) = - (MAT (in, 0, 3) * MAT (out, 1, 0) +
- MAT (in, 1, 3) * MAT (out, 1, 1) +
- MAT (in, 2, 3) * MAT (out, 1, 2) );
- MAT (out,2,3) = - (MAT (in, 0, 3) * MAT (out, 2, 0) +
- MAT (in, 1, 3) * MAT (out, 2, 1) +
- MAT (in, 2, 3) * MAT (out, 2, 2) );
- }
- else
- MAT (out, 0, 3) = MAT (out, 1, 3) = MAT (out, 2, 3) = 0.0;
-
- return TRUE;
-}
-
-/*
- * Compute inverse of an identity transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return always TRUE.
- *
- * Simply copies identity into CoglMatrix::inv.
- */
-static gboolean
-invert_matrix_identity (CoglMatrix *matrix)
-{
- memcpy (matrix->inv, identity, 16 * sizeof (float));
- return TRUE;
-}
-
-/*
- * Compute inverse of a no-rotation 3d transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * Calculates the
- */
-static gboolean
-invert_matrix_3d_no_rotation (CoglMatrix *matrix)
-{
- const float *in = (float *)matrix;
- float *out = matrix->inv;
-
- if (MAT (in,0,0) == 0 || MAT (in,1,1) == 0 || MAT (in,2,2) == 0)
- return FALSE;
-
- memcpy (out, identity, 16 * sizeof (float));
- MAT (out,0,0) = 1.0f / MAT (in,0,0);
- MAT (out,1,1) = 1.0f / MAT (in,1,1);
- MAT (out,2,2) = 1.0f / MAT (in,2,2);
-
- if (matrix->flags & MAT_FLAG_TRANSLATION)
- {
- MAT (out,0,3) = - (MAT (in,0,3) * MAT (out,0,0));
- MAT (out,1,3) = - (MAT (in,1,3) * MAT (out,1,1));
- MAT (out,2,3) = - (MAT (in,2,3) * MAT (out,2,2));
- }
-
- return TRUE;
-}
-
-/*
- * Compute inverse of a no-rotation 2d transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * Calculates the inverse matrix by applying the inverse scaling and
- * translation to the identity matrix.
- */
-static gboolean
-invert_matrix_2d_no_rotation (CoglMatrix *matrix)
-{
- const float *in = (float *)matrix;
- float *out = matrix->inv;
-
- if (MAT (in, 0, 0) == 0 || MAT (in, 1, 1) == 0)
- return FALSE;
-
- memcpy (out, identity, 16 * sizeof (float));
- MAT (out, 0, 0) = 1.0f / MAT (in, 0, 0);
- MAT (out, 1, 1) = 1.0f / MAT (in, 1, 1);
-
- if (matrix->flags & MAT_FLAG_TRANSLATION)
- {
- MAT (out, 0, 3) = - (MAT (in, 0, 3) * MAT (out, 0, 0));
- MAT (out, 1, 3) = - (MAT (in, 1, 3) * MAT (out, 1, 1));
- }
-
- return TRUE;
-}
-
-#if 0
-/* broken */
-static gboolean
-invert_matrix_perspective (CoglMatrix *matrix)
-{
- const float *in = matrix;
- float *out = matrix->inv;
-
- if (MAT (in,2,3) == 0)
- return FALSE;
-
- memcpy( out, identity, 16 * sizeof(float) );
-
- MAT (out, 0, 0) = 1.0f / MAT (in, 0, 0);
- MAT (out, 1, 1) = 1.0f / MAT (in, 1, 1);
-
- MAT (out, 0, 3) = MAT (in, 0, 2);
- MAT (out, 1, 3) = MAT (in, 1, 2);
-
- MAT (out,2,2) = 0;
- MAT (out,2,3) = -1;
-
- MAT (out,3,2) = 1.0f / MAT (in,2,3);
- MAT (out,3,3) = MAT (in,2,2) * MAT (out,3,2);
-
- return TRUE;
-}
-#endif
-
-/*
- * Matrix inversion function pointer type.
- */
-typedef gboolean (*inv_mat_func)(CoglMatrix *matrix);
-
-/*
- * Table of the matrix inversion functions according to the matrix type.
- */
-static inv_mat_func inv_mat_tab[7] = {
- invert_matrix_general,
- invert_matrix_identity,
- invert_matrix_3d_no_rotation,
-#if 0
- /* Don't use this function for now - it fails when the projection matrix
- * is premultiplied by a translation (ala Chromium's tilesort SPU).
- */
- invert_matrix_perspective,
-#else
- invert_matrix_general,
-#endif
- invert_matrix_3d, /* lazy! */
- invert_matrix_2d_no_rotation,
- invert_matrix_3d
-};
-
-/*
- * Compute inverse of a transformation matrix.
- *
- * \param mat pointer to a CoglMatrix structure. The matrix inverse will be
- * stored in the CoglMatrix::inv attribute.
- *
- * \return TRUE for success, FALSE for failure (\p singular matrix).
- *
- * Calls the matrix inversion function in inv_mat_tab corresponding to the
- * given matrix type. In case of failure, updates the MAT_FLAG_SINGULAR flag,
- * and copies the identity matrix into CoglMatrix::inv.
- */
-gboolean
-_math_matrix_update_inverse (CoglMatrix *matrix)
-{
- if (matrix->flags & MAT_DIRTY_FLAGS ||
- matrix->flags & MAT_DIRTY_INVERSE)
- {
- _math_matrix_update_type_and_flags (matrix);
-
- if (inv_mat_tab[matrix->type](matrix))
- matrix->flags &= ~MAT_FLAG_SINGULAR;
- else
- {
- matrix->flags |= MAT_FLAG_SINGULAR;
- memcpy (matrix->inv, identity, 16 * sizeof (float));
- }
-
- matrix->flags &= ~MAT_DIRTY_INVERSE;
- }
-
- if (matrix->flags & MAT_FLAG_SINGULAR)
- return FALSE;
- else
- return TRUE;
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/* \name Matrix generation */
-/*@{*/
-
-/*
- * Generate a 4x4 transformation matrix from glRotate parameters, and
- * post-multiply the input matrix by it.
- *
- * \author
- * This function was contributed by Erich Boleyn (erich@uruk.org).
- * Optimizations contributed by Rudolf Opalla (rudi@khm.de).
- */
-void
-_math_matrix_rotate (CoglMatrix *matrix,
- float angle,
- float x,
- float y,
- float z)
-{
- float xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
- float m[16];
- gboolean optimized;
-
- s = sinf (angle * DEG2RAD);
- c = cosf (angle * DEG2RAD);
-
- memcpy (m, identity, 16 * sizeof (float));
- optimized = FALSE;
-
-#define M(row,col) m[col*4+row]
-
- if (x == 0.0f)
- {
- if (y == 0.0f)
- {
- if (z != 0.0f)
- {
- optimized = TRUE;
- /* rotate only around z-axis */
- M (0,0) = c;
- M (1,1) = c;
- if (z < 0.0f)
- {
- M (0,1) = s;
- M (1,0) = -s;
- }
- else
- {
- M (0,1) = -s;
- M (1,0) = s;
- }
- }
- }
- else if (z == 0.0f)
- {
- optimized = TRUE;
- /* rotate only around y-axis */
- M (0,0) = c;
- M (2,2) = c;
- if (y < 0.0f)
- {
- M (0,2) = -s;
- M (2,0) = s;
- }
- else
- {
- M (0,2) = s;
- M (2,0) = -s;
- }
- }
- }
- else if (y == 0.0f)
- {
- if (z == 0.0f)
- {
- optimized = TRUE;
- /* rotate only around x-axis */
- M (1,1) = c;
- M (2,2) = c;
- if (x < 0.0f)
- {
- M (1,2) = s;
- M (2,1) = -s;
- }
- else
- {
- M (1,2) = -s;
- M (2,1) = s;
- }
- }
- }
-
- if (!optimized)
- {
- const float mag = sqrtf (x * x + y * y + z * z);
-
- if (mag <= 1.0e-4)
- {
- /* no rotation, leave mat as-is */
- return;
- }
-
- x /= mag;
- y /= mag;
- z /= mag;
-
-
- /*
- * Arbitrary axis rotation matrix.
- *
- * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
- * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
- * (which is about the X-axis), and the two composite transforms
- * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
- * from the arbitrary axis to the X-axis then back. They are
- * all elementary rotations.
- *
- * Rz' is a rotation about the Z-axis, to bring the axis vector
- * into the x-z plane. Then Ry' is applied, rotating about the
- * Y-axis to bring the axis vector parallel with the X-axis. The
- * rotation about the X-axis is then performed. Ry and Rz are
- * simply the respective inverse transforms to bring the arbitrary
- * axis back to it's original orientation. The first transforms
- * Rz' and Ry' are considered inverses, since the data from the
- * arbitrary axis gives you info on how to get to it, not how
- * to get away from it, and an inverse must be applied.
- *
- * The basic calculation used is to recognize that the arbitrary
- * axis vector (x, y, z), since it is of unit length, actually
- * represents the sines and cosines of the angles to rotate the
- * X-axis to the same orientation, with theta being the angle about
- * Z and phi the angle about Y (in the order described above)
- * as follows:
- *
- * cos ( theta ) = x / sqrt ( 1 - z^2 )
- * sin ( theta ) = y / sqrt ( 1 - z^2 )
- *
- * cos ( phi ) = sqrt ( 1 - z^2 )
- * sin ( phi ) = z
- *
- * Note that cos ( phi ) can further be inserted to the above
- * formulas:
- *
- * cos ( theta ) = x / cos ( phi )
- * sin ( theta ) = y / sin ( phi )
- *
- * ...etc. Because of those relations and the standard trigonometric
- * relations, it is pssible to reduce the transforms down to what
- * is used below. It may be that any primary axis chosen will give the
- * same results (modulo a sign convention) using thie method.
- *
- * Particularly nice is to notice that all divisions that might
- * have caused trouble when parallel to certain planes or
- * axis go away with care paid to reducing the expressions.
- * After checking, it does perform correctly under all cases, since
- * in all the cases of division where the denominator would have
- * been zero, the numerator would have been zero as well, giving
- * the expected result.
- */
-
- xx = x * x;
- yy = y * y;
- zz = z * z;
- xy = x * y;
- yz = y * z;
- zx = z * x;
- xs = x * s;
- ys = y * s;
- zs = z * s;
- one_c = 1.0f - c;
-
- /* We already hold the identity-matrix so we can skip some statements */
- M (0,0) = (one_c * xx) + c;
- M (0,1) = (one_c * xy) - zs;
- M (0,2) = (one_c * zx) + ys;
- /* M (0,3) = 0.0f; */
-
- M (1,0) = (one_c * xy) + zs;
- M (1,1) = (one_c * yy) + c;
- M (1,2) = (one_c * yz) - xs;
- /* M (1,3) = 0.0f; */
-
- M (2,0) = (one_c * zx) - ys;
- M (2,1) = (one_c * yz) + xs;
- M (2,2) = (one_c * zz) + c;
- /* M (2,3) = 0.0f; */
-
- /*
- M (3,0) = 0.0f;
- M (3,1) = 0.0f;
- M (3,2) = 0.0f;
- M (3,3) = 1.0f;
- */
- }
-#undef M
-
- matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_ROTATION);
-}
-
-/*
- * Apply a perspective projection matrix.
- *
- * \param mat matrix to apply the projection.
- * \param left left clipping plane coordinate.
- * \param right right clipping plane coordinate.
- * \param bottom bottom clipping plane coordinate.
- * \param top top clipping plane coordinate.
- * \param nearval distance to the near clipping plane.
- * \param farval distance to the far clipping plane.
- *
- * Creates the projection matrix and multiplies it with \p mat, marking the
- * MAT_FLAG_PERSPECTIVE flag.
- */
-void
-_math_matrix_frustum (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval)
-{
- float x, y, a, b, c, d;
- float m[16];
-
- x = (2.0f * nearval) / (right - left);
- y = (2.0f * nearval) / (top - bottom);
- a = (right + left) / (right - left);
- b = (top + bottom) / (top - bottom);
- c = -(farval + nearval) / ( farval - nearval);
- d = -(2.0f * farval * nearval) / (farval - nearval); /* error? */
-
-#define M(row,col) m[col*4+row]
- M (0,0) = x; M (0,1) = 0.0f; M (0,2) = a; M (0,3) = 0.0f;
- M (1,0) = 0.0f; M (1,1) = y; M (1,2) = b; M (1,3) = 0.0f;
- M (2,0) = 0.0f; M (2,1) = 0.0f; M (2,2) = c; M (2,3) = d;
- M (3,0) = 0.0f; M (3,1) = 0.0f; M (3,2) = -1.0f; M (3,3) = 0.0f;
-#undef M
-
- matrix_multiply_array_with_flags (matrix, m, MAT_FLAG_PERSPECTIVE);
-}
-
-/*
- * Apply an orthographic projection matrix.
- *
- * \param mat matrix to apply the projection.
- * \param left left clipping plane coordinate.
- * \param right right clipping plane coordinate.
- * \param bottom bottom clipping plane coordinate.
- * \param top top clipping plane coordinate.
- * \param nearval distance to the near clipping plane.
- * \param farval distance to the far clipping plane.
- *
- * Creates the projection matrix and multiplies it with \p mat, marking the
- * MAT_FLAG_GENERAL_SCALE and MAT_FLAG_TRANSLATION flags.
- */
-void
-_math_matrix_ortho (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval)
-{
- float m[16];
-
-#define M(row,col) m[col*4+row]
- M (0,0) = 2.0f / (right-left);
- M (0,1) = 0.0f;
- M (0,2) = 0.0f;
- M (0,3) = -(right+left) / (right-left);
-
- M (1,0) = 0.0f;
- M (1,1) = 2.0f / (top-bottom);
- M (1,2) = 0.0f;
- M (1,3) = -(top+bottom) / (top-bottom);
-
- M (2,0) = 0.0f;
- M (2,1) = 0.0f;
- M (2,2) = -2.0f / (farval-nearval);
- M (2,3) = -(farval+nearval) / (farval-nearval);
-
- M (3,0) = 0.0f;
- M (3,1) = 0.0f;
- M (3,2) = 0.0f;
- M (3,3) = 1.0f;
-#undef M
-
- matrix_multiply_array_with_flags (matrix, m,
- (MAT_FLAG_GENERAL_SCALE |
- MAT_FLAG_TRANSLATION));
-}
-
-/*
- * Multiply a matrix with a general scaling matrix.
- *
- * \param mat matrix.
- * \param x x axis scale factor.
- * \param y y axis scale factor.
- * \param z z axis scale factor.
- *
- * Multiplies in-place the elements of \p mat by the scale factors. Checks if
- * the scales factors are roughly the same, marking the MAT_FLAG_UNIFORM_SCALE
- * flag, or MAT_FLAG_GENERAL_SCALE. Marks the MAT_DIRTY_TYPE and
- * MAT_DIRTY_INVERSE dirty flags.
- */
-void
-_math_matrix_scale (CoglMatrix *matrix, float x, float y, float z)
-{
- float *m = (float *)matrix;
- m[0] *= x; m[4] *= y; m[8] *= z;
- m[1] *= x; m[5] *= y; m[9] *= z;
- m[2] *= x; m[6] *= y; m[10] *= z;
- m[3] *= x; m[7] *= y; m[11] *= z;
-
- if (fabsf (x - y) < 1e-8 && fabsf (x - z) < 1e-8)
- matrix->flags |= MAT_FLAG_UNIFORM_SCALE;
- else
- matrix->flags |= MAT_FLAG_GENERAL_SCALE;
-
- matrix->flags |= (MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
-}
-
-/*
- * Multiply a matrix with a translation matrix.
- *
- * \param mat matrix.
- * \param x translation vector x coordinate.
- * \param y translation vector y coordinate.
- * \param z translation vector z coordinate.
- *
- * Adds the translation coordinates to the elements of \p mat in-place. Marks
- * the MAT_FLAG_TRANSLATION flag, and the MAT_DIRTY_TYPE and MAT_DIRTY_INVERSE
- * dirty flags.
- */
-void
-_math_matrix_translate (CoglMatrix *matrix, float x, float y, float z)
-{
- float *m = (float *)matrix;
- m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
- m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
- m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
- m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
-
- matrix->flags |= (MAT_FLAG_TRANSLATION |
- MAT_DIRTY_TYPE |
- MAT_DIRTY_INVERSE);
-}
-
-
-/*
- * Set matrix to do viewport and depthrange mapping.
- * Transforms Normalized Device Coords to window/Z values.
- */
-void
-_math_matrix_viewport (CoglMatrix *matrix,
- float x, float y,
- float width, float height,
- float zNear, float zFar, float depthMax)
-{
- float *m = (float *)matrix;
- m[MAT_SX] = width / 2.0f;
- m[MAT_TX] = m[MAT_SX] + x;
- m[MAT_SY] = height / 2.0f;
- m[MAT_TY] = m[MAT_SY] + y;
- m[MAT_SZ] = depthMax * ((zFar - zNear) / 2.0f);
- m[MAT_TZ] = depthMax * ((zFar - zNear) / 2.0f + zNear);
- matrix->flags = MAT_FLAG_GENERAL_SCALE | MAT_FLAG_TRANSLATION;
- matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT;
-}
-
-
-/*
- * Set a matrix to the identity matrix.
- *
- * \param mat matrix.
- *
- * Copies ::identity into \p CoglMatrix::m, and into CoglMatrix::inv if
- * not NULL. Sets the matrix type to identity, resets the flags. It
- * doesn't initialize the inverse matrix, it just marks it dirty.
- */
-void
-_math_matrix_init_identity (CoglMatrix *matrix)
-{
- memcpy (matrix, identity, 16 * sizeof (float));
-
- matrix->type = COGL_MATRIX_TYPE_IDENTITY;
- matrix->flags = MAT_DIRTY_INVERSE;
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/* \name Matrix analysis */
-/*@{*/
-
-#define ZERO(x) (1<<x)
-#define ONE(x) (1<<(x+16))
-
-#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14))
-#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5))
-
-#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\
- ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\
- ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
- ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
-
-#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \
- ZERO(1) | ZERO(9) | \
- ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
- ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
-
-#define MASK_2D ( ZERO(8) | \
- ZERO(9) | \
- ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
- ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
-
-
-#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \
- ZERO(1) | ZERO(9) | \
- ZERO(2) | ZERO(6) | \
- ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
-
-#define MASK_3D ( \
- \
- \
- ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
-
-
-#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\
- ZERO(1) | ZERO(13) |\
- ZERO(2) | ZERO(6) | \
- ZERO(3) | ZERO(7) | ZERO(15) )
-
-#define SQ(x) ((x)*(x))
-
-/*
- * Determine type and flags from scratch.
- *
- * \param mat matrix.
- *
- * This is expensive enough to only want to do it once.
- */
-static void
-analyse_from_scratch (CoglMatrix *matrix)
-{
- const float *m = (float *)matrix;
- unsigned int mask = 0;
- unsigned int i;
-
- for (i = 0 ; i < 16 ; i++)
- {
- if (m[i] == 0.0) mask |= (1<<i);
- }
-
- if (m[0] == 1.0f) mask |= (1<<16);
- if (m[5] == 1.0f) mask |= (1<<21);
- if (m[10] == 1.0f) mask |= (1<<26);
- if (m[15] == 1.0f) mask |= (1<<31);
-
- matrix->flags &= ~MAT_FLAGS_GEOMETRY;
-
- /* Check for translation - no-one really cares
- */
- if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
- matrix->flags |= MAT_FLAG_TRANSLATION;
-
- /* Do the real work
- */
- if (mask == (unsigned int) MASK_IDENTITY)
- matrix->type = COGL_MATRIX_TYPE_IDENTITY;
- else if ((mask & MASK_2D_NO_ROT) == (unsigned int) MASK_2D_NO_ROT)
- {
- matrix->type = COGL_MATRIX_TYPE_2D_NO_ROT;
-
- if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
- matrix->flags |= MAT_FLAG_GENERAL_SCALE;
- }
- else if ((mask & MASK_2D) == (unsigned int) MASK_2D)
- {
- float mm = DOT2 (m, m);
- float m4m4 = DOT2 (m+4,m+4);
- float mm4 = DOT2 (m,m+4);
-
- matrix->type = COGL_MATRIX_TYPE_2D;
-
- /* Check for scale */
- if (SQ (mm-1) > SQ (1e-6) ||
- SQ (m4m4-1) > SQ (1e-6))
- matrix->flags |= MAT_FLAG_GENERAL_SCALE;
-
- /* Check for rotation */
- if (SQ (mm4) > SQ (1e-6))
- matrix->flags |= MAT_FLAG_GENERAL_3D;
- else
- matrix->flags |= MAT_FLAG_ROTATION;
-
- }
- else if ((mask & MASK_3D_NO_ROT) == (unsigned int) MASK_3D_NO_ROT)
- {
- matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT;
-
- /* Check for scale */
- if (SQ (m[0]-m[5]) < SQ (1e-6) &&
- SQ (m[0]-m[10]) < SQ (1e-6))
- {
- if (SQ (m[0]-1.0) > SQ (1e-6))
- matrix->flags |= MAT_FLAG_UNIFORM_SCALE;
- }
- else
- matrix->flags |= MAT_FLAG_GENERAL_SCALE;
- }
- else if ((mask & MASK_3D) == (unsigned int) MASK_3D)
- {
- float c1 = DOT3 (m,m);
- float c2 = DOT3 (m+4,m+4);
- float c3 = DOT3 (m+8,m+8);
- float d1 = DOT3 (m, m+4);
- float cp[3];
-
- matrix->type = COGL_MATRIX_TYPE_3D;
-
- /* Check for scale */
- if (SQ (c1-c2) < SQ (1e-6) && SQ (c1-c3) < SQ (1e-6))
- {
- if (SQ (c1-1.0) > SQ (1e-6))
- matrix->flags |= MAT_FLAG_UNIFORM_SCALE;
- /* else no scale at all */
- }
- else
- matrix->flags |= MAT_FLAG_GENERAL_SCALE;
-
- /* Check for rotation */
- if (SQ (d1) < SQ (1e-6))
- {
- CROSS3 ( cp, m, m+4);
- SUB_3V ( cp, cp, (m+8));
- if (LEN_SQUARED_3FV(cp) < SQ(1e-6))
- matrix->flags |= MAT_FLAG_ROTATION;
- else
- matrix->flags |= MAT_FLAG_GENERAL_3D;
- }
- else
- matrix->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
- }
- else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0f)
- {
- matrix->type = COGL_MATRIX_TYPE_PERSPECTIVE;
- matrix->flags |= MAT_FLAG_GENERAL;
- }
- else
- {
- matrix->type = COGL_MATRIX_TYPE_GENERAL;
- matrix->flags |= MAT_FLAG_GENERAL;
- }
-}
-
-/*
- * Analyze a matrix given that its flags are accurate.
- *
- * This is the more common operation, hopefully.
- */
-static void
-analyse_from_flags (CoglMatrix *matrix)
-{
- const float *m = (float *)matrix;
-
- if (TEST_MAT_FLAGS(matrix, 0))
- matrix->type = COGL_MATRIX_TYPE_IDENTITY;
- else if (TEST_MAT_FLAGS(matrix, (MAT_FLAG_TRANSLATION |
- MAT_FLAG_UNIFORM_SCALE |
- MAT_FLAG_GENERAL_SCALE)))
- {
- if ( m[10] == 1.0f && m[14] == 0.0f )
- matrix->type = COGL_MATRIX_TYPE_2D_NO_ROT;
- else
- matrix->type = COGL_MATRIX_TYPE_3D_NO_ROT;
- }
- else if (TEST_MAT_FLAGS (matrix, MAT_FLAGS_3D))
- {
- if ( m[ 8]==0.0f
- && m[ 9]==0.0f
- && m[2]==0.0f && m[6]==0.0f && m[10]==1.0f && m[14]==0.0f)
- {
- matrix->type = COGL_MATRIX_TYPE_2D;
- }
- else
- matrix->type = COGL_MATRIX_TYPE_3D;
- }
- else if ( m[4]==0.0f && m[12]==0.0f
- && m[1]==0.0f && m[13]==0.0f
- && m[2]==0.0f && m[6]==0.0f
- && m[3]==0.0f && m[7]==0.0f && m[11]==-1.0f && m[15]==0.0f)
- {
- matrix->type = COGL_MATRIX_TYPE_PERSPECTIVE;
- }
- else
- matrix->type = COGL_MATRIX_TYPE_GENERAL;
-}
-
-/*
- * Analyze and update the type and flags of a matrix.
- *
- * \param mat matrix.
- *
- * If the matrix type is dirty then calls either analyse_from_scratch() or
- * analyse_from_flags() to determine its type, according to whether the flags
- * are dirty or not, respectively. If the matrix has an inverse and it's dirty
- * then calls matrix_invert(). Finally clears the dirty flags.
- */
-void
-_math_matrix_update_type_and_flags (CoglMatrix *matrix)
-{
- if (matrix->flags & MAT_DIRTY_TYPE)
- {
- if (matrix->flags & MAT_DIRTY_FLAGS)
- analyse_from_scratch (matrix);
- else
- analyse_from_flags (matrix);
- }
-
- matrix->flags &= ~(MAT_DIRTY_FLAGS | MAT_DIRTY_TYPE);
-}
-
-/*@}*/
-
-
-/*
- * Test if the given matrix preserves vector lengths.
- */
-gboolean
-_math_matrix_is_length_preserving (const CoglMatrix *m)
-{
- return TEST_MAT_FLAGS (m, MAT_FLAGS_LENGTH_PRESERVING);
-}
-
-
-/*
- * Test if the given matrix does any rotation.
- * (or perhaps if the upper-left 3x3 is non-identity)
- */
-gboolean
-_math_matrix_has_rotation (const CoglMatrix *matrix)
-{
- if (matrix->flags & (MAT_FLAG_GENERAL |
- MAT_FLAG_ROTATION |
- MAT_FLAG_GENERAL_3D |
- MAT_FLAG_PERSPECTIVE))
- return TRUE;
- else
- return FALSE;
-}
-
-
-gboolean
-_math_matrix_is_general_scale (const CoglMatrix *matrix)
-{
- return (matrix->flags & MAT_FLAG_GENERAL_SCALE) ? TRUE : FALSE;
-}
-
-
-gboolean
-_math_matrix_is_dirty (const CoglMatrix *matrix)
-{
- return (matrix->flags & MAT_DIRTY_ALL) ? TRUE : FALSE;
-}
-
-
-/**********************************************************************/
-/* \name Matrix setup */
-/*@{*/
-
-/*
- * Loads a matrix array into CoglMatrix.
- *
- * \param m matrix array.
- * \param mat matrix.
- *
- * Copies \p m into CoglMatrix::m and marks the MAT_FLAG_GENERAL and
- * MAT_DIRTY_ALL
- * flags.
- */
-void
-_math_matrix_init_from_array (CoglMatrix *matrix, const float *array)
-{
- memcpy (matrix, array, 16 * sizeof (float));
- matrix->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL);
-}
-
-/*@}*/
-
-
-/**********************************************************************/
-/* \name Matrix transpose */
-/*@{*/
-
-/*
- * Transpose a float matrix.
- *
- * \param to destination array.
- * \param from source array.
- */
-void
-_math_transposef (float to[16], const float from[16])
-{
- to[0] = from[0];
- to[1] = from[4];
- to[2] = from[8];
- to[3] = from[12];
- to[4] = from[1];
- to[5] = from[5];
- to[6] = from[9];
- to[7] = from[13];
- to[8] = from[2];
- to[9] = from[6];
- to[10] = from[10];
- to[11] = from[14];
- to[12] = from[3];
- to[13] = from[7];
- to[14] = from[11];
- to[15] = from[15];
-}
-
-/*
- * Transpose a double matrix.
- *
- * \param to destination array.
- * \param from source array.
- */
-void
-_math_transposed (double to[16], const double from[16])
-{
- to[0] = from[0];
- to[1] = from[4];
- to[2] = from[8];
- to[3] = from[12];
- to[4] = from[1];
- to[5] = from[5];
- to[6] = from[9];
- to[7] = from[13];
- to[8] = from[2];
- to[9] = from[6];
- to[10] = from[10];
- to[11] = from[14];
- to[12] = from[3];
- to[13] = from[7];
- to[14] = from[11];
- to[15] = from[15];
-}
-
-/*
- * Transpose a double matrix and convert to float.
- *
- * \param to destination array.
- * \param from source array.
- */
-void
-_math_transposefd (float to[16], const double from[16])
-{
- to[0] = (float)from[0];
- to[1] = (float)from[4];
- to[2] = (float)from[8];
- to[3] = (float)from[12];
- to[4] = (float)from[1];
- to[5] = (float)from[5];
- to[6] = (float)from[9];
- to[7] = (float)from[13];
- to[8] = (float)from[2];
- to[9] = (float)from[6];
- to[10] = (float)from[10];
- to[11] = (float)from[14];
- to[12] = (float)from[3];
- to[13] = (float)from[7];
- to[14] = (float)from[11];
- to[15] = (float)from[15];
-}
-
-/*@}*/
-
-
-/*
- * Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
- * function is used for transforming clipping plane equations and spotlight
- * directions.
- * Mathematically, u = v * m.
- * Input: v - input vector
- * m - transformation matrix
- * Output: u - transformed vector
- */
-void
-_mesa_transform_vector (float u[4], const float v[4], const float m[16])
-{
- const float v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
-#define M(row,col) m[row + col*4]
- u[0] = v0 * M (0,0) + v1 * M (1,0) + v2 * M (2,0) + v3 * M (3,0);
- u[1] = v0 * M (0,1) + v1 * M (1,1) + v2 * M (2,1) + v3 * M (3,1);
- u[2] = v0 * M (0,2) + v1 * M (1,2) + v2 * M (2,2) + v3 * M (3,2);
- u[3] = v0 * M (0,3) + v1 * M (1,3) + v2 * M (2,3) + v3 * M (3,3);
-#undef M
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-/*
- * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-
-/*
- * \file math/m_matrix.h
- * Defines basic structures for matrix-handling.
- */
-
-#ifndef _M_MATRIX_H
-#define _M_MATRIX_H
-
-#include <cogl-matrix.h>
-
-#include <glib.h>
-
-/*
- * \name Symbolic names to some of the entries in the matrix
- *
- * These are handy for the viewport mapping, which is expressed as a matrix.
- */
-/*@{*/
-#define MAT_SX 0
-#define MAT_SY 5
-#define MAT_SZ 10
-#define MAT_TX 12
-#define MAT_TY 13
-#define MAT_TZ 14
-/*@}*/
-
-
-/*
- * Different kinds of 4x4 transformation matrices.
- * We use these to select specific optimized vertex transformation routines.
- */
-enum CoglMatrixType {
- COGL_MATRIX_TYPE_GENERAL, /**< general 4x4 matrix */
- COGL_MATRIX_TYPE_IDENTITY, /**< identity matrix */
- COGL_MATRIX_TYPE_3D_NO_ROT, /**< orthogonal projection and others... */
- COGL_MATRIX_TYPE_PERSPECTIVE, /**< perspective projection matrix */
- COGL_MATRIX_TYPE_2D, /**< 2-D transformation */
- COGL_MATRIX_TYPE_2D_NO_ROT, /**< 2-D scale & translate only */
- COGL_MATRIX_TYPE_3D /**< 3-D transformation */
-} ;
-
-
-#if 0
-/*
- * Matrix type to represent 4x4 transformation matrices.
- */
-typedef struct {
- float *m; /**< 16 matrix elements (16-byte aligned) */
- float *inv; /**< optional 16-element inverse (16-byte aligned) */
- unsigned int flags; /**< possible values determined by (of \link
- * MatFlags MAT_FLAG_* flags\endlink)
- */
- enum CoglMatrixType type;
-} CoglMatrix;
-#endif
-
-
-void
-_math_matrix_multiply (CoglMatrix *result,
- const CoglMatrix *a,
- const CoglMatrix *b);
-
-void
-_math_matrix_multiply_array (CoglMatrix *result, const float *b);
-
-void
-_math_matrix_init_from_array (CoglMatrix *matrix, const float *array);
-
-void
-_math_matrix_translate (CoglMatrix *matrix, float x, float y, float z);
-
-void
-_math_matrix_rotate (CoglMatrix *matrix, float angle,
- float x, float y, float z);
-
-void
-_math_matrix_scale (CoglMatrix *matrix, float x, float y, float z);
-
-void
-_math_matrix_ortho (CoglMatrix *matrix,
- float left, float right,
- float bottom, float top,
- float nearval, float farval);
-
-void
-_math_matrix_frustum (CoglMatrix *matrix,
- float left, float right,
- float bottom, float top,
- float nearval, float farval);
-
-void
-_math_matrix_viewport (CoglMatrix *matrix,
- float x, float y, float width, float height,
- float z_near, float z_far, float depth_max);
-
-void
-_math_matrix_init_identity (CoglMatrix *matrix);
-
-gboolean
-_math_matrix_update_inverse (CoglMatrix *matrix);
-
-void
-_math_matrix_update_type_and_flags (CoglMatrix *matrix);
-
-void
-_math_matrix_print (const CoglMatrix *matrix);
-
-gboolean
-_math_matrix_is_length_preserving (const CoglMatrix *matrix);
-
-gboolean
-_math_matrix_has_rotation (const CoglMatrix *matrix);
-
-gboolean
-_math_matrix_is_general_scale (const CoglMatrix *matrix);
-
-gboolean
-_math_matrix_is_dirty (const CoglMatrix *matrix);
-
-
-/*
- * \name Related functions that don't actually operate on CoglMatrix structs
- */
-/*@{*/
-
-void
-_math_transposef ( float to[16], const float from[16]);
-
-void
-_math_transposed (double to[16], const double from[16]);
-
-void
-_math_transposefd (float to[16], const double from[16]);
-
-
-/*
- * Transform a point (column vector) by a matrix: Q = M * P
- */
-#define TRANSFORM_POINT( Q, M, P ) \
- Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \
- Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \
- Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \
- Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
-
-
-#define TRANSFORM_POINT3( Q, M, P ) \
- Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \
- Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \
- Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \
- Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
-
-
-/*
- * Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT
- */
-#define TRANSFORM_NORMAL( TO, N, MAT ) \
-do { \
- TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \
- TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \
- TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \
-} while (0)
-
-
-/*
- * Transform a direction by a matrix.
- */
-#define TRANSFORM_DIRECTION( TO, DIR, MAT ) \
-do { \
- TO[0] = DIR[0] * MAT[0] + DIR[1] * MAT[4] + DIR[2] * MAT[8]; \
- TO[1] = DIR[0] * MAT[1] + DIR[1] * MAT[5] + DIR[2] * MAT[9]; \
- TO[2] = DIR[0] * MAT[2] + DIR[1] * MAT[6] + DIR[2] * MAT[10];\
-} while (0)
-
-
-void
-_mesa_transform_vector (float u[4], const float v[4], const float m[16]);
-
-
-/*@}*/
-
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_MATRIX_PRIVATE_H
-#define __COGL_MATRIX_PRIVATE_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#define _COGL_MATRIX_DEBUG_PRINT(MATRIX) \
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_MATRICES))) \
- { \
- g_print ("%s:\n", G_STRFUNC); \
- _cogl_matrix_print (MATRIX); \
- }
-
-void
-_cogl_matrix_print (CoglMatrix *matrix);
-
-G_END_DECLS
-
-#endif /* __COGL_MATRIX_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Havoc Pennington <hp@pobox.com> for litl
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-context-private.h"
-#include "cogl-internal.h"
-#include "cogl-matrix-stack.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-object-private.h"
-
-typedef struct {
- CoglMatrix matrix;
- gboolean is_identity;
- /* count of pushes with no changes; when a change is
- * requested, we create a new state and decrement this
- */
- int push_count;
-} CoglMatrixState;
-
-/**
- * CoglMatrixStack:
- *
- * Stores a cogl-side matrix stack, which we use as a cache
- * so we can get the matrix efficiently when using indirect
- * rendering.
- */
-struct _CoglMatrixStack
-{
- CoglObject _parent;
-
- GArray *stack;
-
- /* which state does GL have, NULL if unknown */
- CoglMatrixState *flushed_state;
- gboolean flushed_identity;
-
- unsigned int age;
-};
-
-static void _cogl_matrix_stack_free (CoglMatrixStack *stack);
-
-COGL_OBJECT_INTERNAL_DEFINE (MatrixStack, matrix_stack);
-
-/* XXX: this doesn't initialize the matrix! */
-static void
-_cogl_matrix_state_init (CoglMatrixState *state)
-{
- state->push_count = 0;
- state->is_identity = FALSE;
-}
-
-static CoglMatrixState *
-_cogl_matrix_stack_top (CoglMatrixStack *stack)
-{
- return &g_array_index (stack->stack, CoglMatrixState, stack->stack->len - 1);
-}
-
-/* XXX:
- * Operations like scale, translate, rotate etc need to have an
- * initialized state->matrix to work with, so they will pass
- * initialize = TRUE.
- *
- * _cogl_matrix_stack_load_identity and _cogl_matrix_stack_set on the
- * other hand don't so they will pass initialize = FALSE
- *
- * NB: Identity matrices are represented by setting
- * state->is_identity=TRUE in which case state->matrix will be
- * uninitialized.
- */
-static CoglMatrixState *
-_cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
- gboolean initialize)
-{
- CoglMatrixState *state;
- CoglMatrixState *new_top;
-
- state = _cogl_matrix_stack_top (stack);
-
- if (state->push_count == 0)
- {
- if (state->is_identity && initialize)
- cogl_matrix_init_identity (&state->matrix);
- return state;
- }
-
- state->push_count -= 1;
-
- g_array_set_size (stack->stack, stack->stack->len + 1);
- new_top = &g_array_index (stack->stack, CoglMatrixState,
- stack->stack->len - 1);
- _cogl_matrix_state_init (new_top);
-
- if (initialize)
- {
- if (state->is_identity)
- cogl_matrix_init_identity (&new_top->matrix);
- else
- new_top->matrix = state->matrix;
-
- if (stack->flushed_state == state)
- stack->flushed_state = new_top;
- }
-
- return new_top;
-}
-
-CoglMatrixStack*
-_cogl_matrix_stack_new (void)
-{
- CoglMatrixStack *stack;
- CoglMatrixState *state;
-
- stack = g_slice_new0 (CoglMatrixStack);
-
- stack->stack = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglMatrixState), 10);
- g_array_set_size (stack->stack, 1);
- state = &g_array_index (stack->stack, CoglMatrixState, 0);
- _cogl_matrix_state_init (state);
- state->is_identity = TRUE;
-
- stack->age = 0;
-
- return _cogl_matrix_stack_object_new (stack);
-}
-
-static void
-_cogl_matrix_stack_free (CoglMatrixStack *stack)
-{
- g_array_free (stack->stack, TRUE);
- g_slice_free (CoglMatrixStack, stack);
-}
-
-void
-_cogl_matrix_stack_push (CoglMatrixStack *stack)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top (stack);
-
- /* we lazily create a new stack top if someone changes the matrix
- * while push_count > 0
- */
- state->push_count += 1;
-}
-
-void
-_cogl_matrix_stack_pop (CoglMatrixStack *stack)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top (stack);
-
- if (state->push_count > 0)
- {
- state->push_count -= 1;
- }
- else
- {
- if (stack->stack->len == 1)
- {
- g_warning ("Too many matrix pops");
- return;
- }
-
- if (stack->flushed_state == state)
- {
- stack->flushed_state = NULL;
- }
-
- stack->age++;
- g_array_set_size (stack->stack, stack->stack->len - 1);
- }
-}
-
-void
-_cogl_matrix_stack_load_identity (CoglMatrixStack *stack)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, FALSE);
-
- /* NB: Identity matrices are represented by setting
- * state->is_identity = TRUE and leaving state->matrix
- * uninitialized.
- *
- * This is done to optimize the heavy usage of
- * _cogl_matrix_stack_load_identity by the Cogl Journal.
- */
- if (!state->is_identity)
- {
- state->is_identity = TRUE;
-
- /* mark dirty */
- stack->flushed_state = NULL;
- stack->age++;
- }
-}
-
-void
-_cogl_matrix_stack_scale (CoglMatrixStack *stack,
- float x,
- float y,
- float z)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_scale (&state->matrix, x, y, z);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_translate (CoglMatrixStack *stack,
- float x,
- float y,
- float z)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_translate (&state->matrix, x, y, z);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_rotate (CoglMatrixStack *stack,
- float angle,
- float x,
- float y,
- float z)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_rotate (&state->matrix, angle, x, y, z);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_multiply (CoglMatrixStack *stack,
- const CoglMatrix *matrix)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_multiply (&state->matrix, &state->matrix, matrix);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_frustum (&state->matrix,
- left, right, bottom, top,
- z_near, z_far);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_perspective (CoglMatrixStack *stack,
- float fov_y,
- float aspect,
- float z_near,
- float z_far)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_perspective (&state->matrix,
- fov_y, aspect, z_near, z_far);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-void
-_cogl_matrix_stack_ortho (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
- cogl_matrix_ortho (&state->matrix,
- left, right, bottom, top, z_near, z_far);
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-gboolean
-_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
- CoglMatrix *inverse)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, TRUE);
-
- return cogl_matrix_get_inverse (&state->matrix, inverse);
-}
-
-void
-_cogl_matrix_stack_get (CoglMatrixStack *stack,
- CoglMatrix *matrix)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top (stack);
-
- /* NB: identity matrices are lazily initialized because we can often avoid
- * initializing them at all if nothing is pushed on top of them since we
- * load them using glLoadIdentity()
- *
- * The Cogl journal typically loads an identiy matrix because it performs
- * software transformations, which is why we have optimized this case.
- */
- if (state->is_identity)
- cogl_matrix_init_identity (matrix);
- else
- *matrix = state->matrix;
-}
-
-void
-_cogl_matrix_stack_set (CoglMatrixStack *stack,
- const CoglMatrix *matrix)
-{
- CoglMatrixState *state;
-
- state = _cogl_matrix_stack_top_mutable (stack, FALSE);
- state->matrix = *matrix;
- /* mark dirty */
- stack->flushed_state = NULL;
- state->is_identity = FALSE;
- stack->age++;
-}
-
-#ifndef HAVE_COGL_GLES2
-
-static void
-flush_to_fixed_api_gl (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data)
-{
- CoglMatrixStack *stack = user_data;
-
- if (is_identity)
- {
- if (!stack->flushed_identity)
- GE (glLoadIdentity ());
- stack->flushed_identity = TRUE;
- }
- else
- {
- GE (glLoadMatrixf (cogl_matrix_get_array (matrix)) );
- stack->flushed_identity = FALSE;
- }
-}
-
-#endif /* HAVE_COGL_GLES2 */
-
-void
-_cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack,
- CoglMatrixMode mode,
- CoglMatrixStackFlushFunc callback,
- void *user_data)
-{
- CoglMatrixState *state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- state = _cogl_matrix_stack_top (stack);
-
- /* Because Cogl defines texture coordinates to have a top left origin and
- * because offscreen framebuffers may be used for rendering to textures we
- * always render upside down to offscreen buffers.
- */
- if (mode == COGL_MATRIX_PROJECTION &&
- cogl_is_offscreen (cogl_get_draw_framebuffer ()))
- {
- CoglMatrix flipped_projection;
- CoglMatrix *projection =
- state->is_identity ? &ctx->identity_matrix : &state->matrix;
-
- cogl_matrix_multiply (&flipped_projection,
- &ctx->y_flip_matrix, projection);
- callback (FALSE, &flipped_projection, user_data);
- }
- else
- callback (state->is_identity,
- state->is_identity ? &ctx->identity_matrix : &state->matrix,
- user_data);
-}
-
-void
-_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
- CoglMatrixMode mode)
-{
- CoglMatrixState *state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- state = _cogl_matrix_stack_top (stack);
-
-#ifdef HAVE_COGL_GLES2
-
- /* Under GLES2 we need to flush the matrices differently because
- they are stored in uniforms attached to the program instead of
- the global GL context state. At this point we can't be sure that
- the right program will be generated so instead we'll just store a
- reference to the matrix stack that is intended to be flushed and
- update the uniform once the program is ready. */
-
- switch (mode)
- {
- case COGL_MATRIX_MODELVIEW:
- cogl_object_ref (stack);
- if (ctx->flushed_modelview_stack)
- cogl_object_unref (ctx->flushed_modelview_stack);
- ctx->flushed_modelview_stack = stack;
- break;
-
- case COGL_MATRIX_PROJECTION:
- cogl_object_ref (stack);
- if (ctx->flushed_projection_stack)
- cogl_object_unref (ctx->flushed_projection_stack);
- ctx->flushed_projection_stack = stack;
- break;
-
- case COGL_MATRIX_TEXTURE:
- /* This shouldn't happen because the texture matrices are
- handled by the GLSL pipeline backend */
- g_assert_not_reached ();
- break;
- }
-
-#else /* HAVE_COGL_GLES2 */
-
- if (stack->flushed_state == state)
- return;
-
- if (ctx->flushed_matrix_mode != mode)
- {
- GLenum gl_mode = 0;
-
- switch (mode)
- {
- case COGL_MATRIX_MODELVIEW:
- gl_mode = GL_MODELVIEW;
- break;
-
- case COGL_MATRIX_PROJECTION:
- gl_mode = GL_PROJECTION;
- break;
-
- case COGL_MATRIX_TEXTURE:
- gl_mode = GL_TEXTURE;
- break;
- }
-
- GE (glMatrixMode (gl_mode));
- ctx->flushed_matrix_mode = mode;
- }
-
- _cogl_matrix_stack_prepare_for_flush (stack,
- mode,
- flush_to_fixed_api_gl,
- stack);
-
-#endif /* HAVE_COGL_GLES2 */
-
- stack->flushed_state = state;
-}
-
-void
-_cogl_matrix_stack_dirty (CoglMatrixStack *stack)
-{
- stack->flushed_state = NULL;
- stack->flushed_identity = FALSE;
-}
-
-unsigned int
-_cogl_matrix_stack_get_age (CoglMatrixStack *stack)
-{
- return stack->age;
-}
-
-gboolean
-_cogl_matrix_stack_has_identity_flag (CoglMatrixStack *stack)
-{
- return _cogl_matrix_stack_top (stack)->is_identity;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Havoc Pennington <hp@pobox.com> for litl
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_MATRIX_STACK_H
-#define __COGL_MATRIX_STACK_H
-
-#include "cogl-matrix.h"
-
-typedef struct _CoglMatrixStack CoglMatrixStack;
-
-typedef enum {
- COGL_MATRIX_MODELVIEW,
- COGL_MATRIX_PROJECTION,
- COGL_MATRIX_TEXTURE
-} CoglMatrixMode;
-
-typedef void (* CoglMatrixStackFlushFunc) (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data);
-
-CoglMatrixStack *
-_cogl_matrix_stack_new (void);
-
-void
-_cogl_matrix_stack_push (CoglMatrixStack *stack);
-
-void
-_cogl_matrix_stack_pop (CoglMatrixStack *stack);
-
-void
-_cogl_matrix_stack_load_identity (CoglMatrixStack *stack);
-
-void
-_cogl_matrix_stack_scale (CoglMatrixStack *stack,
- float x,
- float y,
- float z);
-void
-_cogl_matrix_stack_translate (CoglMatrixStack *stack,
- float x,
- float y,
- float z);
-void
-_cogl_matrix_stack_rotate (CoglMatrixStack *stack,
- float angle,
- float x,
- float y,
- float z);
-void
-_cogl_matrix_stack_multiply (CoglMatrixStack *stack,
- const CoglMatrix *matrix);
-void
-_cogl_matrix_stack_frustum (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-void
-_cogl_matrix_stack_perspective (CoglMatrixStack *stack,
- float fov_y,
- float aspect,
- float z_near,
- float z_far);
-void
-_cogl_matrix_stack_ortho (CoglMatrixStack *stack,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-gboolean
-_cogl_matrix_stack_get_inverse (CoglMatrixStack *stack,
- CoglMatrix *inverse);
-void
-_cogl_matrix_stack_get (CoglMatrixStack *stack,
- CoglMatrix *matrix);
-void
-_cogl_matrix_stack_set (CoglMatrixStack *stack,
- const CoglMatrix *matrix);
-void
-_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
- CoglMatrixMode mode);
-void
-_cogl_matrix_stack_dirty (CoglMatrixStack *stack);
-
-unsigned int
-_cogl_matrix_stack_get_age (CoglMatrixStack *stack);
-
-/* If this returns TRUE then the top of the matrix is definitely the
- identity matrix. If it returns FALSE it may or may not be the
- identity matrix but no expensive comparison is performed to verify
- it. */
-gboolean
-_cogl_matrix_stack_has_identity_flag (CoglMatrixStack *stack);
-
-void
-_cogl_matrix_stack_prepare_for_flush (CoglMatrixStack *stack,
- CoglMatrixMode mode,
- CoglMatrixStackFlushFunc callback,
- void *user_data);
-
-#endif /* __COGL_MATRIX_STACK_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define USE_MESA_MATRIX_API
-
-#include <cogl.h>
-#include "cogl-debug.h"
-#include <cogl-matrix.h>
-#include <cogl-matrix-private.h>
-#ifdef USE_MESA_MATRIX_API
-#include <cogl-matrix-mesa.h>
-#endif
-
-#include <glib.h>
-#include <math.h>
-#include <string.h>
-
-#ifdef _COGL_SUPPORTS_GTYPE_INTEGRATION
-#include <cogl-gtype-private.h>
-COGL_GTYPE_DEFINE_BOXED ("Matrix", matrix,
- cogl_matrix_copy,
- cogl_matrix_free);
-#endif
-
-void
-_cogl_matrix_print (CoglMatrix *matrix)
-{
- float *m = (float *)matrix;
- int y;
-
- for (y = 0; y < 4; y++)
- g_print ("\t%6.4f %6.4f %6.4f %6.4f\n", m[y], m[4+y], m[8+y], m[12+y]);
-}
-
-void
-cogl_matrix_init_identity (CoglMatrix *matrix)
-{
-#ifndef USE_MESA_MATRIX_API
- matrix->xx = 1; matrix->xy = 0; matrix->xz = 0; matrix->xw = 0;
- matrix->yx = 0; matrix->yy = 1; matrix->yz = 0; matrix->yw = 0;
- matrix->zx = 0; matrix->zy = 0; matrix->zz = 1; matrix->zw = 0;
- matrix->wx = 0; matrix->wy = 0; matrix->wz = 0; matrix->ww = 1;
-#else
- _math_matrix_init_identity (matrix);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_multiply (CoglMatrix *result,
- const CoglMatrix *a,
- const CoglMatrix *b)
-{
-#ifndef USE_MESA_MATRIX_API
- CoglMatrix r;
-
- /* row 0 */
- r.xx = a->xx * b->xx + a->xy * b->yx + a->xz * b->zx + a->xw * b->wx;
- r.xy = a->xx * b->xy + a->xy * b->yy + a->xz * b->zy + a->xw * b->wy;
- r.xz = a->xx * b->xz + a->xy * b->yz + a->xz * b->zz + a->xw * b->wz;
- r.xw = a->xx * b->xw + a->xy * b->yw + a->xz * b->zw + a->xw * b->ww;
-
- /* row 1 */
- r.yx = a->yx * b->xx + a->yy * b->yx + a->yz * b->zx + a->yw * b->wx;
- r.yy = a->yx * b->xy + a->yy * b->yy + a->yz * b->zy + a->yw * b->wy;
- r.yz = a->yx * b->xz + a->yy * b->yz + a->yz * b->zz + a->yw * b->wz;
- r.yw = a->yx * b->xw + a->yy * b->yw + a->yz * b->zw + a->yw * b->ww;
-
- /* row 2 */
- r.zx = a->zx * b->xx + a->zy * b->yx + a->zz * b->zx + a->zw * b->wx;
- r.zy = a->zx * b->xy + a->zy * b->yy + a->zz * b->zy + a->zw * b->wy;
- r.zz = a->zx * b->xz + a->zy * b->yz + a->zz * b->zz + a->zw * b->wz;
- r.zw = a->zx * b->xw + a->zy * b->yw + a->zz * b->zw + a->zw * b->ww;
-
- /* row 3 */
- r.wx = a->wx * b->xx + a->wy * b->yx + a->wz * b->zx + a->ww * b->wx;
- r.wy = a->wx * b->xy + a->wy * b->yy + a->wz * b->zy + a->ww * b->wy;
- r.wz = a->wx * b->xz + a->wy * b->yz + a->wz * b->zz + a->ww * b->wz;
- r.ww = a->wx * b->xw + a->wy * b->yw + a->wz * b->zw + a->ww * b->ww;
-
- /* The idea was that having this unrolled; it might be easier for the
- * compiler to vectorize, but that's probably not true. Mesa does it
- * using a single for (i=0; i<4; i++) approach, maybe that's better...
- */
-
- *result = r;
-#else
- _math_matrix_multiply (result, a, b);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (result);
-}
-
-void
-cogl_matrix_rotate (CoglMatrix *matrix,
- float angle,
- float x,
- float y,
- float z)
-{
-#ifndef USE_MESA_MATRIX_API
- CoglMatrix rotation;
- CoglMatrix result;
- float c, s;
-
- angle *= G_PI / 180.0f;
- c = cosf (angle);
- s = sinf (angle);
-
- rotation.xx = x * x * (1.0f - c) + c;
- rotation.yx = y * x * (1.0f - c) + z * s;
- rotation.zx = x * z * (1.0f - c) - y * s;
- rotation.wx = 0.0f;
-
- rotation.xy = x * y * (1.0f - c) - z * s;
- rotation.yy = y * y * (1.0f - c) + c;
- rotation.zy = y * z * (1.0f - c) + x * s;
- rotation.wy = 0.0f;
-
- rotation.xz = x * z * (1.0f - c) + y * s;
- rotation.yz = y * z * (1.0f - c) - x * s;
- rotation.zz = z * z * (1.0f - c) + c;
- rotation.wz = 0.0f;
-
- rotation.xw = 0.0f;
- rotation.yw = 0.0f;
- rotation.zw = 0.0f;
- rotation.ww = 1.0f;
-
- cogl_matrix_multiply (&result, matrix, &rotation);
- *matrix = result;
-#else
- _math_matrix_rotate (matrix, angle, x, y, z);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_translate (CoglMatrix *matrix,
- float x,
- float y,
- float z)
-{
-#ifndef USE_MESA_MATRIX_API
- matrix->xw = matrix->xx * x + matrix->xy * y + matrix->xz * z + matrix->xw;
- matrix->yw = matrix->yx * x + matrix->yy * y + matrix->yz * z + matrix->yw;
- matrix->zw = matrix->zx * x + matrix->zy * y + matrix->zz * z + matrix->zw;
- matrix->ww = matrix->wx * x + matrix->wy * y + matrix->wz * z + matrix->ww;
-#else
- _math_matrix_translate (matrix, x, y, z);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_scale (CoglMatrix *matrix,
- float sx,
- float sy,
- float sz)
-{
-#ifndef USE_MESA_MATRIX_API
- matrix->xx *= sx; matrix->xy *= sy; matrix->xz *= sz;
- matrix->yx *= sx; matrix->yy *= sy; matrix->yz *= sz;
- matrix->zx *= sx; matrix->zy *= sy; matrix->zz *= sz;
- matrix->wx *= sx; matrix->wy *= sy; matrix->wz *= sz;
-#else
- _math_matrix_scale (matrix, sx, sy, sz);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_frustum (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
-#ifndef USE_MESA_MATRIX_API
- float x, y, a, b, c, d;
- CoglMatrix frustum;
-
- x = (2.0f * z_near) / (right - left);
- y = (2.0f * z_near) / (top - bottom);
- a = (right + left) / (right - left);
- b = (top + bottom) / (top - bottom);
- c = -(z_far + z_near) / ( z_far - z_near);
- d = -(2.0f * z_far* z_near) / (z_far - z_near);
-
- frustum.xx = x;
- frustum.yx = 0.0f;
- frustum.zx = 0.0f;
- frustum.wx = 0.0f;
-
- frustum.xy = 0.0f;
- frustum.yy = y;
- frustum.zy = 0.0f;
- frustum.wy = 0.0f;
-
- frustum.xz = a;
- frustum.yz = b;
- frustum.zz = c;
- frustum.wz = -1.0f;
-
- frustum.xw = 0.0f;
- frustum.yw = 0.0f;
- frustum.zw = d;
- frustum.ww = 0.0f;
-
- cogl_matrix_multiply (matrix, matrix, &frustum);
-#else
- _math_matrix_frustum (matrix, left, right, bottom, top, z_near, z_far);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_perspective (CoglMatrix *matrix,
- float fov_y,
- float aspect,
- float z_near,
- float z_far)
-{
- float ymax = z_near * tan (fov_y * G_PI / 360.0);
-
- cogl_matrix_frustum (matrix,
- -ymax * aspect, /* left */
- ymax * aspect, /* right */
- -ymax, /* bottom */
- ymax, /* top */
- z_near,
- z_far);
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_ortho (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float near_val,
- float far_val)
-{
-#ifndef USE_MESA_MATRIX_API
- CoglMatrix ortho;
-
- /* column 0 */
- ortho.xx = 2.0 / (right - left);
- ortho.yx = 0.0;
- ortho.zx = 0.0;
- ortho.wx = 0.0;
-
- /* column 1 */
- ortho.xy = 0.0;
- ortho.yy = 2.0 / (top - bottom);
- ortho.zy = 0.0;
- ortho.wy = 0.0;
-
- /* column 2 */
- ortho.xz = 0.0;
- ortho.yz = 0.0;
- ortho.zz = -2.0 / (far_val - near_val);
- ortho.wz = 0.0;
-
- /* column 3 */
- ortho.xw = -(right + left) / (right - left);
- ortho.yw = -(top + bottom) / (top - bottom);
- ortho.zw = -(far_val + near_val) / (far_val - near_val);
- ortho.ww = 1.0;
-
- cogl_matrix_multiply (matrix, matrix, &ortho);
-#else
- _math_matrix_ortho (matrix, left, right, bottom, top, near_val, far_val);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_2d,
- float width_2d,
- float height_2d)
-{
- float left_2d_plane = left / z_near * z_2d;
- float right_2d_plane = right / z_near * z_2d;
- float bottom_2d_plane = bottom / z_near * z_2d;
- float top_2d_plane = top / z_near * z_2d;
-
- float width_2d_start = right_2d_plane - left_2d_plane;
- float height_2d_start = top_2d_plane - bottom_2d_plane;
-
- /* Factors to scale from framebuffer geometry to frustum
- * cross-section geometry. */
- float width_scale = width_2d_start / width_2d;
- float height_scale = height_2d_start / height_2d;
-
- cogl_matrix_translate (matrix,
- left_2d_plane, top_2d_plane, -z_2d);
-
- cogl_matrix_scale (matrix, width_scale, -height_scale, width_scale);
-}
-
-/* Assuming a symmetric perspective matrix is being used for your
- * projective transform this convenience function lets you compose a
- * view transform such that geometry on the z=0 plane will map to
- * screen coordinates with a top left origin of (0,0) and with the
- * given width and height.
- */
-void
-cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix,
- float fov_y,
- float aspect,
- float z_near,
- float z_2d,
- float width_2d,
- float height_2d)
-{
- float top = z_near * tan (fov_y * G_PI / 360.0);
- cogl_matrix_view_2d_in_frustum (matrix,
- -top * aspect,
- top * aspect,
- -top,
- top,
- z_near,
- z_2d,
- width_2d,
- height_2d);
-}
-
-void
-cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
-{
-#ifndef USE_MESA_MATRIX_API
- memcpy (matrix, array, sizeof (float) * 16);
-#else
- _math_matrix_init_from_array (matrix, array);
-#endif
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-gboolean
-cogl_matrix_equal (gconstpointer v1, gconstpointer v2)
-{
- const CoglMatrix *a = v1;
- const CoglMatrix *b = v2;
-
- g_return_val_if_fail (v1 != NULL, FALSE);
- g_return_val_if_fail (v2 != NULL, FALSE);
-
- /* We want to avoid having a fuzzy _equal() function (e.g. that uses
- * an arbitrary epsilon value) since this function noteably conforms
- * to the prototype suitable for use with g_hash_table_new() and a
- * fuzzy hash function isn't really appropriate for comparing hash
- * table keys since it's possible that you could end up fetching
- * different values if you end up with multiple similar keys in use
- * at the same time. If you consider that fuzzyness allows cases
- * such as A == B == C but A != C then you could also end up loosing
- * values in a hash table.
- *
- * We do at least use the == operator to compare values though so
- * that -0 is considered equal to 0.
- */
-
- /* XXX: We don't compare the flags, inverse matrix or padding */
- if (a->xx == b->xx &&
- a->xy == b->xy &&
- a->xz == b->xz &&
- a->xw == b->xw &&
- a->yx == b->yx &&
- a->yy == b->yy &&
- a->yz == b->yz &&
- a->yw == b->yw &&
- a->zx == b->zx &&
- a->zy == b->zy &&
- a->zz == b->zz &&
- a->zw == b->zw &&
- a->wx == b->wx &&
- a->wy == b->wy &&
- a->wz == b->wz &&
- a->ww == b->ww)
- return TRUE;
- else
- return FALSE;
-}
-
-CoglMatrix *
-cogl_matrix_copy (const CoglMatrix *matrix)
-{
- if (G_LIKELY (matrix))
- return g_slice_dup (CoglMatrix, matrix);
-
- return NULL;
-}
-
-void
-cogl_matrix_free (CoglMatrix *matrix)
-{
- g_slice_free (CoglMatrix, matrix);
-}
-
-const float *
-cogl_matrix_get_array (const CoglMatrix *matrix)
-{
- return (float *)matrix;
-}
-
-gboolean
-cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
-{
-#ifndef USE_MESA_MATRIX_API
-#warning "cogl_matrix_get_inverse not supported without Mesa matrix API"
- cogl_matrix_init_identity (inverse);
- return FALSE;
-#else
- if (_math_matrix_update_inverse ((CoglMatrix *)matrix))
- {
- cogl_matrix_init_from_array (inverse, matrix->inv);
- return TRUE;
- }
- else
- {
- cogl_matrix_init_identity (inverse);
- return FALSE;
- }
-#endif
-}
-
-void
-cogl_matrix_transform_point (const CoglMatrix *matrix,
- float *x,
- float *y,
- float *z,
- float *w)
-{
- float _x = *x, _y = *y, _z = *z, _w = *w;
-
- *x = matrix->xx * _x + matrix->xy * _y + matrix->xz * _z + matrix->xw * _w;
- *y = matrix->yx * _x + matrix->yy * _y + matrix->yz * _z + matrix->yw * _w;
- *z = matrix->zx * _x + matrix->zy * _y + matrix->zz * _z + matrix->zw * _w;
- *w = matrix->wx * _x + matrix->wy * _y + matrix->wz * _z + matrix->ww * _w;
-}
-
-typedef struct _Point2f
-{
- float x;
- float y;
-} Point2f;
-
-typedef struct _Point3f
-{
- float x;
- float y;
- float z;
-} Point3f;
-
-typedef struct _Point4f
-{
- float x;
- float y;
- float z;
- float w;
-} Point4f;
-
-static void
-_cogl_matrix_transform_points_f2 (const CoglMatrix *matrix,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
- Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
-
- o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
- o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
- o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
- }
-}
-
-static void
-_cogl_matrix_project_points_f2 (const CoglMatrix *matrix,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point2f p = *(Point2f *)((guint8 *)points_in + i * stride_in);
- Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
-
- o->x = matrix->xx * p.x + matrix->xy * p.y + matrix->xw;
- o->y = matrix->yx * p.x + matrix->yy * p.y + matrix->yw;
- o->z = matrix->zx * p.x + matrix->zy * p.y + matrix->zw;
- o->w = matrix->wx * p.x + matrix->wy * p.y + matrix->ww;
- }
-}
-
-static void
-_cogl_matrix_transform_points_f3 (const CoglMatrix *matrix,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
- Point3f *o = (Point3f *)((guint8 *)points_out + i * stride_out);
-
- o->x = matrix->xx * p.x + matrix->xy * p.y +
- matrix->xz * p.z + matrix->xw;
- o->y = matrix->yx * p.x + matrix->yy * p.y +
- matrix->yz * p.z + matrix->yw;
- o->z = matrix->zx * p.x + matrix->zy * p.y +
- matrix->zz * p.z + matrix->zw;
- }
-}
-
-static void
-_cogl_matrix_project_points_f3 (const CoglMatrix *matrix,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point3f p = *(Point3f *)((guint8 *)points_in + i * stride_in);
- Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
-
- o->x = matrix->xx * p.x + matrix->xy * p.y +
- matrix->xz * p.z + matrix->xw;
- o->y = matrix->yx * p.x + matrix->yy * p.y +
- matrix->yz * p.z + matrix->yw;
- o->z = matrix->zx * p.x + matrix->zy * p.y +
- matrix->zz * p.z + matrix->zw;
- o->w = matrix->wx * p.x + matrix->wy * p.y +
- matrix->wz * p.z + matrix->ww;
- }
-}
-
-static void
-_cogl_matrix_project_points_f4 (const CoglMatrix *matrix,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- int i;
-
- for (i = 0; i < n_points; i++)
- {
- Point4f p = *(Point4f *)((guint8 *)points_in + i * stride_in);
- Point4f *o = (Point4f *)((guint8 *)points_out + i * stride_out);
-
- o->x = matrix->xx * p.x + matrix->xy * p.y +
- matrix->xz * p.z + matrix->xw * p.w;
- o->y = matrix->yx * p.x + matrix->yy * p.y +
- matrix->yz * p.z + matrix->yw * p.w;
- o->z = matrix->zx * p.x + matrix->zy * p.y +
- matrix->zz * p.z + matrix->zw * p.w;
- o->w = matrix->wx * p.x + matrix->wy * p.y +
- matrix->wz * p.z + matrix->ww * p.w;
- }
-}
-
-void
-cogl_matrix_transform_points (const CoglMatrix *matrix,
- int n_components,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- /* The results of transforming always have three components... */
- g_return_if_fail (stride_out >= sizeof (Point3f));
-
- if (n_components == 2)
- _cogl_matrix_transform_points_f2 (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- else
- {
- g_return_if_fail (n_components == 3);
-
- _cogl_matrix_transform_points_f3 (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- }
-}
-
-void
-cogl_matrix_project_points (const CoglMatrix *matrix,
- int n_components,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points)
-{
- if (n_components == 2)
- _cogl_matrix_project_points_f2 (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- else if (n_components == 3)
- _cogl_matrix_project_points_f3 (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- else
- {
- g_return_if_fail (n_components == 4);
-
- _cogl_matrix_project_points_f4 (matrix,
- stride_in, points_in,
- stride_out, points_out,
- n_points);
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_MATRIX_H
-#define __COGL_MATRIX_H
-
-#include <glib.h>
-#include "cogl-types.h"
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-matrix
- * @short_description: Fuctions for initializing and manipulating 4x4 matrices
- *
- * Matrices are used in Cogl to describe affine model-view transforms, texture
- * transforms, and projective transforms. This exposes a utility API that can
- * be used for direct manipulation of these matrices.
- */
-
-typedef struct _CoglMatrix CoglMatrix;
-
-/**
- * CoglMatrix:
- *
- * A CoglMatrix holds a 4x4 transform matrix. This is a single precision,
- * column-major matrix which means it is compatible with what OpenGL expects.
- *
- * A CoglMatrix can represent transforms such as, rotations, scaling,
- * translation, sheering, and linear projections. You can combine these
- * transforms by multiplying multiple matrices in the order you want them
- * applied.
- *
- * The transformation of a vertex (x, y, z, w) by a CoglMatrix is given by:
- *
- * |[
- * x_new = xx * x + xy * y + xz * z + xw * w
- * y_new = yx * x + yy * y + yz * z + yw * w
- * z_new = zx * x + zy * y + zz * z + zw * w
- * w_new = wx * x + wy * y + wz * z + ww * w
- * ]|
- *
- * Where w is normally 1
- *
- * <note>You must consider the members of the CoglMatrix structure read only,
- * and all matrix modifications must be done via the cogl_matrix API. This
- * allows Cogl to annotate the matrices internally. Violation of this will give
- * undefined results. If you need to initialize a matrix with a constant other
- * than the identity matrix you can use cogl_matrix_init_from_array().</note>
- */
-struct _CoglMatrix
-{
- /* column 0 */
- float xx;
- float yx;
- float zx;
- float wx;
-
- /* column 1 */
- float xy;
- float yy;
- float zy;
- float wy;
-
- /* column 2 */
- float xz;
- float yz;
- float zz;
- float wz;
-
- /* column 3 */
- float xw;
- float yw;
- float zw;
- float ww;
-
- /*< private >*/
-
- /* Note: we may want to extend this later with private flags
- * and a cache of the inverse transform matrix. */
- float COGL_PRIVATE (inv)[16];
- unsigned long COGL_PRIVATE (type);
- unsigned long COGL_PRIVATE (flags);
- unsigned long COGL_PRIVATE (_padding3);
-};
-
-/**
- * cogl_matrix_init_identity:
- * @matrix: A 4x4 transformation matrix
- *
- * Resets matrix to the identity matrix:
- *
- * |[
- * .xx=1; .xy=0; .xz=0; .xw=0;
- * .yx=0; .yy=1; .yz=0; .yw=0;
- * .zx=0; .zy=0; .zz=1; .zw=0;
- * .wx=0; .wy=0; .wz=0; .ww=1;
- * ]|
- */
-void
-cogl_matrix_init_identity (CoglMatrix *matrix);
-
-/**
- * cogl_matrix_multiply:
- * @result: The address of a 4x4 matrix to store the result in
- * @a: A 4x4 transformation matrix
- * @b: A 4x4 transformation matrix
- *
- * Multiplies the two supplied matrices together and stores
- * the resulting matrix inside @result.
- *
- * <note>It is possible to multiply the @a matrix in-place, so
- * @result can be equal to @a but can't be equal to @b.</note>
- */
-void
-cogl_matrix_multiply (CoglMatrix *result,
- const CoglMatrix *a,
- const CoglMatrix *b);
-
-/**
- * cogl_matrix_rotate:
- * @matrix: A 4x4 transformation matrix
- * @angle: The angle you want to rotate in degrees
- * @x: X component of your rotation vector
- * @y: Y component of your rotation vector
- * @z: Z component of your rotation vector
- *
- * Multiplies @matrix with a rotation matrix that applies a rotation
- * of @angle degrees around the specified 3D vector.
- */
-void
-cogl_matrix_rotate (CoglMatrix *matrix,
- float angle,
- float x,
- float y,
- float z);
-
-/**
- * cogl_matrix_translate:
- * @matrix: A 4x4 transformation matrix
- * @x: The X translation you want to apply
- * @y: The Y translation you want to apply
- * @z: The Z translation you want to apply
- *
- * Multiplies @matrix with a transform matrix that translates along
- * the X, Y and Z axis.
- */
-void
-cogl_matrix_translate (CoglMatrix *matrix,
- float x,
- float y,
- float z);
-
-/**
- * cogl_matrix_scale:
- * @matrix: A 4x4 transformation matrix
- * @sx: The X scale factor
- * @sy: The Y scale factor
- * @sz: The Z scale factor
- *
- * Multiplies @matrix with a transform matrix that scales along the X,
- * Y and Z axis.
- */
-void
-cogl_matrix_scale (CoglMatrix *matrix,
- float sx,
- float sy,
- float sz);
-
-/**
- * cogl_matrix_frustum:
- * @matrix: A 4x4 transformation matrix
- * @left: coord of left vertical clipping plane
- * @right: coord of right vertical clipping plane
- * @bottom: coord of bottom horizontal clipping plane
- * @top: coord of top horizontal clipping plane
- * @z_near: positive distance to near depth clipping plane
- * @z_far: positive distance to far depth clipping plane
- *
- * Multiplies @matrix by the given frustum perspective matrix.
- */
-void
-cogl_matrix_frustum (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-
-/**
- * cogl_matrix_perspective:
- * @matrix: A 4x4 transformation matrix
- * @fov_y: A field of view angle for the Y axis
- * @aspect: The ratio of width to height determining the field of view angle
- * for the x axis.
- * @z_near: The distance to the near clip plane. Never pass 0 and always pass
- * a positive number.
- * @z_far: The distance to the far clip plane. (Should always be positive)
- *
- * Multiplies @matrix by the described perspective matrix
- *
- * <note>You should be careful not to have to great a @z_far / @z_near ratio
- * since that will reduce the effectiveness of depth testing since there wont
- * be enough precision to identify the depth of objects near to each
- * other.</note>
- */
-void
-cogl_matrix_perspective (CoglMatrix *matrix,
- float fov_y,
- float aspect,
- float z_near,
- float z_far);
-
-/**
- * cogl_matrix_ortho:
- * @matrix: A 4x4 transformation matrix
- * @left: The coordinate for the left clipping plane
- * @right: The coordinate for the right clipping plane
- * @bottom: The coordinate for the bottom clipping plane
- * @top: The coordinate for the top clipping plane
- * @z_near: The coordinate for the near clipping plane (may be negative if
- * the plane is behind the viewer)
- * @z_far: The coordinate for the far clipping plane (may be negative if
- * the plane is behind the viewer)
- *
- * Multiplies @matrix by a parallel projection matrix.
- */
-void
-cogl_matrix_ortho (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-#define cogl_matrix_view_2d_in_frustum cogl_matrix_view_2d_in_frustum_EXP
-#define cogl_matrix_view_2d_in_perspective \
- cogl_matrix_view_2d_in_perspective_EXP
-
-/**
- * cogl_matrix_view_2d_in_frustum:
- * @matrix: A 4x4 transformation matrix
- * @left: coord of left vertical clipping plane
- * @right: coord of right vertical clipping plane
- * @bottom: coord of bottom horizontal clipping plane
- * @top: coord of top horizontal clipping plane
- * @z_near: The distance to the near clip plane. Never pass 0 and always pass
- * a positive number.
- * @z_2d: The distance to the 2D plane. (Should always be positive and
- * be between @z_near and the z_far value that was passed to
- * cogl_matrix_frustum())
- * @width_2d: The width of the 2D coordinate system
- * @height_2d: The height of the 2D coordinate system
- *
- * Multiplies @matrix by a view transform that maps the 2D coordinates
- * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport
- * size. Geometry at a depth of 0 will now lie on this 2D plane.
- *
- * Note: this doesn't multiply the matrix by any projection matrix,
- * but it assumes you have a perspective projection as defined by
- * passing the corresponding arguments to cogl_matrix_frustum().
-
- * Toolkits such as Clutter that mix 2D and 3D drawing can use this to
- * create a 2D coordinate system within a 3D perspective projected
- * view frustum.
- */
-void
-cogl_matrix_view_2d_in_frustum (CoglMatrix *matrix,
- float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_2d,
- float width_2d,
- float height_2d);
-
-/**
- * cogl_matrix_view_2d_in_perspective:
- * @fov_y: A field of view angle for the Y axis
- * @aspect: The ratio of width to height determining the field of view angle
- * for the x axis.
- * @z_near: The distance to the near clip plane. Never pass 0 and always pass
- * a positive number.
- * @z_2d: The distance to the 2D plane. (Should always be positive and
- * be between @z_near and the z_far value that was passed to
- * cogl_matrix_frustum())
- * @width_2d: The width of the 2D coordinate system
- * @height_2d: The height of the 2D coordinate system
- *
- * Multiplies @matrix by a view transform that maps the 2D coordinates
- * (0,0) top left and (@width_2d,@height_2d) bottom right the full viewport
- * size. Geometry at a depth of 0 will now lie on this 2D plane.
- *
- * Note: this doesn't multiply the matrix by any projection matrix,
- * but it assumes you have a perspective projection as defined by
- * passing the corresponding arguments to cogl_matrix_perspective().
- *
- * Toolkits such as Clutter that mix 2D and 3D drawing can use this to
- * create a 2D coordinate system within a 3D perspective projected
- * view frustum.
-
- */
-void
-cogl_matrix_view_2d_in_perspective (CoglMatrix *matrix,
- float fov_y,
- float aspect,
- float z_near,
- float z_2d,
- float width_2d,
- float height_2d);
-
-#endif
-
-/**
- * cogl_matrix_init_from_array:
- * @matrix: A 4x4 transformation matrix
- * @array: A linear array of 16 floats (column-major order)
- *
- * Initializes @matrix with the contents of @array
- */
-void
-cogl_matrix_init_from_array (CoglMatrix *matrix,
- const float *array);
-
-/**
- * cogl_matrix_get_array:
- * @matrix: A 4x4 transformation matrix
- *
- * Casts @matrix to a float array which can be directly passed to OpenGL.
- *
- * Return value: a pointer to the float array
- */
-G_CONST_RETURN float *
-cogl_matrix_get_array (const CoglMatrix *matrix);
-
-/**
- * cogl_matrix_equal:
- * @v1: A 4x4 transformation matrix
- * @v2: A 4x4 transformation matrix
- *
- * Compares two matrices to see if they represent the same
- * transformation. Although internally the matrices may have different
- * annotations associated with them and may potentially have a cached
- * inverse matrix these are not considered in the comparison.
- *
- * Since: 1.4
- */
-gboolean
-cogl_matrix_equal (gconstpointer v1, gconstpointer v2);
-
-/**
- * cogl_matrix_copy:
- * @matrix: A 4x4 transformation matrix you want to copy
- *
- * Allocates a new #CoglMatrix on the heap and initializes it with
- * the same values as @matrix.
- *
- * Returns: A newly allocated #CoglMatrix which should be freed using
- * cogl_matrix_free()
- *
- * Since: 1.6
- */
-CoglMatrix *
-cogl_matrix_copy (const CoglMatrix *matrix);
-
-/**
- * cogl_matrix_free:
- * @matrix: A 4x4 transformation matrix you want to free
- *
- * Frees a #CoglMatrix that was previously allocated via a call to
- * cogl_matrix_copy().
- *
- * Since: 1.6
- */
-void
-cogl_matrix_free (CoglMatrix *matrix);
-
-/**
- * cogl_matrix_get_inverse:
- * @matrix: A 4x4 transformation matrix
- * @inverse: (out): The destination for a 4x4 inverse transformation matrix
- *
- * Gets the inverse transform of a given matrix and uses it to initialize
- * a new #CoglMatrix.
- *
- * <note>Although the first parameter is annotated as const to indicate
- * that the transform it represents isn't modified this function may
- * technically save a copy of the inverse transform within the given
- * #CoglMatrix so that subsequent requests for the inverse transform may
- * avoid costly inversion calculations.</note>
- *
- * Return value: %TRUE if the inverse was successfully calculated or %FALSE
- * for degenerate transformations that can't be inverted (in this case the
- * @inverse matrix will simply be initialized with the identity matrix)
- *
- * Since: 1.2
- */
-gboolean
-cogl_matrix_get_inverse (const CoglMatrix *matrix,
- CoglMatrix *inverse);
-
-/* FIXME: to be consistent with cogl_matrix_{transform,project}_points
- * this could be renamed to cogl_matrix_project_point for Cogl 2.0...
- */
-
-/**
- * cogl_matrix_transform_point:
- * @matrix: A 4x4 transformation matrix
- * @x: (inout): The X component of your points position
- * @y: (inout): The Y component of your points position
- * @z: (inout): The Z component of your points position
- * @w: (inout): The W component of your points position
- *
- * Transforms a point whos position is given and returned as four float
- * components.
- */
-void
-cogl_matrix_transform_point (const CoglMatrix *matrix,
- float *x,
- float *y,
- float *z,
- float *w);
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-#define cogl_matrix_transform_points cogl_matrix_transform_points_EXP
-#define cogl_matrix_project_points cogl_matrix_project_points_EXP
-
-/**
- * cogl_matrix_transform_points:
- * @matrix: A transformation matrix
- * @n_components: The number of position components for each input point.
- * (either 2 or 3)
- * @stride_in: The stride in bytes between input points.
- * @points_in: A pointer to the first component of the first input point.
- * @stride_out: The stride in bytes between output points.
- * @points_out: A pointer to the first component of the first output point.
- * @n_points: The number of points to transform.
- *
- * Transforms an array of input points and writes the result to
- * another array of output points. The input points can either have 2
- * or 3 components each. The output points always have 3 components.
- * The output array can simply point to the input array to do the
- * transform in-place.
- *
- * If you need to transform 4 component points see
- * cogl_matrix_project_points().
- *
- * Here's an example with differing input/output strides:
- * |[
- * typedef struct {
- * float x,y;
- * guint8 r,g,b,a;
- * float s,t,p;
- * } MyInVertex;
- * typedef struct {
- * guint8 r,g,b,a;
- * float x,y,z;
- * } MyOutVertex;
- * MyInVertex vertices[N_VERTICES];
- * MyOutVertex results[N_VERTICES];
- * CoglMatrix matrix;
- *
- * my_load_vertices (vertices);
- * my_get_matrix (&matrix);
- *
- * cogl_matrix_transform_points (&matrix,
- * 2,
- * sizeof (MyInVertex),
- * &vertices[0].x,
- * sizeof (MyOutVertex),
- * &results[0].x,
- * N_VERTICES);
- * ]|
- *
- * Stability: Unstable
- */
-void
-cogl_matrix_transform_points (const CoglMatrix *matrix,
- int n_components,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points);
-
-/**
- * cogl_matrix_project_points:
- * @matrix: A projection matrix
- * @n_components: The number of position components for each input point.
- * (either 2, 3 or 4)
- * @stride_in: The stride in bytes between input points.
- * @points_in: A pointer to the first component of the first input point.
- * @stride_out: The stride in bytes between output points.
- * @points_out: A pointer to the first component of the first output point.
- * @n_points: The number of points to transform.
- *
- * Projects an array of input points and writes the result to another
- * array of output points. The input points can either have 2, 3 or 4
- * components each. The output points always have 4 components (known
- * as homogenous coordinates). The output array can simply point to
- * the input array to do the transform in-place.
- *
- * Here's an example with differing input/output strides:
- * |[
- * typedef struct {
- * float x,y;
- * guint8 r,g,b,a;
- * float s,t,p;
- * } MyInVertex;
- * typedef struct {
- * guint8 r,g,b,a;
- * float x,y,z;
- * } MyOutVertex;
- * MyInVertex vertices[N_VERTICES];
- * MyOutVertex results[N_VERTICES];
- * CoglMatrix matrix;
- *
- * my_load_vertices (vertices);
- * my_get_matrix (&matrix);
- *
- * cogl_matrix_project_points (&matrix,
- * 2,
- * sizeof (MyInVertex),
- * &vertices[0].x,
- * sizeof (MyOutVertex),
- * &results[0].x,
- * N_VERTICES);
- * ]|
- *
- * Stability: Unstable
- */
-void
-cogl_matrix_project_points (const CoglMatrix *matrix,
- int n_components,
- size_t stride_in,
- const void *points_in,
- size_t stride_out,
- void *points_out,
- int n_points);
-
-#endif /* COGL_ENABLE_EXPERIMENTAL_API */
-
-#ifdef _COGL_SUPPORTS_GTYPE_INTEGRATION
-
-#define COGL_GTYPE_TYPE_MATRIX (cogl_gtype_matrix_get_type ())
-
-/**
- * cogl_gtype_matrix_get_type:
- *
- * Returns the GType for the registered "CoglMatrix" boxed type. This
- * can be used for example to define GObject properties that accept a
- * #CoglMatrix value.
- */
-GType
-cogl_gtype_matrix_get_type (void);
-
-#endif /* _COGL_SUPPORTS_GTYPE_INTEGRATION */
-
-G_END_DECLS
-
-#endif /* __COGL_MATRIX_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_OBJECT_PRIVATE_H
-#define __COGL_OBJECT_PRIVATE_H
-
-#include <glib.h>
-
-#include "cogl-types.h"
-#include "cogl-object.h"
-#include "cogl-debug.h"
-
-/* For compatability until all components have been converted */
-typedef struct _CoglObjectClass CoglHandleClass;
-typedef struct _CoglObject CoglHandleObject;
-
-/* XXX: sadly we didn't fully consider when we copied the cairo API
- * for _set_user_data that the callback doesn't get a pointer to the
- * instance which is desired in most cases. This means you tend to end
- * up creating micro allocations for the private data just so you can
- * pair up the data of interest with the original instance for
- * identification when it is later destroyed.
- *
- * Internally we use a small hack to avoid needing these micro
- * allocations by actually passing the instance as a second argument
- * to the callback */
-typedef void (*CoglUserDataDestroyInternalCallback) (void *user_data,
- void *instance);
-
-typedef struct _CoglObjectClass
-{
- GQuark type;
- void *virt_free;
-} CoglObjectClass;
-
-#define COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES 2
-
-typedef struct
-{
- CoglUserDataKey *key;
- void *user_data;
- CoglUserDataDestroyInternalCallback destroy;
-} CoglUserDataEntry;
-
-/* All Cogl objects inherit from this base object by adding a member:
- *
- * CoglObject _parent;
- *
- * at the top of its main structure. This structure is initialized
- * when you call _cogl_#type_name#_object_new (new_object);
- */
-struct _CoglObject
-{
- unsigned int ref_count;
-
- CoglUserDataEntry user_data_entry[
- COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES];
- GArray *user_data_array;
- int n_user_data_entries;
-
- CoglObjectClass *klass;
-};
-
-/* Helper macro to encapsulate the common code for COGL reference
- counted objects */
-
-#ifdef COGL_OBJECT_DEBUG
-
-#define _COGL_OBJECT_DEBUG_NEW(type_name, obj) \
- COGL_NOTE (HANDLE, "COGL " G_STRINGIFY (type_name) " NEW %p %i", \
- (obj), (obj)->ref_count)
-
-#define _COGL_OBJECT_DEBUG_REF(type_name, object) G_STMT_START { \
- CoglObject *__obj = (CoglObject *)object; \
- COGL_NOTE (HANDLE, "COGL %s REF %p %i", \
- g_quark_to_string ((__obj)->klass->type), \
- (__obj), (__obj)->ref_count); } G_STMT_END
-
-#define _COGL_OBJECT_DEBUG_UNREF(type_name, object) G_STMT_START { \
- CoglObject *__obj = (CoglObject *)object; \
- COGL_NOTE (HANDLE, "COGL %s UNREF %p %i", \
- g_quark_to_string ((__obj)->klass->type), \
- (__obj), (__obj)->ref_count - 1); } G_STMT_END
-
-#define COGL_OBJECT_DEBUG_FREE(obj) \
- COGL_NOTE (HANDLE, "COGL %s FREE %p", \
- g_quark_to_string ((obj)->klass->type), (obj))
-
-#else /* !COGL_OBJECT_DEBUG */
-
-#define _COGL_OBJECT_DEBUG_NEW(type_name, obj)
-#define _COGL_OBJECT_DEBUG_REF(type_name, obj)
-#define _COGL_OBJECT_DEBUG_UNREF(type_name, obj)
-#define COGL_OBJECT_DEBUG_FREE(obj)
-
-#endif /* COGL_OBJECT_DEBUG */
-
-/* For temporary compatability */
-#define _COGL_HANDLE_DEBUG_NEW _COGL_OBJECT_DEBUG_NEW
-#define _COGL_HANDLE_DEBUG_REF _COGL_OBJECT_DEBUG_REF
-#define _COGL_HANDLE_DEBUG_UNREF _COGL_OBJECT_DEBUG_UNREF
-#define COGL_HANDLE_DEBUG_FREE COGL_OBJECT_DEBUG_FREE
-
-#define COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-static CoglObjectClass _cogl_##type_name##_class; \
- \
-GQuark \
-_cogl_object_##type_name##_get_type (void) \
-{ \
- static GQuark type = 0; \
- if (!type) \
- { \
- type = g_quark_from_static_string ("Cogl"#TypeName); \
- { code; } \
- } \
- return type; \
-} \
- \
-GQuark \
-_cogl_handle_##type_name##_get_type (void) \
-{ \
- return _cogl_object_##type_name##_get_type (); \
-} \
- \
-static Cogl##TypeName * \
-_cogl_##type_name##_object_new (Cogl##TypeName *new_obj) \
-{ \
- CoglObject *obj = (CoglObject *)&new_obj->_parent; \
- obj->ref_count = 1; \
- obj->n_user_data_entries = 0; \
- obj->user_data_array = NULL; \
- \
- obj->klass = &_cogl_##type_name##_class; \
- if (!obj->klass->type) \
- { \
- obj->klass->type = _cogl_object_##type_name##_get_type ();\
- obj->klass->virt_free = _cogl_##type_name##_free; \
- } \
- \
- _COGL_OBJECT_DEBUG_NEW (TypeName, obj); \
- return new_obj; \
-} \
- \
-Cogl##TypeName * \
-_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \
-{ \
- return handle; \
-}
-
-#define COGL_OBJECT_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-gboolean \
-cogl_is_##type_name (void *object) \
-{ \
- CoglObject *obj = object; \
- \
- if (object == NULL) \
- return FALSE; \
- \
- return (obj->klass->type == \
- _cogl_object_##type_name##_get_type ()); \
-}
-
-#define COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-COGL_OBJECT_COMMON_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-gboolean \
-_cogl_is_##type_name (void *object) \
-{ \
- CoglObject *obj = object; \
- \
- if (object == NULL) \
- return FALSE; \
- \
- return (obj->klass->type == \
- _cogl_object_##type_name##_get_type ()); \
-}
-
-#define COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING(type_name) \
- \
-void * G_GNUC_DEPRECATED \
-cogl_##type_name##_ref (void *object) \
-{ \
- if (!cogl_is_##type_name (object)) \
- return NULL; \
- \
- _COGL_OBJECT_DEBUG_REF (TypeName, object); \
- \
- cogl_handle_ref (object); \
- \
- return object; \
-} \
- \
-void G_GNUC_DEPRECATED \
-cogl_##type_name##_unref (void *object) \
-{ \
- if (!cogl_is_##type_name (object)) \
- { \
- g_warning (G_STRINGIFY (cogl_##type_name##_unref) \
- ": Ignoring unref of Cogl handle " \
- "due to type mismatch"); \
- return; \
- } \
- \
- _COGL_OBJECT_DEBUG_UNREF (TypeName, object); \
- \
- cogl_handle_unref (object); \
-}
-
-#define COGL_OBJECT_DEFINE(TypeName, type_name) \
- COGL_OBJECT_DEFINE_WITH_CODE (TypeName, type_name, (void) 0)
-
-#define COGL_OBJECT_INTERNAL_DEFINE(TypeName, type_name) \
- COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE (TypeName, type_name, (void) 0)
-
-/* For temporary compatability */
-#define COGL_HANDLE_INTERNAL_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-COGL_OBJECT_INTERNAL_DEFINE_WITH_CODE (TypeName, type_name, code) \
- \
-static Cogl##TypeName * \
-_cogl_##type_name##_handle_new (CoglHandle handle) \
-{ \
- return _cogl_##type_name##_object_new (handle); \
-}
-
-#define COGL_HANDLE_DEFINE_WITH_CODE(TypeName, type_name, code) \
- \
-COGL_OBJECT_DEFINE_WITH_CODE (TypeName, type_name, code) \
- \
-static Cogl##TypeName * \
-_cogl_##type_name##_handle_new (CoglHandle handle) \
-{ \
- return _cogl_##type_name##_object_new (handle); \
-}
-
-#define COGL_HANDLE_INTERNAL_DEFINE(TypeName, type_name) \
- COGL_HANDLE_INTERNAL_DEFINE_WITH_CODE (TypeName, type_name, (void) 0)
-
-#define COGL_HANDLE_DEFINE(TypeName, type_name) \
- COGL_HANDLE_DEFINE_WITH_CODE (TypeName, type_name, (void) 0)
-
-void
-_cogl_object_set_user_data (CoglObject *object,
- CoglUserDataKey *key,
- void *user_data,
- CoglUserDataDestroyInternalCallback destroy);
-
-#endif /* __COGL_OBJECT_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <string.h>
-
-#include "cogl-types.h"
-#include "cogl-object-private.h"
-
-void *
-cogl_object_ref (void *object)
-{
- CoglObject *obj = object;
-
- g_return_val_if_fail (object != NULL, NULL);
-
- obj->ref_count++;
- return object;
-}
-
-CoglHandle
-cogl_handle_ref (CoglHandle handle)
-{
- return cogl_object_ref (handle);
-}
-
-void
-cogl_object_unref (void *object)
-{
- CoglObject *obj = object;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (obj->ref_count > 0);
-
- if (--obj->ref_count < 1)
- {
- void (*free_func)(void *obj);
-
- if (obj->n_user_data_entries)
- {
- int i;
- int count = MIN (obj->n_user_data_entries,
- COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
-
- for (i = 0; i < count; i++)
- {
- CoglUserDataEntry *entry = &obj->user_data_entry[i];
- if (entry->destroy)
- entry->destroy (entry->user_data, obj);
- }
-
- if (obj->user_data_array != NULL)
- {
- for (i = 0; i < obj->user_data_array->len; i++)
- {
- CoglUserDataEntry *entry =
- &g_array_index (obj->user_data_array,
- CoglUserDataEntry, i);
-
- if (entry->destroy)
- entry->destroy (entry->user_data, obj);
- }
- g_array_free (obj->user_data_array, TRUE);
- }
- }
-
- COGL_OBJECT_DEBUG_FREE (obj);
- free_func = obj->klass->virt_free;
- free_func (obj);
- }
-}
-
-void
-cogl_handle_unref (CoglHandle handle)
-{
- cogl_object_unref (handle);
-}
-
-GType
-cogl_handle_get_type (void)
-{
- static GType our_type = 0;
-
- /* XXX: We are keeping the "CoglHandle" name for now incase it would
- * break bindings to change to "CoglObject" */
- if (G_UNLIKELY (our_type == 0))
- our_type = g_boxed_type_register_static (g_intern_static_string ("CoglHandle"),
- (GBoxedCopyFunc) cogl_object_ref,
- (GBoxedFreeFunc) cogl_object_unref);
-
- return our_type;
-}
-
-/* XXX: Unlike for cogl_object_get_user_data this code will return
- * an empty entry if available and no entry for the given key can be
- * found. */
-static CoglUserDataEntry *
-_cogl_object_find_entry (CoglObject *object, CoglUserDataKey *key)
-{
- CoglUserDataEntry *entry = NULL;
- int count;
- int i;
-
- count = MIN (object->n_user_data_entries,
- COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
-
- for (i = 0; i < count; i++)
- {
- CoglUserDataEntry *current = &object->user_data_entry[i];
- if (current->key == key)
- return current;
- if (current->user_data == NULL)
- entry = current;
- }
-
- if (G_UNLIKELY (object->user_data_array != NULL))
- {
- for (i = 0; i < object->user_data_array->len; i++)
- {
- CoglUserDataEntry *current =
- &g_array_index (object->user_data_array, CoglUserDataEntry, i);
-
- if (current->key == key)
- return current;
- if (current->user_data == NULL)
- entry = current;
- }
- }
-
- return entry;
-}
-
-void
-_cogl_object_set_user_data (CoglObject *object,
- CoglUserDataKey *key,
- void *user_data,
- CoglUserDataDestroyInternalCallback destroy)
-{
- CoglUserDataEntry new_entry;
- CoglUserDataEntry *entry;
-
- if (user_data)
- {
- new_entry.key = key;
- new_entry.user_data = user_data;
- new_entry.destroy = destroy;
- }
- else
- memset (&new_entry, 0, sizeof (new_entry));
-
- entry = _cogl_object_find_entry (object, key);
- if (entry)
- {
- if (G_LIKELY (entry->destroy))
- entry->destroy (entry->user_data, object);
- }
- else
- {
- if (G_LIKELY (object->n_user_data_entries <
- COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES))
- entry = &object->user_data_entry[object->n_user_data_entries++];
- else
- {
- if (G_UNLIKELY (object->user_data_array == NULL))
- {
- object->user_data_array =
- g_array_new (FALSE, FALSE, sizeof (CoglUserDataEntry));
- }
-
- g_array_set_size (object->user_data_array,
- object->user_data_array->len + 1);
- entry =
- &g_array_index (object->user_data_array, CoglUserDataEntry,
- object->user_data_array->len - 1);
-
- object->n_user_data_entries++;
- }
- }
-
- *entry = new_entry;
-}
-
-void
-cogl_object_set_user_data (CoglObject *object,
- CoglUserDataKey *key,
- void *user_data,
- CoglUserDataDestroyCallback destroy)
-{
- _cogl_object_set_user_data (object, key, user_data,
- (CoglUserDataDestroyInternalCallback)destroy);
-}
-
-void *
-cogl_object_get_user_data (CoglObject *object, CoglUserDataKey *key)
-{
- int count;
- int i;
-
- count = MIN (object->n_user_data_entries,
- COGL_OBJECT_N_PRE_ALLOCATED_USER_DATA_ENTRIES);
-
- for (i = 0; i < count; i++)
- {
- CoglUserDataEntry *entry = &object->user_data_entry[i];
- if (entry->key == key)
- return entry->user_data;
- }
-
- if (object->user_data_array != NULL)
- {
- for (i = 0; i < object->user_data_array->len; i++)
- {
- CoglUserDataEntry *entry =
- &g_array_index (object->user_data_array, CoglUserDataEntry, i);
-
- if (entry->key == key)
- return entry->user_data;
- }
- }
-
- return NULL;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_OBJECT_H
-#define __COGL_OBJECT_H
-
-typedef struct _CoglObject CoglObject;
-
-#define COGL_OBJECT(X) ((CoglObject *)X)
-
-/**
- * CoglUserDataKey:
- * @unused: ignored.
- *
- * A #CoglUserDataKey is used to declare a key for attaching data to a
- * #CoglObject using cogl_object_set_user_data. The typedef only exists as a
- * formality to make code self documenting since only the unique address of a
- * #CoglUserDataKey is used.
- *
- * Typically you would declare a static #CoglUserDataKey and set private data
- * on an object something like this:
- *
- * |[
- * static CoglUserDataKey path_private_key;
- *
- * static void
- * destroy_path_private_cb (void *data)
- * {
- * g_free (data);
- * }
- *
- * static void
- * my_path_set_data (CoglPath *path, void *data)
- * {
- * cogl_object_set_user_data (COGL_OBJECT (path),
- * &private_key,
- * data,
- * destroy_path_private_cb);
- * }
- * ]|
- *
- * Since: 1.4
- */
-typedef struct
-{
- int unused;
-} CoglUserDataKey;
-
-/**
- * CoglUserDataDestroyCallback:
- * @user_data: The data whos association with a #CoglObject has been
- * destoyed.
- *
- * When associating private data with a #CoglObject a callback can be
- * given which will be called either if the object is destroyed or if
- * cogl_object_set_user_data() is called with NULL user_data for the
- * same key.
- *
- * Since: 1.4
- */
-typedef void (*CoglUserDataDestroyCallback) (void *user_data);
-
-/**
- * cogl_object_set_user_data: (skip)
- * @object: The object to associate private data with
- * @key: The address of a #CoglUserDataKey which provides a unique value
- * with which to index the private data.
- * @user_data: The data to associate with the given object,
- * or %NULL to remove a previous association.
- * @destroy: A #CoglUserDataDestroyCallback to call if the object is
- * destroyed or if the association is removed by later setting
- * %NULL data for the same key.
- *
- * Associates some private @user_data with a given #CoglObject. To
- * later remove the association call cogl_object_set_user_data() with
- * the same @key but NULL for the @user_data.
- *
- * Since: 1.4
- */
-void
-cogl_object_set_user_data (CoglObject *object,
- CoglUserDataKey *key,
- void *user_data,
- CoglUserDataDestroyCallback destroy);
-
-/**
- * cogl_object_get_user_data: (skip)
- * @object: The object with associated private data to query
- * @key: The address of a #CoglUserDataKey which provides a unique value
- * with which to index the private data.
- *
- * Finds the user data previously associated with @object using
- * the given @key. If no user data has been associated with @object
- * for the given @key this function returns NULL.
- *
- * Returns: (transfer none): The user data previously associated
- * with @object using the given @key; or %NULL if no associated
- * data is found.
- *
- * Since: 1.4
- */
-void *
-cogl_object_get_user_data (CoglObject *object,
- CoglUserDataKey *key);
-#endif /* __COGL_OBJECT_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_OFFSCREEN_H__
-#define __COGL_OFFSCREEN_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-offscreen
- * @short_description: Fuctions for creating and manipulating offscreen
- * framebuffers.
- *
- * Cogl allows creating and operating on offscreen framebuffers.
- */
-
-/* Offscreen api */
-
-/**
- * cogl_offscreen_new_to_texture:
- * @handle: A CoglHandle for a Cogl texture
- *
- * This creates an offscreen buffer object using the given texture as the
- * primary color buffer. It doesn't just initialize the contents of the
- * offscreen buffer with the texture; they are tightly bound so that
- * drawing to the offscreen buffer effectivly updates the contents of the
- * given texture. You don't need to destroy the offscreen buffer before
- * you can use the texture again.
- *
- * Note: This does not work with sliced Cogl textures.
- *
- * Return value: (transfer full): a #CoglHandle for the new offscreen
- * buffer or %COGL_INVALID_HANDLE if it wasn't possible to create the
- * buffer.
- */
-CoglHandle cogl_offscreen_new_to_texture (CoglHandle handle);
-
-/**
- * cogl_is_offscreen:
- * @handle: A CoglHandle for an offscreen buffer
- *
- * Determines whether the given #CoglHandle references an offscreen buffer
- * object.
- *
- * Returns: %TRUE if the handle references an offscreen buffer,
- * %FALSE otherwise
- */
-gboolean cogl_is_offscreen (CoglHandle handle);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_offscreen_ref:
- * @handle: A CoglHandle for an offscreen buffer
- *
- * Increments the reference count on the offscreen buffer.
- *
- * Return value: (transfer none): For convenience it returns the given CoglHandle
- *
- * Deprecated: 1.2: cogl_handle_ref() should be used in new code.
- */
-CoglHandle cogl_offscreen_ref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-/**
- * cogl_offscreen_unref:
- * @handle: A CoglHandle for an offscreen buffer
- *
- * Decreases the reference count for the offscreen buffer and frees it when
- * the count reaches 0.
- *
- * Deprecated: 1.2: cogl_handle_unref() should be used in new code.
- */
-void cogl_offscreen_unref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-G_END_DECLS
-
-#endif /* __COGL_OFFSCREEN_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_ONSCREEN_TEMPLATE_PRIVATE_H
-#define __COGL_ONSCREEN_TEMPLATE_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-swap-chain.h"
-
-struct _CoglOnscreenTemplate
-{
- CoglObject _parent;
-
- CoglSwapChain *swap_chain;
-};
-
-#endif /* __COGL_ONSCREEN_TEMPLATE_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-object.h"
-
-#include "cogl-onscreen-template-private.h"
-
-static void _cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template);
-
-COGL_OBJECT_DEFINE (OnscreenTemplate, onscreen_template);
-
-GQuark
-cogl_onscreen_template_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-onscreen-template-error-quark");
-}
-
-static void
-_cogl_onscreen_template_free (CoglOnscreenTemplate *onscreen_template)
-{
- g_slice_free (CoglOnscreenTemplate, onscreen_template);
-}
-
-CoglOnscreenTemplate *
-cogl_onscreen_template_new (CoglSwapChain *swap_chain)
-{
- CoglOnscreenTemplate *onscreen_template = g_slice_new0 (CoglOnscreenTemplate);
-
- onscreen_template->swap_chain = swap_chain;
- if (swap_chain)
- cogl_object_ref (swap_chain);
-
- return _cogl_onscreen_template_object_new (onscreen_template);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_ONSCREEN_TEMPLATE_H__
-#define __COGL_ONSCREEN_TEMPLATE_H__
-
-#include <cogl/cogl-swap-chain.h>
-
-G_BEGIN_DECLS
-
-typedef struct _CoglOnscreenTemplate CoglOnscreenTemplate;
-
-#define COGL_ONSCREEN_TEMPLATE(OBJECT) ((CoglOnscreenTemplate *)OBJECT)
-
-#define cogl_onscreen_template_new cogl_onscreen_template_new_EXP
-CoglOnscreenTemplate *
-cogl_onscreen_template_new (CoglSwapChain *swap_chain);
-
-G_END_DECLS
-
-#endif /* __COGL_ONSCREEN_TEMPLATE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PATH_PRIVATE_H
-#define __COGL_PATH_PRIVATE_H
-
-#include "cogl-object.h"
-
-typedef struct _floatVec2
-{
- float x;
- float y;
-} floatVec2;
-
-typedef struct _CoglPathNode
-{
- float x;
- float y;
- unsigned int path_size;
-} CoglPathNode;
-
-typedef struct _CoglBezQuad
-{
- floatVec2 p1;
- floatVec2 p2;
- floatVec2 p3;
-} CoglBezQuad;
-
-typedef struct _CoglBezCubic
-{
- floatVec2 p1;
- floatVec2 p2;
- floatVec2 p3;
- floatVec2 p4;
-} CoglBezCubic;
-
-typedef struct _CoglPathData CoglPathData;
-
-struct _CoglPath
-{
- CoglObject _parent;
-
- CoglPathData *data;
-};
-
-#define COGL_PATH_N_ATTRIBUTES 2
-
-struct _CoglPathData
-{
- unsigned int ref_count;
-
- CoglPathFillRule fill_rule;
-
- GArray *path_nodes;
-
- floatVec2 path_start;
- floatVec2 path_pen;
- unsigned int last_path;
- floatVec2 path_nodes_min;
- floatVec2 path_nodes_max;
-
- CoglVertexArray *fill_vbo;
- CoglIndices *fill_vbo_indices;
- unsigned int fill_vbo_n_indices;
- CoglAttribute *fill_vbo_attributes[COGL_PATH_N_ATTRIBUTES + 1];
-
- CoglVertexArray *stroke_vbo;
- CoglAttribute **stroke_vbo_attributes;
- unsigned int stroke_vbo_n_attributes;
-
- /* This is used as an optimisation for when the path contains a
- single contour specified using cogl2_path_rectangle. Cogl is more
- optimised to handle rectangles than paths so we can detect this
- case and divert to the journal or a rectangle clip. If it is TRUE
- then the entire path can be described by calling
- _cogl_path_get_bounds */
- gboolean is_rectangle;
-};
-
-void
-_cogl_add_path_to_stencil_buffer (CoglPath *path,
- gboolean merge,
- gboolean need_clear);
-
-void
-_cogl_path_get_bounds (CoglPath *path,
- float *min_x,
- float *min_y,
- float *max_x,
- float *max_y);
-
-gboolean
-_cogl_path_is_rectangle (CoglPath *path);
-
-#endif /* __COGL_PATH_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl2-path.h"
-
-#include <string.h>
-#include <math.h>
-
-#undef cogl_path_set_fill_rule
-void
-cogl_path_set_fill_rule (CoglPathFillRule fill_rule)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_set_fill_rule (ctx->current_path, fill_rule);
-}
-
-#undef cogl_path_get_fill_rule
-CoglPathFillRule
-cogl_path_get_fill_rule (void)
-{
- _COGL_GET_CONTEXT (ctx, COGL_PATH_FILL_RULE_EVEN_ODD);
-
- return cogl2_path_get_fill_rule (ctx->current_path);
-}
-
-#undef cogl_path_fill
-void
-cogl_path_fill (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_fill (ctx->current_path);
-
- cogl_object_unref (ctx->current_path);
- ctx->current_path = cogl2_path_new ();
-}
-
-#undef cogl_path_fill_preserve
-void
-cogl_path_fill_preserve (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_fill (ctx->current_path);
-}
-
-#undef cogl_path_stroke
-void
-cogl_path_stroke (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_stroke (ctx->current_path);
-
- cogl_object_unref (ctx->current_path);
- ctx->current_path = cogl2_path_new ();
-}
-
-#undef cogl_path_stroke_preserve
-void
-cogl_path_stroke_preserve (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_stroke (ctx->current_path);
-}
-
-#undef cogl_path_move_to
-void
-cogl_path_move_to (float x,
- float y)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_move_to (ctx->current_path, x, y);
-}
-
-#undef cogl_path_rel_move_to
-void
-cogl_path_rel_move_to (float x,
- float y)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_rel_move_to (ctx->current_path, x, y);
-}
-
-#undef cogl_path_line_to
-void
-cogl_path_line_to (float x,
- float y)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_line_to (ctx->current_path, x, y);
-}
-
-#undef cogl_path_rel_line_to
-void
-cogl_path_rel_line_to (float x,
- float y)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_rel_line_to (ctx->current_path, x, y);
-}
-
-#undef cogl_path_close
-void
-cogl_path_close (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_close (ctx->current_path);
-}
-
-#undef cogl_path_new
-void
-cogl_path_new (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_object_unref (ctx->current_path);
- ctx->current_path = cogl2_path_new ();
-}
-
-#undef cogl_path_line
-void
-cogl_path_line (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_line (ctx->current_path, x_1, y_1, x_2, y_2);
-}
-
-#undef cogl_path_polyline
-void
-cogl_path_polyline (const float *coords,
- int num_points)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_polyline (ctx->current_path, coords, num_points);
-}
-
-#undef cogl_path_polygon
-void
-cogl_path_polygon (const float *coords,
- int num_points)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_polygon (ctx->current_path, coords, num_points);
-}
-
-#undef cogl_path_rectangle
-void
-cogl_path_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_rectangle (ctx->current_path, x_1, y_1, x_2, y_2);
-}
-
-#undef cogl_path_arc
-void
-cogl_path_arc (float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_arc (ctx->current_path,
- center_x,
- center_y,
- radius_x,
- radius_y,
- angle_1,
- angle_2);
-}
-
-#undef cogl_path_ellipse
-void
-cogl_path_ellipse (float center_x,
- float center_y,
- float radius_x,
- float radius_y)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_ellipse (ctx->current_path,
- center_x,
- center_y,
- radius_x,
- radius_y);
-}
-
-#undef cogl_path_round_rectangle
-void
-cogl_path_round_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float radius,
- float arc_step)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_round_rectangle (ctx->current_path,
- x_1, y_1, x_2, y_2, radius, arc_step);
-}
-
-#undef cogl_path_curve_to
-void
-cogl_path_curve_to (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_curve_to (ctx->current_path,
- x_1, y_2, x_2, y_2, x_3, y_3);
-}
-
-#undef cogl_path_rel_curve_to
-void
-cogl_path_rel_curve_to (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl2_path_rel_curve_to (ctx->current_path,
- x_1, y_1, x_2, y_2, x_3, y_3);
-}
-
-CoglPath *
-cogl_get_path (void)
-{
- _COGL_GET_CONTEXT (ctx, NULL);
-
- return ctx->current_path;
-}
-
-void
-cogl_set_path (CoglPath *path)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (cogl_is_path (path));
-
- /* Reference the new object first in case it is the same as the old
- object */
- cogl_object_ref (path);
- cogl_object_unref (ctx->current_path);
- ctx->current_path = path;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_PATH_H__
-#define __COGL_PATH_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-paths
- * @short_description: Functions for constructing and drawing 2D paths.
- *
- * There are two levels on which drawing with cogl-paths can be used.
- * The highest level functions construct various simple primitive
- * shapes to be either filled or stroked. Using a lower-level set of
- * functions more complex and arbitrary paths can be constructed by
- * concatenating straight line, bezier curve and arc segments.
- *
- * When constructing arbitrary paths, the current pen location is
- * initialized using the move_to command. The subsequent path segments
- * implicitly use the last pen location as their first vertex and move
- * the pen location to the last vertex they produce at the end. Also
- * there are special versions of functions that allow specifying the
- * vertices of the path segments relative to the last pen location
- * rather then in the absolute coordinates.
- */
-
-typedef struct _CoglPath CoglPath;
-
-#define COGL_PATH(obj) ((CoglPath *)(obj))
-
-/**
- * CoglPathFillRule:
- * @COGL_PATH_FILL_RULE_NON_ZERO: Each time the line crosses an edge of
- * the path from left to right one is added to a counter and each time
- * it crosses from right to left the counter is decremented. If the
- * counter is non-zero then the point will be filled. See <xref
- * linkend="fill-rule-non-zero"/>.
- * @COGL_PATH_FILL_RULE_EVEN_ODD: If the line crosses an edge of the
- * path an odd number of times then the point will filled, otherwise
- * it won't. See <xref linkend="fill-rule-even-odd"/>.
- *
- * #CoglPathFillRule is used to determine how a path is filled. There
- * are two options - 'non-zero' and 'even-odd'. To work out whether any
- * point will be filled imagine drawing an infinetely long line in any
- * direction from that point. The number of times and the direction
- * that the edges of the path crosses this line determines whether the
- * line is filled as described below. Any open sub paths are treated
- * as if there was an extra line joining the first point and the last
- * point.
- *
- * The default fill rule is %COGL_PATH_FILL_RULE_EVEN_ODD. The fill
- * rule is attached to the current path so preserving a path with
- * cogl_get_path() also preserves the fill rule. Calling
- * cogl_path_new() resets the current fill rule to the default.
- *
- * <figure id="fill-rule-non-zero">
- * <title>Example of filling various paths using the non-zero rule</title>
- * <graphic fileref="fill-rule-non-zero.png" format="PNG"/>
- * </figure>
- *
- * <figure id="fill-rule-even-odd">
- * <title>Example of filling various paths using the even-odd rule</title>
- * <graphic fileref="fill-rule-even-odd.png" format="PNG"/>
- * </figure>
- *
- * Since: 1.4
- */
-typedef enum {
- COGL_PATH_FILL_RULE_NON_ZERO,
- COGL_PATH_FILL_RULE_EVEN_ODD
-} CoglPathFillRule;
-
-/**
- * cogl_is_path:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing path object.
- *
- * Return value: %TRUE if the handle references a #CoglPath,
- * %FALSE otherwise
- */
-gboolean
-cogl_is_path (CoglHandle handle);
-
-/**
- * cogl_path_set_fill_rule:
- * @fill_rule: The new fill rule.
- *
- * Sets the fill rule of the current path to @fill_rule. This will
- * affect how the path is filled when cogl_path_fill() is later
- * called. Note that the fill rule state is attached to the path so
- * calling cogl_get_path() will preserve the fill rule and calling
- * cogl_path_new() will reset the fill rule back to the default.
- *
- * Since: 1.4
- */
-void
-cogl_path_set_fill_rule (CoglPathFillRule fill_rule);
-
-/**
- * cogl_path_get_fill_rule:
- *
- * Retrieves the fill rule set using cogl_path_set_fill_rule().
- *
- * Return value: the fill rule that is used for the current path.
- *
- * Since: 1.4
- */
-CoglPathFillRule
-cogl_path_get_fill_rule (void);
-
-/**
- * cogl_path_fill:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color. The current path is then cleared. To use the path
- * again, call cogl_path_fill_preserve() instead.
- *
- * The interior of the shape is determined using the fill rule of the
- * path. See %CoglPathFillRule for details.
- **/
-void
-cogl_path_fill (void);
-
-/**
- * cogl_path_fill_preserve:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color and preserves the path to be used again. See
- * cogl_path_fill() for a description what is considered the interior
- * of the shape.
- *
- * Since: 1.0
- **/
-void
-cogl_path_fill_preserve (void);
-
-/**
- * cogl_path_stroke:
- *
- * Strokes the constructed shape using the current drawing color and a
- * width of 1 pixel (regardless of the current transformation
- * matrix). To current path is then cleared. To use the path again,
- * call cogl_path_stroke_preserve() instead.
- **/
-void
-cogl_path_stroke (void);
-
-/**
- * cogl_path_stroke_preserve:
- *
- * Strokes the constructed shape using the current drawing color and
- * preserves the path to be used again.
- *
- * Since: 1.0
- **/
-void
-cogl_path_stroke_preserve (void);
-
-/**
- * cogl_path_new:
- *
- * Clears the current path and starts a new one. Creating a new path
- * also resets the fill rule to the default which is
- * %COGL_PATH_FILL_RULE_EVEN_ODD.
- *
- * Since: 1.0
- */
-void
-cogl_path_new (void);
-
-/**
- * cogl_path_move_to:
- * @x: X coordinate of the pen location to move to.
- * @y: Y coordinate of the pen location to move to.
- *
- * Moves the pen to the given location. If there is an existing path
- * this will start a new disjoint subpath.
- **/
-void
-cogl_path_move_to (float x,
- float y);
-
-
-/**
- * cogl_path_rel_move_to:
- * @x: X offset from the current pen location to move the pen to.
- * @y: Y offset from the current pen location to move the pen to.
- *
- * Moves the pen to the given offset relative to the current pen
- * location. If there is an existing path this will start a new
- * disjoint subpath.
- **/
-void
-cogl_path_rel_move_to (float x,
- float y);
-
-/**
- * cogl_path_line_to:
- * @x: X coordinate of the end line vertex
- * @y: Y coordinate of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates.
- **/
-void
-cogl_path_line_to (float x,
- float y);
-
-/**
- * cogl_path_rel_line_to:
- * @x: X offset from the current pen location of the end line vertex
- * @y: Y offset from the current pen location of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates relative to the current pen location.
- **/
-void
-cogl_path_rel_line_to (float x,
- float y);
-
-
-/**
- * cogl_path_arc:
- * @center_x: X coordinate of the elliptical arc center
- * @center_y: Y coordinate of the elliptical arc center
- * @radius_x: X radius of the elliptical arc
- * @radius_y: Y radius of the elliptical arc
- * @angle_1: Angle in degrees at which the arc begin
- * @angle_2: Angle in degrees at which the arc ends
- *
- * Adds an elliptical arc segment to the current path. A straight line
- * segment will link the current pen location with the first vertex
- * of the arc. If you perform a move_to to the arcs start just before
- * drawing it you create a free standing arc.
- *
- * The angles are measured in degrees where 0° is in the direction of
- * the positive X axis and 90° is in the direction of the positive Y
- * axis. The angle of the arc begins at @angle_1 and heads towards
- * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease,
- * otherwise it will increase).
- **/
-void
-cogl_path_arc (float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2);
-
-/**
- * cogl_path_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point.
- **/
-void
-cogl_path_curve_to (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3);
-
-/**
- * cogl_path_rel_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point. The given coordinates are relative to the
- * current pen location.
- */
-void
-cogl_path_rel_curve_to (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3);
-
-/**
- * cogl_path_close:
- *
- * Closes the path being constructed by adding a straight line segment
- * to it that ends at the first vertex of the path.
- **/
-void
-cogl_path_close (void);
-
-/**
- * cogl_path_line:
- * @x_1: X coordinate of the start line vertex
- * @y_1: Y coordinate of the start line vertex
- * @x_2: X coordinate of the end line vertex
- * @y_2: Y coordinate of the end line vertex
- *
- * Constructs a straight line shape starting and ending at the given
- * coordinates. If there is an existing path this will start a new
- * disjoint sub-path.
- **/
-void
-cogl_path_line (float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-/**
- * cogl_path_polyline:
- * @coords: (in) (array) (transfer none): A pointer to the first element of an
- * array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a series of straight line segments, starting from the
- * first given vertex coordinate. If there is an existing path this
- * will start a new disjoint sub-path. Each subsequent segment starts
- * where the previous one ended and ends at the next given vertex
- * coordinate.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices. (num_points - 1) segments will
- * be constructed.
- **/
-void
-cogl_path_polyline (const float *coords,
- int num_points);
-
-
-/**
- * cogl_path_polygon:
- * @coords: (in) (array) (transfer none): A pointer to the first element of
- * an array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a polygonal shape of the given number of vertices. If
- * there is an existing path this will start a new disjoint sub-path.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices.
- **/
-void
-cogl_path_polygon (const float *coords,
- int num_points);
-
-
-/**
- * cogl_path_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- *
- * Constructs a rectangular shape at the given coordinates. If there
- * is an existing path this will start a new disjoint sub-path.
- **/
-void
-cogl_path_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-/**
- * cogl_path_ellipse:
- * @center_x: X coordinate of the ellipse center
- * @center_y: Y coordinate of the ellipse center
- * @radius_x: X radius of the ellipse
- * @radius_y: Y radius of the ellipse
- *
- * Constructs an ellipse shape. If there is an existing path this will
- * start a new disjoint sub-path.
- **/
-void
-cogl_path_ellipse (float center_x,
- float center_y,
- float radius_x,
- float radius_y);
-
-/**
- * cogl_path_round_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- * @radius: Radius of the corner arcs.
- * @arc_step: Angle increment resolution for subdivision of
- * the corner arcs.
- *
- * Constructs a rectangular shape with rounded corners. If there is an
- * existing path this will start a new disjoint sub-path.
- **/
-void
-cogl_path_round_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float radius,
- float arc_step);
-
-/**
- * cogl_get_path: (skip)
- *
- * Gets a pointer to the current path. The path can later be used
- * again by calling cogl_path_set(). Note that the path isn't copied
- * so if you later call any functions to add to the path it will
- * affect the returned object too. No reference is taken on the path
- * so if you want to retain it you should take your own reference with
- * cogl_object_ref().
- *
- * Return value: a pointer to the current path.
- *
- * Since: 1.4
- */
-CoglPath *
-cogl_get_path (void);
-
-/**
- * cogl_set_path: (skip)
- * @path: A #CoglPath object
- *
- * Replaces the current path with @path. A reference is taken on the
- * object so if you no longer need the path you should unref with
- * cogl_object_unref().
- *
- * Since: 1.4
- */
-void
-cogl_set_path (CoglPath *path);
-
-/**
- * cogl_path_copy: (skip)
- * @path: A #CoglPath object
- *
- * Returns a new copy of the path in @path. The new path has a
- * reference count of 1 so you should unref it with
- * cogl_object_unref() if you no longer need it.
- *
- * Internally the path will share the data until one of the paths is
- * modified so copying paths should be relatively cheap.
- *
- * Return value: (transfer full): a copy of the path in @path.
- */
-CoglPath *
-cogl_path_copy (CoglPath *path);
-
-G_END_DECLS
-
-#endif /* __COGL_PATH_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H
-#define __COGL_PIPELINE_FRAGEND_ARBFP_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-
-extern const CoglPipelineFragend _cogl_pipeline_arbfp_fragend;
-
-unsigned int
-_cogl_pipeline_fragend_arbfp_hash (const void *pipeline);
-
-gboolean
-_cogl_pipeline_fragend_arbfp_equal (const void *pipeline0,
- const void *pipeline1);
-
-#endif /* __COGL_PIPELINE_ARBFP_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-debug.h"
-#include "cogl-pipeline-private.h"
-
-#ifdef COGL_PIPELINE_FRAGEND_ARBFP
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-
-#include "cogl-texture-private.h"
-#include "cogl-blend-string.h"
-#include "cogl-journal-private.h"
-#include "cogl-color-private.h"
-#include "cogl-profile.h"
-#include "cogl-program-private.h"
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <string.h>
-
-/*
- * GL/GLES compatability defines for pipeline thingies:
- */
-
-#ifdef HAVE_COGL_GL
-#define glProgramString ctx->drv.pf_glProgramString
-#define glBindProgram ctx->drv.pf_glBindProgram
-#define glDeletePrograms ctx->drv.pf_glDeletePrograms
-#define glGenPrograms ctx->drv.pf_glGenPrograms
-#define glProgramLocalParameter4fv ctx->drv.pf_glProgramLocalParameter4fv
-#define glUseProgram ctx->drv.pf_glUseProgram
-#endif
-
-/* This might not be defined on GLES */
-#ifndef GL_TEXTURE_3D
-#define GL_TEXTURE_3D 0x806F
-#endif
-
-typedef struct _UnitState
-{
- int constant_id; /* The program.local[] index */
- unsigned int dirty_combine_constant:1;
-
- unsigned int sampled:1;
-} UnitState;
-
-typedef struct _ArbfpProgramState
-{
- int ref_count;
-
- /* XXX: only valid during codegen */
- CoglPipeline *arbfp_authority;
-
- CoglHandle user_program;
- /* XXX: only valid during codegen */
- GString *source;
- GLuint gl_program;
- UnitState *unit_state;
- int next_constant_id;
-
- /* Age of the program the last time the uniforms were flushed. This
- is used to detect when we need to flush all of the uniforms */
- unsigned int user_program_age;
-
- /* We need to track the last pipeline that an ARBfp program was used
- * with so know if we need to update any program.local parameters. */
- CoglPipeline *last_used_for_pipeline;
-} ArbfpProgramState;
-
-typedef struct _CoglPipelineFragendARBfpPrivate
-{
- ArbfpProgramState *arbfp_program_state;
-} CoglPipelineFragendARBfpPrivate;
-
-const CoglPipelineFragend _cogl_pipeline_arbfp_fragend;
-
-
-static ArbfpProgramState *
-arbfp_program_state_new (int n_layers)
-{
- ArbfpProgramState *state = g_slice_new0 (ArbfpProgramState);
- state->ref_count = 1;
- state->unit_state = g_new0 (UnitState, n_layers);
- return state;
-}
-
-static ArbfpProgramState *
-arbfp_program_state_ref (ArbfpProgramState *state)
-{
- state->ref_count++;
- return state;
-}
-
-void
-arbfp_program_state_unref (ArbfpProgramState *state)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (state->ref_count > 0);
-
- state->ref_count--;
- if (state->ref_count == 0)
- {
- if (state->gl_program)
- {
- GE (glDeletePrograms (1, &state->gl_program));
- state->gl_program = 0;
- }
-
- g_free (state->unit_state);
-
- g_slice_free (ArbfpProgramState, state);
- }
-}
-
-static CoglPipelineFragendARBfpPrivate *
-get_arbfp_priv (CoglPipeline *pipeline)
-{
- if (!(pipeline->fragend_priv_set_mask & COGL_PIPELINE_FRAGEND_ARBFP_MASK))
- return NULL;
-
- return pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_ARBFP];
-}
-
-static void
-set_arbfp_priv (CoglPipeline *pipeline, CoglPipelineFragendARBfpPrivate *priv)
-{
- if (priv)
- {
- pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_ARBFP] = priv;
- pipeline->fragend_priv_set_mask |= COGL_PIPELINE_FRAGEND_ARBFP_MASK;
- }
- else
- pipeline->fragend_priv_set_mask &= ~COGL_PIPELINE_FRAGEND_ARBFP_MASK;
-}
-
-static ArbfpProgramState *
-get_arbfp_program_state (CoglPipeline *pipeline)
-{
- CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (pipeline);
- if (!priv)
- return NULL;
- return priv->arbfp_program_state;
-}
-
-static gboolean
-_cogl_pipeline_fragend_arbfp_start (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs)
-{
- CoglPipelineFragendARBfpPrivate *priv;
- CoglPipeline *authority;
- CoglPipelineFragendARBfpPrivate *authority_priv;
- ArbfpProgramState *arbfp_program_state;
- CoglHandle user_program;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* First validate that we can handle the current state using ARBfp
- */
-
- if (!cogl_features_available (COGL_FEATURE_SHADERS_ARBFP))
- return FALSE;
-
- /* TODO: support fog */
- if (ctx->legacy_fog_state.enabled)
- return FALSE;
-
- user_program = cogl_pipeline_get_user_program (pipeline);
- if (user_program != COGL_INVALID_HANDLE)
- {
- /* If the program doesn't have a fragment shader then some other
- vertend will handle the vertex shader state and we still need
- to generate a fragment program */
- if (!_cogl_program_has_fragment_shader (user_program))
- user_program = COGL_INVALID_HANDLE;
- /* If the user program does have a fragment shader then we can
- only handle it if it's in ARBfp */
- else if (_cogl_program_get_language (user_program) !=
- COGL_SHADER_LANGUAGE_ARBFP)
- return FALSE;
- }
-
- /* Now lookup our ARBfp backend private state (allocating if
- * necessary) */
- priv = get_arbfp_priv (pipeline);
- if (!priv)
- {
- priv = g_slice_new0 (CoglPipelineFragendARBfpPrivate);
- set_arbfp_priv (pipeline, priv);
- }
-
- /* If we have a valid arbfp_program_state pointer then we are all
- * set and don't need to generate a new program. */
- if (priv->arbfp_program_state)
- return TRUE;
-
- /* If we don't have an associated arbfp program yet then find the
- * arbfp-authority (the oldest ancestor whose state will result in
- * the same program being generated as for this pipeline).
- *
- * We always make sure to associate new programs with the
- * arbfp-authority to maximize the chance that other pipelines can
- * share it.
- */
- authority = _cogl_pipeline_find_equivalent_parent
- (pipeline,
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
- ~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
- authority_priv = get_arbfp_priv (authority);
- if (authority_priv &&
- authority_priv->arbfp_program_state)
- {
- /* If we are going to share our program state with an arbfp-authority
- * then steal a reference to the program state associated with that
- * arbfp-authority... */
- priv->arbfp_program_state =
- arbfp_program_state_ref (authority_priv->arbfp_program_state);
- return TRUE;
- }
-
- if (!authority_priv)
- {
- authority_priv = g_slice_new0 (CoglPipelineFragendARBfpPrivate);
- set_arbfp_priv (authority, authority_priv);
- }
-
- /* If we haven't yet found an existing program then before we resort to
- * generating a new arbfp program we see if we can find a suitable
- * program in the arbfp_cache. */
- if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
- {
- arbfp_program_state = g_hash_table_lookup (ctx->arbfp_cache, authority);
- if (arbfp_program_state)
- {
- priv->arbfp_program_state =
- arbfp_program_state_ref (arbfp_program_state);
-
- /* Since we have already resolved the arbfp-authority at this point
- * we might as well also associate any program we find from the cache
- * with the authority too... */
- if (authority_priv != priv)
- authority_priv->arbfp_program_state =
- arbfp_program_state_ref (arbfp_program_state);
- return TRUE;
- }
- }
-
- /* If we still haven't found an existing program then start
- * generating code for a new program...
- */
-
- arbfp_program_state = arbfp_program_state_new (n_layers);
-
- priv->arbfp_program_state = arbfp_program_state_ref (arbfp_program_state);
-
- /* Since we have already resolved the arbfp-authority at this point we might
- * as well also associate any program we generate with the authority too...
- */
- if (authority_priv != priv)
- authority_priv->arbfp_program_state =
- arbfp_program_state_ref (arbfp_program_state);
-
- arbfp_program_state->user_program = user_program;
- if (user_program == COGL_INVALID_HANDLE)
- {
- int i;
-
- /* We reuse a single grow-only GString for code-gen */
- g_string_set_size (ctx->codegen_source_buffer, 0);
- arbfp_program_state->source = ctx->codegen_source_buffer;
- g_string_append (arbfp_program_state->source,
- "!!ARBfp1.0\n"
- "TEMP output;\n"
- "TEMP tmp0, tmp1, tmp2, tmp3, tmp4;\n"
- "PARAM half = {.5, .5, .5, .5};\n"
- "PARAM one = {1, 1, 1, 1};\n"
- "PARAM two = {2, 2, 2, 2};\n"
- "PARAM minus_one = {-1, -1, -1, -1};\n");
-
- /* At the end of code-gen we'll add the program to a cache and
- * we'll use the authority pipeline as the basis for key into
- * that cache... */
- arbfp_program_state->arbfp_authority = authority;
-
- for (i = 0; i < n_layers; i++)
- {
- arbfp_program_state->unit_state[i].sampled = FALSE;
- arbfp_program_state->unit_state[i].dirty_combine_constant = FALSE;
- }
- arbfp_program_state->next_constant_id = 0;
- }
-
- return TRUE;
-}
-
-unsigned int
-_cogl_pipeline_fragend_arbfp_hash (const void *data)
-{
- unsigned long fragment_state =
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
- unsigned long layer_fragment_state =
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
-
- return _cogl_pipeline_hash ((CoglPipeline *)data,
- fragment_state, layer_fragment_state,
- 0);
-}
-
-gboolean
-_cogl_pipeline_fragend_arbfp_equal (const void *a, const void *b)
-{
- unsigned long fragment_state =
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN;
- unsigned long layer_fragment_state =
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN;
-
- return _cogl_pipeline_equal ((CoglPipeline *)a, (CoglPipeline *)b,
- fragment_state, layer_fragment_state,
- 0);
-}
-
-static const char *
-gl_target_to_arbfp_string (GLenum gl_target)
-{
-#ifndef HAVE_COGL_GLES2
- if (gl_target == GL_TEXTURE_1D)
- return "1D";
- else
-#endif
- if (gl_target == GL_TEXTURE_2D)
- return "2D";
-#ifdef GL_ARB_texture_rectangle
- else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
- return "RECT";
-#endif
- else if (gl_target == GL_TEXTURE_3D)
- return "3D";
- else
- return "2D";
-}
-
-static void
-setup_texture_source (ArbfpProgramState *arbfp_program_state,
- int unit_index,
- GLenum gl_target)
-{
- if (!arbfp_program_state->unit_state[unit_index].sampled)
- {
- g_string_append_printf (arbfp_program_state->source,
- "TEMP texel%d;\n"
- "TEX texel%d,fragment.texcoord[%d],"
- "texture[%d],%s;\n",
- unit_index,
- unit_index,
- unit_index,
- unit_index,
- gl_target_to_arbfp_string (gl_target));
- arbfp_program_state->unit_state[unit_index].sampled = TRUE;
- }
-}
-
-typedef enum _CoglPipelineFragendARBfpArgType
-{
- COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE,
- COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT,
- COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE
-} CoglPipelineFragendARBfpArgType;
-
-typedef struct _CoglPipelineFragendARBfpArg
-{
- const char *name;
-
- CoglPipelineFragendARBfpArgType type;
-
- /* for type = TEXTURE */
- int texture_unit;
- GLenum texture_target;
-
- /* for type = CONSTANT */
- int constant_id;
-
- const char *swizzle;
-
-} CoglPipelineFragendARBfpArg;
-
-static void
-append_arg (GString *source, const CoglPipelineFragendARBfpArg *arg)
-{
- switch (arg->type)
- {
- case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE:
- g_string_append_printf (source, "texel%d%s",
- arg->texture_unit, arg->swizzle);
- break;
- case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT:
- g_string_append_printf (source, "program.local[%d]%s",
- arg->constant_id, arg->swizzle);
- break;
- case COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE:
- g_string_append_printf (source, "%s%s",
- arg->name, arg->swizzle);
- break;
- }
-}
-
-/* Note: we are trying to avoid duplicating strings during codegen
- * which is why we have the slightly awkward
- * CoglPipelineFragendARBfpArg mechanism. */
-static void
-setup_arg (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- CoglBlendStringChannelMask mask,
- int arg_index,
- GLint src,
- GLint op,
- CoglPipelineFragendARBfpArg *arg)
-{
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline);
- static const char *tmp_name[3] = { "tmp0", "tmp1", "tmp2" };
- GLenum gl_target;
- CoglHandle texture;
-
- switch (src)
- {
- case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE:
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE;
- arg->name = "texel%d";
- arg->texture_unit = _cogl_pipeline_layer_get_unit_index (layer);
- texture = _cogl_pipeline_layer_get_texture (layer);
- cogl_texture_get_gl_texture (texture, NULL, &gl_target);
- setup_texture_source (arbfp_program_state, arg->texture_unit, gl_target);
- break;
- case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT:
- {
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- UnitState *unit_state = &arbfp_program_state->unit_state[unit_index];
-
- unit_state->constant_id = arbfp_program_state->next_constant_id++;
- unit_state->dirty_combine_constant = TRUE;
-
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT;
- arg->name = "program.local[%d]";
- arg->constant_id = unit_state->constant_id;
- break;
- }
- case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR:
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
- arg->name = "fragment.color.primary";
- break;
- case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS:
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
- if (_cogl_pipeline_layer_get_unit_index (layer) == 0)
- arg->name = "fragment.color.primary";
- else
- arg->name = "output";
- break;
- default: /* GL_TEXTURE0..N */
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE;
- arg->name = "texture[%d]";
- arg->texture_unit = src - GL_TEXTURE0;
- texture = _cogl_pipeline_layer_get_texture (layer);
- cogl_texture_get_gl_texture (texture, NULL, &gl_target);
- setup_texture_source (arbfp_program_state, arg->texture_unit, gl_target);
- }
-
- arg->swizzle = "";
-
- switch (op)
- {
- case COGL_PIPELINE_COMBINE_OP_SRC_COLOR:
- break;
- case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR:
- g_string_append_printf (arbfp_program_state->source,
- "SUB tmp%d, one, ",
- arg_index);
- append_arg (arbfp_program_state->source, arg);
- g_string_append_printf (arbfp_program_state->source, ";\n");
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
- arg->name = tmp_name[arg_index];
- arg->swizzle = "";
- break;
- case COGL_PIPELINE_COMBINE_OP_SRC_ALPHA:
- /* avoid a swizzle if we know RGB are going to be masked
- * in the end anyway */
- if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- arg->swizzle = ".a";
- break;
- case COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA:
- g_string_append_printf (arbfp_program_state->source,
- "SUB tmp%d, one, ",
- arg_index);
- append_arg (arbfp_program_state->source, arg);
- /* avoid a swizzle if we know RGB are going to be masked
- * in the end anyway */
- if (mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- g_string_append_printf (arbfp_program_state->source, ".a;\n");
- else
- g_string_append_printf (arbfp_program_state->source, ";\n");
- arg->type = COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_SIMPLE;
- arg->name = tmp_name[arg_index];
- break;
- default:
- g_error ("Unknown texture combine operator %d", op);
- break;
- }
-}
-
-static gboolean
-fragend_arbfp_args_equal (CoglPipelineFragendARBfpArg *arg0,
- CoglPipelineFragendARBfpArg *arg1)
-{
- if (arg0->type != arg1->type)
- return FALSE;
-
- if (arg0->name != arg1->name &&
- strcmp (arg0->name, arg1->name) != 0)
- return FALSE;
-
- if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_TEXTURE &&
- arg0->texture_unit != arg1->texture_unit)
- return FALSE;
- /* Note we don't have to check the target; a texture unit can only
- * have one target enabled at a time. */
-
- if (arg0->type == COGL_PIPELINE_FRAGEND_ARBFP_ARG_TYPE_CONSTANT &&
- arg0->constant_id != arg0->constant_id)
- return FALSE;
-
- if (arg0->swizzle != arg1->swizzle &&
- strcmp (arg0->swizzle, arg1->swizzle) != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-append_function (CoglPipeline *pipeline,
- CoglBlendStringChannelMask mask,
- GLint function,
- CoglPipelineFragendARBfpArg *args,
- int n_args)
-{
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline);
- const char *mask_name;
-
- switch (mask)
- {
- case COGL_BLEND_STRING_CHANNEL_MASK_RGB:
- mask_name = ".rgb";
- break;
- case COGL_BLEND_STRING_CHANNEL_MASK_ALPHA:
- mask_name = ".a";
- break;
- case COGL_BLEND_STRING_CHANNEL_MASK_RGBA:
- mask_name = "";
- break;
- default:
- g_error ("Unknown channel mask %d", mask);
- mask_name = "";
- }
-
- switch (function)
- {
- case COGL_PIPELINE_COMBINE_FUNC_ADD:
- g_string_append_printf (arbfp_program_state->source,
- "ADD_SAT output%s, ",
- mask_name);
- break;
- case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
- /* Note: no need to saturate since we can assume operands
- * have values in the range [0,1] */
- g_string_append_printf (arbfp_program_state->source, "MUL output%s, ",
- mask_name);
- break;
- case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
- /* Note: no need to saturate since we can assume operand
- * has a value in the range [0,1] */
- g_string_append_printf (arbfp_program_state->source, "MOV output%s, ",
- mask_name);
- break;
- case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
- g_string_append_printf (arbfp_program_state->source,
- "SUB_SAT output%s, ",
- mask_name);
- break;
- case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
- g_string_append_printf (arbfp_program_state->source, "ADD tmp3%s, ",
- mask_name);
- append_arg (arbfp_program_state->source, &args[0]);
- g_string_append (arbfp_program_state->source, ", ");
- append_arg (arbfp_program_state->source, &args[1]);
- g_string_append (arbfp_program_state->source, ";\n");
- g_string_append_printf (arbfp_program_state->source,
- "SUB_SAT output%s, tmp3, half",
- mask_name);
- n_args = 0;
- break;
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
- /* These functions are the same except that GL_DOT3_RGB never
- * updates the alpha channel.
- *
- * NB: GL_DOT3_RGBA is a bit special because it effectively forces
- * an RGBA mask and we end up ignoring any separate alpha channel
- * function.
- */
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
- {
- const char *tmp4 = "tmp4";
-
- /* The maths for this was taken from Mesa;
- * apparently:
- *
- * tmp3 = 2*src0 - 1
- * tmp4 = 2*src1 - 1
- * output = DP3 (tmp3, tmp4)
- *
- * is the same as:
- *
- * output = 4 * DP3 (src0 - 0.5, src1 - 0.5)
- */
-
- g_string_append (arbfp_program_state->source, "MAD tmp3, two, ");
- append_arg (arbfp_program_state->source, &args[0]);
- g_string_append (arbfp_program_state->source, ", minus_one;\n");
-
- if (!fragend_arbfp_args_equal (&args[0], &args[1]))
- {
- g_string_append (arbfp_program_state->source, "MAD tmp4, two, ");
- append_arg (arbfp_program_state->source, &args[1]);
- g_string_append (arbfp_program_state->source, ", minus_one;\n");
- }
- else
- tmp4 = "tmp3";
-
- g_string_append_printf (arbfp_program_state->source,
- "DP3_SAT output%s, tmp3, %s",
- mask_name, tmp4);
- n_args = 0;
- }
- break;
- case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
- /* Note: no need to saturate since we can assume operands
- * have values in the range [0,1] */
-
- /* NB: GL_INTERPOLATE = arg0*arg2 + arg1*(1-arg2)
- * but LRP dst, a, b, c = b*a + c*(1-a) */
- g_string_append_printf (arbfp_program_state->source, "LRP output%s, ",
- mask_name);
- append_arg (arbfp_program_state->source, &args[2]);
- g_string_append (arbfp_program_state->source, ", ");
- append_arg (arbfp_program_state->source, &args[0]);
- g_string_append (arbfp_program_state->source, ", ");
- append_arg (arbfp_program_state->source, &args[1]);
- n_args = 0;
- break;
- default:
- g_error ("Unknown texture combine function %d", function);
- g_string_append_printf (arbfp_program_state->source, "MUL_SAT output%s, ",
- mask_name);
- n_args = 2;
- break;
- }
-
- if (n_args > 0)
- append_arg (arbfp_program_state->source, &args[0]);
- if (n_args > 1)
- {
- g_string_append (arbfp_program_state->source, ", ");
- append_arg (arbfp_program_state->source, &args[1]);
- }
- g_string_append (arbfp_program_state->source, ";\n");
-}
-
-static void
-append_masked_combine (CoglPipeline *arbfp_authority,
- CoglPipelineLayer *layer,
- CoglBlendStringChannelMask mask,
- CoglPipelineCombineFunc function,
- CoglPipelineCombineSource *src,
- CoglPipelineCombineOp *op)
-{
- int i;
- int n_args;
- CoglPipelineFragendARBfpArg args[3];
-
- n_args = _cogl_get_n_args_for_combine_func (function);
-
- for (i = 0; i < n_args; i++)
- {
- setup_arg (arbfp_authority,
- layer,
- mask,
- i,
- src[i],
- op[i],
- &args[i]);
- }
-
- append_function (arbfp_authority,
- mask,
- function,
- args,
- n_args);
-}
-
-static gboolean
-_cogl_pipeline_fragend_arbfp_add_layer (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference)
-{
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline);
- CoglPipelineLayer *combine_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_COMBINE);
- CoglPipelineLayerBigState *big_state = combine_authority->big_state;
-
- /* Notes...
- *
- * We are ignoring the issue of texture indirection limits until
- * someone complains (Ref Section 3.11.6 in the ARB_fragment_program
- * spec)
- *
- * There always five TEMPs named tmp0, tmp1 and tmp2, tmp3 and tmp4
- * available and these constants: 'one' = {1, 1, 1, 1}, 'half'
- * {.5, .5, .5, .5}, 'two' = {2, 2, 2, 2}, 'minus_one' = {-1, -1,
- * -1, -1}
- *
- * tmp0-2 are intended for dealing with some of the texture combine
- * operands (e.g. GL_ONE_MINUS_SRC_COLOR) tmp3/4 are for dealing
- * with the GL_ADD_SIGNED texture combine and the GL_DOT3_RGB[A]
- * functions.
- *
- * Each layer outputs to the TEMP called "output", and reads from
- * output if it needs to refer to GL_PREVIOUS. (we detect if we are
- * layer0 so we will read fragment.color for GL_PREVIOUS in that
- * case)
- *
- * We aim to do all the channels together if the same function is
- * used for RGB as for A.
- *
- * We aim to avoid string duplication / allocations during codegen.
- *
- * We are careful to only saturate when writing to output.
- */
-
- if (!arbfp_program_state->source)
- return TRUE;
-
- if (!_cogl_pipeline_need_texture_combine_separate (combine_authority))
- {
- append_masked_combine (pipeline,
- layer,
- COGL_BLEND_STRING_CHANNEL_MASK_RGBA,
- big_state->texture_combine_rgb_func,
- big_state->texture_combine_rgb_src,
- big_state->texture_combine_rgb_op);
- }
- else if (big_state->texture_combine_rgb_func ==
- COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA)
- {
- /* GL_DOT3_RGBA Is a bit weird as a GL_COMBINE_RGB function
- * since if you use it, it overrides your ALPHA function...
- */
- append_masked_combine (pipeline,
- layer,
- COGL_BLEND_STRING_CHANNEL_MASK_RGBA,
- big_state->texture_combine_rgb_func,
- big_state->texture_combine_rgb_src,
- big_state->texture_combine_rgb_op);
- }
- else
- {
- append_masked_combine (pipeline,
- layer,
- COGL_BLEND_STRING_CHANNEL_MASK_RGB,
- big_state->texture_combine_rgb_func,
- big_state->texture_combine_rgb_src,
- big_state->texture_combine_rgb_op);
- append_masked_combine (pipeline,
- layer,
- COGL_BLEND_STRING_CHANNEL_MASK_ALPHA,
- big_state->texture_combine_alpha_func,
- big_state->texture_combine_alpha_src,
- big_state->texture_combine_alpha_op);
- }
-
- return TRUE;
-}
-
-gboolean
-_cogl_pipeline_fragend_arbfp_passthrough (CoglPipeline *pipeline)
-{
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline);
-
- if (!arbfp_program_state->source)
- return TRUE;
-
- g_string_append (arbfp_program_state->source,
- "MOV output, fragment.color.primary;\n");
- return TRUE;
-}
-
-typedef struct _UpdateConstantsState
-{
- int unit;
- gboolean update_all;
- ArbfpProgramState *arbfp_program_state;
-} UpdateConstantsState;
-
-static gboolean
-update_constants_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- UpdateConstantsState *state = user_data;
- ArbfpProgramState *arbfp_program_state = state->arbfp_program_state;
- UnitState *unit_state = &arbfp_program_state->unit_state[state->unit++];
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (state->update_all || unit_state->dirty_combine_constant)
- {
- float constant[4];
- _cogl_pipeline_get_layer_combine_constant (pipeline,
- layer_index,
- constant);
- GE (glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB,
- unit_state->constant_id,
- constant));
- unit_state->dirty_combine_constant = FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_fragend_arbfp_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference)
-{
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (pipeline);
- GLuint gl_program;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (arbfp_program_state->source)
- {
- GLenum gl_error;
- COGL_STATIC_COUNTER (fragend_arbfp_compile_counter,
- "arbfp compile counter",
- "Increments each time a new ARBfp "
- "program is compiled",
- 0 /* no application private data */);
-
- COGL_COUNTER_INC (_cogl_uprof_context, fragend_arbfp_compile_counter);
-
- g_string_append (arbfp_program_state->source,
- "MOV result.color,output;\n");
- g_string_append (arbfp_program_state->source, "END\n");
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
- g_message ("pipeline program:\n%s", arbfp_program_state->source->str);
-
- GE (glGenPrograms (1, &arbfp_program_state->gl_program));
-
- GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB,
- arbfp_program_state->gl_program));
-
- while ((gl_error = glGetError ()) != GL_NO_ERROR)
- ;
- glProgramString (GL_FRAGMENT_PROGRAM_ARB,
- GL_PROGRAM_FORMAT_ASCII_ARB,
- arbfp_program_state->source->len,
- arbfp_program_state->source->str);
- if (glGetError () != GL_NO_ERROR)
- {
- g_warning ("\n%s\n%s",
- arbfp_program_state->source->str,
- glGetString (GL_PROGRAM_ERROR_STRING_ARB));
- }
-
- arbfp_program_state->source = NULL;
-
- if (G_LIKELY (!(COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_PROGRAM_CACHES))))
- {
- CoglPipeline *key;
-
- /* XXX: I wish there was a way to insert into a GHashTable
- * with a pre-calculated hash value since there is a cost to
- * calculating the hash of a CoglPipeline and in this case
- * we know we have already called _cogl_pipeline_hash during
- * _cogl_pipeline_fragend_arbfp_backend_start so we could pass the
- * value through to here to avoid hashing it again.
- */
-
- /* XXX: Any keys referenced by the hash table need to remain
- * valid all the while that there are corresponding values,
- * so for now we simply make a copy of the current authority
- * pipeline.
- *
- * FIXME: A problem with this is that our key into the cache
- * may hold references to some arbitrary user textures which
- * will now be kept alive indefinitly which is a shame. A
- * better solution will be to derive a special "key
- * pipeline" from the authority which derives from the base
- * Cogl pipeline (to avoid affecting the lifetime of any
- * other pipelines) and only takes a copy of the state that
- * relates to the arbfp program and references small dummy
- * textures instead of potentially large user textures. */
- key = cogl_pipeline_copy (arbfp_program_state->arbfp_authority);
- arbfp_program_state_ref (arbfp_program_state);
- g_hash_table_insert (ctx->arbfp_cache, key, arbfp_program_state);
- if (G_UNLIKELY (g_hash_table_size (ctx->arbfp_cache) > 50))
- {
- static gboolean seen = FALSE;
- if (!seen)
- g_warning ("Over 50 separate ARBfp programs have been "
- "generated which is very unusual, so something "
- "is probably wrong!\n");
- seen = TRUE;
- }
- }
-
- /* The authority is only valid during codegen since the program
- * state may have a longer lifetime than the original authority
- * it is created for. */
- arbfp_program_state->arbfp_authority = NULL;
- }
-
- if (arbfp_program_state->user_program != COGL_INVALID_HANDLE)
- {
- /* An arbfp program should contain exactly one shader which we
- can use directly */
- CoglProgram *program = arbfp_program_state->user_program;
- CoglShader *shader = program->attached_shaders->data;
-
- gl_program = shader->gl_handle;
- }
- else
- gl_program = arbfp_program_state->gl_program;
-
- GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, gl_program));
- _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_ARBFP);
-
- if (arbfp_program_state->user_program == COGL_INVALID_HANDLE)
- {
- UpdateConstantsState state;
- state.unit = 0;
- state.arbfp_program_state = arbfp_program_state;
- /* If this arbfp program was last used with a different pipeline
- * then we need to ensure we update all program.local params */
- state.update_all =
- pipeline != arbfp_program_state->last_used_for_pipeline;
- cogl_pipeline_foreach_layer (pipeline,
- update_constants_cb,
- &state);
- }
- else
- {
- CoglProgram *program = arbfp_program_state->user_program;
- gboolean program_changed;
-
- /* If the shader has changed since it was last flushed then we
- need to update all uniforms */
- program_changed = program->age != arbfp_program_state->user_program_age;
-
- _cogl_program_flush_uniforms (program, gl_program, program_changed);
-
- arbfp_program_state->user_program_age = program->age;
- }
-
- /* We need to track what pipeline used this arbfp program last since
- * we will need to update program.local params when switching
- * between different pipelines. */
- arbfp_program_state->last_used_for_pipeline = pipeline;
-
- return TRUE;
-}
-
-static void
-dirty_arbfp_program_state (CoglPipeline *pipeline)
-{
- CoglPipelineFragendARBfpPrivate *priv;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- priv = get_arbfp_priv (pipeline);
- if (!priv)
- return;
-
- if (priv->arbfp_program_state)
- {
- arbfp_program_state_unref (priv->arbfp_program_state);
- priv->arbfp_program_state = NULL;
- }
-}
-
-static void
-_cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify (
- CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color)
-{
- if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
- dirty_arbfp_program_state (pipeline);
-}
-
-/* NB: layers are considered immutable once they have any dependants
- * so although multiple pipelines can end up depending on a single
- * static layer, we can guarantee that if a layer is being *changed*
- * then it can only have one pipeline depending on it.
- *
- * XXX: Don't forget this is *pre* change, we can't read the new value
- * yet!
- */
-static void
-_cogl_pipeline_fragend_arbfp_layer_pre_change_notify (
- CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (owner);
- if (!priv)
- return;
-
- if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
- {
- dirty_arbfp_program_state (owner);
- return;
- }
-
- if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
- {
- ArbfpProgramState *arbfp_program_state = get_arbfp_program_state (owner);
-
- if (arbfp_program_state)
- {
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- arbfp_program_state->unit_state[unit_index].dirty_combine_constant =
- TRUE;
- }
- }
-
- /* TODO: we could be saving snippets of texture combine code along
- * with each layer and then when a layer changes we would just free
- * the snippet. */
- return;
-}
-
-static void
-_cogl_pipeline_fragend_arbfp_free_priv (CoglPipeline *pipeline)
-{
- CoglPipelineFragendARBfpPrivate *priv = get_arbfp_priv (pipeline);
- if (priv)
- {
- if (priv->arbfp_program_state)
- arbfp_program_state_unref (priv->arbfp_program_state);
- g_slice_free (CoglPipelineFragendARBfpPrivate, priv);
- set_arbfp_priv (pipeline, NULL);
- }
-}
-
-const CoglPipelineFragend _cogl_pipeline_arbfp_fragend =
-{
- _cogl_pipeline_fragend_arbfp_start,
- _cogl_pipeline_fragend_arbfp_add_layer,
- _cogl_pipeline_fragend_arbfp_passthrough,
- _cogl_pipeline_fragend_arbfp_end,
- _cogl_pipeline_fragend_arbfp_pipeline_pre_change_notify,
- NULL,
- _cogl_pipeline_fragend_arbfp_layer_pre_change_notify,
- _cogl_pipeline_fragend_arbfp_free_priv
-};
-
-#endif /* COGL_PIPELINE_FRAGEND_ARBFP */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H
-#define __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-
-extern const CoglPipelineFragend _cogl_pipeline_fixed_fragend;
-
-#endif /* __COGL_PIPELINE_FRAGEND_FIXED_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#ifdef COGL_PIPELINE_FRAGEND_FIXED
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-
-#include "cogl-texture-private.h"
-#include "cogl-blend-string.h"
-#include "cogl-profile.h"
-#include "cogl-program-private.h"
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <string.h>
-
-const CoglPipelineFragend _cogl_pipeline_fixed_fragend;
-
-static void
-_cogl_disable_texture_unit (int unit_index)
-{
- CoglTextureUnit *unit;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- unit = &g_array_index (ctx->texture_units, CoglTextureUnit, unit_index);
-
- if (unit->enabled_gl_target)
- {
- _cogl_set_active_texture_unit (unit_index);
- GE (glDisable (unit->enabled_gl_target));
- unit->enabled_gl_target = 0;
- }
-}
-
-static int
-get_max_texture_units (void)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- /* This function is called quite often so we cache the value to
- avoid too many GL calls */
- if (ctx->max_texture_units == -1)
- {
- ctx->max_texture_units = 1;
- GE (glGetIntegerv (GL_MAX_TEXTURE_UNITS,
- &ctx->max_texture_units));
- }
-
- return ctx->max_texture_units;
-}
-
-static gboolean
-_cogl_pipeline_fragend_fixed_start (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs)
-{
- CoglHandle user_program;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
- return FALSE;
-
- /* If there is a user program with a fragment shader then the
- appropriate backend for that language should handle it. We can
- still use the fixed fragment backend if the program only contains
- a vertex shader */
- user_program = cogl_pipeline_get_user_program (pipeline);
- if (user_program != COGL_INVALID_HANDLE &&
- _cogl_program_has_fragment_shader (user_program))
- return FALSE;
-
- _cogl_use_fragment_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_fragend_fixed_add_layer (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference)
-{
- CoglTextureUnit *unit =
- _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
- int unit_index = unit->index;
- int n_rgb_func_args;
- int n_alpha_func_args;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* XXX: Beware that since we are changing the active texture unit we
- * must make sure we don't call into other Cogl components that may
- * temporarily bind texture objects to query/modify parameters since
- * they will end up binding texture unit 1. See
- * _cogl_bind_gl_texture_transient for more details.
- */
- _cogl_set_active_texture_unit (unit_index);
-
- if (G_UNLIKELY (unit_index >= get_max_texture_units ()))
- {
- _cogl_disable_texture_unit (unit_index);
- /* TODO: although this isn't considered an error that
- * warrants falling back to a different backend we
- * should print a warning here. */
- return TRUE;
- }
-
- /* Handle enabling or disabling the right texture target */
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
- {
- CoglPipelineLayer *tex_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
- CoglPipelineLayer *target_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET);
- /* XXX: currently layers with no associated texture fallback to
- * using ctx->default_gl_texture_2d_tex so they have a texture
- * target of GL_TEXTURE_2D */
- GLenum gl_target =
- tex_authority->texture ? target_authority->target : GL_TEXTURE_2D;
-
- _cogl_set_active_texture_unit (unit_index);
-
- /* The common GL code handles binding the right texture so we
- just need to handle enabling and disabling it */
-
- if (unit->enabled_gl_target != gl_target)
- {
- /* Disable the previous target if it's still enabled */
- if (unit->enabled_gl_target)
- GE (glDisable (unit->enabled_gl_target));
-
- /* Enable the new target */
- if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)))
- {
- GE (glEnable (gl_target));
- unit->enabled_gl_target = gl_target;
- }
- }
- }
- else
- {
- /* Even though there may be no difference between the last flushed
- * texture state and the current layers texture state it may be that the
- * texture unit has been disabled for some time so we need to assert that
- * it's enabled now.
- */
- if (!G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING)) &&
- !unit->enabled_gl_target == 0)
- {
- _cogl_set_active_texture_unit (unit_index);
- GE (glEnable (unit->gl_target));
- unit->enabled_gl_target = unit->gl_target;
- }
- }
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE)
- {
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_COMBINE);
- CoglPipelineLayerBigState *big_state = authority->big_state;
-
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE));
-
- /* Set the combiner functions... */
- GE (glTexEnvi (GL_TEXTURE_ENV,
- GL_COMBINE_RGB,
- big_state->texture_combine_rgb_func));
- GE (glTexEnvi (GL_TEXTURE_ENV,
- GL_COMBINE_ALPHA,
- big_state->texture_combine_alpha_func));
-
- /*
- * Setup the function arguments...
- */
-
- /* For the RGB components... */
- n_rgb_func_args =
- _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func);
-
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB,
- big_state->texture_combine_rgb_src[0]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB,
- big_state->texture_combine_rgb_op[0]));
- if (n_rgb_func_args > 1)
- {
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_RGB,
- big_state->texture_combine_rgb_src[1]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB,
- big_state->texture_combine_rgb_op[1]));
- }
- if (n_rgb_func_args > 2)
- {
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_RGB,
- big_state->texture_combine_rgb_src[2]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB,
- big_state->texture_combine_rgb_op[2]));
- }
-
- /* For the Alpha component */
- n_alpha_func_args =
- _cogl_get_n_args_for_combine_func (big_state->texture_combine_alpha_func);
-
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA,
- big_state->texture_combine_alpha_src[0]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA,
- big_state->texture_combine_alpha_op[0]));
- if (n_alpha_func_args > 1)
- {
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA,
- big_state->texture_combine_alpha_src[1]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA,
- big_state->texture_combine_alpha_op[1]));
- }
- if (n_alpha_func_args > 2)
- {
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_SRC2_ALPHA,
- big_state->texture_combine_alpha_src[2]));
- GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
- big_state->texture_combine_alpha_op[2]));
- }
- }
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
- {
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority
- (layer, COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT);
- CoglPipelineLayerBigState *big_state = authority->big_state;
-
- GE (glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
- big_state->texture_combine_constant));
- }
-
- return TRUE;
-}
-
-static gboolean
-get_highest_unit_index_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- int *highest_index = user_data;
-
- *highest_index = unit_index;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_fragend_fixed_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference)
-{
- int highest_unit_index = -1;
- int i;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- get_highest_unit_index_cb,
- &highest_unit_index);
-
- /* Disable additional texture units that may have previously been in use.. */
- for (i = highest_unit_index + 1; i < ctx->texture_units->len; i++)
- _cogl_disable_texture_unit (i);
-
- if (pipelines_difference & COGL_PIPELINE_STATE_FOG)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_FOG);
- CoglPipelineFogState *fog_state = &authority->big_state->fog_state;
-
- if (fog_state->enabled)
- {
- GLfloat fogColor[4];
- GLenum gl_mode = GL_LINEAR;
-
- fogColor[0] = cogl_color_get_red_float (&fog_state->color);
- fogColor[1] = cogl_color_get_green_float (&fog_state->color);
- fogColor[2] = cogl_color_get_blue_float (&fog_state->color);
- fogColor[3] = cogl_color_get_alpha_float (&fog_state->color);
-
- GE (glEnable (GL_FOG));
-
- GE (glFogfv (GL_FOG_COLOR, fogColor));
-
-#if HAVE_COGL_GLES
- switch (fog_state->mode)
- {
- case COGL_FOG_MODE_LINEAR:
- gl_mode = GL_LINEAR;
- break;
- case COGL_FOG_MODE_EXPONENTIAL:
- gl_mode = GL_EXP;
- break;
- case COGL_FOG_MODE_EXPONENTIAL_SQUARED:
- gl_mode = GL_EXP2;
- break;
- }
-#endif
- /* TODO: support other modes for GLES2 */
-
- /* NB: GLES doesn't have glFogi */
- GE (glFogf (GL_FOG_MODE, gl_mode));
- GE (glHint (GL_FOG_HINT, GL_NICEST));
-
- GE (glFogf (GL_FOG_DENSITY, fog_state->density));
- GE (glFogf (GL_FOG_START, fog_state->z_near));
- GE (glFogf (GL_FOG_END, fog_state->z_far));
- }
- else
- GE (glDisable (GL_FOG));
- }
-
- return TRUE;
-}
-
-const CoglPipelineFragend _cogl_pipeline_fixed_fragend =
-{
- _cogl_pipeline_fragend_fixed_start,
- _cogl_pipeline_fragend_fixed_add_layer,
- NULL, /* passthrough */
- _cogl_pipeline_fragend_fixed_end,
- NULL, /* pipeline_change_notify */
- NULL, /* pipeline_set_parent_notify */
- NULL, /* layer_change_notify */
- NULL /* free_priv */
-};
-
-#endif /* COGL_PIPELINE_FRAGEND_FIXED */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H
-#define __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-
-extern const CoglPipelineFragend _cogl_pipeline_glsl_fragend;
-
-GLuint
-_cogl_pipeline_fragend_glsl_get_shader (CoglPipeline *pipeline);
-
-#endif /* __COGL_PIPELINE_FRAGEND_GLSL_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl-pipeline-private.h"
-#include "cogl-shader-private.h"
-#include "cogl-blend-string.h"
-
-#ifdef COGL_PIPELINE_FRAGEND_GLSL
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-shader-private.h"
-#include "cogl-program-private.h"
-
-#ifndef HAVE_COGL_GLES2
-
-#define glCreateShader ctx->drv.pf_glCreateShader
-#define glGetShaderiv ctx->drv.pf_glGetShaderiv
-#define glGetShaderInfoLog ctx->drv.pf_glGetShaderInfoLog
-#define glCompileShader ctx->drv.pf_glCompileShader
-#define glShaderSource ctx->drv.pf_glShaderSource
-#define glDeleteShader ctx->drv.pf_glDeleteShader
-
-#endif /* HAVE_COGL_GLES2 */
-
-#include <glib.h>
-
-/*
- * GL/GLES compatability defines for pipeline thingies:
- */
-
-/* This might not be defined on GLES */
-#ifndef GL_TEXTURE_3D
-#define GL_TEXTURE_3D 0x806F
-#endif
-
-typedef struct _UnitState
-{
- unsigned int sampled:1;
- unsigned int combine_constant_used:1;
-} UnitState;
-
-typedef struct _GlslShaderState
-{
- int ref_count;
-
- GLuint gl_shader;
- GString *header, *source;
- UnitState *unit_state;
-
- /* Age of the user program that was current when the shader was
- generated. We need to keep track of this because if the user
- program changes then we may need to redecide whether to generate
- a shader at all */
- unsigned int user_program_age;
-} GlslShaderState;
-
-typedef struct _CoglPipelineFragendGlslPrivate
-{
- GlslShaderState *glsl_shader_state;
-} CoglPipelineFragendGlslPrivate;
-
-const CoglPipelineFragend _cogl_pipeline_glsl_backend;
-
-static GlslShaderState *
-glsl_shader_state_new (int n_layers)
-{
- GlslShaderState *state = g_slice_new0 (GlslShaderState);
-
- state->ref_count = 1;
- state->unit_state = g_new0 (UnitState, n_layers);
-
- return state;
-}
-
-static GlslShaderState *
-glsl_shader_state_ref (GlslShaderState *state)
-{
- state->ref_count++;
- return state;
-}
-
-void
-glsl_shader_state_unref (GlslShaderState *state)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (state->ref_count > 0);
-
- state->ref_count--;
- if (state->ref_count == 0)
- {
- if (state->gl_shader)
- GE( glDeleteShader (state->gl_shader) );
-
- g_free (state->unit_state);
-
- g_slice_free (GlslShaderState, state);
- }
-}
-
-static CoglPipelineFragendGlslPrivate *
-get_glsl_priv (CoglPipeline *pipeline)
-{
- if (!(pipeline->fragend_priv_set_mask & COGL_PIPELINE_FRAGEND_GLSL_MASK))
- return NULL;
-
- return pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_GLSL];
-}
-
-static void
-set_glsl_priv (CoglPipeline *pipeline, CoglPipelineFragendGlslPrivate *priv)
-{
- if (priv)
- {
- pipeline->fragend_privs[COGL_PIPELINE_FRAGEND_GLSL] = priv;
- pipeline->fragend_priv_set_mask |= COGL_PIPELINE_FRAGEND_GLSL_MASK;
- }
- else
- pipeline->fragend_priv_set_mask &= ~COGL_PIPELINE_FRAGEND_GLSL_MASK;
-}
-
-static GlslShaderState *
-get_glsl_shader_state (CoglPipeline *pipeline)
-{
- CoglPipelineFragendGlslPrivate *priv = get_glsl_priv (pipeline);
- if (!priv)
- return NULL;
- return priv->glsl_shader_state;
-}
-
-GLuint
-_cogl_pipeline_fragend_glsl_get_shader (CoglPipeline *pipeline)
-{
- GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline);
-
- if (glsl_shader_state)
- return glsl_shader_state->gl_shader;
- else
- return 0;
-}
-
-static void
-dirty_glsl_shader_state (CoglPipeline *pipeline)
-{
- CoglPipelineFragendGlslPrivate *priv;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- priv = get_glsl_priv (pipeline);
- if (!priv)
- return;
-
- if (priv->glsl_shader_state)
- {
- glsl_shader_state_unref (priv->glsl_shader_state);
- priv->glsl_shader_state = NULL;
- }
-}
-
-static gboolean
-_cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs)
-{
- CoglPipelineFragendGlslPrivate *priv;
- CoglPipeline *authority;
- CoglPipelineFragendGlslPrivate *authority_priv;
- CoglProgram *user_program;
- int i;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
- return FALSE;
-
- user_program = cogl_pipeline_get_user_program (pipeline);
-
- /* If the user fragment shader isn't GLSL then we should let
- another backend handle it */
- if (user_program &&
- _cogl_program_has_fragment_shader (user_program) &&
- _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
- return FALSE;
-
- /* Now lookup our glsl backend private state (allocating if
- * necessary) */
- priv = get_glsl_priv (pipeline);
- if (!priv)
- {
- priv = g_slice_new0 (CoglPipelineFragendGlslPrivate);
- set_glsl_priv (pipeline, priv);
- }
-
- if (!priv->glsl_shader_state)
- {
- /* If we don't have an associated glsl shader yet then find the
- * glsl-authority (the oldest ancestor whose state will result in
- * the same shader being generated as for this pipeline).
- *
- * We always make sure to associate new shader with the
- * glsl-authority to maximize the chance that other pipelines can
- * share it.
- */
- authority = _cogl_pipeline_find_equivalent_parent
- (pipeline,
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN &
- ~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN);
-
- authority_priv = get_glsl_priv (authority);
- if (!authority_priv)
- {
- authority_priv = g_slice_new0 (CoglPipelineFragendGlslPrivate);
- set_glsl_priv (authority, authority_priv);
- }
-
- /* If we don't have an existing program associated with the
- * glsl-authority then start generating code for a new shader...
- */
- if (!authority_priv->glsl_shader_state)
- {
- GlslShaderState *glsl_shader_state =
- glsl_shader_state_new (n_layers);
- authority_priv->glsl_shader_state = glsl_shader_state;
- }
-
- /* If the pipeline isn't actually its own glsl-authority
- * then take a reference to the program state associated
- * with the glsl-authority... */
- if (authority != pipeline)
- priv->glsl_shader_state =
- glsl_shader_state_ref (authority_priv->glsl_shader_state);
- }
-
- if (priv->glsl_shader_state->gl_shader)
- {
- /* If we already have a valid GLSL shader then we don't need to
- generate a new one. However if there's a user program and it
- has changed since the last link then we do need a new shader */
- if (user_program == NULL ||
- (priv->glsl_shader_state->user_program_age == user_program->age))
- return TRUE;
-
- /* We need to recreate the shader so destroy the existing one */
- GE( glDeleteShader (priv->glsl_shader_state->gl_shader) );
- priv->glsl_shader_state->gl_shader = 0;
- }
-
- /* If we make it here then we have a glsl_shader_state struct
- without a gl_shader either because this is the first time we've
- encountered it or because the user program has changed */
-
- if (user_program)
- priv->glsl_shader_state->user_program_age = user_program->age;
-
- /* If the user program contains a fragment shader then we don't need
- to generate one */
- if (user_program &&
- _cogl_program_has_fragment_shader (user_program))
- return TRUE;
-
- /* We reuse two grow-only GStrings for code-gen. One string
- contains the uniform and attribute declarations while the
- other contains the main function. We need two strings
- because we need to dynamically declare attributes as the
- add_layer callback is invoked */
- g_string_set_size (ctx->codegen_header_buffer, 0);
- g_string_set_size (ctx->codegen_source_buffer, 0);
- priv->glsl_shader_state->header = ctx->codegen_header_buffer;
- priv->glsl_shader_state->source = ctx->codegen_source_buffer;
-
- g_string_append (priv->glsl_shader_state->source,
- "void\n"
- "main ()\n"
- "{\n");
-
- for (i = 0; i < n_layers; i++)
- {
- priv->glsl_shader_state->unit_state[i].sampled = FALSE;
- priv->glsl_shader_state->unit_state[i].combine_constant_used = FALSE;
- }
-
- return TRUE;
-}
-
-static void
-add_constant_lookup (GlslShaderState *glsl_shader_state,
- CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- const char *swizzle)
-{
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
- /* Create a sampler uniform for this layer if we haven't already */
- if (!glsl_shader_state->unit_state[unit_index].combine_constant_used)
- {
- g_string_append_printf (glsl_shader_state->header,
- "uniform vec4 _cogl_layer_constant_%i;\n",
- unit_index);
- glsl_shader_state->unit_state[unit_index].combine_constant_used = TRUE;
- }
-
- g_string_append_printf (glsl_shader_state->source,
- "_cogl_layer_constant_%i.%s",
- unit_index, swizzle);
-}
-
-static void
-add_texture_lookup (GlslShaderState *glsl_shader_state,
- CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- const char *swizzle)
-{
- CoglHandle texture;
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- const char *target_string, *tex_coord_swizzle;
-
- texture = _cogl_pipeline_layer_get_texture (layer);
-
- if (texture == COGL_INVALID_HANDLE)
- {
- target_string = "2D";
- tex_coord_swizzle = "st";
- }
- else
- {
- GLenum gl_target;
-
- cogl_texture_get_gl_texture (texture, NULL, &gl_target);
- switch (gl_target)
- {
-#ifndef HAVE_COGL_GLES2
- case GL_TEXTURE_1D:
- target_string = "1D";
- tex_coord_swizzle = "s";
- break;
-#endif
-
- case GL_TEXTURE_2D:
- target_string = "2D";
- tex_coord_swizzle = "st";
- break;
-
-#ifdef GL_ARB_texture_rectangle
- case GL_TEXTURE_RECTANGLE_ARB:
- target_string = "2DRect";
- tex_coord_swizzle = "st";
- break;
-#endif
-
- case GL_TEXTURE_3D:
- target_string = "3D";
- tex_coord_swizzle = "stp";
- break;
-
- default:
- g_assert_not_reached ();
- }
- }
-
- /* Create a sampler uniform for this layer if we haven't already */
- if (!glsl_shader_state->unit_state[unit_index].sampled)
- {
- g_string_append_printf (glsl_shader_state->header,
- "uniform sampler%s _cogl_sampler_%i;\n",
- target_string,
- unit_index);
- glsl_shader_state->unit_state[unit_index].sampled = TRUE;
- }
-
- g_string_append_printf (glsl_shader_state->source,
- "texture%s (_cogl_sampler_%i, ",
- target_string, unit_index);
-
- /* If point sprite coord generation is being used then divert to the
- built-in varying var for that instead of the texture
- coordinates. We don't want to do this under GL because in that
- case we will instead use glTexEnv(GL_COORD_REPLACE) to replace
- the texture coords with the point sprite coords. Although GL also
- supports the gl_PointCoord variable, it requires GLSL 1.2 which
- would mean we would have to declare the GLSL version and check
- for it */
-#ifdef HAVE_COGL_GLES2
- if (cogl_pipeline_get_layer_point_sprite_coords_enabled (pipeline,
- layer->index))
- g_string_append_printf (glsl_shader_state->source,
- "gl_PointCoord.%s",
- tex_coord_swizzle);
- else
-#endif
- g_string_append_printf (glsl_shader_state->source,
- "cogl_tex_coord_in[%d].%s",
- unit_index, tex_coord_swizzle);
-
- g_string_append_printf (glsl_shader_state->source, ").%s", swizzle);
-}
-
-typedef struct
-{
- int unit_index;
- CoglPipelineLayer *layer;
-} FindPipelineLayerData;
-
-static gboolean
-find_pipeline_layer_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- FindPipelineLayerData *data = user_data;
- int unit_index;
-
- unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
- if (unit_index == data->unit_index)
- {
- data->layer = layer;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-add_arg (GlslShaderState *glsl_shader_state,
- CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- CoglPipelineCombineSource src,
- CoglPipelineCombineOp operand,
- const char *swizzle)
-{
- GString *shader_source = glsl_shader_state->source;
- char alpha_swizzle[5] = "aaaa";
-
- g_string_append_c (shader_source, '(');
-
- if (operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR ||
- operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA)
- g_string_append_printf (shader_source,
- "vec4(1.0, 1.0, 1.0, 1.0).%s - ",
- swizzle);
-
- /* If the operand is reading from the alpha then replace the swizzle
- with the same number of copies of the alpha */
- if (operand == COGL_PIPELINE_COMBINE_OP_SRC_ALPHA ||
- operand == COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA)
- {
- alpha_swizzle[strlen (swizzle)] = '\0';
- swizzle = alpha_swizzle;
- }
-
- switch (src)
- {
- case COGL_PIPELINE_COMBINE_SOURCE_TEXTURE:
- add_texture_lookup (glsl_shader_state,
- pipeline,
- layer,
- swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_SOURCE_CONSTANT:
- add_constant_lookup (glsl_shader_state,
- pipeline,
- layer,
- swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS:
- if (_cogl_pipeline_layer_get_unit_index (layer) > 0)
- {
- g_string_append_printf (shader_source, "cogl_color_out.%s", swizzle);
- break;
- }
- /* flow through */
- case COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR:
- g_string_append_printf (shader_source, "cogl_color_in.%s", swizzle);
- break;
-
- default:
- if (src >= COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 &&
- src < COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 + 32)
- {
- FindPipelineLayerData data;
-
- data.unit_index = src - COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0;
- data.layer = layer;
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- find_pipeline_layer_cb,
- &data);
-
- add_texture_lookup (glsl_shader_state,
- pipeline,
- data.layer,
- swizzle);
- }
- break;
- }
-
- g_string_append_c (shader_source, ')');
-}
-
-static void
-append_masked_combine (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- const char *swizzle,
- CoglPipelineCombineFunc function,
- CoglPipelineCombineSource *src,
- CoglPipelineCombineOp *op)
-{
- GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline);
- GString *shader_source = glsl_shader_state->source;
-
- g_string_append_printf (glsl_shader_state->source,
- " cogl_color_out.%s = ", swizzle);
-
- switch (function)
- {
- case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- g_string_append (shader_source, " * ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_ADD:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- g_string_append (shader_source, " + ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- g_string_append (shader_source, " + ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], swizzle);
- g_string_append_printf (shader_source,
- " - vec4(0.5, 0.5, 0.5, 0.5).%s",
- swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- g_string_append (shader_source, " - ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], swizzle);
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], swizzle);
- g_string_append (shader_source, " * ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[2], op[2], swizzle);
- g_string_append (shader_source, " + ");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], swizzle);
- g_string_append_printf (shader_source,
- " * (vec4(1.0, 1.0, 1.0, 1.0).%s - ",
- swizzle);
- add_arg (glsl_shader_state, pipeline, layer,
- src[2], op[2], swizzle);
- g_string_append_c (shader_source, ')');
- break;
-
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
- g_string_append (shader_source, "vec4(4.0 * ((");
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], "r");
- g_string_append (shader_source, " - 0.5) * (");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], "r");
- g_string_append (shader_source, " - 0.5) + (");
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], "g");
- g_string_append (shader_source, " - 0.5) * (");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], "g");
- g_string_append (shader_source, " - 0.5) + (");
- add_arg (glsl_shader_state, pipeline, layer,
- src[0], op[0], "b");
- g_string_append (shader_source, " - 0.5) * (");
- add_arg (glsl_shader_state, pipeline, layer,
- src[1], op[1], "b");
- g_string_append_printf (shader_source, " - 0.5))).%s", swizzle);
- break;
- }
-
- g_string_append_printf (shader_source, ";\n");
-}
-
-static gboolean
-_cogl_pipeline_fragend_glsl_add_layer (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference)
-{
- GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline);
- CoglPipelineLayer *combine_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_COMBINE);
- CoglPipelineLayerBigState *big_state = combine_authority->big_state;
-
- if (!glsl_shader_state->source)
- return TRUE;
-
- if (!_cogl_pipeline_need_texture_combine_separate (combine_authority) ||
- /* GL_DOT3_RGBA Is a bit weird as a GL_COMBINE_RGB function
- * since if you use it, it overrides your ALPHA function...
- */
- big_state->texture_combine_rgb_func ==
- COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA)
- append_masked_combine (pipeline,
- layer,
- "rgba",
- big_state->texture_combine_rgb_func,
- big_state->texture_combine_rgb_src,
- big_state->texture_combine_rgb_op);
- else
- {
- append_masked_combine (pipeline,
- layer,
- "rgb",
- big_state->texture_combine_rgb_func,
- big_state->texture_combine_rgb_src,
- big_state->texture_combine_rgb_op);
- append_masked_combine (pipeline,
- layer,
- "a",
- big_state->texture_combine_alpha_func,
- big_state->texture_combine_alpha_src,
- big_state->texture_combine_alpha_op);
- }
-
- return TRUE;
-}
-
-gboolean
-_cogl_pipeline_fragend_glsl_passthrough (CoglPipeline *pipeline)
-{
- GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline);
-
- if (!glsl_shader_state->source)
- return TRUE;
-
- g_string_append (glsl_shader_state->source,
- " cogl_color_out = cogl_color_in;\n");
-
- return TRUE;
-}
-
-/* GLES2 doesn't have alpha testing so we need to implement it in the
- shader */
-
-#ifdef HAVE_COGL_GLES2
-
-static void
-add_alpha_test_snippet (CoglPipeline *pipeline,
- GlslShaderState *glsl_shader_state)
-{
- CoglPipelineAlphaFunc alpha_func;
-
- alpha_func = cogl_pipeline_get_alpha_test_function (pipeline);
-
- if (alpha_func == COGL_PIPELINE_ALPHA_FUNC_ALWAYS)
- /* Do nothing */
- return;
-
- if (alpha_func == COGL_PIPELINE_ALPHA_FUNC_NEVER)
- {
- /* Always discard the fragment */
- g_string_append (glsl_shader_state->source,
- " discard;\n");
- return;
- }
-
- /* For all of the other alpha functions we need a uniform for the
- reference */
-
- g_string_append (glsl_shader_state->header,
- "uniform float _cogl_alpha_test_ref;\n");
-
- g_string_append (glsl_shader_state->source,
- " if (cogl_color_out.a ");
-
- switch (alpha_func)
- {
- case COGL_PIPELINE_ALPHA_FUNC_LESS:
- g_string_append (glsl_shader_state->source, ">=");
- break;
- case COGL_PIPELINE_ALPHA_FUNC_EQUAL:
- g_string_append (glsl_shader_state->source, "!=");
- break;
- case COGL_PIPELINE_ALPHA_FUNC_LEQUAL:
- g_string_append (glsl_shader_state->source, ">");
- break;
- case COGL_PIPELINE_ALPHA_FUNC_GREATER:
- g_string_append (glsl_shader_state->source, "<=");
- break;
- case COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL:
- g_string_append (glsl_shader_state->source, "==");
- break;
- case COGL_PIPELINE_ALPHA_FUNC_GEQUAL:
- g_string_append (glsl_shader_state->source, "< ");
- break;
-
- case COGL_PIPELINE_ALPHA_FUNC_ALWAYS:
- case COGL_PIPELINE_ALPHA_FUNC_NEVER:
- g_assert_not_reached ();
- break;
- }
-
- g_string_append (glsl_shader_state->source,
- " _cogl_alpha_test_ref)\n discard;\n");
-}
-
-#endif /* HAVE_COGL_GLES2 */
-
-gboolean
-_cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference)
-{
- GlslShaderState *glsl_shader_state = get_glsl_shader_state (pipeline);
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (glsl_shader_state->source)
- {
- const char *source_strings[2];
- GLint lengths[2];
- GLint compile_status;
- GLuint shader;
- int n_tex_coord_attribs = 0;
- int i, n_layers;
-
- COGL_STATIC_COUNTER (fragend_glsl_compile_counter,
- "glsl fragment compile counter",
- "Increments each time a new GLSL "
- "fragment shader is compiled",
- 0 /* no application private data */);
- COGL_COUNTER_INC (_cogl_uprof_context, fragend_glsl_compile_counter);
-
-#ifdef HAVE_COGL_GLES2
- add_alpha_test_snippet (pipeline, glsl_shader_state);
-#endif
-
- g_string_append (glsl_shader_state->source, "}\n");
-
- GE_RET( shader, glCreateShader (GL_FRAGMENT_SHADER) );
-
- lengths[0] = glsl_shader_state->header->len;
- source_strings[0] = glsl_shader_state->header->str;
- lengths[1] = glsl_shader_state->source->len;
- source_strings[1] = glsl_shader_state->source->str;
-
- /* Find the highest texture unit that is sampled to pass as the
- number of texture coordinate attributes */
- n_layers = cogl_pipeline_get_n_layers (pipeline);
- for (i = 0; i < n_layers; i++)
- if (glsl_shader_state->unit_state[i].sampled)
- n_tex_coord_attribs = i + 1;
-
- _cogl_shader_set_source_with_boilerplate (shader, GL_FRAGMENT_SHADER,
- n_tex_coord_attribs,
- 2, /* count */
- source_strings, lengths);
-
- GE( glCompileShader (shader) );
- GE( glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) );
-
- if (!compile_status)
- {
- GLint len = 0;
- char *shader_log;
-
- GE( glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) );
- shader_log = g_alloca (len);
- GE( glGetShaderInfoLog (shader, len, &len, shader_log) );
- g_warning ("Shader compilation failed:\n%s", shader_log);
- }
-
- glsl_shader_state->header = NULL;
- glsl_shader_state->source = NULL;
- glsl_shader_state->gl_shader = shader;
- }
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_fragend_glsl_pre_change_notify (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color)
-{
- if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
- dirty_glsl_shader_state (pipeline);
-}
-
-/* NB: layers are considered immutable once they have any dependants
- * so although multiple pipelines can end up depending on a single
- * static layer, we can guarantee that if a layer is being *changed*
- * then it can only have one pipeline depending on it.
- *
- * XXX: Don't forget this is *pre* change, we can't read the new value
- * yet!
- */
-static void
-_cogl_pipeline_fragend_glsl_layer_pre_change_notify (
- CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- CoglPipelineFragendGlslPrivate *priv;
-
- priv = get_glsl_priv (owner);
- if (!priv)
- return;
-
- if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
- {
- dirty_glsl_shader_state (owner);
- return;
- }
-
- /* TODO: we could be saving snippets of texture combine code along
- * with each layer and then when a layer changes we would just free
- * the snippet. */
-}
-
-static void
-_cogl_pipeline_fragend_glsl_free_priv (CoglPipeline *pipeline)
-{
- CoglPipelineFragendGlslPrivate *priv = get_glsl_priv (pipeline);
- if (priv)
- {
- if (priv->glsl_shader_state)
- glsl_shader_state_unref (priv->glsl_shader_state);
- g_slice_free (CoglPipelineFragendGlslPrivate, priv);
- set_glsl_priv (pipeline, NULL);
- }
-}
-
-const CoglPipelineFragend _cogl_pipeline_glsl_fragend =
-{
- _cogl_pipeline_fragend_glsl_start,
- _cogl_pipeline_fragend_glsl_add_layer,
- _cogl_pipeline_fragend_glsl_passthrough,
- _cogl_pipeline_fragend_glsl_end,
- _cogl_pipeline_fragend_glsl_pre_change_notify,
- NULL, /* pipeline_set_parent_notify */
- _cogl_pipeline_fragend_glsl_layer_pre_change_notify,
- _cogl_pipeline_fragend_glsl_free_priv,
-};
-
-#endif /* COGL_PIPELINE_FRAGEND_GLSL */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_OPENGL_PRIVATE_H
-#define __COGL_PIPELINE_OPENGL_PRIVATE_H
-
-#include "cogl.h"
-
-#include "cogl-pipeline-private.h"
-#include "cogl-matrix-stack.h"
-
-/*
- * cogl-pipeline.c owns the GPU's texture unit state so we have some
- * private structures for describing the current state of a texture
- * unit that we track in a per context array (ctx->texture_units) that
- * grows according to the largest texture unit used so far...
- *
- * Roughly speaking the members in this structure are of two kinds:
- * either they are a low level reflection of the state we send to
- * OpenGL or they are for high level meta data assoicated with the
- * texture unit when flushing CoglPipelineLayers that is typically
- * used to optimize subsequent re-flushing of the same layer.
- *
- * The low level members are at the top, and the high level members
- * start with the .layer member.
- */
-typedef struct _CoglTextureUnit
-{
- /* The base 0 texture unit index which can be used with
- * glActiveTexture () */
- int index;
-
- /* The GL target currently glEnabled or 0 if nothing is
- * enabled. This is only used by the fixed pipeline fragend */
- GLenum enabled_gl_target;
-
- /* The raw GL texture object name for which we called glBindTexture when
- * we flushed the last layer. (NB: The CoglTexture associated
- * with a layer may represent more than one GL texture) */
- GLuint gl_texture;
- /* The target of the GL texture object. This is just used so that we
- * can quickly determine the intended target to flush when
- * dirty_gl_texture == TRUE */
- GLenum gl_target;
-
- /* Foreign textures are those not created or deleted by Cogl. If we ever
- * call glBindTexture for a foreign texture then the next time we are
- * asked to glBindTexture we can't try and optimize a redundant state
- * change because we don't know if the original texture name was deleted
- * and now we are being asked to bind a recycled name. */
- gboolean is_foreign;
-
- /* We have many components in Cogl that need to temporarily bind arbitrary
- * textures e.g. to query texture object parameters and since we don't
- * want that to result in too much redundant reflushing of layer state
- * when all that's needed is to re-bind the layer's gl_texture we use this
- * to track when the unit->gl_texture state is out of sync with the GL
- * texture object really bound too (GL_TEXTURE0+unit->index).
- *
- * XXX: as a further optimization cogl-pipeline.c uses a convention
- * of always using texture unit 1 for these transient bindings so we
- * can assume this is only ever TRUE for unit 1.
- */
- gboolean dirty_gl_texture;
-
- /* A matrix stack giving us the means to associate a texture
- * transform matrix with the texture unit. */
- CoglMatrixStack *matrix_stack;
-
- /*
- * Higher level layer state associated with the unit...
- */
-
- /* The CoglPipelineLayer whos state was flushed to update this
- * texture unit last.
- *
- * This will be set to NULL if the layer is modified or freed which
- * means when we come to flush a layer; if this pointer is still
- * valid and == to the layer being flushed we don't need to update
- * any texture unit state. */
- CoglPipelineLayer *layer;
-
- /* To help minimize the state changes required we track the
- * difference flags associated with the layer whos state was last
- * flushed to update this texture unit.
- *
- * Note: we track this explicitly because .layer may get invalidated
- * if that layer is modified or deleted. Even if the layer is
- * invalidated though these flags can be used to optimize the state
- * flush of the next layer
- */
- unsigned long layer_changes_since_flush;
-
- /* Whenever a CoglTexture's internal GL texture storage changes
- * cogl-pipeline.c is notified with a call to
- * _cogl_pipeline_texture_storage_change_notify which inturn sets
- * this to TRUE for each texture unit that it is currently bound
- * too. When we later come to flush some pipeline state then we will
- * always check this to potentially force an update of the texture
- * state even if the pipeline hasn't changed. */
- gboolean texture_storage_changed;
-
-} CoglTextureUnit;
-
-CoglTextureUnit *
-_cogl_get_texture_unit (int index_);
-
-void
-_cogl_destroy_texture_units (void);
-
-void
-_cogl_set_active_texture_unit (int unit_index);
-
-void
-_cogl_bind_gl_texture_transient (GLenum gl_target,
- GLuint gl_texture,
- gboolean is_foreign);
-
-void
-_cogl_delete_gl_texture (GLuint gl_texture);
-
-void
-_cogl_gl_use_program_wrapper (CoglHandle program);
-
-void
-_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
- gboolean skip_gl_state,
- int n_tex_coord_attribs);
-
-#endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-#include "cogl-debug.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-context-private.h"
-#include "cogl-texture-private.h"
-
-/* This is needed to set the color attribute on GLES2 */
-#ifdef HAVE_COGL_GLES2
-#include "cogl-pipeline-progend-glsl-private.h"
-#endif
-
-#include <glib.h>
-#include <string.h>
-
-/*
- * GL/GLES compatability defines for pipeline thingies:
- */
-
-#ifdef HAVE_COGL_GL
-#define glActiveTexture ctx->drv.pf_glActiveTexture
-#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
-#define glBlendFuncSeparate ctx->drv.pf_glBlendFuncSeparate
-#define glBlendEquation ctx->drv.pf_glBlendEquation
-#define glBlendColor ctx->drv.pf_glBlendColor
-#define glBlendEquationSeparate ctx->drv.pf_glBlendEquationSeparate
-
-#define glProgramString ctx->drv.pf_glProgramString
-#define glBindProgram ctx->drv.pf_glBindProgram
-#define glDeletePrograms ctx->drv.pf_glDeletePrograms
-#define glGenPrograms ctx->drv.pf_glGenPrograms
-#define glProgramLocalParameter4fv ctx->drv.pf_glProgramLocalParameter4fv
-#define glUseProgram ctx->drv.pf_glUseProgram
-#endif
-
-/* These aren't defined in the GLES headers */
-#ifndef GL_POINT_SPRITE
-#define GL_POINT_SPRITE 0x8861
-#endif
-#ifndef GL_COORD_REPLACE
-#define GL_COORD_REPLACE 0x8862
-#endif
-#ifndef GL_CLAMP_TO_BORDER
-#define GL_CLAMP_TO_BORDER 0x812d
-#endif
-
-
-static void
-texture_unit_init (CoglTextureUnit *unit, int index_)
-{
- unit->index = index_;
- unit->enabled_gl_target = 0;
- unit->gl_texture = 0;
- unit->gl_target = 0;
- unit->is_foreign = FALSE;
- unit->dirty_gl_texture = FALSE;
- unit->matrix_stack = _cogl_matrix_stack_new ();
-
- unit->layer = NULL;
- unit->layer_changes_since_flush = 0;
- unit->texture_storage_changed = FALSE;
-}
-
-static void
-texture_unit_free (CoglTextureUnit *unit)
-{
- if (unit->layer)
- cogl_object_unref (unit->layer);
- cogl_object_unref (unit->matrix_stack);
-}
-
-CoglTextureUnit *
-_cogl_get_texture_unit (int index_)
-{
- _COGL_GET_CONTEXT (ctx, NULL);
-
- if (ctx->texture_units->len < (index_ + 1))
- {
- int i;
- int prev_len = ctx->texture_units->len;
- ctx->texture_units = g_array_set_size (ctx->texture_units, index_ + 1);
- for (i = prev_len; i <= index_; i++)
- {
- CoglTextureUnit *unit =
- &g_array_index (ctx->texture_units, CoglTextureUnit, i);
-
- texture_unit_init (unit, i);
- }
- }
-
- return &g_array_index (ctx->texture_units, CoglTextureUnit, index_);
-}
-
-void
-_cogl_destroy_texture_units (void)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (i = 0; i < ctx->texture_units->len; i++)
- {
- CoglTextureUnit *unit =
- &g_array_index (ctx->texture_units, CoglTextureUnit, i);
- texture_unit_free (unit);
- }
- g_array_free (ctx->texture_units, TRUE);
-}
-
-void
-_cogl_set_active_texture_unit (int unit_index)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->active_texture_unit != unit_index)
- {
- GE (glActiveTexture (GL_TEXTURE0 + unit_index));
- ctx->active_texture_unit = unit_index;
- }
-}
-
-/* Note: _cogl_bind_gl_texture_transient conceptually has slightly
- * different semantics to OpenGL's glBindTexture because Cogl never
- * cares about tracking multiple textures bound to different targets
- * on the same texture unit.
- *
- * glBindTexture lets you bind multiple textures to a single texture
- * unit if they are bound to different targets. So it does something
- * like:
- * unit->current_texture[target] = texture;
- *
- * Cogl only lets you associate one texture with the currently active
- * texture unit, so the target is basically a redundant parameter
- * that's implicitly set on that texture.
- *
- * Technically this is just a thin wrapper around glBindTexture so
- * actually it does have the GL semantics but it seems worth
- * mentioning the conceptual difference in case anyone wonders why we
- * don't associate the gl_texture with a gl_target in the
- * CoglTextureUnit.
- */
-void
-_cogl_bind_gl_texture_transient (GLenum gl_target,
- GLuint gl_texture,
- gboolean is_foreign)
-{
- CoglTextureUnit *unit;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* We choose to always make texture unit 1 active for transient
- * binds so that in the common case where multitexturing isn't used
- * we can simply ignore the state of this texture unit. Notably we
- * didn't use a large texture unit (.e.g. (GL_MAX_TEXTURE_UNITS - 1)
- * in case the driver doesn't have a sparse data structure for
- * texture units.
- */
- _cogl_set_active_texture_unit (1);
- unit = _cogl_get_texture_unit (1);
-
- /* NB: If we have previously bound a foreign texture to this texture
- * unit we don't know if that texture has since been deleted and we
- * are seeing the texture name recycled */
- if (unit->gl_texture == gl_texture &&
- !unit->dirty_gl_texture &&
- !unit->is_foreign)
- return;
-
- GE (glBindTexture (gl_target, gl_texture));
-
- unit->dirty_gl_texture = TRUE;
- unit->is_foreign = is_foreign;
-}
-
-void
-_cogl_delete_gl_texture (GLuint gl_texture)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (i = 0; i < ctx->texture_units->len; i++)
- {
- CoglTextureUnit *unit =
- &g_array_index (ctx->texture_units, CoglTextureUnit, i);
-
- if (unit->gl_texture == gl_texture)
- {
- unit->gl_texture = 0;
- unit->gl_target = 0;
- unit->dirty_gl_texture = FALSE;
- }
- }
-
- GE (glDeleteTextures (1, &gl_texture));
-}
-
-/* Whenever the underlying GL texture storage of a CoglTexture is
- * changed (e.g. due to migration out of a texture atlas) then we are
- * notified. This lets us ensure that we reflush that texture's state
- * if it is reused again with the same texture unit.
- */
-void
-_cogl_pipeline_texture_storage_change_notify (CoglHandle texture)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (i = 0; i < ctx->texture_units->len; i++)
- {
- CoglTextureUnit *unit =
- &g_array_index (ctx->texture_units, CoglTextureUnit, i);
-
- if (unit->layer &&
- _cogl_pipeline_layer_get_texture (unit->layer) == texture)
- unit->texture_storage_changed = TRUE;
-
- /* NB: the texture may be bound to multiple texture units so
- * we continue to check the rest */
- }
-}
-
-static void
-set_glsl_program (GLuint gl_program)
-{
-#ifdef HAVE_COGL_GLES
-
- g_return_if_reached ();
-
-#else /* HAVE_COGL_GLES */
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->current_gl_program != gl_program)
- {
- GLenum gl_error;
-
- while ((gl_error = glGetError ()) != GL_NO_ERROR)
- ;
- glUseProgram (gl_program);
- if (glGetError () == GL_NO_ERROR)
- ctx->current_gl_program = gl_program;
- else
- {
- GE( glUseProgram (0) );
- ctx->current_gl_program = 0;
- }
- }
-
-#endif /* HAVE_COGL_GLES */
-}
-
-void
-_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If we're changing program type... */
- if (type != ctx->current_fragment_program_type)
- {
- /* ... disable the old type */
- switch (ctx->current_fragment_program_type)
- {
- case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
- /* If the program contains a vertex shader then we shouldn't
- disable it */
- if (ctx->current_vertex_program_type !=
- COGL_PIPELINE_PROGRAM_TYPE_GLSL)
- set_glsl_program (0);
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
-#ifdef HAVE_COGL_GL
- GE( glDisable (GL_FRAGMENT_PROGRAM_ARB) );
-#endif
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
- /* don't need to to anything */
- break;
- }
-
- /* ... and enable the new type */
- switch (type)
- {
- case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
-#ifdef HAVE_COGL_GL
- GE( glEnable (GL_FRAGMENT_PROGRAM_ARB) );
-#endif
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
- case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
- /* don't need to to anything */
- break;
- }
- }
-
- if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL)
- {
-#ifdef COGL_PIPELINE_FRAGEND_GLSL
- set_glsl_program (gl_program);
-
-#else
-
- g_warning ("Unexpected use of GLSL fragend!");
-
-#endif /* COGL_PIPELINE_FRAGEND_GLSL */
- }
-#ifndef COGL_PIPELINE_FRAGEND_ARBFP
- else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
- g_warning ("Unexpected use of ARBFP fragend!");
-#endif /* COGL_PIPELINE_FRAGEND_ARBFP */
-
- ctx->current_fragment_program_type = type;
-}
-
-void
-_cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If we're changing program type... */
- if (type != ctx->current_vertex_program_type)
- {
- /* ... disable the old type */
- switch (ctx->current_vertex_program_type)
- {
- case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
- /* If the program contains a fragment shader then we shouldn't
- disable it */
- if (ctx->current_fragment_program_type !=
- COGL_PIPELINE_PROGRAM_TYPE_GLSL)
- set_glsl_program (0);
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
- /* It doesn't make sense to enable ARBfp for the vertex program */
- g_assert_not_reached ();
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
- /* don't need to to anything */
- break;
- }
-
- /* ... and enable the new type */
- switch (type)
- {
- case COGL_PIPELINE_PROGRAM_TYPE_ARBFP:
- /* It doesn't make sense to enable ARBfp for the vertex program */
- g_assert_not_reached ();
- break;
-
- case COGL_PIPELINE_PROGRAM_TYPE_GLSL:
- case COGL_PIPELINE_PROGRAM_TYPE_FIXED:
- /* don't need to to anything */
- break;
- }
- }
-
- if (type == COGL_PIPELINE_PROGRAM_TYPE_GLSL)
- {
-#ifdef COGL_PIPELINE_VERTEND_GLSL
- set_glsl_program (gl_program);
-
-#else
-
- g_warning ("Unexpected use of GLSL vertend!");
-
-#endif /* COGL_PIPELINE_VERTEND_GLSL */
- }
-#ifndef COGL_PIPELINE_VERTEND_ARBFP
- else if (type == COGL_PIPELINE_PROGRAM_TYPE_ARBFP)
- g_warning ("Unexpected use of ARBFP vertend!");
-#endif /* COGL_PIPELINE_VERTEND_ARBFP */
-
- ctx->current_vertex_program_type = type;
-}
-
-#if defined (COGL_PIPELINE_FRAGEND_GLSL) || \
- defined (COGL_PIPELINE_FRAGEND_ARBFP)
-int
-_cogl_get_max_texture_image_units (void)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- /* This function is called quite often so we cache the value to
- avoid too many GL calls */
- if (G_UNLIKELY (ctx->max_texture_image_units == -1))
- {
- ctx->max_texture_image_units = 1;
- GE (glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS,
- &ctx->max_texture_image_units));
- }
-
- return ctx->max_texture_image_units;
-}
-#endif
-
-#ifndef HAVE_COGL_GLES
-
-static gboolean
-blend_factor_uses_constant (GLenum blend_factor)
-{
- return (blend_factor == GL_CONSTANT_COLOR ||
- blend_factor == GL_ONE_MINUS_CONSTANT_COLOR ||
- blend_factor == GL_CONSTANT_ALPHA ||
- blend_factor == GL_ONE_MINUS_CONSTANT_ALPHA);
-}
-
-#endif
-
-static void
-flush_depth_state (CoglPipelineDepthState *depth_state)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->depth_test_function_cache != depth_state->depth_test_function)
- {
- GE (glDepthFunc (depth_state->depth_test_function));
- ctx->depth_test_function_cache = depth_state->depth_test_function;
- }
-
- if (ctx->depth_writing_enabled_cache != depth_state->depth_writing_enabled)
- {
- GE (glDepthMask (depth_state->depth_writing_enabled ?
- GL_TRUE : GL_FALSE));
- ctx->depth_writing_enabled_cache = depth_state->depth_writing_enabled;
- }
-
-#ifndef COGL_HAS_GLES
- if (ctx->depth_range_near_cache != depth_state->depth_range_near ||
- ctx->depth_range_far_cache != depth_state->depth_range_far)
- {
-#ifdef COGL_HAS_GLES2
- GE (glDepthRangef (depth_state->depth_range_near,
- depth_state->depth_range_far));
-#else
- GE (glDepthRange (depth_state->depth_range_near,
- depth_state->depth_range_far));
-#endif
- ctx->depth_range_near_cache = depth_state->depth_range_near;
- ctx->depth_range_far_cache = depth_state->depth_range_far;
- }
-#endif /* COGL_HAS_GLES */
-}
-
-static void
-_cogl_pipeline_flush_color_blend_alpha_depth_state (
- CoglPipeline *pipeline,
- unsigned long pipelines_difference,
- gboolean skip_gl_color)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* On GLES2 we'll flush the color later */
-#ifndef HAVE_COGL_GLES2
- if (!skip_gl_color)
- {
- if ((pipelines_difference & COGL_PIPELINE_STATE_COLOR) ||
- /* Assume if we were previously told to skip the color, then
- * the current color needs updating... */
- ctx->current_pipeline_skip_gl_color)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
- GE (glColor4ub (cogl_color_get_red_byte (&authority->color),
- cogl_color_get_green_byte (&authority->color),
- cogl_color_get_blue_byte (&authority->color),
- cogl_color_get_alpha_byte (&authority->color)));
- }
- }
-#endif
-
- if (pipelines_difference & COGL_PIPELINE_STATE_BLEND)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND);
- CoglPipelineBlendState *blend_state =
- &authority->big_state->blend_state;
-
-#if defined (HAVE_COGL_GLES2)
- gboolean have_blend_equation_seperate = TRUE;
- gboolean have_blend_func_separate = TRUE;
-#elif defined (HAVE_COGL_GL)
- gboolean have_blend_equation_seperate = FALSE;
- gboolean have_blend_func_separate = FALSE;
- if (ctx->drv.pf_glBlendEquationSeparate) /* Only GL 2.0 + */
- have_blend_equation_seperate = TRUE;
- if (ctx->drv.pf_glBlendFuncSeparate) /* Only GL 1.4 + */
- have_blend_func_separate = TRUE;
-#endif
-
-#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */
- if (blend_factor_uses_constant (blend_state->blend_src_factor_rgb) ||
- blend_factor_uses_constant (blend_state->blend_src_factor_alpha) ||
- blend_factor_uses_constant (blend_state->blend_dst_factor_rgb) ||
- blend_factor_uses_constant (blend_state->blend_dst_factor_alpha))
- {
- float red =
- cogl_color_get_red_float (&blend_state->blend_constant);
- float green =
- cogl_color_get_green_float (&blend_state->blend_constant);
- float blue =
- cogl_color_get_blue_float (&blend_state->blend_constant);
- float alpha =
- cogl_color_get_alpha_float (&blend_state->blend_constant);
-
-
- GE (glBlendColor (red, green, blue, alpha));
- }
-
- if (have_blend_equation_seperate &&
- blend_state->blend_equation_rgb != blend_state->blend_equation_alpha)
- GE (glBlendEquationSeparate (blend_state->blend_equation_rgb,
- blend_state->blend_equation_alpha));
- else
- GE (glBlendEquation (blend_state->blend_equation_rgb));
-
- if (have_blend_func_separate &&
- (blend_state->blend_src_factor_rgb != blend_state->blend_src_factor_alpha ||
- (blend_state->blend_src_factor_rgb !=
- blend_state->blend_src_factor_alpha)))
- GE (glBlendFuncSeparate (blend_state->blend_src_factor_rgb,
- blend_state->blend_dst_factor_rgb,
- blend_state->blend_src_factor_alpha,
- blend_state->blend_dst_factor_alpha));
- else
-#endif
- GE (glBlendFunc (blend_state->blend_src_factor_rgb,
- blend_state->blend_dst_factor_rgb));
- }
-
-#ifndef HAVE_COGL_GLES2
-
- /* Under GLES2 the alpha function is implemented as part of the
- fragment shader */
- if (pipelines_difference & (COGL_PIPELINE_STATE_ALPHA_FUNC |
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE))
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);
- CoglPipelineAlphaFuncState *alpha_state =
- &authority->big_state->alpha_state;
-
- /* NB: Currently the Cogl defines are compatible with the GL ones: */
- GE (glAlphaFunc (alpha_state->alpha_func,
- alpha_state->alpha_func_reference));
- }
-
- /* Under GLES2 the lighting parameters are implemented as uniforms
- in the progend */
- if (pipelines_difference & COGL_PIPELINE_STATE_LIGHTING)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
- CoglPipelineLightingState *lighting_state =
- &authority->big_state->lighting_state;
-
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT,
- lighting_state->ambient));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE,
- lighting_state->diffuse));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR,
- lighting_state->specular));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_EMISSION,
- lighting_state->emission));
- GE (glMaterialfv (GL_FRONT_AND_BACK, GL_SHININESS,
- &lighting_state->shininess));
- }
-
-#endif /* HAVE_COGL_GLES2 */
-
- if (pipelines_difference & COGL_PIPELINE_STATE_DEPTH)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
- CoglPipelineDepthState *depth_state = &authority->big_state->depth_state;
-
- if (depth_state->depth_test_enabled)
- {
- if (ctx->depth_test_enabled_cache != TRUE)
- {
- GE (glEnable (GL_DEPTH_TEST));
- ctx->depth_test_enabled_cache = depth_state->depth_test_enabled;
- }
- flush_depth_state (depth_state);
- }
- else if (ctx->depth_test_enabled_cache != FALSE)
- {
- GE (glDisable (GL_DEPTH_TEST));
- ctx->depth_test_enabled_cache = depth_state->depth_test_enabled;
- }
- }
-
- if (pipeline->real_blend_enable != ctx->gl_blend_enable_cache)
- {
- if (pipeline->real_blend_enable)
- GE (glEnable (GL_BLEND));
- else
- GE (glDisable (GL_BLEND));
- /* XXX: we shouldn't update any other blend state if blending
- * is disabled! */
- ctx->gl_blend_enable_cache = pipeline->real_blend_enable;
- }
-}
-
-static int
-get_max_activateable_texture_units (void)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- if (G_UNLIKELY (ctx->max_activateable_texture_units == -1))
- {
-#if defined (HAVE_COGL_GL)
- GLint max_tex_coords;
- GLint max_combined_tex_units;
- GE (glGetIntegerv (GL_MAX_TEXTURE_COORDS, &max_tex_coords));
- GE (glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
- &max_combined_tex_units));
- ctx->max_activateable_texture_units =
- MAX (max_tex_coords - 1, max_combined_tex_units);
-#elif defined (HAVE_COGL_GLES2)
- GLint max_vertex_attribs;
- GLint max_combined_tex_units;
- GE (glGetIntegerv (GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs));
- GE (glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
- &max_combined_tex_units));
- /* Two of the vertex attribs need to be used for the position
- and color */
- ctx->max_activateable_texture_units =
- MAX (max_vertex_attribs - 2, max_combined_tex_units);
-#else
- GE (glGetIntegerv (GL_MAX_TEXTURE_UNITS,
- &ctx->max_activateable_texture_units));
-#endif
- }
-
- return ctx->max_activateable_texture_units;
-}
-
-typedef struct
-{
- int i;
- unsigned long *layer_differences;
-} CoglPipelineFlushLayerState;
-
-static gboolean
-flush_layers_common_gl_state_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglPipelineFlushLayerState *flush_state = user_data;
- int unit_index = flush_state->i;
- CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
- unsigned long layers_difference =
- flush_state->layer_differences[unit_index];
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* There may not be enough texture units so we can bail out if
- * that's the case...
- */
- if (G_UNLIKELY (unit_index >= get_max_activateable_texture_units ()))
- {
- static gboolean shown_warning = FALSE;
-
- if (!shown_warning)
- {
- g_warning ("Your hardware does not have enough texture units"
- "to handle this many texture layers");
- shown_warning = TRUE;
- }
- return FALSE;
- }
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
- {
- unsigned long state = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, state);
- CoglHandle texture;
- GLuint gl_texture;
- GLenum gl_target;
-
- texture = (authority->texture == COGL_INVALID_HANDLE ?
- ctx->default_gl_texture_2d_tex :
- authority->texture);
-
- cogl_texture_get_gl_texture (texture,
- &gl_texture,
- &gl_target);
-
- _cogl_set_active_texture_unit (unit_index);
-
- /* NB: There are several Cogl components and some code in
- * Clutter that will temporarily bind arbitrary GL textures to
- * query and modify texture object parameters. If you look at
- * _cogl_bind_gl_texture_transient() you can see we make sure
- * that such code always binds to texture unit 1 which means we
- * can't rely on the unit->gl_texture state if unit->index == 1.
- *
- * Because texture unit 1 is a bit special we actually defer any
- * necessary glBindTexture for it until the end of
- * _cogl_pipeline_flush_gl_state().
- *
- * NB: we get notified whenever glDeleteTextures is used (see
- * _cogl_delete_gl_texture()) where we invalidate
- * unit->gl_texture references to deleted textures so it's safe
- * to compare unit->gl_texture with gl_texture. (Without the
- * hook it would be possible to delete a GL texture and create a
- * new one with the same name and comparing unit->gl_texture and
- * gl_texture wouldn't detect that.)
- *
- * NB: for foreign textures we don't know how the deletion of
- * the GL texture objects correspond to the deletion of the
- * CoglTextures so if there was previously a foreign texture
- * associated with the texture unit then we can't assume that we
- * aren't seeing a recycled texture name so we have to bind.
- */
- if (unit->gl_texture != gl_texture || unit->is_foreign)
- {
- if (unit_index == 1)
- unit->dirty_gl_texture = TRUE;
- else
- GE (glBindTexture (gl_target, gl_texture));
- unit->gl_texture = gl_texture;
- unit->gl_target = gl_target;
- }
-
- unit->is_foreign = _cogl_texture_is_foreign (texture);
-
- /* The texture_storage_changed boolean indicates if the
- * CoglTexture's underlying GL texture storage has changed since
- * it was flushed to the texture unit. We've just flushed the
- * latest state so we can reset this. */
- unit->texture_storage_changed = FALSE;
- }
-
- /* Under GLES2 the fragment shader will use gl_PointCoord instead of
- replacing the texture coordinates */
-#ifndef HAVE_COGL_GLES2
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)
- {
- CoglPipelineState change = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, change);
- CoglPipelineLayerBigState *big_state = authority->big_state;
-
- _cogl_set_active_texture_unit (unit_index);
-
- GE (glTexEnvi (GL_POINT_SPRITE, GL_COORD_REPLACE,
- big_state->point_sprite_coords));
- }
-#endif /* HAVE_COGL_GLES2 */
-
- cogl_handle_ref (layer);
- if (unit->layer != COGL_INVALID_HANDLE)
- cogl_handle_unref (unit->layer);
-
- unit->layer = layer;
- unit->layer_changes_since_flush = 0;
-
- flush_state->i++;
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_flush_common_gl_state (CoglPipeline *pipeline,
- unsigned long pipelines_difference,
- unsigned long *layer_differences,
- gboolean skip_gl_color)
-{
- CoglPipelineFlushLayerState state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_pipeline_flush_color_blend_alpha_depth_state (pipeline,
- pipelines_difference,
- skip_gl_color);
-
- state.i = 0;
- state.layer_differences = layer_differences;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- flush_layers_common_gl_state_cb,
- &state);
-}
-
-/* Re-assert the layer's wrap modes on the given CoglTexture.
- *
- * Note: we don't simply forward the wrap modes to layer->texture
- * since the actual texture being used may have been overridden.
- */
-static void
-_cogl_pipeline_layer_forward_wrap_modes (CoglPipelineLayer *layer,
- CoglHandle texture)
-{
- CoglPipelineWrapModeInternal wrap_mode_s, wrap_mode_t, wrap_mode_p;
- GLenum gl_wrap_mode_s, gl_wrap_mode_t, gl_wrap_mode_p;
-
- if (texture == COGL_INVALID_HANDLE)
- return;
-
- _cogl_pipeline_layer_get_wrap_modes (layer,
- &wrap_mode_s,
- &wrap_mode_t,
- &wrap_mode_p);
-
- /* Update the wrap mode on the texture object. The texture backend
- should cache the value so that it will be a no-op if the object
- already has the same wrap mode set. The backend is best placed to
- do this because it knows how many of the coordinates will
- actually be used (ie, a 1D texture only cares about the 's'
- coordinate but a 3D texture would use all three). GL uses the
- wrap mode as part of the texture object state but we are
- pretending it's part of the per-layer environment state. This
- will break if the application tries to use different modes in
- different layers using the same texture. */
-
- if (wrap_mode_s == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
- gl_wrap_mode_s = GL_CLAMP_TO_EDGE;
- else
- gl_wrap_mode_s = wrap_mode_s;
-
- if (wrap_mode_t == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
- gl_wrap_mode_t = GL_CLAMP_TO_EDGE;
- else
- gl_wrap_mode_t = wrap_mode_t;
-
- if (wrap_mode_p == COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC)
- gl_wrap_mode_p = GL_CLAMP_TO_EDGE;
- else
- gl_wrap_mode_p = wrap_mode_p;
-
- _cogl_texture_set_wrap_mode_parameters (texture,
- gl_wrap_mode_s,
- gl_wrap_mode_t,
- gl_wrap_mode_p);
-}
-
-/* OpenGL associates the min/mag filters and repeat modes with the
- * texture object not the texture unit so we always have to re-assert
- * the filter and repeat modes whenever we use a texture since it may
- * be referenced by multiple pipelines with different modes.
- *
- * XXX: GL_ARB_sampler_objects fixes this in OpenGL so we should
- * eventually look at using this extension when available.
- */
-static void
-foreach_texture_unit_update_filter_and_wrap_modes (void)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (i = 0; i < ctx->texture_units->len; i++)
- {
- CoglTextureUnit *unit =
- &g_array_index (ctx->texture_units, CoglTextureUnit, i);
-
- if (unit->layer)
- {
- CoglHandle texture = _cogl_pipeline_layer_get_texture (unit->layer);
-
- if (texture != COGL_INVALID_HANDLE)
- {
- CoglPipelineFilter min;
- CoglPipelineFilter mag;
-
- _cogl_pipeline_layer_get_filters (unit->layer, &min, &mag);
- _cogl_texture_set_filters (texture, min, mag);
-
- _cogl_pipeline_layer_forward_wrap_modes (unit->layer, texture);
- }
- }
- }
-}
-
-typedef struct
-{
- int i;
- unsigned long *layer_differences;
-} CoglPipelineCompareLayersState;
-
-static gboolean
-compare_layer_differences_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglPipelineCompareLayersState *state = user_data;
- CoglTextureUnit *unit = _cogl_get_texture_unit (state->i);
-
- if (unit->layer == layer)
- state->layer_differences[state->i] = unit->layer_changes_since_flush;
- else if (unit->layer)
- {
- state->layer_differences[state->i] = unit->layer_changes_since_flush;
- state->layer_differences[state->i] |=
- _cogl_pipeline_layer_compare_differences (layer, unit->layer);
- }
- else
- state->layer_differences[state->i] = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
-
- /* XXX: There is always a possibility that a CoglTexture's
- * underlying GL texture storage has been changed since it was last
- * bound to a texture unit which is why we have a callback into
- * _cogl_pipeline_texture_storage_change_notify whenever a textures
- * underlying GL texture storage changes which will set the
- * unit->texture_intern_changed flag. If we see that's been set here
- * then we force an update of the texture state...
- */
- if (unit->texture_storage_changed)
- state->layer_differences[state->i] |=
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
-
- state->i++;
-
- return TRUE;
-}
-
-typedef struct
-{
- const CoglPipelineFragend *fragend;
- CoglPipeline *pipeline;
- unsigned long *layer_differences;
- gboolean error_adding_layer;
- gboolean added_layer;
-} CoglPipelineFragendAddLayerState;
-
-
-static gboolean
-fragend_add_layer_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- CoglPipelineFragendAddLayerState *state = user_data;
- const CoglPipelineFragend *fragend = state->fragend;
- CoglPipeline *pipeline = state->pipeline;
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* Either generate per layer code snippets or setup the
- * fixed function glTexEnv for each layer... */
- if (G_LIKELY (fragend->add_layer (pipeline,
- layer,
- state->layer_differences[unit_index])))
- state->added_layer = TRUE;
- else
- {
- state->error_adding_layer = TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-typedef struct
-{
- const CoglPipelineVertend *vertend;
- CoglPipeline *pipeline;
- unsigned long *layer_differences;
- gboolean error_adding_layer;
- gboolean added_layer;
-} CoglPipelineVertendAddLayerState;
-
-
-static gboolean
-vertend_add_layer_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- CoglPipelineVertendAddLayerState *state = user_data;
- const CoglPipelineVertend *vertend = state->vertend;
- CoglPipeline *pipeline = state->pipeline;
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* Either enerate per layer code snippets or setup the
- * fixed function matrix uniforms for each layer... */
- if (G_LIKELY (vertend->add_layer (pipeline,
- layer,
- state->layer_differences[unit_index])))
- state->added_layer = TRUE;
- else
- {
- state->error_adding_layer = TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-/*
- * _cogl_pipeline_flush_gl_state:
- *
- * Details of override options:
- * ->fallback_mask: is a bitmask of the pipeline layers that need to be
- * replaced with the default, fallback textures. The fallback textures are
- * fully transparent textures so they hopefully wont contribute to the
- * texture combining.
- *
- * The intention of fallbacks is to try and preserve
- * the number of layers the user is expecting so that texture coordinates
- * they gave will mostly still correspond to the textures they intended, and
- * have a fighting chance of looking close to their originally intended
- * result.
- *
- * ->disable_mask: is a bitmask of the pipeline layers that will simply have
- * texturing disabled. It's only really intended for disabling all layers
- * > X; i.e. we'd expect to see a contiguous run of 0 starting from the LSB
- * and at some point the remaining bits flip to 1. It might work to disable
- * arbitrary layers; though I'm not sure a.t.m how OpenGL would take to
- * that.
- *
- * The intention of the disable_mask is for emitting geometry when the user
- * hasn't supplied enough texture coordinates for all the layers and it's
- * not possible to auto generate default texture coordinates for those
- * layers.
- *
- * ->layer0_override_texture: forcibly tells us to bind this GL texture name for
- * layer 0 instead of plucking the gl_texture from the CoglTexture of layer
- * 0.
- *
- * The intention of this is for any primitives that supports sliced textures.
- * The code will can iterate each of the slices and re-flush the pipeline
- * forcing the GL texture of each slice in turn.
- *
- * ->wrap_mode_overrides: overrides the wrap modes set on each
- * layer. This is used to implement the automatic wrap mode.
- *
- * XXX: It might also help if we could specify a texture matrix for code
- * dealing with slicing that would be multiplied with the users own matrix.
- *
- * Normaly texture coords in the range [0, 1] refer to the extents of the
- * texture, but when your GL texture represents a slice of the real texture
- * (from the users POV) then a texture matrix would be a neat way of
- * transforming the mapping for each slice.
- *
- * Currently for textured rectangles we manually calculate the texture
- * coords for each slice based on the users given coords, but this solution
- * isn't ideal, and can't be used with CoglVertexBuffers.
- */
-void
-_cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
- gboolean skip_gl_color,
- int n_tex_coord_attribs)
-{
- unsigned long pipelines_difference;
- int n_layers;
- unsigned long *layer_differences;
- int i;
- CoglTextureUnit *unit1;
-
- COGL_STATIC_TIMER (pipeline_flush_timer,
- "Mainloop", /* parent */
- "Material Flush",
- "The time spent flushing material state",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- COGL_TIMER_START (_cogl_uprof_context, pipeline_flush_timer);
-
- if (ctx->current_pipeline == pipeline)
- {
- /* Bail out asap if we've been asked to re-flush the already current
- * pipeline and we can see the pipeline hasn't changed */
- if (ctx->current_pipeline_age == pipeline->age &&
- ctx->current_pipeline_skip_gl_color == skip_gl_color)
- goto done;
-
- pipelines_difference = ctx->current_pipeline_changes_since_flush;
- }
- else if (ctx->current_pipeline)
- {
- pipelines_difference = ctx->current_pipeline_changes_since_flush;
- pipelines_difference |=
- _cogl_pipeline_compare_differences (ctx->current_pipeline,
- pipeline);
- }
- else
- pipelines_difference = COGL_PIPELINE_STATE_ALL_SPARSE;
-
- /* Get a layer_differences mask for each layer to be flushed */
- n_layers = cogl_pipeline_get_n_layers (pipeline);
- if (n_layers)
- {
- CoglPipelineCompareLayersState state;
- layer_differences = g_alloca (sizeof (unsigned long *) * n_layers);
- memset (layer_differences, 0, sizeof (layer_differences));
- state.i = 0;
- state.layer_differences = layer_differences;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- compare_layer_differences_cb,
- &state);
- }
- else
- layer_differences = NULL;
-
- /* First flush everything that's the same regardless of which
- * pipeline backend is being used...
- *
- * 1) top level state:
- * glColor (or skip if a vertex attribute is being used for color)
- * blend state
- * alpha test state (except for GLES 2.0)
- *
- * 2) then foreach layer:
- * determine gl_target/gl_texture
- * bind texture
- *
- * Note: After _cogl_pipeline_flush_common_gl_state you can expect
- * all state of the layers corresponding texture unit to be
- * updated.
- */
- _cogl_pipeline_flush_common_gl_state (pipeline,
- pipelines_difference,
- layer_differences,
- skip_gl_color);
-
- /* Now flush the fragment processing state according to the current
- * fragment processing backend.
- *
- * Note: Some of the backends may not support the current pipeline
- * configuration and in that case it will report an error and we
- * will fallback to a different backend.
- *
- * NB: if pipeline->backend != COGL_PIPELINE_FRAGEND_UNDEFINED then
- * we have previously managed to successfully flush this pipeline
- * with the given backend so we will simply use that to avoid
- * fallback code paths.
- */
-
- if (pipeline->fragend == COGL_PIPELINE_FRAGEND_UNDEFINED)
- _cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
-
- for (i = pipeline->fragend;
- i < G_N_ELEMENTS (_cogl_pipeline_fragends);
- i++, _cogl_pipeline_set_fragend (pipeline, i))
- {
- const CoglPipelineFragend *fragend = _cogl_pipeline_fragends[i];
- CoglPipelineFragendAddLayerState state;
-
- /* E.g. For fragends generating code they can setup their
- * scratch buffers here... */
- if (G_UNLIKELY (!fragend->start (pipeline,
- n_layers,
- pipelines_difference,
- n_tex_coord_attribs)))
- continue;
-
- state.fragend = fragend;
- state.pipeline = pipeline;
- state.layer_differences = layer_differences;
- state.error_adding_layer = FALSE;
- state.added_layer = FALSE;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- fragend_add_layer_cb,
- &state);
-
- if (G_UNLIKELY (state.error_adding_layer))
- continue;
-
- if (!state.added_layer &&
- fragend->passthrough &&
- G_UNLIKELY (!fragend->passthrough (pipeline)))
- continue;
-
- /* For fragends generating code they may compile and link their
- * programs here, update any uniforms and tell OpenGL to use
- * that program.
- */
- if (G_UNLIKELY (!fragend->end (pipeline, pipelines_difference)))
- continue;
-
- break;
- }
-
- if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_fragends)))
- g_warning ("No usable pipeline fragment backend was found!");
-
- /* Now flush the vertex processing state according to the current
- * vertex processing backend.
- */
-
- if (pipeline->vertend == COGL_PIPELINE_VERTEND_UNDEFINED)
- _cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
-
- for (i = pipeline->vertend;
- i < G_N_ELEMENTS (_cogl_pipeline_vertends);
- i++, _cogl_pipeline_set_vertend (pipeline, i))
- {
- const CoglPipelineVertend *vertend = _cogl_pipeline_vertends[i];
- CoglPipelineVertendAddLayerState state;
-
- /* E.g. For vertends generating code they can setup their
- * scratch buffers here... */
- if (G_UNLIKELY (!vertend->start (pipeline,
- n_layers,
- pipelines_difference)))
- continue;
-
- state.vertend = vertend;
- state.pipeline = pipeline;
- state.layer_differences = layer_differences;
- state.error_adding_layer = FALSE;
- state.added_layer = FALSE;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- vertend_add_layer_cb,
- &state);
-
- if (G_UNLIKELY (state.error_adding_layer))
- continue;
-
- /* For vertends generating code they may compile and link their
- * programs here, update any uniforms and tell OpenGL to use
- * that program.
- */
- if (G_UNLIKELY (!vertend->end (pipeline, pipelines_difference)))
- continue;
-
- break;
- }
-
- if (G_UNLIKELY (i >= G_N_ELEMENTS (_cogl_pipeline_vertends)))
- g_warning ("No usable pipeline vertex backend was found!");
-
- for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
- if (_cogl_pipeline_progends[i]->end)
- _cogl_pipeline_progends[i]->end (pipeline, pipelines_difference,
- n_tex_coord_attribs);
-
- /* FIXME: This reference is actually resulting in lots of
- * copy-on-write reparenting because one-shot pipelines end up
- * living for longer than necessary and so any later modification of
- * the parent will cause a copy-on-write.
- *
- * XXX: The issue should largely go away when we switch to using
- * weak pipelines for overrides.
- */
- cogl_object_ref (pipeline);
- if (ctx->current_pipeline != NULL)
- cogl_object_unref (ctx->current_pipeline);
- ctx->current_pipeline = pipeline;
- ctx->current_pipeline_changes_since_flush = 0;
- ctx->current_pipeline_skip_gl_color = skip_gl_color;
- ctx->current_pipeline_age = pipeline->age;
-
-done:
-
- /* We can't assume the color will be retained between flushes on
- GLES2 because the generic attribute values are not stored as part
- of the program object so they could be overridden by any
- attribute changes in another program */
-#ifdef HAVE_COGL_GLES2
- if (!skip_gl_color)
- {
- int attribute;
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
-
- attribute = _cogl_pipeline_progend_glsl_get_color_attribute (pipeline);
- if (attribute != -1)
- GE (glVertexAttrib4f (attribute,
- cogl_color_get_red_float (&authority->color),
- cogl_color_get_green_float (&authority->color),
- cogl_color_get_blue_float (&authority->color),
- cogl_color_get_alpha_float (&authority->color)));
- }
-#endif
-
- /* Give any progends a chance to update any uniforms that might not
- depend on the material state. This is used on GLES2 to update the
- matrices */
- for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
- if (_cogl_pipeline_progends[i]->pre_paint)
- _cogl_pipeline_progends[i]->pre_paint (pipeline);
-
- /* Handle the fact that OpenGL associates texture filter and wrap
- * modes with the texture objects not the texture units... */
- foreach_texture_unit_update_filter_and_wrap_modes ();
-
- /* If this pipeline has more than one layer then we always need
- * to make sure we rebind the texture for unit 1.
- *
- * NB: various components of Cogl may temporarily bind arbitrary
- * textures to texture unit 1 so they can query and modify texture
- * object parameters. cogl-pipeline.c (See
- * _cogl_bind_gl_texture_transient)
- */
- unit1 = _cogl_get_texture_unit (1);
- if (cogl_pipeline_get_n_layers (pipeline) > 1 && unit1->dirty_gl_texture)
- {
- _cogl_set_active_texture_unit (1);
- GE (glBindTexture (unit1->gl_target, unit1->gl_texture));
- unit1->dirty_gl_texture = FALSE;
- }
-
- COGL_TIMER_STOP (_cogl_uprof_context, pipeline_flush_timer);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_PRIVATE_H
-#define __COGL_PIPELINE_PRIVATE_H
-
-#include "cogl.h"
-
-#include "cogl-pipeline.h"
-#include "cogl-matrix.h"
-#include "cogl-object-private.h"
-#include "cogl-profile.h"
-
-#include <glib.h>
-
-typedef struct _CoglPipelineLayer CoglPipelineLayer;
-#define COGL_PIPELINE_LAYER(OBJECT) ((CoglPipelineLayer *)OBJECT)
-
-#if defined (HAVE_COGL_GL)
-
-/* NB: pipeline->fragend is currently a 3bit unsigned int bitfield */
-#define COGL_PIPELINE_FRAGEND_ARBFP 0
-#define COGL_PIPELINE_FRAGEND_ARBFP_MASK (1L<<0)
-#define COGL_PIPELINE_FRAGEND_FIXED 1
-#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<1)
-#define COGL_PIPELINE_FRAGEND_GLSL 2
-#define COGL_PIPELINE_FRAGEND_GLSL_MASK (1L<<2)
-
-#define COGL_PIPELINE_N_FRAGENDS 3
-
-#elif defined (HAVE_COGL_GLES2)
-
-#define COGL_PIPELINE_FRAGEND_GLSL 0
-#define COGL_PIPELINE_FRAGEND_GLSL_MASK (1L<<0)
-
-#define COGL_PIPELINE_N_FRAGENDS 1
-
-#else /* HAVE_COGL_GLES */
-
-#define COGL_PIPELINE_FRAGEND_FIXED 0
-#define COGL_PIPELINE_FRAGEND_FIXED_MASK (1L<<0)
-
-#define COGL_PIPELINE_N_FRAGENDS 1
-
-#endif
-
-#define COGL_PIPELINE_FRAGEND_DEFAULT 0
-#define COGL_PIPELINE_FRAGEND_UNDEFINED 3
-
-#if defined (HAVE_COGL_GL)
-
-#define COGL_PIPELINE_VERTEND_FIXED 0
-#define COGL_PIPELINE_VERTEND_GLSL 1
-
-#define COGL_PIPELINE_N_VERTENDS 2
-
-#elif defined (HAVE_COGL_GLES2)
-
-#define COGL_PIPELINE_VERTEND_GLSL 0
-
-#define COGL_PIPELINE_N_VERTENDS 1
-
-#else /* HAVE_COGL_GLES */
-
-#define COGL_PIPELINE_VERTEND_FIXED 0
-
-#define COGL_PIPELINE_N_VERTENDS 1
-
-#endif
-
-#define COGL_PIPELINE_VERTEND_DEFAULT 0
-#define COGL_PIPELINE_VERTEND_UNDEFINED 3
-
-/* If we have either of the GLSL backends then we also need a GLSL
- progend to combine the shaders generated into a single
- program. Currently there is only one progend but if we ever add
- other languages they would likely need their own progend too. The
- progends are different from the other backends because there can be
- more than one in use for each pipeline. All of the progends are
- invoked whenever a pipeline is flushed. */
-#ifdef COGL_PIPELINE_FRAGEND_GLSL
-#define COGL_PIPELINE_PROGEND_GLSL 0
-#define COGL_PIPELINE_N_PROGENDS 1
-#else
-#define COGL_PIPELINE_N_PROGENDS 0
-#endif
-
-/* XXX: should I rename these as
- * COGL_PIPELINE_LAYER_STATE_INDEX_XYZ... ?
- */
-typedef enum
-{
- /* sparse state */
- COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
- COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
- COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
- COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
- COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
-
- /* note: layers don't currently have any non-sparse state */
-
- COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT,
- COGL_PIPELINE_LAYER_STATE_COUNT = COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT
-} CoglPipelineLayerStateIndex;
-
-/* XXX: If you add or remove state groups here you may need to update
- * some of the state masks following this enum too!
- *
- * FIXME: perhaps it would be better to rename this enum to
- * CoglPipelineLayerStateGroup to better convey the fact that a single
- * enum here can map to multiple properties.
- */
-typedef enum
-{
- COGL_PIPELINE_LAYER_STATE_UNIT =
- 1L<<COGL_PIPELINE_LAYER_STATE_UNIT_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET =
- 1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA =
- 1L<<COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX,
- COGL_PIPELINE_LAYER_STATE_FILTERS =
- 1L<<COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
- COGL_PIPELINE_LAYER_STATE_WRAP_MODES =
- 1L<<COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
-
- COGL_PIPELINE_LAYER_STATE_COMBINE =
- 1L<<COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
- COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT =
- 1L<<COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX =
- 1L<<COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
-
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS =
- 1L<<COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
-
- /* COGL_PIPELINE_LAYER_STATE_TEXTURE_INTERN = 1L<<8, */
-
-} CoglPipelineLayerState;
-
-/*
- * Various special masks that tag state-groups in different ways...
- */
-
-#define COGL_PIPELINE_LAYER_STATE_ALL \
- ((1L<<COGL_PIPELINE_LAYER_STATE_COUNT) - 1)
-
-#define COGL_PIPELINE_LAYER_STATE_ALL_SPARSE \
- COGL_PIPELINE_LAYER_STATE_ALL
-
-#define COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE \
- (COGL_PIPELINE_LAYER_STATE_COMBINE | \
- COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX | \
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS)
-
-#define COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY \
- (COGL_PIPELINE_LAYER_STATE_FILTERS | \
- COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
- COGL_PIPELINE_LAYER_STATE_COMBINE)
-
-/* FIXME: Only texture target changes should really affect the
- * codegen, but this is difficult to detect */
-#ifdef HAVE_COGL_GLES2
-/* On GLES2 we need to use a different varying for the texture lookups
- * when point sprite coords are enabled */
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
- (COGL_PIPELINE_LAYER_STATE_COMBINE | \
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
- COGL_PIPELINE_LAYER_STATE_UNIT)
-#else
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN \
- (COGL_PIPELINE_LAYER_STATE_COMBINE | \
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET | \
- COGL_PIPELINE_LAYER_STATE_UNIT)
-#endif
-
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0
-
-
-typedef enum
-{
- /* These are the same values as GL */
- COGL_PIPELINE_COMBINE_FUNC_ADD = 0x0104,
- COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED = 0x8574,
- COGL_PIPELINE_COMBINE_FUNC_SUBTRACT = 0x84E7,
- COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE = 0x8575,
- COGL_PIPELINE_COMBINE_FUNC_REPLACE = 0x1E01,
- COGL_PIPELINE_COMBINE_FUNC_MODULATE = 0x2100,
- COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB = 0x86AE,
- COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA = 0x86AF
-} CoglPipelineCombineFunc;
-
-typedef enum
-{
- /* These are the same values as GL */
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE = 0x1702,
- COGL_PIPELINE_COMBINE_SOURCE_CONSTANT = 0x8576,
- COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR = 0x8577,
- COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS = 0x8578,
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 = 0x84C0
-} CoglPipelineCombineSource;
-
-typedef enum
-{
- /* These are the same values as GL */
- COGL_PIPELINE_COMBINE_OP_SRC_COLOR = 0x0300,
- COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR = 0x0301,
- COGL_PIPELINE_COMBINE_OP_SRC_ALPHA = 0x0302,
- COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA = 0x0303
-} CoglPipelineCombineOp;
-
-typedef struct
-{
- /* The texture combine state determines how the color of individual
- * texture fragments are calculated. */
- CoglPipelineCombineFunc texture_combine_rgb_func;
- CoglPipelineCombineSource texture_combine_rgb_src[3];
- CoglPipelineCombineOp texture_combine_rgb_op[3];
-
- CoglPipelineCombineFunc texture_combine_alpha_func;
- CoglPipelineCombineSource texture_combine_alpha_src[3];
- CoglPipelineCombineOp texture_combine_alpha_op[3];
-
- float texture_combine_constant[4];
-
- /* The texture matrix dscribes how to transform texture coordinates */
- CoglMatrix matrix;
-
- gboolean point_sprite_coords;
-
-} CoglPipelineLayerBigState;
-
-/* Materials and layers represent their state in a tree structure where
- * some of the state relating to a given pipeline or layer may actually
- * be owned by one if is ancestors in the tree. We have a common data
- * type to track the tree heirachy so we can share code... */
-typedef struct _CoglPipelineNode CoglPipelineNode;
-struct _CoglPipelineNode
-{
- /* the parent in terms of class hierarchy, so anything inheriting
- * from CoglPipelineNode also inherits from CoglObject. */
- CoglObject _parent;
-
- /* The parent pipeline/layer */
- CoglPipelineNode *parent;
-
- /* TRUE if the node took a strong reference on its parent. Weak
- * pipelines for instance don't take a reference on their parent. */
- gboolean has_parent_reference;
-
- /* As an optimization for creating leaf node pipelines/layers (the
- * most common) we don't require any list node allocations to link
- * to a single descendant. */
- CoglPipelineNode *first_child;
-
- /* Determines if node->first_child and node->children are
- * initialized pointers. */
- gboolean has_children;
-
- /* Materials and layers are sparse structures defined as a diff
- * against their parent and may have multiple children which depend
- * on them to define the values of properties which they don't
- * change. */
- GList *children;
-};
-
-#define COGL_PIPELINE_NODE(X) ((CoglPipelineNode *)(X))
-
-typedef void (*CoglPipelineNodeUnparentVFunc) (CoglPipelineNode *node);
-
-typedef gboolean (*CoglPipelineNodeChildCallback) (CoglPipelineNode *child,
- void *user_data);
-
-void
-_cogl_pipeline_node_foreach_child (CoglPipelineNode *node,
- CoglPipelineNodeChildCallback callback,
- void *user_data);
-
-/* This isn't defined in the GLES headers */
-#ifndef GL_CLAMP_TO_BORDER
-#define GL_CLAMP_TO_BORDER 0x812d
-#endif
-
-/* GL_ALWAYS is just used here as a value that is known not to clash
- * with any valid GL wrap modes.
- *
- * XXX: keep the values in sync with the CoglPipelineWrapMode enum
- * so no conversion is actually needed.
- */
-typedef enum _CoglPipelineWrapModeInternal
-{
- COGL_PIPELINE_WRAP_MODE_INTERNAL_REPEAT = GL_REPEAT,
- COGL_PIPELINE_WRAP_MODE_INTERNAL_CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE,
- COGL_PIPELINE_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER,
- COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC = GL_ALWAYS
-} CoglPipelineWrapModeInternal;
-
-struct _CoglPipelineLayer
-{
- /* XXX: Please think twice about adding members that *have* be
- * initialized during a _cogl_pipeline_layer_copy. We are aiming
- * to have copies be as cheap as possible and copies may be
- * done by the primitives APIs which means they may happen
- * in performance critical code paths.
- *
- * XXX: If you are extending the state we track please consider if
- * the state is expected to vary frequently across many pipelines or
- * if the state can be shared among many derived pipelines instead.
- * This will determine if the state should be added directly to this
- * structure which will increase the memory overhead for *all*
- * layers or if instead it can go under ->big_state.
- */
-
- /* Layers represent their state in a tree structure where some of
- * the state relating to a given pipeline or layer may actually be
- * owned by one if is ancestors in the tree. We have a common data
- * type to track the tree heirachy so we can share code... */
- CoglPipelineNode _parent;
-
- /* Some layers have a pipeline owner, which is to say that the layer
- * is referenced in that pipelines->layer_differences list. A layer
- * doesn't always have an owner and may simply be an ancestor for
- * other layers that keeps track of some shared state. */
- CoglPipeline *owner;
-
- /* The lowest index is blended first then others on top */
- int index;
-
- /* A mask of which state groups are different in this layer
- * in comparison to its parent. */
- unsigned long differences;
-
- /* Common differences
- *
- * As a basic way to reduce memory usage we divide the layer
- * state into two groups; the minimal state modified in 90% of
- * all layers and the rest, so that the second group can
- * be allocated dynamically when required.
- */
-
- /* Each layer is directly associated with a single texture unit */
- int unit_index;
-
- /* The texture for this layer, or COGL_INVALID_HANDLE for an empty
- * layer */
- CoglHandle texture;
- GLenum target;
-
- CoglPipelineFilter mag_filter;
- CoglPipelineFilter min_filter;
-
- CoglPipelineWrapModeInternal wrap_mode_s;
- CoglPipelineWrapModeInternal wrap_mode_t;
- CoglPipelineWrapModeInternal wrap_mode_p;
-
- /* Infrequent differences aren't currently tracked in
- * a separate, dynamically allocated structure as they are
- * for pipelines... */
- CoglPipelineLayerBigState *big_state;
-
- /* bitfields */
-
- /* Determines if layer->big_state is valid */
- unsigned int has_big_state:1;
-
-};
-
-/* XXX: should I rename these as
- * COGL_PIPELINE_STATE_INDEX_XYZ... ?
- */
-typedef enum
-{
- /* sparse state */
- COGL_PIPELINE_STATE_COLOR_INDEX,
- COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX,
- COGL_PIPELINE_STATE_LAYERS_INDEX,
- COGL_PIPELINE_STATE_LIGHTING_INDEX,
- COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
- COGL_PIPELINE_STATE_BLEND_INDEX,
- COGL_PIPELINE_STATE_USER_SHADER_INDEX,
- COGL_PIPELINE_STATE_DEPTH_INDEX,
- COGL_PIPELINE_STATE_FOG_INDEX,
- COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
-
- /* non-sparse */
- COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
-
- COGL_PIPELINE_STATE_COUNT,
- COGL_PIPELINE_STATE_SPARSE_COUNT = COGL_PIPELINE_STATE_COUNT - 1,
-} CoglPipelineStateIndex;
-
-/* Used in pipeline->differences masks and for notifying pipeline
- * state changes.
- *
- * XXX: If you add or remove state groups here you may need to update
- * some of the state masks following this enum too!
- *
- * FIXME: perhaps it would be better to rename this enum to
- * CoglPipelineStateGroup to better convey the fact that a single enum
- * here can map to multiple properties.
- */
-typedef enum _CoglPipelineState
-{
- COGL_PIPELINE_STATE_COLOR =
- 1L<<COGL_PIPELINE_STATE_COLOR_INDEX,
- COGL_PIPELINE_STATE_BLEND_ENABLE =
- 1L<<COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX,
- COGL_PIPELINE_STATE_LAYERS =
- 1L<<COGL_PIPELINE_STATE_LAYERS_INDEX,
-
- COGL_PIPELINE_STATE_LIGHTING =
- 1L<<COGL_PIPELINE_STATE_LIGHTING_INDEX,
- COGL_PIPELINE_STATE_ALPHA_FUNC =
- 1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE =
- 1L<<COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
- COGL_PIPELINE_STATE_BLEND =
- 1L<<COGL_PIPELINE_STATE_BLEND_INDEX,
- COGL_PIPELINE_STATE_USER_SHADER =
- 1L<<COGL_PIPELINE_STATE_USER_SHADER_INDEX,
- COGL_PIPELINE_STATE_DEPTH =
- 1L<<COGL_PIPELINE_STATE_DEPTH_INDEX,
- COGL_PIPELINE_STATE_FOG =
- 1L<<COGL_PIPELINE_STATE_FOG_INDEX,
- COGL_PIPELINE_STATE_POINT_SIZE =
- 1L<<COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
-
- COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
- 1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
-
-} CoglPipelineState;
-
-/*
- * Various special masks that tag state-groups in different ways...
- */
-
-#define COGL_PIPELINE_STATE_ALL \
- ((1L<<COGL_PIPELINE_STATE_COUNT) - 1)
-
-#define COGL_PIPELINE_STATE_ALL_SPARSE \
- (COGL_PIPELINE_STATE_ALL \
- & ~COGL_PIPELINE_STATE_REAL_BLEND_ENABLE)
-
-#define COGL_PIPELINE_STATE_AFFECTS_BLENDING \
- (COGL_PIPELINE_STATE_COLOR | \
- COGL_PIPELINE_STATE_BLEND_ENABLE | \
- COGL_PIPELINE_STATE_LAYERS | \
- COGL_PIPELINE_STATE_LIGHTING | \
- COGL_PIPELINE_STATE_BLEND | \
- COGL_PIPELINE_STATE_USER_SHADER)
-
-#define COGL_PIPELINE_STATE_NEEDS_BIG_STATE \
- (COGL_PIPELINE_STATE_LIGHTING | \
- COGL_PIPELINE_STATE_ALPHA_FUNC | \
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE | \
- COGL_PIPELINE_STATE_BLEND | \
- COGL_PIPELINE_STATE_USER_SHADER | \
- COGL_PIPELINE_STATE_DEPTH | \
- COGL_PIPELINE_STATE_FOG | \
- COGL_PIPELINE_STATE_POINT_SIZE)
-
-#define COGL_PIPELINE_STATE_MULTI_PROPERTY \
- (COGL_PIPELINE_STATE_LAYERS | \
- COGL_PIPELINE_STATE_LIGHTING | \
- COGL_PIPELINE_STATE_BLEND | \
- COGL_PIPELINE_STATE_DEPTH | \
- COGL_PIPELINE_STATE_FOG)
-
-#ifdef HAVE_COGL_GLES2
- /* Under GLES2 the alpha func becomes part of the fragment program
- so we can't share programs there */
-#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
- (COGL_PIPELINE_STATE_LAYERS | \
- COGL_PIPELINE_STATE_ALPHA_FUNC | \
- COGL_PIPELINE_STATE_USER_SHADER)
-#else
-#define COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN \
- (COGL_PIPELINE_STATE_LAYERS | \
- COGL_PIPELINE_STATE_USER_SHADER)
-#endif
-
-#define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
- (COGL_PIPELINE_STATE_LAYERS | \
- COGL_PIPELINE_STATE_USER_SHADER)
-
-typedef enum
-{
- COGL_PIPELINE_LIGHTING_STATE_PROPERTY_AMBIENT = 1,
- COGL_PIPELINE_LIGHTING_STATE_PROPERTY_DIFFUSE,
- COGL_PIPELINE_LIGHTING_STATE_PROPERTY_SPECULAR,
- COGL_PIPELINE_LIGHTING_STATE_PROPERTY_EMISSION,
- COGL_PIPELINE_LIGHTING_STATE_PROPERTY_SHININESS
-} CoglPipelineLightingStateProperty;
-
-typedef struct
-{
- /* Standard OpenGL lighting model attributes */
- float ambient[4];
- float diffuse[4];
- float specular[4];
- float emission[4];
- float shininess;
-} CoglPipelineLightingState;
-
-typedef struct
-{
- /* Determines what fragments are discarded based on their alpha */
- CoglPipelineAlphaFunc alpha_func;
- float alpha_func_reference;
-} CoglPipelineAlphaFuncState;
-
-typedef enum _CoglPipelineBlendEnable
-{
- /* XXX: we want to detect users mistakenly using TRUE or FALSE
- * so start the enum at 2. */
- COGL_PIPELINE_BLEND_ENABLE_ENABLED = 2,
- COGL_PIPELINE_BLEND_ENABLE_DISABLED,
- COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC
-} CoglPipelineBlendEnable;
-
-typedef struct
-{
- /* Determines how this pipeline is blended with other primitives */
-#ifndef HAVE_COGL_GLES
- GLenum blend_equation_rgb;
- GLenum blend_equation_alpha;
- GLint blend_src_factor_alpha;
- GLint blend_dst_factor_alpha;
- CoglColor blend_constant;
-#endif
- GLint blend_src_factor_rgb;
- GLint blend_dst_factor_rgb;
-} CoglPipelineBlendState;
-
-typedef struct
-{
- gboolean depth_test_enabled;
- CoglDepthTestFunction depth_test_function;
- gboolean depth_writing_enabled;
- float depth_range_near;
- float depth_range_far;
-} CoglPipelineDepthState;
-
-typedef struct
-{
- gboolean enabled;
- CoglColor color;
- CoglFogMode mode;
- float density;
- float z_near;
- float z_far;
-} CoglPipelineFogState;
-
-typedef struct
-{
- CoglPipelineLightingState lighting_state;
- CoglPipelineAlphaFuncState alpha_state;
- CoglPipelineBlendState blend_state;
- CoglHandle user_program;
- CoglPipelineDepthState depth_state;
- CoglPipelineFogState fog_state;
- float point_size;
-} CoglPipelineBigState;
-
-typedef enum
-{
- COGL_PIPELINE_FLAG_DIRTY_LAYERS_CACHE = 1L<<0,
- COGL_PIPELINE_FLAG_DIRTY_GET_LAYERS_LIST = 1L<<1
-} CoglPipelineFlag;
-
-typedef struct
-{
- CoglPipeline *owner;
- CoglPipelineLayer *layer;
-} CoglPipelineLayerCacheEntry;
-
-/*
- * CoglPipelineDestroyCallback
- * @pipeline: The #CoglPipeline that has been destroyed
- * @user_data: The private data associated with the callback
- *
- * Notifies when a weak pipeline has been destroyed because one
- * of its ancestors has been freed or modified.
- */
-typedef void (*CoglPipelineDestroyCallback)(CoglPipeline *pipeline,
- void *user_data);
-
-struct _CoglPipeline
-{
- /* XXX: Please think twice about adding members that *have* be
- * initialized during a cogl_pipeline_copy. We are aiming to have
- * copies be as cheap as possible and copies may be done by the
- * primitives APIs which means they may happen in performance
- * critical code paths.
- *
- * XXX: If you are extending the state we track please consider if
- * the state is expected to vary frequently across many pipelines or
- * if the state can be shared among many derived pipelines instead.
- * This will determine if the state should be added directly to this
- * structure which will increase the memory overhead for *all*
- * pipelines or if instead it can go under ->big_state.
- */
-
- /* Layers represent their state in a tree structure where some of
- * the state relating to a given pipeline or layer may actually be
- * owned by one if is ancestors in the tree. We have a common data
- * type to track the tree heirachy so we can share code... */
- CoglPipelineNode _parent;
-
- /* We need to track if a pipeline is referenced in the journal
- * because we can't allow modification to these pipelines without
- * flushing the journal first */
- unsigned long journal_ref_count;
-
- /* When weak pipelines are destroyed the user is notified via this
- * callback */
- CoglPipelineDestroyCallback destroy_callback;
-
- /* When notifying that a weak pipeline has been destroyed this
- * private data is passed to the above callback */
- void *destroy_data;
-
- /* A mask of which sparse state groups are different in this
- * pipeline in comparison to its parent. */
- unsigned long differences;
-
- /* The fragment processing backends can associate private data with a
- * pipeline. */
- void *fragend_privs[COGL_PIPELINE_N_FRAGENDS];
-
- /* Whenever a pipeline is modified we increment the age. There's no
- * guarantee that it won't wrap but it can nevertheless be a
- * convenient mechanism to determine when a pipeline has been
- * changed to you can invalidate some some associated cache that
- * depends on the old state. */
- unsigned long age;
-
- /* This is the primary color of the pipeline.
- *
- * This is a sparse property, ref COGL_PIPELINE_STATE_COLOR */
- CoglColor color;
-
- /* A pipeline may be made up with multiple layers used to combine
- * textures together.
- *
- * This is sparse state, ref COGL_PIPELINE_STATE_LAYERS */
- GList *layer_differences;
- unsigned int n_layers;
-
- /* As a basic way to reduce memory usage we divide the pipeline
- * state into two groups; the minimal state modified in 90% of
- * all pipelines and the rest, so that the second group can
- * be allocated dynamically when required... */
- CoglPipelineBigState *big_state;
-
- /* For debugging purposes it's possible to associate a static const
- * string with a pipeline which can be an aid when trying to trace
- * where the pipeline originates from */
- const char *static_breadcrumb;
-
- /* Cached state... */
-
- /* A cached, complete list of the layers this pipeline depends
- * on sorted by layer->unit_index. */
- CoglPipelineLayer **layers_cache;
- /* To avoid a separate ->layers_cache allocation for common
- * pipelines with only a few layers... */
- CoglPipelineLayer *short_layers_cache[3];
-
- /* The deprecated cogl_pipeline_get_layers() API returns a
- * const GList of layers, which we track here... */
- GList *deprecated_get_layers_list;
-
- /* XXX: consider adding an authorities cache to speed up sparse
- * property value lookups:
- * CoglPipeline *authorities_cache[COGL_PIPELINE_N_SPARSE_PROPERTIES];
- * and corresponding authorities_cache_dirty:1 bitfield
- */
-
- /* bitfields */
-
- /* A pipeline can have private data associated with it for multiple
- * fragment processing backends. Although only one backend is
- * associated with a pipeline the backends may want to cache private
- * state with the ancestors of other pipelines and those ancestors
- * could currently be associated with different backends.
- *
- * Each set bit indicates if the corresponding ->fragend_privs[]
- * entry is valid.
- */
- unsigned int fragend_priv_set_mask:COGL_PIPELINE_N_FRAGENDS;
-
- /* Weak pipelines don't count as dependants on their parents which
- * means that the parent pipeline can be modified without
- * considering how the modifications may affect the weak pipeline.
- */
- unsigned int is_weak:1;
-
- /* Determines if pipeline->big_state is valid */
- unsigned int has_big_state:1;
-
- /* By default blending is enabled automatically depending on the
- * unlit color, the lighting colors or the texture format. The user
- * can override this to explicitly enable or disable blending.
- *
- * This is a sparse property */
- unsigned int blend_enable:3;
-
- /* There are many factors that can determine if we need to enable
- * blending, this holds our final decision */
- unsigned int real_blend_enable:1;
-
- unsigned int layers_cache_dirty:1;
- unsigned int deprecated_get_layers_list_dirty:1;
-
- /* For debugging purposes it's possible to associate a static const
- * string with a pipeline which can be an aid when trying to trace
- * where the pipeline originates from */
- unsigned int has_static_breadcrumb:1;
-
- /* There are multiple fragment processing backends for CoglPipeline,
- * glsl, arbfp and fixed. This identifies the backend being used for
- * the pipeline and any private state the backend has associated
- * with the pipeline. */
- unsigned int fragend:3;
- unsigned int vertend:3;
-};
-
-typedef struct _CoglPipelineFragend
-{
- gboolean (*start) (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs);
- gboolean (*add_layer) (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference);
- gboolean (*passthrough) (CoglPipeline *pipeline);
- gboolean (*end) (CoglPipeline *pipeline,
- unsigned long pipelines_difference);
-
- void (*pipeline_pre_change_notify) (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color);
- void (*pipeline_set_parent_notify) (CoglPipeline *pipeline);
- void (*layer_pre_change_notify) (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change);
-
- void (*free_priv) (CoglPipeline *pipeline);
-} CoglPipelineFragend;
-
-typedef struct _CoglPipelineVertend
-{
- gboolean (*start) (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference);
- gboolean (*add_layer) (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference);
- gboolean (*end) (CoglPipeline *pipeline,
- unsigned long pipelines_difference);
-
- void (*pipeline_pre_change_notify) (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color);
- void (*layer_pre_change_notify) (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change);
-} CoglPipelineVertend;
-
-typedef struct
-{
- void (*end) (CoglPipeline *pipeline,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs);
- void (*pipeline_pre_change_notify) (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color);
- void (*layer_pre_change_notify) (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change);
- /* This is called after all of the other functions whenever the
- pipeline is flushed, even if the pipeline hasn't changed since
- the last flush */
- void (* pre_paint) (CoglPipeline *pipeline);
-} CoglPipelineProgend;
-
-typedef enum
-{
- COGL_PIPELINE_PROGRAM_TYPE_GLSL = 1,
- COGL_PIPELINE_PROGRAM_TYPE_ARBFP,
- COGL_PIPELINE_PROGRAM_TYPE_FIXED
-} CoglPipelineProgramType;
-
-extern const CoglPipelineFragend *
-_cogl_pipeline_fragends[COGL_PIPELINE_N_FRAGENDS];
-extern const CoglPipelineVertend *
-_cogl_pipeline_vertends[COGL_PIPELINE_N_VERTENDS];
-extern const CoglPipelineProgend *
-_cogl_pipeline_progends[];
-
-void
-_cogl_pipeline_init_default_pipeline (void);
-
-void
-_cogl_pipeline_init_default_layers (void);
-
-static inline CoglPipeline *
-_cogl_pipeline_get_parent (CoglPipeline *pipeline)
-{
- CoglPipelineNode *parent_node = COGL_PIPELINE_NODE (pipeline)->parent;
- return COGL_PIPELINE (parent_node);
-}
-
-static inline CoglPipeline *
-_cogl_pipeline_get_authority (CoglPipeline *pipeline,
- unsigned long difference)
-{
- CoglPipeline *authority = pipeline;
- while (!(authority->differences & difference))
- authority = _cogl_pipeline_get_parent (authority);
- return authority;
-}
-
-/*
- * SECTION:cogl-pipeline-internals
- * @short_description: Functions for creating custom primitives that make use
- * of Cogl pipelines for filling.
- *
- * Normally you shouldn't need to use this API directly, but if you need to
- * developing a custom/specialised primitive - probably using raw OpenGL - then
- * this API aims to expose enough of the pipeline internals to support being
- * able to fill your geometry according to a given Cogl pipeline.
- */
-
-gboolean
-_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline);
-
-gboolean
-_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline,
- int layer_index);
-
-/*
- * Calls the pre_paint method on the layer texture if there is
- * one. This will determine whether mipmaps are needed based on the
- * filter settings.
- */
-void
-_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layerr);
-
-/*
- * Calls the pre_paint method on the layer texture if there is
- * one. This will determine whether mipmaps are needed based on the
- * filter settings.
- */
-void
-_cogl_pipeline_pre_paint_for_layer (CoglPipeline *pipeline,
- int layer_id);
-
-/*
- * CoglPipelineFlushFlag:
- * @COGL_PIPELINE_FLUSH_FALLBACK_MASK: The fallback_layers member is set to
- * a guint32 mask of the layers that can't be supported with the user
- * supplied texture and need to be replaced with fallback textures. (1 =
- * fallback, and the least significant bit = layer 0)
- * @COGL_PIPELINE_FLUSH_DISABLE_MASK: The disable_layers member is set to
- * a guint32 mask of the layers that you want to completly disable
- * texturing for (1 = fallback, and the least significant bit = layer 0)
- * @COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE: The layer0_override_texture member is
- * set to a GLuint OpenGL texture name to override the texture used for
- * layer 0 of the pipeline. This is intended for dealing with sliced
- * textures where you will need to point to each of the texture slices in
- * turn when drawing your geometry. Passing a value of 0 is the same as
- * not passing the option at all.
- * @COGL_PIPELINE_FLUSH_SKIP_GL_COLOR: When flushing the GL state for the
- * pipeline don't call glColor.
- */
-typedef enum _CoglPipelineFlushFlag
-{
- COGL_PIPELINE_FLUSH_FALLBACK_MASK = 1L<<0,
- COGL_PIPELINE_FLUSH_DISABLE_MASK = 1L<<1,
- COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE = 1L<<2,
- COGL_PIPELINE_FLUSH_SKIP_GL_COLOR = 1L<<3
-} CoglPipelineFlushFlag;
-
-/*
- * CoglPipelineFlushOptions:
- *
- */
-typedef struct _CoglPipelineFlushOptions
-{
- CoglPipelineFlushFlag flags;
-
- guint32 fallback_layers;
- guint32 disable_layers;
- CoglHandle layer0_override_texture;
-} CoglPipelineFlushOptions;
-
-
-int
-_cogl_get_max_texture_image_units (void);
-
-
-void
-_cogl_use_fragment_program (GLuint gl_program, CoglPipelineProgramType type);
-
-void
-_cogl_use_vertex_program (GLuint gl_program, CoglPipelineProgramType type);
-
-unsigned int
-_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func);
-
-/*
- * _cogl_pipeline_weak_copy:
- * @pipeline: A #CoglPipeline object
- * @callback: A callback to notify when your weak pipeline is destroyed
- * @user_data: Private data to pass to your given callback.
- *
- * Returns a weak copy of the given source @pipeline. Unlike a normal
- * copy no internal reference is taken on the source @pipeline and you
- * can expect that later modifications of the source pipeline (or in
- * fact any other pipeline) can result in the weak pipeline being
- * destroyed.
- *
- * To understand this better its good to know a bit about the internal
- * design of #CoglPipeline...
- *
- * Internally #CoglPipeline<!-- -->s are represented as a graph of
- * property diff's, where each node is a diff of properties that gets
- * applied on top of its parent. Copying a pipeline creates an empty
- * diff and a child->parent relationship between the empty diff and
- * the source @pipeline, parent.
- *
- * Because of this internal graph design a single #CoglPipeline may
- * indirectly depend on a chain of ancestors to fully define all of
- * its properties. Because a node depends on its ancestors it normally
- * owns a reference to its parent to stop it from being freed. Also if
- * you try to modify a pipeline with children we internally use a
- * copy-on-write mechanism to ensure that you don't indirectly change
- * the properties those children.
- *
- * Weak pipelines avoid the use of copy-on-write to preserve the
- * integrity of weak dependants and instead weak dependants are
- * simply destroyed allowing the parent to be modified directly. Also
- * because weak pipelines don't own a reference to their parent they
- * won't stop the source @pipeline from being freed when the user
- * releases their reference on it.
- *
- * Because weak pipelines don't own a reference on their parent they
- * are the recommended mechanism for creating derived pipelines that you
- * want to cache as a private property of the original pipeline
- * because they won't result in a circular dependency.
- *
- * An example use case:
- *
- * Consider for example you are implementing a custom primitive that is
- * not compatible with certain source pipelines. To handle this you
- * implement a validation stage that given an arbitrary pipeline as
- * input will create a derived pipeline that is suitable for drawing
- * your primitive.
- *
- * Because you don't want to have to repeat this validation every time
- * the same incompatible pipeline is given as input you want to cache
- * the result as a private property of the original pipeline. If the
- * derived pipeline were created using cogl_pipeline_copy that would
- * create a circular dependency so the original pipeline can never be
- * freed.
- *
- * If you instead create a weak copy you won't stop the original pipeline
- * from being freed if it's no longer needed, and you will instead simply
- * be notified that your weak pipeline has been destroyed.
- *
- * This is the recommended coding pattern for validating an input
- * pipeline and caching a derived result:
- * |[
- * static CoglUserDataKey _cogl_my_cache_key;
- *
- * typedef struct {
- * CoglPipeline *validated_source;
- * } MyValidatedMaterialCache;
- *
- * static void
- * destroy_cache_cb (CoglObject *object, void *user_data)
- * {
- * g_slice_free (MyValidatedMaterialCache, user_data);
- * }
- *
- * static void
- * invalidate_cache_cb (CoglPipeline *destroyed, void *user_data)
- * {
- * MyValidatedMaterialCache *cache = user_data;
- * cogl_object_unref (cache->validated_source);
- * cache->validated_source = NULL;
- * }
- *
- * static CoglPipeline *
- * get_validated_pipeline (CoglPipeline *source)
- * {
- * MyValidatedMaterialCache *cache =
- * cogl_object_get_user_data (COGL_OBJECT (source),
- * &_cogl_my_cache_key);
- * if (G_UNLIKELY (cache == NULL))
- * {
- * cache = g_slice_new (MyValidatedMaterialCache);
- * cogl_object_set_user_data (COGL_OBJECT (source),
- * &_cogl_my_cache_key,
- * cache, destroy_cache_cb);
- * cache->validated_source = source;
- * }
- *
- * if (G_UNLIKELY (cache->validated_source == NULL))
- * {
- * cache->validated_source = source;
- *
- * / * Start validating source... * /
- *
- * / * If you find you need to change something... * /
- * if (cache->validated_source == source)
- * cache->validated_source =
- * cogl_pipeline_weak_copy (source,
- * invalidate_cache_cb,
- * cache);
- *
- * / * Modify cache->validated_source * /
- * }
- *
- * return cache->validated_source;
- * }
- * ]|
- */
-CoglPipeline *
-_cogl_pipeline_weak_copy (CoglPipeline *pipeline,
- CoglPipelineDestroyCallback callback,
- void *user_data);
-
-void
-_cogl_pipeline_set_fragend (CoglPipeline *pipeline, int fragend);
-
-void
-_cogl_pipeline_set_vertend (CoglPipeline *pipeline, int vertend);
-
-CoglPipeline *
-_cogl_pipeline_get_parent (CoglPipeline *pipeline);
-
-void
-_cogl_pipeline_get_colorubv (CoglPipeline *pipeline,
- guint8 *color);
-
-/* XXX: At some point it could be good for this to accept a mask of
- * the state groups we are interested in comparing since we can
- * probably use that information in a number situations to reduce
- * the work we do. */
-unsigned long
-_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
- CoglPipeline *pipeline1);
-
-/* Sometimes when evaluating pipelines, either during comparisons or
- * if calculating a hash value we need to tweak the evaluation
- * semantics */
-typedef enum _CoglPipelineEvalFlags
-{
- COGL_PIPELINE_EVAL_FLAG_NONE = 0
-} CoglPipelineEvalFlags;
-
-gboolean
-_cogl_pipeline_equal (CoglPipeline *pipeline0,
- CoglPipeline *pipeline1,
- unsigned long differences,
- unsigned long layer_differences,
- CoglPipelineEvalFlags flags);
-
-unsigned int
-_cogl_pipeline_hash (CoglPipeline *pipeline,
- unsigned long differences,
- unsigned long layer_differences,
- CoglPipelineEvalFlags flags);
-
-CoglPipeline *
-_cogl_pipeline_journal_ref (CoglPipeline *pipeline);
-
-void
-_cogl_pipeline_journal_unref (CoglPipeline *pipeline);
-
-CoglPipelineFilter
-_cogl_pipeline_get_layer_min_filter (CoglPipeline *pipeline,
- int layer_index);
-
-CoglPipelineFilter
-_cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline,
- int layer_index);
-
-const CoglMatrix *
-_cogl_pipeline_get_layer_matrix (CoglPipeline *pipeline,
- int layer_index);
-
-void
-_cogl_pipeline_texture_storage_change_notify (CoglHandle texture);
-
-void
-_cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline);
-
-void
-_cogl_pipeline_apply_overrides (CoglPipeline *pipeline,
- CoglPipelineFlushOptions *options);
-
-CoglPipelineBlendEnable
-_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline);
-
-void
-_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline,
- CoglPipelineBlendEnable enable);
-
-void
-_cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline,
- const char *breadcrumb);
-
-unsigned long
-_cogl_pipeline_get_age (CoglPipeline *pipeline);
-
-CoglPipeline *
-_cogl_pipeline_get_authority (CoglPipeline *pipeline,
- unsigned long difference);
-
-CoglPipeline *
-_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
- CoglPipelineState pipeline_state,
- CoglPipelineLayerState layer_state);
-
-CoglHandle
-_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
- int layer_index);
-
-void
-_cogl_pipeline_get_layer_combine_constant (CoglPipeline *pipeline,
- int layer_index,
- float *constant);
-
-void
-_cogl_pipeline_prune_to_n_layers (CoglPipeline *pipeline, int n);
-
-
-/*
- * API to support the deprecate cogl_pipeline_layer_xyz functions...
- */
-
-G_CONST_RETURN GList *
-_cogl_pipeline_get_layers (CoglPipeline *pipeline);
-
-void
-_cogl_pipeline_layer_get_wrap_modes (CoglPipelineLayer *layer,
- CoglPipelineWrapModeInternal *wrap_mode_s,
- CoglPipelineWrapModeInternal *wrap_mode_t,
- CoglPipelineWrapModeInternal *wrap_mode_r);
-
-void
-_cogl_pipeline_layer_get_filters (CoglPipelineLayer *layer,
- CoglPipelineFilter *min_filter,
- CoglPipelineFilter *mag_filter);
-
-void
-_cogl_pipeline_get_layer_filters (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineFilter *min_filter,
- CoglPipelineFilter *mag_filter);
-
-typedef enum {
- COGL_PIPELINE_LAYER_TYPE_TEXTURE
-} CoglPipelineLayerType;
-
-CoglPipelineLayerType
-_cogl_pipeline_layer_get_type (CoglPipelineLayer *layer);
-
-CoglHandle
-_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer);
-
-CoglHandle
-_cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer);
-
-CoglPipelineFilter
-_cogl_pipeline_layer_get_min_filter (CoglPipelineLayer *layer);
-
-CoglPipelineFilter
-_cogl_pipeline_layer_get_mag_filter (CoglPipelineLayer *layer);
-
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_s (CoglPipelineLayer *layer);
-
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_t (CoglPipelineLayer *layer);
-
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_p (CoglPipelineLayer *layer);
-
-unsigned long
-_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
- CoglPipelineLayer *layer1);
-
-CoglPipelineLayer *
-_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer,
- unsigned long difference);
-
-CoglHandle
-_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer);
-
-typedef gboolean (*CoglPipelineInternalLayerCallback) (CoglPipelineLayer *layer,
- void *user_data);
-
-void
-_cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline,
- CoglPipelineInternalLayerCallback callback,
- void *user_data);
-
-int
-_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer);
-
-gboolean
-_cogl_pipeline_need_texture_combine_separate
- (CoglPipelineLayer *combine_authority);
-
-void
-_cogl_pipeline_init_state_hash_functions (void);
-
-void
-_cogl_pipeline_init_layer_state_hash_functions (void);
-
-#endif /* __COGL_PIPELINE_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H
-#define __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-#include "cogl-attribute-private.h"
-
-extern const CoglPipelineProgend _cogl_pipeline_glsl_progend;
-
-#ifdef HAVE_COGL_GLES2
-
-int
-_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline);
-
-int
-_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline);
-
-int
-_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline);
-
-int
-_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
- int unit);
-
-#endif /* HAVE_COGL_GLES2 */
-
-#endif /* __COGL_PIPELINE_PROGEND_GLSL_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#ifdef COGL_PIPELINE_PROGEND_GLSL
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-program-private.h"
-#include "cogl-pipeline-fragend-glsl-private.h"
-#include "cogl-pipeline-vertend-glsl-private.h"
-
-#ifndef HAVE_COGL_GLES2
-
-#define glCreateProgram ctx->drv.pf_glCreateProgram
-#define glAttachShader ctx->drv.pf_glAttachShader
-#define glUseProgram ctx->drv.pf_glUseProgram
-#define glLinkProgram ctx->drv.pf_glLinkProgram
-#define glDeleteProgram ctx->drv.pf_glDeleteProgram
-#define glGetProgramInfoLog ctx->drv.pf_glGetProgramInfoLog
-#define glGetProgramiv ctx->drv.pf_glGetProgramiv
-#define glGetUniformLocation ctx->drv.pf_glGetUniformLocation
-#define glUniform1i ctx->drv.pf_glUniform1i
-#define glUniform1f ctx->drv.pf_glUniform1f
-#define glUniform4fv ctx->drv.pf_glUniform4fv
-
-#else
-
-/* These are used to generalise updating some uniforms that are
- required when building for GLES2 */
-
-typedef void (* UpdateUniformFunc) (CoglPipeline *pipeline,
- int uniform_location,
- void *getter_func);
-
-static void update_float_uniform (CoglPipeline *pipeline,
- int uniform_location,
- void *getter_func);
-
-typedef struct
-{
- const char *uniform_name;
- void *getter_func;
- UpdateUniformFunc update_func;
- CoglPipelineState change;
-} BuiltinUniformData;
-
-static BuiltinUniformData builtin_uniforms[] =
- {
- { "cogl_point_size_in",
- cogl_pipeline_get_point_size, update_float_uniform,
- COGL_PIPELINE_STATE_POINT_SIZE },
- { "_cogl_alpha_test_ref",
- cogl_pipeline_get_alpha_test_reference, update_float_uniform,
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE }
- };
-
-#endif /* HAVE_COGL_GLES2 */
-
-const CoglPipelineProgend _cogl_pipeline_glsl_progend;
-
-typedef struct _UnitState
-{
- unsigned int dirty_combine_constant:1;
- unsigned int dirty_texture_matrix:1;
-
- GLint combine_constant_uniform;
-
- GLint texture_matrix_uniform;
-} UnitState;
-
-typedef struct
-{
- unsigned int ref_count;
-
- /* Age that the user program had last time we generated a GL
- program. If it's different then we need to relink the program */
- unsigned int user_program_age;
-
- GLuint program;
-
- /* To allow writing shaders that are portable between GLES 2 and
- * OpenGL Cogl prepends a number of boilerplate #defines and
- * declarations to user shaders. One of those declarations is an
- * array of texture coordinate varyings, but to know how to emit the
- * declaration we need to know how many texture coordinate
- * attributes are in use. The boilerplate also needs to be changed
- * if this increases. */
- int n_tex_coord_attribs;
-
-#ifdef HAVE_COGL_GLES2
- unsigned long dirty_builtin_uniforms;
- GLint builtin_uniform_locations[G_N_ELEMENTS (builtin_uniforms)];
-
- /* Under GLES2 we can't use the builtin functions to set attribute
- pointers such as the vertex position. Instead the vertex
- attribute code needs to query the attribute numbers from the
- progend backend */
- int position_attribute_location;
- int color_attribute_location;
- int normal_attribute_location;
- int tex_coord0_attribute_location;
- /* We only allocate this array if more than one tex coord attribute
- is requested because most pipelines will only use one layer */
- GArray *tex_coord_attribute_locations;
-
- GLint modelview_uniform;
- GLint projection_uniform;
- GLint mvp_uniform;
-
- CoglMatrixStack *flushed_modelview_stack;
- unsigned int flushed_modelview_stack_age;
- gboolean flushed_modelview_is_identity;
- CoglMatrixStack *flushed_projection_stack;
- unsigned int flushed_projection_stack_age;
-#endif
-
- /* We need to track the last pipeline that the program was used with
- * so know if we need to update all of the uniforms */
- CoglPipeline *last_used_for_pipeline;
-
- UnitState *unit_state;
-} CoglPipelineProgendPrivate;
-
-static CoglUserDataKey glsl_priv_key;
-
-static CoglPipelineProgendPrivate *
-get_glsl_priv (CoglPipeline *pipeline)
-{
- return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key);
-}
-
-#ifdef HAVE_COGL_GLES2
-
-#define ATTRIBUTE_LOCATION_UNKNOWN -2
-
-/* Under GLES2 the vertex attribute API needs to query the attribute
- numbers because it can't used the fixed function API to set the
- builtin attributes. We cache the attributes here because the
- progend knows when the program is changed so it can clear the
- cache. This should always be called after the pipeline is flushed
- so they can assert that the gl program is valid */
-
-int
-_cogl_pipeline_progend_glsl_get_position_attribute (CoglPipeline *pipeline)
-{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
-
- g_return_val_if_fail (priv != NULL, -1);
- g_return_val_if_fail (priv->program != 0, -1);
-
- if (priv->position_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
- GE_RET( priv->position_attribute_location,
- glGetAttribLocation (priv->program, "cogl_position_in") );
-
- return priv->position_attribute_location;
-}
-
-int
-_cogl_pipeline_progend_glsl_get_color_attribute (CoglPipeline *pipeline)
-{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
-
- g_return_val_if_fail (priv != NULL, -1);
- g_return_val_if_fail (priv->program != 0, -1);
-
- if (priv->color_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
- GE_RET( priv->color_attribute_location,
- glGetAttribLocation (priv->program, "cogl_color_in") );
-
- return priv->color_attribute_location;
-}
-
-int
-_cogl_pipeline_progend_glsl_get_normal_attribute (CoglPipeline *pipeline)
-{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
-
- g_return_val_if_fail (priv != NULL, -1);
- g_return_val_if_fail (priv->program != 0, -1);
-
- if (priv->normal_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
- GE_RET( priv->normal_attribute_location,
- glGetAttribLocation (priv->program, "cogl_normal_in") );
-
- return priv->normal_attribute_location;
-}
-
-int
-_cogl_pipeline_progend_glsl_get_tex_coord_attribute (CoglPipeline *pipeline,
- int unit)
-{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
-
- g_return_val_if_fail (priv != NULL, -1);
- g_return_val_if_fail (priv->program != 0, -1);
-
- if (unit == 0)
- {
- if (priv->tex_coord0_attribute_location == ATTRIBUTE_LOCATION_UNKNOWN)
- GE_RET( priv->tex_coord0_attribute_location,
- glGetAttribLocation (priv->program, "cogl_tex_coord0_in") );
-
- return priv->tex_coord0_attribute_location;
- }
- else
- {
- char *name = g_strdup_printf ("cogl_tex_coord%i_in", unit);
- int *locations;
-
- if (priv->tex_coord_attribute_locations == NULL)
- priv->tex_coord_attribute_locations = g_array_new (FALSE, FALSE,
- sizeof (int));
- if (priv->tex_coord_attribute_locations->len <= unit - 1)
- {
- int i = priv->tex_coord_attribute_locations->len;
- g_array_set_size (priv->tex_coord_attribute_locations, unit);
- for (; i < unit; i++)
- g_array_index (priv->tex_coord_attribute_locations, int, i) =
- ATTRIBUTE_LOCATION_UNKNOWN;
- }
-
- locations = &g_array_index (priv->tex_coord_attribute_locations, int, 0);
-
- if (locations[unit - 1] == ATTRIBUTE_LOCATION_UNKNOWN)
- GE_RET( locations[unit - 1],
- glGetAttribLocation (priv->program, name) );
-
- g_free (name);
-
- return locations[unit - 1];
- }
-}
-
-static void
-clear_attribute_cache (CoglPipelineProgendPrivate *priv)
-{
- priv->position_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
- priv->color_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
- priv->normal_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
- priv->tex_coord0_attribute_location = ATTRIBUTE_LOCATION_UNKNOWN;
- if (priv->tex_coord_attribute_locations)
- {
- g_array_free (priv->tex_coord_attribute_locations, TRUE);
- priv->tex_coord_attribute_locations = NULL;
- }
-}
-
-static void
-clear_flushed_matrix_stacks (CoglPipelineProgendPrivate *priv)
-{
- if (priv->flushed_modelview_stack)
- {
- cogl_object_unref (priv->flushed_modelview_stack);
- priv->flushed_modelview_stack = NULL;
- }
- if (priv->flushed_projection_stack)
- {
- cogl_object_unref (priv->flushed_projection_stack);
- priv->flushed_projection_stack = NULL;
- }
- priv->flushed_modelview_is_identity = FALSE;
-}
-
-#endif /* HAVE_COGL_GLES2 */
-
-static void
-destroy_glsl_priv (void *user_data)
-{
- CoglPipelineProgendPrivate *priv = user_data;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (--priv->ref_count == 0)
- {
-#ifdef HAVE_COGL_GLES2
- clear_attribute_cache (priv);
- clear_flushed_matrix_stacks (priv);
-#endif
-
- if (priv->program)
- GE( glDeleteProgram (priv->program) );
-
- g_free (priv->unit_state);
-
- g_slice_free (CoglPipelineProgendPrivate, priv);
- }
-}
-
-static void
-set_glsl_priv (CoglPipeline *pipeline, CoglPipelineProgendPrivate *priv)
-{
- cogl_object_set_user_data (COGL_OBJECT (pipeline),
- &glsl_priv_key,
- priv,
- destroy_glsl_priv);
-}
-
-static void
-dirty_glsl_program_state (CoglPipeline *pipeline)
-{
- cogl_object_set_user_data (COGL_OBJECT (pipeline),
- &glsl_priv_key,
- NULL,
- destroy_glsl_priv);
-}
-
-static void
-link_program (GLint gl_program)
-{
- GLint link_status;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- GE( glLinkProgram (gl_program) );
-
- GE( glGetProgramiv (gl_program, GL_LINK_STATUS, &link_status) );
-
- if (!link_status)
- {
- GLint log_length;
- GLsizei out_log_length;
- char *log;
-
- GE( glGetProgramiv (gl_program, GL_INFO_LOG_LENGTH, &log_length) );
-
- log = g_malloc (log_length);
-
- GE( glGetProgramInfoLog (gl_program, log_length,
- &out_log_length, log) );
-
- g_warning ("Failed to link GLSL program:\n%.*s\n",
- log_length, log);
-
- g_free (log);
- }
-}
-
-typedef struct
-{
- int unit;
- GLuint gl_program;
- gboolean update_all;
- CoglPipelineProgendPrivate *priv;
-} UpdateUniformsState;
-
-static gboolean
-get_uniform_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- UpdateUniformsState *state = user_data;
- CoglPipelineProgendPrivate *priv = state->priv;
- UnitState *unit_state = &priv->unit_state[state->unit];
- GLint uniform_location;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* We can reuse the source buffer to create the uniform name because
- the program has now been linked */
- g_string_set_size (ctx->codegen_source_buffer, 0);
- g_string_append_printf (ctx->codegen_source_buffer,
- "_cogl_sampler_%i", state->unit);
-
- GE_RET( uniform_location,
- glGetUniformLocation (state->gl_program,
- ctx->codegen_source_buffer->str) );
-
- /* We can set the uniform immediately because the samplers are the
- unit index not the texture object number so it will never
- change. Unfortunately GL won't let us use a constant instead of a
- uniform */
- if (uniform_location != -1)
- GE( glUniform1i (uniform_location, state->unit) );
-
- g_string_set_size (ctx->codegen_source_buffer, 0);
- g_string_append_printf (ctx->codegen_source_buffer,
- "_cogl_layer_constant_%i", state->unit);
-
- GE_RET( uniform_location,
- glGetUniformLocation (state->gl_program,
- ctx->codegen_source_buffer->str) );
-
- unit_state->combine_constant_uniform = uniform_location;
-
-#ifdef HAVE_COGL_GLES2
-
- g_string_set_size (ctx->codegen_source_buffer, 0);
- g_string_append_printf (ctx->codegen_source_buffer,
- "cogl_texture_matrix[%i]", state->unit);
-
- GE_RET( uniform_location,
- glGetUniformLocation (state->gl_program,
- ctx->codegen_source_buffer->str) );
-
- unit_state->texture_matrix_uniform = uniform_location;
-
-#endif
-
- state->unit++;
-
- return TRUE;
-}
-
-static gboolean
-update_constants_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- UpdateUniformsState *state = user_data;
- CoglPipelineProgendPrivate *priv = state->priv;
- UnitState *unit_state = &priv->unit_state[state->unit++];
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (unit_state->combine_constant_uniform != -1 &&
- (state->update_all || unit_state->dirty_combine_constant))
- {
- float constant[4];
- _cogl_pipeline_get_layer_combine_constant (pipeline,
- layer_index,
- constant);
- GE (glUniform4fv (unit_state->combine_constant_uniform,
- 1, constant));
- unit_state->dirty_combine_constant = FALSE;
- }
-
-#ifdef HAVE_COGL_GLES2
-
- if (unit_state->texture_matrix_uniform != -1 &&
- (state->update_all || unit_state->dirty_texture_matrix))
- {
- const CoglMatrix *matrix;
- const float *array;
-
- matrix = _cogl_pipeline_get_layer_matrix (pipeline, layer_index);
- array = cogl_matrix_get_array (matrix);
- GE (glUniformMatrix4fv (unit_state->texture_matrix_uniform,
- 1, FALSE, array));
- unit_state->dirty_texture_matrix = FALSE;
- }
-
-#endif /* HAVE_COGL_GLES2 */
-
- return TRUE;
-}
-
-#ifdef HAVE_COGL_GLES2
-
-static void
-update_builtin_uniforms (CoglPipeline *pipeline,
- GLuint gl_program,
- CoglPipelineProgendPrivate *priv)
-{
- int i;
-
- if (priv->dirty_builtin_uniforms == 0)
- return;
-
- for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
- if ((priv->dirty_builtin_uniforms & (1 << i)) &&
- priv->builtin_uniform_locations[i] != -1)
- builtin_uniforms[i].update_func (pipeline,
- priv->builtin_uniform_locations[i],
- builtin_uniforms[i].getter_func);
-
- priv->dirty_builtin_uniforms = 0;
-}
-
-#endif /* HAVE_COGL_GLES2 */
-
-static void
-_cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference,
- int n_tex_coord_attribs)
-{
- CoglPipelineProgendPrivate *priv;
- GLuint gl_program;
- gboolean program_changed = FALSE;
- UpdateUniformsState state;
- CoglProgram *user_program;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If neither of the glsl fragend or vertends are used then we don't
- need to do anything */
- if (pipeline->fragend != COGL_PIPELINE_FRAGEND_GLSL &&
- pipeline->vertend != COGL_PIPELINE_VERTEND_GLSL)
- return;
-
- priv = get_glsl_priv (pipeline);
-
- user_program = cogl_pipeline_get_user_program (pipeline);
-
- if (priv == NULL)
- {
- CoglPipeline *authority;
-
- /* Get the authority for anything affecting program state. This
- should include both fragment codegen state and vertex codegen
- state */
- authority = _cogl_pipeline_find_equivalent_parent
- (pipeline,
- (COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN |
- COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN) &
- ~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN |
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
-
- priv = get_glsl_priv (authority);
-
- if (priv == NULL)
- {
- priv = g_slice_new (CoglPipelineProgendPrivate);
- priv->ref_count = 1;
- priv->program = 0;
- priv->n_tex_coord_attribs = 0;
- priv->unit_state = g_new (UnitState,
- cogl_pipeline_get_n_layers (pipeline));
-#ifdef HAVE_COGL_GLES2
- priv->tex_coord_attribute_locations = NULL;
- priv->flushed_modelview_stack = NULL;
- priv->flushed_modelview_is_identity = FALSE;
- priv->flushed_projection_stack = NULL;
-#endif
- set_glsl_priv (authority, priv);
- }
-
- if (authority != pipeline)
- {
- priv->ref_count++;
- set_glsl_priv (pipeline, priv);
- }
- }
-
- /* If the program has changed since the last link then we do
- * need to relink
- *
- * Also if the number of texture coordinate attributes in use has
- * increased, then delete the program so we can prepend a new
- * _cogl_tex_coord[] varying array declaration. */
- if (priv->program && user_program &&
- (user_program->age != priv->user_program_age ||
- n_tex_coord_attribs > priv->n_tex_coord_attribs))
- {
- GE( glDeleteProgram (priv->program) );
- priv->program = 0;
- }
-
- if (priv->program == 0)
- {
- GLuint backend_shader;
- GSList *l;
-
- GE_RET( priv->program, glCreateProgram () );
-
- /* Attach all of the shader from the user program */
- if (user_program)
- {
- if (priv->n_tex_coord_attribs > n_tex_coord_attribs)
- n_tex_coord_attribs = priv->n_tex_coord_attribs;
-
-#ifdef HAVE_COGL_GLES2
- /* Find the largest count of texture coordinate attributes
- * associated with each of the shaders so we can ensure a consistent
- * _cogl_tex_coord[] array declaration across all of the shaders.*/
- if (user_program)
- for (l = user_program->attached_shaders; l; l = l->next)
- {
- CoglShader *shader = l->data;
- n_tex_coord_attribs = MAX (shader->n_tex_coord_attribs,
- n_tex_coord_attribs);
- }
-#endif
-
- for (l = user_program->attached_shaders; l; l = l->next)
- {
- CoglShader *shader = l->data;
-
- _cogl_shader_compile_real (shader, n_tex_coord_attribs);
-
- g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
-
- GE( glAttachShader (priv->program,
- shader->gl_handle) );
- }
-
- priv->user_program_age = user_program->age;
- }
-
- /* Attach any shaders from the GLSL backends */
- if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL &&
- (backend_shader = _cogl_pipeline_fragend_glsl_get_shader (pipeline)))
- GE( glAttachShader (priv->program, backend_shader) );
- if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL &&
- (backend_shader = _cogl_pipeline_vertend_glsl_get_shader (pipeline)))
- GE( glAttachShader (priv->program, backend_shader) );
-
- link_program (priv->program);
-
- program_changed = TRUE;
-
- priv->n_tex_coord_attribs = n_tex_coord_attribs;
- }
-
- gl_program = priv->program;
-
- if (pipeline->fragend == COGL_PIPELINE_FRAGEND_GLSL)
- _cogl_use_fragment_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
- if (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL)
- _cogl_use_vertex_program (gl_program, COGL_PIPELINE_PROGRAM_TYPE_GLSL);
-
- state.unit = 0;
- state.gl_program = gl_program;
- state.priv = priv;
-
- if (program_changed)
- cogl_pipeline_foreach_layer (pipeline,
- get_uniform_cb,
- &state);
-
- state.unit = 0;
- state.update_all = (program_changed ||
- priv->last_used_for_pipeline != pipeline);
-
- cogl_pipeline_foreach_layer (pipeline,
- update_constants_cb,
- &state);
-
-#ifdef HAVE_COGL_GLES2
- if (program_changed)
- {
- int i;
-
- clear_attribute_cache (priv);
- clear_flushed_matrix_stacks (priv);
-
- for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
- GE_RET( priv->builtin_uniform_locations[i],
- glGetUniformLocation (gl_program,
- builtin_uniforms[i].uniform_name) );
-
- GE_RET( priv->modelview_uniform,
- glGetUniformLocation (gl_program,
- "cogl_modelview_matrix") );
-
- GE_RET( priv->projection_uniform,
- glGetUniformLocation (gl_program,
- "cogl_projection_matrix") );
-
- GE_RET( priv->mvp_uniform,
- glGetUniformLocation (gl_program,
- "cogl_modelview_projection_matrix") );
- }
- if (program_changed ||
- priv->last_used_for_pipeline != pipeline)
- priv->dirty_builtin_uniforms = ~(unsigned long) 0;
-
- update_builtin_uniforms (pipeline, gl_program, priv);
-#endif
-
- if (user_program)
- _cogl_program_flush_uniforms (user_program,
- gl_program,
- program_changed);
-
- /* We need to track the last pipeline that the program was used with
- * so know if we need to update all of the uniforms */
- priv->last_used_for_pipeline = pipeline;
-}
-
-static void
-_cogl_pipeline_progend_glsl_pre_change_notify (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color)
-{
- if ((change & COGL_PIPELINE_STATE_AFFECTS_FRAGMENT_CODEGEN))
- dirty_glsl_program_state (pipeline);
-#ifdef HAVE_COGL_GLES2
- else
- {
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (builtin_uniforms); i++)
- if ((change & builtin_uniforms[i].change))
- {
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
- if (priv)
- priv->dirty_builtin_uniforms |= 1 << i;
- return;
- }
- }
-#endif /* HAVE_COGL_GLES2 */
-}
-
-/* NB: layers are considered immutable once they have any dependants
- * so although multiple pipelines can end up depending on a single
- * static layer, we can guarantee that if a layer is being *changed*
- * then it can only have one pipeline depending on it.
- *
- * XXX: Don't forget this is *pre* change, we can't read the new value
- * yet!
- */
-static void
-_cogl_pipeline_progend_glsl_layer_pre_change_notify (
- CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_FRAGMENT_CODEGEN))
- {
- dirty_glsl_program_state (owner);
- return;
- }
-
- if (change & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT)
- {
- CoglPipelineProgendPrivate *priv = get_glsl_priv (owner);
- if (priv)
- {
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- priv->unit_state[unit_index].dirty_combine_constant = TRUE;
- }
- }
-
- if (change & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
- {
- CoglPipelineProgendPrivate *priv = get_glsl_priv (owner);
- if (priv)
- {
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- priv->unit_state[unit_index].dirty_texture_matrix = TRUE;
- }
- }
-}
-
-#ifdef HAVE_COGL_GLES2
-
-static void
-flush_modelview_cb (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data)
-{
- CoglPipelineProgendPrivate *priv = user_data;
-
- GE( glUniformMatrix4fv (priv->modelview_uniform, 1, FALSE,
- cogl_matrix_get_array (matrix)) );
-}
-
-static void
-flush_projection_cb (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data)
-{
- CoglPipelineProgendPrivate *priv = user_data;
-
- GE( glUniformMatrix4fv (priv->projection_uniform, 1, FALSE,
- cogl_matrix_get_array (matrix)) );
-}
-
-typedef struct
-{
- CoglPipelineProgendPrivate *priv;
- const CoglMatrix *projection_matrix;
-} FlushCombinedData;
-
-static void
-flush_combined_step_two_cb (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data)
-{
- FlushCombinedData *data = user_data;
- CoglMatrix mvp_matrix;
-
- /* If the modelview is the identity then we can bypass the matrix
- multiplication */
- if (is_identity)
- GE( glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE,
- cogl_matrix_get_array (data->projection_matrix)) );
- else
- {
- cogl_matrix_multiply (&mvp_matrix,
- data->projection_matrix,
- matrix);
-
- GE( glUniformMatrix4fv (data->priv->mvp_uniform, 1, FALSE,
- cogl_matrix_get_array (&mvp_matrix)) );
- }
-}
-
-static void
-flush_combined_step_one_cb (gboolean is_identity,
- const CoglMatrix *matrix,
- void *user_data)
-{
- FlushCombinedData data;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- data.priv = user_data;
- data.projection_matrix = matrix;
-
- _cogl_matrix_stack_prepare_for_flush (ctx->flushed_modelview_stack,
- COGL_MATRIX_MODELVIEW,
- flush_combined_step_two_cb,
- &data);
-}
-
-static void
-_cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
-{
- CoglPipelineProgendPrivate *priv = get_glsl_priv (pipeline);
- gboolean modelview_changed;
- gboolean projection_changed;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* We only need to update the matrices if we're using the the GLSL
- vertend, but this is a requirement on GLES2 anyway */
- g_return_if_fail (pipeline->vertend == COGL_PIPELINE_VERTEND_GLSL);
-
- priv = get_glsl_priv (pipeline);
-
- /* An initial pipeline is flushed while creating the context. At
- this point there are no matrices flushed so we can't do
- anything */
- if (ctx->flushed_modelview_stack == NULL ||
- ctx->flushed_projection_stack == NULL)
- return;
-
- /* When flushing from the journal the modelview matrix is usually
- the identity matrix so it makes sense to optimise this case by
- specifically checking whether we already have the identity matrix
- which will catch a lot of common cases of redundant flushing */
- if (priv->flushed_modelview_is_identity &&
- _cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack))
- modelview_changed = FALSE;
- else
- modelview_changed =
- priv->flushed_modelview_stack != ctx->flushed_modelview_stack ||
- priv->flushed_modelview_stack_age !=
- _cogl_matrix_stack_get_age (priv->flushed_modelview_stack);
-
- projection_changed =
- priv->flushed_projection_stack != ctx->flushed_projection_stack ||
- priv->flushed_projection_stack_age !=
- _cogl_matrix_stack_get_age (priv->flushed_projection_stack);
-
- if (modelview_changed)
- {
- cogl_object_ref (ctx->flushed_modelview_stack);
- if (priv->flushed_modelview_stack)
- cogl_object_unref (priv->flushed_modelview_stack);
- priv->flushed_modelview_stack = ctx->flushed_modelview_stack;
- priv->flushed_modelview_stack_age =
- _cogl_matrix_stack_get_age (ctx->flushed_modelview_stack);
- priv->flushed_modelview_is_identity =
- _cogl_matrix_stack_has_identity_flag (ctx->flushed_modelview_stack);
-
- if (priv->modelview_uniform != -1)
- _cogl_matrix_stack_prepare_for_flush (priv->flushed_modelview_stack,
- COGL_MATRIX_MODELVIEW,
- flush_modelview_cb,
- priv);
- }
-
- if (projection_changed)
- {
- cogl_object_ref (ctx->flushed_projection_stack);
- if (priv->flushed_projection_stack)
- cogl_object_unref (priv->flushed_projection_stack);
- priv->flushed_projection_stack = ctx->flushed_projection_stack;
- priv->flushed_projection_stack_age =
- _cogl_matrix_stack_get_age (ctx->flushed_projection_stack);
-
- if (priv->projection_uniform != -1)
- _cogl_matrix_stack_prepare_for_flush (priv->flushed_projection_stack,
- COGL_MATRIX_PROJECTION,
- flush_projection_cb,
- priv);
- }
-
- if (priv->mvp_uniform != -1 && (modelview_changed || projection_changed))
- _cogl_matrix_stack_prepare_for_flush (ctx->flushed_projection_stack,
- COGL_MATRIX_PROJECTION,
- flush_combined_step_one_cb,
- priv);
-}
-
-static void
-update_float_uniform (CoglPipeline *pipeline,
- int uniform_location,
- void *getter_func)
-{
- float (* float_getter_func) (CoglPipeline *) = getter_func;
- float value;
-
- value = float_getter_func (pipeline);
- GE( glUniform1f (uniform_location, value) );
-}
-
-#endif
-
-const CoglPipelineProgend _cogl_pipeline_glsl_progend =
- {
- _cogl_pipeline_progend_glsl_end,
- _cogl_pipeline_progend_glsl_pre_change_notify,
- _cogl_pipeline_progend_glsl_layer_pre_change_notify,
-#ifdef HAVE_COGL_GLES2
- _cogl_pipeline_progend_glsl_pre_paint
-#else
- NULL
-#endif
- };
-
-#endif /* COGL_PIPELINE_PROGEND_GLSL */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H
-#define __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-
-extern const CoglPipelineVertend _cogl_pipeline_fixed_vertend;
-
-#endif /* __COGL_PIPELINE_VERTEND_FIXED_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#ifdef COGL_PIPELINE_VERTEND_FIXED
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-program-private.h"
-
-const CoglPipelineVertend _cogl_pipeline_fixed_vertend;
-
-static gboolean
-_cogl_pipeline_vertend_fixed_start (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference)
-{
- CoglProgram *user_program;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_FIXED)))
- return FALSE;
-
- /* If there is a user program with a vertex shader then the
- appropriate backend for that language should handle it. We can
- still use the fixed vertex backend if the program only contains
- a fragment shader */
- user_program = cogl_pipeline_get_user_program (pipeline);
- if (user_program != COGL_INVALID_HANDLE &&
- _cogl_program_has_vertex_shader (user_program))
- return FALSE;
-
- _cogl_use_vertex_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_vertend_fixed_add_layer (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference)
-{
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
- {
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, state);
-
- _cogl_matrix_stack_set (unit->matrix_stack,
- &authority->big_state->matrix);
-
- _cogl_set_active_texture_unit (unit_index);
-
- _cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
- }
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_vertend_fixed_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference)
-{
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
-
- if (ctx->point_size_cache != authority->big_state->point_size)
- {
- GE( glPointSize (authority->big_state->point_size) );
- ctx->point_size_cache = authority->big_state->point_size;
- }
- }
-
- return TRUE;
-}
-
-const CoglPipelineVertend _cogl_pipeline_fixed_vertend =
-{
- _cogl_pipeline_vertend_fixed_start,
- _cogl_pipeline_vertend_fixed_add_layer,
- _cogl_pipeline_vertend_fixed_end,
- NULL, /* pipeline_change_notify */
- NULL /* layer_change_notify */
-};
-
-#endif /* COGL_PIPELINE_VERTEND_FIXED */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H
-#define __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H
-
-#include "cogl-pipeline-private.h"
-
-extern const CoglPipelineVertend _cogl_pipeline_glsl_vertend;
-
-GLuint
-_cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline);
-
-#endif /* __COGL_PIPELINE_VERTEND_GLSL_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#ifdef COGL_PIPELINE_VERTEND_GLSL
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-program-private.h"
-#include "cogl-pipeline-vertend-glsl-private.h"
-
-#ifndef HAVE_COGL_GLES2
-
-#define glCreateShader ctx->drv.pf_glCreateShader
-#define glGetShaderiv ctx->drv.pf_glGetShaderiv
-#define glGetShaderInfoLog ctx->drv.pf_glGetShaderInfoLog
-#define glCompileShader ctx->drv.pf_glCompileShader
-#define glShaderSource ctx->drv.pf_glShaderSource
-#define glDeleteShader ctx->drv.pf_glDeleteShader
-
-#endif /* HAVE_COGL_GLES2 */
-
-const CoglPipelineVertend _cogl_pipeline_glsl_vertend;
-
-typedef struct
-{
- unsigned int ref_count;
-
- GLuint gl_shader;
- GString *header, *source;
-
- /* Age of the user program that was current when the shader was
- generated. We need to keep track of this because if the user
- program changes then we may need to redecide whether to generate
- a shader at all */
- unsigned int user_program_age;
-} CoglPipelineVertendPrivate;
-
-static CoglUserDataKey glsl_priv_key;
-
-static CoglPipelineVertendPrivate *
-get_glsl_priv (CoglPipeline *pipeline)
-{
- return cogl_object_get_user_data (COGL_OBJECT (pipeline), &glsl_priv_key);
-}
-
-static void
-destroy_glsl_priv (void *user_data)
-{
- CoglPipelineVertendPrivate *priv = user_data;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (--priv->ref_count == 0)
- {
- if (priv->gl_shader)
- GE( glDeleteShader (priv->gl_shader) );
-
- g_slice_free (CoglPipelineVertendPrivate, priv);
- }
-}
-
-static void
-set_glsl_priv (CoglPipeline *pipeline, CoglPipelineVertendPrivate *priv)
-{
- cogl_object_set_user_data (COGL_OBJECT (pipeline),
- &glsl_priv_key,
- priv,
- destroy_glsl_priv);
-}
-
-static void
-dirty_glsl_shader_state (CoglPipeline *pipeline)
-{
- cogl_object_set_user_data (COGL_OBJECT (pipeline),
- &glsl_priv_key,
- NULL,
- destroy_glsl_priv);
-}
-
-GLuint
-_cogl_pipeline_vertend_glsl_get_shader (CoglPipeline *pipeline)
-{
- CoglPipelineVertendPrivate *priv = get_glsl_priv (pipeline);
-
- if (priv)
- return priv->gl_shader;
- else
- return 0;
-}
-
-static gboolean
-_cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
- int n_layers,
- unsigned long pipelines_difference)
-{
- CoglPipelineVertendPrivate *priv;
- CoglProgram *user_program;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
- return FALSE;
-
- user_program = cogl_pipeline_get_user_program (pipeline);
-
- /* If the user program has a vertex shader that isn't GLSL then the
- appropriate vertend for that language should handle it */
- if (user_program &&
- _cogl_program_has_vertex_shader (user_program) &&
- _cogl_program_get_language (user_program) != COGL_SHADER_LANGUAGE_GLSL)
- return FALSE;
-
- /* Now lookup our glsl backend private state (allocating if
- * necessary) */
- priv = get_glsl_priv (pipeline);
-
- if (priv == NULL)
- {
- CoglPipeline *authority;
-
- /* Get the authority for anything affecting vertex shader
- state */
- authority = _cogl_pipeline_find_equivalent_parent
- (pipeline,
- COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN &
- ~COGL_PIPELINE_STATE_LAYERS,
- COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN);
-
- priv = get_glsl_priv (authority);
-
- if (priv == NULL)
- {
- priv = g_slice_new0 (CoglPipelineVertendPrivate);
- priv->ref_count = 1;
- set_glsl_priv (authority, priv);
- }
-
- if (authority != pipeline)
- {
- priv->ref_count++;
- set_glsl_priv (pipeline, priv);
- }
- }
-
- if (priv->gl_shader)
- {
- /* If we already have a valid GLSL shader then we don't need to
- generate a new one. However if there's a user program and it
- has changed since the last link then we do need a new shader */
- if (user_program == NULL ||
- priv->user_program_age == user_program->age)
- return TRUE;
-
- /* We need to recreate the shader so destroy the existing one */
- GE( glDeleteShader (priv->gl_shader) );
- priv->gl_shader = 0;
- }
-
- /* If we make it here then we have a priv struct without a gl_shader
- either because this is the first time we've encountered it or
- because the user program has changed */
-
- if (user_program)
- priv->user_program_age = user_program->age;
-
- /* If the user program contains a vertex shader then we don't need
- to generate one */
- if (user_program &&
- _cogl_program_has_vertex_shader (user_program))
- return TRUE;
-
- /* We reuse two grow-only GStrings for code-gen. One string
- contains the uniform and attribute declarations while the
- other contains the main function. We need two strings
- because we need to dynamically declare attributes as the
- add_layer callback is invoked */
- g_string_set_size (ctx->codegen_header_buffer, 0);
- g_string_set_size (ctx->codegen_source_buffer, 0);
- priv->header = ctx->codegen_header_buffer;
- priv->source = ctx->codegen_source_buffer;
-
- g_string_append (priv->source,
- "void\n"
- "main ()\n"
- "{\n");
-
-#ifdef HAVE_COGL_GLES2
-
- /* There is no builtin uniform for the pointsize on GLES2 so we need
- to copy it from the custom uniform in the vertex shader */
- g_string_append (priv->source,
- " cogl_point_size_out = cogl_point_size_in;\n");
-
-#else /* HAVE_COGL_GLES2 */
-
- /* On regular OpenGL we'll just flush the point size builtin */
- if (pipelines_difference & COGL_PIPELINE_STATE_POINT_SIZE)
- {
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
-
- if (ctx->point_size_cache != authority->big_state->point_size)
- {
- GE( glPointSize (authority->big_state->point_size) );
- ctx->point_size_cache = authority->big_state->point_size;
- }
- }
-
-#endif /* HAVE_COGL_GLES2 */
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- unsigned long layers_difference)
-{
- CoglPipelineVertendPrivate *priv;
- int unit_index;
-
- priv = get_glsl_priv (pipeline);
-
- unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
-#ifndef HAVE_COGL_GLES2
-
- /* We are using the fixed function uniforms for the user matrices
- and the only way to set them is with the fixed function API so we
- still need to flush them here */
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX)
- {
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, state);
- CoglTextureUnit *unit = _cogl_get_texture_unit (unit_index);
-
- _cogl_matrix_stack_set (unit->matrix_stack,
- &authority->big_state->matrix);
-
- _cogl_set_active_texture_unit (unit_index);
-
- _cogl_matrix_stack_flush_to_gl (unit->matrix_stack, COGL_MATRIX_TEXTURE);
- }
-
-#endif /* HAVE_COGL_GLES2 */
-
- if (priv->source == NULL)
- return TRUE;
-
- /* Transform the texture coordinates by the layer's user matrix.
- *
- * FIXME: this should avoid doing the transform if there is no user
- * matrix set. This might need a separate layer state flag for
- * whether there is a user matrix
- *
- * FIXME: we could be more clever here and try to detect if the
- * fragment program is going to use the texture coordinates and
- * avoid setting them if not
- */
-
- g_string_append_printf (priv->source,
- " cogl_tex_coord_out[%i] = "
- "cogl_texture_matrix[%i] * cogl_tex_coord%i_in;\n",
- unit_index, unit_index, unit_index);
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
- unsigned long pipelines_difference)
-{
- CoglPipelineVertendPrivate *priv;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- priv = get_glsl_priv (pipeline);
-
- if (priv->source)
- {
- const char *source_strings[2];
- GLint lengths[2];
- GLint compile_status;
- GLuint shader;
- int n_layers;
-
- COGL_STATIC_COUNTER (vertend_glsl_compile_counter,
- "glsl vertex compile counter",
- "Increments each time a new GLSL "
- "vertex shader is compiled",
- 0 /* no application private data */);
- COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter);
-
- g_string_append (priv->source,
- " cogl_position_out = "
- "cogl_modelview_projection_matrix * "
- "cogl_position_in;\n"
- " cogl_color_out = cogl_color_in;\n"
- "}\n");
-
- GE_RET( shader, glCreateShader (GL_VERTEX_SHADER) );
-
- lengths[0] = priv->header->len;
- source_strings[0] = priv->header->str;
- lengths[1] = priv->source->len;
- source_strings[1] = priv->source->str;
-
- n_layers = cogl_pipeline_get_n_layers (pipeline);
-
- _cogl_shader_set_source_with_boilerplate (shader, GL_VERTEX_SHADER,
- n_layers,
- 2, /* count */
- source_strings, lengths);
-
- GE( glCompileShader (shader) );
- GE( glGetShaderiv (shader, GL_COMPILE_STATUS, &compile_status) );
-
- if (!compile_status)
- {
- GLint len = 0;
- char *shader_log;
-
- GE( glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &len) );
- shader_log = g_alloca (len);
- GE( glGetShaderInfoLog (shader, len, &len, shader_log) );
- g_warning ("Shader compilation failed:\n%s", shader_log);
- }
-
- priv->header = NULL;
- priv->source = NULL;
- priv->gl_shader = shader;
- }
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_vertend_glsl_pre_change_notify (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color)
-{
- if ((change & COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN))
- dirty_glsl_shader_state (pipeline);
-}
-
-/* NB: layers are considered immutable once they have any dependants
- * so although multiple pipelines can end up depending on a single
- * static layer, we can guarantee that if a layer is being *changed*
- * then it can only have one pipeline depending on it.
- *
- * XXX: Don't forget this is *pre* change, we can't read the new value
- * yet!
- */
-static void
-_cogl_pipeline_vertend_glsl_layer_pre_change_notify (
- CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- CoglPipelineVertendPrivate *priv;
-
- priv = get_glsl_priv (owner);
- if (!priv)
- return;
-
- if ((change & COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN))
- {
- dirty_glsl_shader_state (owner);
- return;
- }
-
- /* TODO: we could be saving snippets of texture combine code along
- * with each layer and then when a layer changes we would just free
- * the snippet. */
-}
-
-const CoglPipelineVertend _cogl_pipeline_glsl_vertend =
- {
- _cogl_pipeline_vertend_glsl_start,
- _cogl_pipeline_vertend_glsl_add_layer,
- _cogl_pipeline_vertend_glsl_end,
- _cogl_pipeline_vertend_glsl_pre_change_notify,
- _cogl_pipeline_vertend_glsl_layer_pre_change_notify
- };
-
-#endif /* COGL_PIPELINE_VERTEND_GLSL */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-object.h"
-
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-blend-string.h"
-#include "cogl-journal-private.h"
-#include "cogl-color-private.h"
-#include "cogl-util.h"
-#include "cogl-profile.h"
-
-#include <glib.h>
-#include <glib/gprintf.h>
-#include <string.h>
-
-typedef gboolean (*CoglPipelineStateComparitor) (CoglPipeline *authority0,
- CoglPipeline *authority1);
-
-static CoglPipelineLayer *_cogl_pipeline_layer_copy (CoglPipelineLayer *layer);
-
-static void _cogl_pipeline_free (CoglPipeline *tex);
-static void _cogl_pipeline_layer_free (CoglPipelineLayer *layer);
-static void _cogl_pipeline_add_layer_difference (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- gboolean inc_n_layers);
-static void handle_automatic_blend_enable (CoglPipeline *pipeline,
- CoglPipelineState changes);
-static void recursively_free_layer_caches (CoglPipeline *pipeline);
-static gboolean _cogl_pipeline_is_weak (CoglPipeline *pipeline);
-
-const CoglPipelineFragend *_cogl_pipeline_fragends[COGL_PIPELINE_N_FRAGENDS];
-const CoglPipelineVertend *_cogl_pipeline_vertends[COGL_PIPELINE_N_VERTENDS];
-/* The 'MAX' here is so that we don't define an empty array when there
- are no progends */
-const CoglPipelineProgend *
-_cogl_pipeline_progends[MAX (COGL_PIPELINE_N_PROGENDS, 1)];
-
-#ifdef COGL_PIPELINE_FRAGEND_GLSL
-#include "cogl-pipeline-fragend-glsl-private.h"
-#endif
-#ifdef COGL_PIPELINE_FRAGEND_ARBFP
-#include "cogl-pipeline-fragend-arbfp-private.h"
-#endif
-#ifdef COGL_PIPELINE_FRAGEND_FIXED
-#include "cogl-pipeline-fragend-fixed-private.h"
-#endif
-#ifdef COGL_PIPELINE_PROGEND_GLSL
-#include "cogl-pipeline-progend-glsl-private.h"
-#endif
-
-#ifdef COGL_PIPELINE_VERTEND_GLSL
-#include "cogl-pipeline-vertend-glsl-private.h"
-#endif
-#ifdef COGL_PIPELINE_VERTEND_FIXED
-#include "cogl-pipeline-vertend-fixed-private.h"
-#endif
-
-COGL_OBJECT_DEFINE (Pipeline, pipeline);
-/* This type was made deprecated before the cogl_is_pipeline_layer
- function was ever exposed in the public headers so there's no need
- to make the cogl_is_pipeline_layer function public. We use INTERNAL
- so that the cogl_is_* function won't get defined */
-COGL_OBJECT_INTERNAL_DEFINE (PipelineLayer, pipeline_layer);
-
-GQuark
-_cogl_pipeline_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-pipeline-error-quark");
-}
-
-static void
-_cogl_pipeline_node_init (CoglPipelineNode *node)
-{
- node->parent = NULL;
- node->has_children = FALSE;
-}
-
-static void
-_cogl_pipeline_node_set_parent_real (CoglPipelineNode *node,
- CoglPipelineNode *parent,
- CoglPipelineNodeUnparentVFunc unparent,
- gboolean take_strong_reference)
-{
- /* NB: the old parent may indirectly be keeping the new parent alive
- * so we have to ref the new parent before unrefing the old.
- *
- * Note: we take a reference here regardless of
- * take_strong_reference because weak children may need special
- * handling when the parent disposes itself which relies on a
- * consistent link to all weak nodes. Once the node is linked to its
- * parent then we remove the reference at the end if
- * take_strong_reference == FALSE. */
- cogl_object_ref (parent);
-
- if (node->parent)
- unparent (node);
-
- if (G_UNLIKELY (parent->has_children))
- parent->children = g_list_prepend (parent->children, node);
- else
- {
- parent->has_children = TRUE;
- parent->first_child = node;
- parent->children = NULL;
- }
-
- node->parent = parent;
- node->has_parent_reference = take_strong_reference;
-
- /* Now that there is a consistent parent->child link we can remove
- * the parent reference if no reference was requested. If it turns
- * out that the new parent was only being kept alive by the old
- * parent then it will be disposed of here. */
- if (!take_strong_reference)
- cogl_object_unref (parent);
-}
-
-static void
-_cogl_pipeline_node_unparent_real (CoglPipelineNode *node)
-{
- CoglPipelineNode *parent = node->parent;
-
- if (parent == NULL)
- return;
-
- g_return_if_fail (parent->has_children);
-
- if (parent->first_child == node)
- {
- if (parent->children)
- {
- parent->first_child = parent->children->data;
- parent->children =
- g_list_delete_link (parent->children, parent->children);
- }
- else
- parent->has_children = FALSE;
- }
- else
- parent->children = g_list_remove (parent->children, node);
-
- if (node->has_parent_reference)
- cogl_object_unref (parent);
-
- node->parent = NULL;
-}
-
-void
-_cogl_pipeline_node_foreach_child (CoglPipelineNode *node,
- CoglPipelineNodeChildCallback callback,
- void *user_data)
-{
- if (node->has_children)
- {
- callback (node->first_child, user_data);
- g_list_foreach (node->children, (GFunc)callback, user_data);
- }
-}
-
-/*
- * This initializes the first pipeline owned by the Cogl context. All
- * subsequently instantiated pipelines created via the cogl_pipeline_new()
- * API will initially be a copy of this pipeline.
- *
- * The default pipeline is the topmost ancester for all pipelines.
- */
-void
-_cogl_pipeline_init_default_pipeline (void)
-{
- /* Create new - blank - pipeline */
- CoglPipeline *pipeline = g_slice_new0 (CoglPipeline);
- /* XXX: NB: It's important that we zero this to avoid polluting
- * pipeline hash values with un-initialized data */
- CoglPipelineBigState *big_state = g_slice_new0 (CoglPipelineBigState);
- CoglPipelineLightingState *lighting_state = &big_state->lighting_state;
- CoglPipelineAlphaFuncState *alpha_state = &big_state->alpha_state;
- CoglPipelineBlendState *blend_state = &big_state->blend_state;
- CoglPipelineDepthState *depth_state = &big_state->depth_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Take this opportunity to setup the backends... */
-#ifdef COGL_PIPELINE_FRAGEND_GLSL
- _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_GLSL] =
- &_cogl_pipeline_glsl_fragend;
-#endif
-#ifdef COGL_PIPELINE_FRAGEND_ARBFP
- _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_ARBFP] =
- &_cogl_pipeline_arbfp_fragend;
-#endif
-#ifdef COGL_PIPELINE_FRAGEND_FIXED
- _cogl_pipeline_fragends[COGL_PIPELINE_FRAGEND_FIXED] =
- &_cogl_pipeline_fixed_fragend;
-#endif
-#ifdef COGL_PIPELINE_PROGEND_GLSL
- _cogl_pipeline_progends[COGL_PIPELINE_PROGEND_GLSL] =
- &_cogl_pipeline_glsl_progend;
-#endif
-
-#ifdef COGL_PIPELINE_VERTEND_GLSL
- _cogl_pipeline_vertends[COGL_PIPELINE_VERTEND_GLSL] =
- &_cogl_pipeline_glsl_vertend;
-#endif
-#ifdef COGL_PIPELINE_VERTEND_FIXED
- _cogl_pipeline_vertends[COGL_PIPELINE_VERTEND_FIXED] =
- &_cogl_pipeline_fixed_vertend;
-#endif
-
- _cogl_pipeline_node_init (COGL_PIPELINE_NODE (pipeline));
-
- pipeline->is_weak = FALSE;
- pipeline->journal_ref_count = 0;
- pipeline->fragend = COGL_PIPELINE_FRAGEND_UNDEFINED;
- pipeline->vertend = COGL_PIPELINE_VERTEND_UNDEFINED;
- pipeline->differences = COGL_PIPELINE_STATE_ALL_SPARSE;
-
- pipeline->real_blend_enable = FALSE;
-
- pipeline->blend_enable = COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC;
- pipeline->layer_differences = NULL;
- pipeline->n_layers = 0;
-
- pipeline->big_state = big_state;
- pipeline->has_big_state = TRUE;
-
- pipeline->static_breadcrumb = "default pipeline";
- pipeline->has_static_breadcrumb = TRUE;
-
- pipeline->age = 0;
-
- /* Use the same defaults as the GL spec... */
- cogl_color_init_from_4ub (&pipeline->color, 0xff, 0xff, 0xff, 0xff);
-
- /* Use the same defaults as the GL spec... */
- lighting_state->ambient[0] = 0.2;
- lighting_state->ambient[1] = 0.2;
- lighting_state->ambient[2] = 0.2;
- lighting_state->ambient[3] = 1.0;
-
- lighting_state->diffuse[0] = 0.8;
- lighting_state->diffuse[1] = 0.8;
- lighting_state->diffuse[2] = 0.8;
- lighting_state->diffuse[3] = 1.0;
-
- lighting_state->specular[0] = 0;
- lighting_state->specular[1] = 0;
- lighting_state->specular[2] = 0;
- lighting_state->specular[3] = 1.0;
-
- lighting_state->emission[0] = 0;
- lighting_state->emission[1] = 0;
- lighting_state->emission[2] = 0;
- lighting_state->emission[3] = 1.0;
-
- lighting_state->shininess = 0.0f;
-
- /* Use the same defaults as the GL spec... */
- alpha_state->alpha_func = COGL_PIPELINE_ALPHA_FUNC_ALWAYS;
- alpha_state->alpha_func_reference = 0.0;
-
- /* Not the same as the GL default, but seems saner... */
-#ifndef HAVE_COGL_GLES
- blend_state->blend_equation_rgb = GL_FUNC_ADD;
- blend_state->blend_equation_alpha = GL_FUNC_ADD;
- blend_state->blend_src_factor_alpha = GL_ONE;
- blend_state->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA;
- cogl_color_init_from_4ub (&blend_state->blend_constant,
- 0x00, 0x00, 0x00, 0x00);
-#endif
- blend_state->blend_src_factor_rgb = GL_ONE;
- blend_state->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
-
- big_state->user_program = COGL_INVALID_HANDLE;
-
- /* The same as the GL defaults */
- depth_state->depth_test_enabled = FALSE;
- depth_state->depth_test_function = COGL_DEPTH_TEST_FUNCTION_LESS;
- depth_state->depth_writing_enabled = TRUE;
- depth_state->depth_range_near = 0;
- depth_state->depth_range_far = 1;
-
- big_state->point_size = 1.0f;
-
- ctx->default_pipeline = _cogl_pipeline_object_new (pipeline);
-}
-
-static void
-_cogl_pipeline_unparent (CoglPipelineNode *pipeline)
-{
- /* Chain up */
- _cogl_pipeline_node_unparent_real (pipeline);
-}
-
-static gboolean
-recursively_free_layer_caches_cb (CoglPipelineNode *node,
- void *user_data)
-{
- recursively_free_layer_caches (COGL_PIPELINE (node));
- return TRUE;
-}
-
-/* This recursively frees the layers_cache of a pipeline and all of
- * its descendants.
- *
- * For instance if we change a pipelines ->layer_differences list
- * then that pipeline and all of its descendants may now have
- * incorrect layer caches. */
-static void
-recursively_free_layer_caches (CoglPipeline *pipeline)
-{
- /* Note: we maintain the invariable that if a pipeline already has a
- * dirty layers_cache then so do all of its descendants. */
- if (pipeline->layers_cache_dirty)
- return;
-
- if (G_UNLIKELY (pipeline->layers_cache != pipeline->short_layers_cache))
- g_slice_free1 (sizeof (CoglPipelineLayer *) * pipeline->n_layers,
- pipeline->layers_cache);
- pipeline->layers_cache_dirty = TRUE;
-
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- recursively_free_layer_caches_cb,
- NULL);
-}
-
-static void
-_cogl_pipeline_set_parent (CoglPipeline *pipeline,
- CoglPipeline *parent,
- gboolean take_strong_reference)
-{
- /* Chain up */
- _cogl_pipeline_node_set_parent_real (COGL_PIPELINE_NODE (pipeline),
- COGL_PIPELINE_NODE (parent),
- _cogl_pipeline_unparent,
- take_strong_reference);
-
- /* Since we just changed the ancestry of the pipeline its cache of
- * layers could now be invalid so free it... */
- if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
- recursively_free_layer_caches (pipeline);
-
- /* If the backends are also caching state along with the pipeline
- * that depends on the pipeline's ancestry then it may be notified
- * here...
- */
- if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
- _cogl_pipeline_fragends[pipeline->fragend]->pipeline_set_parent_notify)
- {
- const CoglPipelineFragend *fragend =
- _cogl_pipeline_fragends[pipeline->fragend];
- fragend->pipeline_set_parent_notify (pipeline);
- }
-}
-
-static void
-_cogl_pipeline_promote_weak_ancestors (CoglPipeline *strong)
-{
- CoglPipelineNode *n;
-
- g_return_if_fail (!strong->is_weak);
-
- for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent)
- {
- CoglPipeline *pipeline = COGL_PIPELINE (n);
-
- cogl_object_ref (pipeline);
-
- if (!pipeline->is_weak)
- return;
- }
-}
-
-static void
-_cogl_pipeline_revert_weak_ancestors (CoglPipeline *strong)
-{
- CoglPipeline *parent = _cogl_pipeline_get_parent (strong);
- CoglPipelineNode *n;
-
- g_return_if_fail (!strong->is_weak);
-
- if (!parent || !parent->is_weak)
- return;
-
- for (n = COGL_PIPELINE_NODE (strong)->parent; n; n = n->parent)
- {
- CoglPipeline *pipeline = COGL_PIPELINE (n);
-
- cogl_object_unref (pipeline);
-
- if (!pipeline->is_weak)
- return;
- }
-}
-
-/* XXX: Always have an eye out for opportunities to lower the cost of
- * cogl_pipeline_copy. */
-static CoglPipeline *
-_cogl_pipeline_copy (CoglPipeline *src, gboolean is_weak)
-{
- CoglPipeline *pipeline = g_slice_new (CoglPipeline);
-
- _cogl_pipeline_node_init (COGL_PIPELINE_NODE (pipeline));
-
- pipeline->is_weak = is_weak;
-
- pipeline->journal_ref_count = 0;
-
- pipeline->differences = 0;
-
- pipeline->has_big_state = FALSE;
-
- /* NB: real_blend_enable isn't a sparse property, it's valid for
- * every pipeline node so we have fast access to it. */
- pipeline->real_blend_enable = src->real_blend_enable;
-
- /* XXX:
- * consider generalizing the idea of "cached" properties. These
- * would still have an authority like other sparse properties but
- * you wouldn't have to walk up the ancestry to find the authority
- * because the value would be cached directly in each pipeline.
- */
-
- pipeline->layers_cache_dirty = TRUE;
- pipeline->deprecated_get_layers_list_dirty = TRUE;
-
- pipeline->fragend = src->fragend;
- pipeline->fragend_priv_set_mask = 0;
-
- pipeline->vertend = src->vertend;
-
- pipeline->has_static_breadcrumb = FALSE;
-
- pipeline->age = 0;
-
- _cogl_pipeline_set_parent (pipeline, src, !is_weak);
-
- /* The semantics for copying a weak pipeline are that we promote all
- * weak ancestors to temporarily become strong pipelines until the
- * copy is freed. */
- if (!is_weak)
- _cogl_pipeline_promote_weak_ancestors (pipeline);
-
- return _cogl_pipeline_object_new (pipeline);
-}
-
-CoglPipeline *
-cogl_pipeline_copy (CoglPipeline *src)
-{
- return _cogl_pipeline_copy (src, FALSE);
-}
-
-CoglPipeline *
-_cogl_pipeline_weak_copy (CoglPipeline *pipeline,
- CoglPipelineDestroyCallback callback,
- void *user_data)
-{
- CoglPipeline *copy;
- CoglPipeline *copy_pipeline;
-
- copy = _cogl_pipeline_copy (pipeline, TRUE);
- copy_pipeline = COGL_PIPELINE (copy);
- copy_pipeline->destroy_callback = callback;
- copy_pipeline->destroy_data = user_data;
-
- return copy;
-}
-
-CoglPipeline *
-cogl_pipeline_new (void)
-{
- CoglPipeline *new;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- new = cogl_pipeline_copy (ctx->default_pipeline);
- _cogl_pipeline_set_static_breadcrumb (new, "new");
- return new;
-}
-
-static void
-_cogl_pipeline_fragend_free_priv (CoglPipeline *pipeline)
-{
- if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
- _cogl_pipeline_fragends[pipeline->fragend]->free_priv)
- {
- const CoglPipelineFragend *fragend =
- _cogl_pipeline_fragends[pipeline->fragend];
- fragend->free_priv (pipeline);
- }
-}
-
-static gboolean
-destroy_weak_children_cb (CoglPipelineNode *node,
- void *user_data)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (node);
-
- if (_cogl_pipeline_is_weak (pipeline))
- {
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- destroy_weak_children_cb,
- NULL);
-
- pipeline->destroy_callback (pipeline, pipeline->destroy_data);
- _cogl_pipeline_unparent (COGL_PIPELINE_NODE (pipeline));
- }
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_free (CoglPipeline *pipeline)
-{
- if (!pipeline->is_weak)
- _cogl_pipeline_revert_weak_ancestors (pipeline);
-
- /* Weak pipelines don't take a reference on their parent */
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- destroy_weak_children_cb,
- NULL);
-
- g_assert (!COGL_PIPELINE_NODE (pipeline)->has_children);
-
- _cogl_pipeline_fragend_free_priv (pipeline);
-
- _cogl_pipeline_unparent (COGL_PIPELINE_NODE (pipeline));
-
- if (pipeline->differences & COGL_PIPELINE_STATE_USER_SHADER &&
- pipeline->big_state->user_program)
- cogl_handle_unref (pipeline->big_state->user_program);
-
- if (pipeline->differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
- g_slice_free (CoglPipelineBigState, pipeline->big_state);
-
- if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
- {
- g_list_foreach (pipeline->layer_differences,
- (GFunc)cogl_object_unref, NULL);
- g_list_free (pipeline->layer_differences);
- }
-
- g_slice_free (CoglPipeline, pipeline);
-}
-
-gboolean
-_cogl_pipeline_get_real_blend_enabled (CoglPipeline *pipeline)
-{
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- return pipeline->real_blend_enable;
-}
-
-/* XXX: Think twice before making this non static since it is used
- * heavily and we expect the compiler to inline it...
- */
-static CoglPipelineLayer *
-_cogl_pipeline_layer_get_parent (CoglPipelineLayer *layer)
-{
- CoglPipelineNode *parent_node = COGL_PIPELINE_NODE (layer)->parent;
- return COGL_PIPELINE_LAYER (parent_node);
-}
-
-CoglPipelineLayer *
-_cogl_pipeline_layer_get_authority (CoglPipelineLayer *layer,
- unsigned long difference)
-{
- CoglPipelineLayer *authority = layer;
- while (!(authority->differences & difference))
- authority = _cogl_pipeline_layer_get_parent (authority);
- return authority;
-}
-
-int
-_cogl_pipeline_layer_get_unit_index (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, COGL_PIPELINE_LAYER_STATE_UNIT);
- return authority->unit_index;
-}
-
-static void
-_cogl_pipeline_update_layers_cache (CoglPipeline *pipeline)
-{
- /* Note: we assume this pipeline is a _LAYERS authority */
- int n_layers;
- CoglPipeline *current;
- int layers_found;
-
- if (G_LIKELY (!pipeline->layers_cache_dirty) ||
- pipeline->n_layers == 0)
- return;
-
- pipeline->layers_cache_dirty = FALSE;
-
- n_layers = pipeline->n_layers;
- if (G_LIKELY (n_layers < G_N_ELEMENTS (pipeline->short_layers_cache)))
- {
- pipeline->layers_cache = pipeline->short_layers_cache;
- memset (pipeline->layers_cache, 0,
- sizeof (CoglPipelineLayer *) *
- G_N_ELEMENTS (pipeline->short_layers_cache));
- }
- else
- {
- pipeline->layers_cache =
- g_slice_alloc0 (sizeof (CoglPipelineLayer *) * n_layers);
- }
-
- /* Notes:
- *
- * Each pipeline doesn't have to contain a complete list of the layers
- * it depends on, some of them are indirectly referenced through the
- * pipeline's ancestors.
- *
- * pipeline->layer_differences only contains a list of layers that
- * have changed in relation to its parent.
- *
- * pipeline->layer_differences is not maintained sorted, but it
- * won't contain multiple layers corresponding to a particular
- * ->unit_index.
- *
- * Some of the ancestor pipelines may reference layers with
- * ->unit_index values >= n_layers so we ignore them.
- *
- * As we ascend through the ancestors we are searching for any
- * CoglPipelineLayers corresponding to the texture ->unit_index
- * values in the range [0,n_layers-1]. As soon as a pointer is found
- * we ignore layers of further ancestors with the same ->unit_index
- * values.
- */
-
- layers_found = 0;
- for (current = pipeline;
- _cogl_pipeline_get_parent (current);
- current = _cogl_pipeline_get_parent (current))
- {
- GList *l;
-
- if (!(current->differences & COGL_PIPELINE_STATE_LAYERS))
- continue;
-
- for (l = current->layer_differences; l; l = l->next)
- {
- CoglPipelineLayer *layer = l->data;
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
-
- if (unit_index < n_layers && !pipeline->layers_cache[unit_index])
- {
- pipeline->layers_cache[unit_index] = layer;
- layers_found++;
- if (layers_found == n_layers)
- return;
- }
- }
- }
-
- g_warn_if_reached ();
-}
-
-/* XXX: Be carefull when using this API that the callback given doesn't result
- * in the layer cache being invalidated during the iteration! */
-void
-_cogl_pipeline_foreach_layer_internal (CoglPipeline *pipeline,
- CoglPipelineInternalLayerCallback callback,
- void *user_data)
-{
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS);
- int n_layers;
- int i;
- gboolean cont;
-
- n_layers = authority->n_layers;
- if (n_layers == 0)
- return;
-
- _cogl_pipeline_update_layers_cache (authority);
-
- for (i = 0, cont = TRUE; i < n_layers && cont == TRUE; i++)
- {
- g_return_if_fail (authority->layers_cache_dirty == FALSE);
- cont = callback (authority->layers_cache[i], user_data);
- }
-}
-
-typedef struct
-{
- int i;
- int *indices;
-} AppendLayerIndexState;
-
-static gboolean
-append_layer_index_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- AppendLayerIndexState *state = user_data;
- state->indices[state->i++] = layer->index;
- return TRUE;
-}
-
-void
-cogl_pipeline_foreach_layer (CoglPipeline *pipeline,
- CoglPipelineLayerCallback callback,
- void *user_data)
-{
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS);
- AppendLayerIndexState state;
- gboolean cont;
- int i;
-
- /* XXX: We don't know what the user is going to want to do to the layers
- * but any modification of layers can result in the layer graph changing
- * which could confuse _cogl_pipeline_foreach_layer_internal(). We first
- * get a list of layer indices which will remain valid so long as the
- * user doesn't remove layers. */
-
- state.i = 0;
- state.indices = g_alloca (authority->n_layers * sizeof (int));
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- append_layer_index_cb,
- &state);
-
- for (i = 0, cont = TRUE; i < authority->n_layers && cont; i++)
- cont = callback (pipeline, state.indices[i], user_data);
-}
-
-static gboolean
-layer_has_alpha_cb (CoglPipelineLayer *layer, void *data)
-{
- CoglPipelineLayer *combine_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_COMBINE);
- CoglPipelineLayerBigState *big_state = combine_authority->big_state;
- CoglPipelineLayer *tex_authority;
- gboolean *has_alpha = data;
-
- /* has_alpha maintains the alpha status for the GL_PREVIOUS layer */
-
- /* For anything but the default texture combine we currently just
- * assume it may result in an alpha value < 1
- *
- * FIXME: we could do better than this. */
- if (big_state->texture_combine_alpha_func !=
- COGL_PIPELINE_COMBINE_FUNC_MODULATE ||
- big_state->texture_combine_alpha_src[0] !=
- COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS ||
- big_state->texture_combine_alpha_op[0] !=
- COGL_PIPELINE_COMBINE_OP_SRC_ALPHA ||
- big_state->texture_combine_alpha_src[1] !=
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE ||
- big_state->texture_combine_alpha_op[1] !=
- COGL_PIPELINE_COMBINE_OP_SRC_ALPHA)
- {
- *has_alpha = TRUE;
- /* return FALSE to stop iterating layers... */
- return FALSE;
- }
-
- /* NB: A layer may have a combine mode set on it but not yet
- * have an associated texture which would mean we'd fallback
- * to the default texture which doesn't have an alpha component
- */
- tex_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
- if (tex_authority->texture &&
- cogl_texture_get_format (tex_authority->texture) & COGL_A_BIT)
- {
- *has_alpha = TRUE;
- /* return FALSE to stop iterating layers... */
- return FALSE;
- }
-
- *has_alpha = FALSE;
- /* return FALSE to continue iterating layers... */
- return TRUE;
-}
-
-static CoglPipeline *
-_cogl_pipeline_get_user_program (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
-
- return authority->big_state->user_program;
-}
-
-static gboolean
-_cogl_pipeline_needs_blending_enabled (CoglPipeline *pipeline,
- unsigned long changes,
- const CoglColor *override_color)
-{
- CoglPipeline *enable_authority;
- CoglPipeline *blend_authority;
- CoglPipelineBlendState *blend_state;
- CoglPipelineBlendEnable enabled;
- unsigned long other_state;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_BLENDING)))
- return FALSE;
-
- enable_authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE);
-
- enabled = enable_authority->blend_enable;
- if (enabled != COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC)
- return enabled == COGL_PIPELINE_BLEND_ENABLE_ENABLED ? TRUE : FALSE;
-
- blend_authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND);
-
- blend_state = &blend_authority->big_state->blend_state;
-
- /* We are trying to identify awkward cases that are equivalent to
- * blending being disable, where the output is simply GL_SRC_COLOR.
- *
- * Note: we assume that all OpenGL drivers will identify the simple
- * case of ADD (ONE, ZERO) as equivalent to blending being disabled.
- *
- * We should update this when we add support for more blend
- * functions...
- */
-
-#ifndef HAVE_COGL_GLES
- /* GLES 1 can't change the function or have separate alpha factors */
- if (blend_state->blend_equation_rgb != GL_FUNC_ADD ||
- blend_state->blend_equation_alpha != GL_FUNC_ADD)
- return TRUE;
-
- if (blend_state->blend_src_factor_alpha != GL_ONE ||
- blend_state->blend_dst_factor_alpha != GL_ONE_MINUS_SRC_ALPHA)
- return TRUE;
-#endif
-
- if (blend_state->blend_src_factor_rgb != GL_ONE ||
- blend_state->blend_dst_factor_rgb != GL_ONE_MINUS_SRC_ALPHA)
- return TRUE;
-
- /* Given the above constraints, it's now a case of finding any
- * SRC_ALPHA that != 1 */
-
- /* In the case of a layer state change we need to check everything
- * else first since they contribute to the has_alpha status of the
- * GL_PREVIOUS layer. */
- if (changes & COGL_PIPELINE_STATE_LAYERS)
- changes = COGL_PIPELINE_STATE_AFFECTS_BLENDING;
-
- if ((override_color && cogl_color_get_alpha_byte (override_color) != 0xff))
- return TRUE;
-
- if (changes & COGL_PIPELINE_STATE_COLOR)
- {
- CoglColor tmp;
- cogl_pipeline_get_color (pipeline, &tmp);
- if (cogl_color_get_alpha_byte (&tmp) != 0xff)
- return TRUE;
- }
-
- if (changes & COGL_PIPELINE_STATE_USER_SHADER)
- {
- /* We can't make any assumptions about the alpha channel if the user
- * is using an unknown fragment shader.
- *
- * TODO: check that it isn't just a vertex shader!
- */
- if (_cogl_pipeline_get_user_program (pipeline) != COGL_INVALID_HANDLE)
- return TRUE;
- }
-
- /* XXX: we should only need to look at these if lighting is enabled
- */
- if (changes & COGL_PIPELINE_STATE_LIGHTING)
- {
- /* XXX: This stuff is showing up in sysprof reports which is
- * silly because lighting isn't currently actually supported
- * by Cogl except for these token properties. When we actually
- * expose lighting support we can avoid these checks when
- * lighting is disabled. */
-#if 0
- CoglColor tmp;
- cogl_pipeline_get_ambient (pipeline, &tmp);
- if (cogl_color_get_alpha_byte (&tmp) != 0xff)
- return TRUE;
- cogl_pipeline_get_diffuse (pipeline, &tmp);
- if (cogl_color_get_alpha_byte (&tmp) != 0xff)
- return TRUE;
- cogl_pipeline_get_specular (pipeline, &tmp);
- if (cogl_color_get_alpha_byte (&tmp) != 0xff)
- return TRUE;
- cogl_pipeline_get_emission (pipeline, &tmp);
- if (cogl_color_get_alpha_byte (&tmp) != 0xff)
- return TRUE;
-#endif
- }
-
- if (changes & COGL_PIPELINE_STATE_LAYERS)
- {
- /* has_alpha tracks the alpha status of the GL_PREVIOUS layer.
- * To start with that's defined by the pipeline color which
- * must be fully opaque if we got this far. */
- gboolean has_alpha = FALSE;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- layer_has_alpha_cb,
- &has_alpha);
- if (has_alpha)
- return TRUE;
- }
-
- /* At this point, considering just the state that has changed it
- * looks like blending isn't needed. If blending was previously
- * enabled though it could be that some other state still requires
- * that we have blending enabled. In this case we still need to
- * go and check the other state...
- *
- * FIXME: We should explicitly keep track of the mask of state
- * groups that are currently causing blending to be enabled so that
- * we never have to resort to checking *all* the state and can
- * instead always limit the check to those in the mask.
- */
- if (pipeline->real_blend_enable)
- {
- other_state = COGL_PIPELINE_STATE_AFFECTS_BLENDING & ~changes;
- if (other_state &&
- _cogl_pipeline_needs_blending_enabled (pipeline,
- other_state,
- NULL))
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-_cogl_pipeline_set_fragend (CoglPipeline *pipeline, int fragend)
-{
- _cogl_pipeline_fragend_free_priv (pipeline);
- pipeline->fragend = fragend;
-}
-
-void
-_cogl_pipeline_set_vertend (CoglPipeline *pipeline, int vertend)
-{
- pipeline->vertend = vertend;
-}
-
-static void
-_cogl_pipeline_copy_differences (CoglPipeline *dest,
- CoglPipeline *src,
- unsigned long differences)
-{
- CoglPipelineBigState *big_state;
-
- if (differences & COGL_PIPELINE_STATE_COLOR)
- dest->color = src->color;
-
- if (differences & COGL_PIPELINE_STATE_BLEND_ENABLE)
- dest->blend_enable = src->blend_enable;
-
- if (differences & COGL_PIPELINE_STATE_LAYERS)
- {
- GList *l;
-
- if (dest->differences & COGL_PIPELINE_STATE_LAYERS &&
- dest->layer_differences)
- {
- g_list_foreach (dest->layer_differences,
- (GFunc)cogl_object_unref,
- NULL);
- g_list_free (dest->layer_differences);
- }
-
- for (l = src->layer_differences; l; l = l->next)
- {
- /* NB: a layer can't have more than one ->owner so we can't
- * simply take a references on each of the original
- * layer_differences, we have to derive new layers from the
- * originals instead. */
- CoglPipelineLayer *copy = _cogl_pipeline_layer_copy (l->data);
- _cogl_pipeline_add_layer_difference (dest, copy, FALSE);
- cogl_object_unref (copy);
- }
-
- /* Note: we initialize n_layers after adding the layer differences
- * since the act of adding the layers will initialize n_layers to 0
- * because dest isn't initially a STATE_LAYERS authority. */
- dest->n_layers = src->n_layers;
- }
-
- if (differences & COGL_PIPELINE_STATE_NEEDS_BIG_STATE)
- {
- if (!dest->has_big_state)
- {
- dest->big_state = g_slice_new (CoglPipelineBigState);
- dest->has_big_state = TRUE;
- }
- big_state = dest->big_state;
- }
- else
- goto check_for_blending_change;
-
- if (differences & COGL_PIPELINE_STATE_LIGHTING)
- {
- memcpy (&big_state->lighting_state,
- &src->big_state->lighting_state,
- sizeof (CoglPipelineLightingState));
- }
-
- if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC)
- big_state->alpha_state.alpha_func =
- src->big_state->alpha_state.alpha_func;
-
- if (differences & COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE)
- big_state->alpha_state.alpha_func_reference =
- src->big_state->alpha_state.alpha_func_reference;
-
- if (differences & COGL_PIPELINE_STATE_BLEND)
- {
- memcpy (&big_state->blend_state,
- &src->big_state->blend_state,
- sizeof (CoglPipelineBlendState));
- }
-
- if (differences & COGL_PIPELINE_STATE_USER_SHADER)
- {
- if (src->big_state->user_program)
- big_state->user_program =
- cogl_handle_ref (src->big_state->user_program);
- else
- big_state->user_program = COGL_INVALID_HANDLE;
- }
-
- if (differences & COGL_PIPELINE_STATE_DEPTH)
- {
- memcpy (&big_state->depth_state,
- &src->big_state->depth_state,
- sizeof (CoglPipelineDepthState));
- }
-
- if (differences & COGL_PIPELINE_STATE_FOG)
- {
- memcpy (&big_state->fog_state,
- &src->big_state->fog_state,
- sizeof (CoglPipelineFogState));
- }
-
- if (differences & COGL_PIPELINE_STATE_POINT_SIZE)
- big_state->point_size = src->big_state->point_size;
-
- /* XXX: we shouldn't bother doing this in most cases since
- * _copy_differences is typically used to initialize pipeline state
- * by copying it from the current authority, so it's not actually
- * *changing* anything.
- */
-check_for_blending_change:
- if (differences & COGL_PIPELINE_STATE_AFFECTS_BLENDING)
- handle_automatic_blend_enable (dest, differences);
-
- dest->differences |= differences;
-}
-
-static void
-_cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
- CoglPipelineState change)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (change & COGL_PIPELINE_STATE_ALL_SPARSE);
-
- if (!(change & COGL_PIPELINE_STATE_MULTI_PROPERTY))
- return;
-
- authority = _cogl_pipeline_get_authority (pipeline, change);
-
- switch (change)
- {
- /* XXX: avoid using a default: label so we get a warning if we
- * don't explicitly handle a newly defined state-group here. */
- case COGL_PIPELINE_STATE_COLOR:
- case COGL_PIPELINE_STATE_BLEND_ENABLE:
- case COGL_PIPELINE_STATE_ALPHA_FUNC:
- case COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE:
- case COGL_PIPELINE_STATE_POINT_SIZE:
- case COGL_PIPELINE_STATE_USER_SHADER:
- case COGL_PIPELINE_STATE_REAL_BLEND_ENABLE:
- g_return_if_reached ();
-
- case COGL_PIPELINE_STATE_LAYERS:
- pipeline->n_layers = authority->n_layers;
- pipeline->layer_differences = NULL;
- break;
- case COGL_PIPELINE_STATE_LIGHTING:
- {
- memcpy (&pipeline->big_state->lighting_state,
- &authority->big_state->lighting_state,
- sizeof (CoglPipelineLightingState));
- break;
- }
- case COGL_PIPELINE_STATE_BLEND:
- {
- memcpy (&pipeline->big_state->blend_state,
- &authority->big_state->blend_state,
- sizeof (CoglPipelineBlendState));
- break;
- }
- case COGL_PIPELINE_STATE_DEPTH:
- {
- memcpy (&pipeline->big_state->depth_state,
- &authority->big_state->depth_state,
- sizeof (CoglPipelineDepthState));
- break;
- }
- case COGL_PIPELINE_STATE_FOG:
- {
- memcpy (&pipeline->big_state->fog_state,
- &authority->big_state->fog_state,
- sizeof (CoglPipelineFogState));
- break;
- }
- }
-}
-
-static gboolean
-check_if_strong_cb (CoglPipelineNode *node, void *user_data)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (node);
- gboolean *has_strong_child = user_data;
-
- if (!_cogl_pipeline_is_weak (pipeline))
- {
- *has_strong_child = TRUE;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-has_strong_children (CoglPipeline *pipeline)
-{
- gboolean has_strong_child = FALSE;
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- check_if_strong_cb,
- &has_strong_child);
- return has_strong_child;
-}
-
-static gboolean
-_cogl_pipeline_is_weak (CoglPipeline *pipeline)
-{
- if (pipeline->is_weak && !has_strong_children (pipeline))
- return TRUE;
- else
- return FALSE;
-}
-
-static gboolean
-reparent_children_cb (CoglPipelineNode *node,
- void *user_data)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (node);
- CoglPipeline *parent = user_data;
-
- _cogl_pipeline_set_parent (pipeline, parent, TRUE);
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_pre_change_notify (CoglPipeline *pipeline,
- CoglPipelineState change,
- const CoglColor *new_color,
- gboolean from_layer_change)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If primitives have been logged in the journal referencing the
- * current state of this pipeline we need to flush the journal
- * before we can modify it... */
- if (pipeline->journal_ref_count)
- {
- gboolean skip_journal_flush = FALSE;
-
- /* XXX: We don't usually need to flush the journal just due to
- * color changes since pipeline colors are logged in the
- * journal's vertex buffer. The exception is when the change in
- * color enables or disables the need for blending. */
- if (change == COGL_PIPELINE_STATE_COLOR)
- {
- gboolean will_need_blending =
- _cogl_pipeline_needs_blending_enabled (pipeline,
- change,
- new_color);
- gboolean blend_enable = pipeline->real_blend_enable ? TRUE : FALSE;
-
- if (will_need_blending == blend_enable)
- skip_journal_flush = TRUE;
- }
-
- if (!skip_journal_flush)
- {
- /* XXX: note we use cogl_flush() not _cogl_flush_journal() so
- * we will flush *all* known journals that might reference the
- * current pipeline. */
- cogl_flush ();
- }
- }
-
- /* The fixed function backend has no private state and can't
- * do anything special to handle small pipeline changes so we may as
- * well try to find a better backend whenever the pipeline changes.
- *
- * The programmable backends may be able to cache a lot of the code
- * they generate and only need to update a small section of that
- * code in response to a pipeline change therefore we don't want to
- * try searching for another backend when the pipeline changes.
- */
-#ifdef COGL_PIPELINE_FRAGEND_FIXED
- if (pipeline->fragend == COGL_PIPELINE_FRAGEND_FIXED)
- _cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_UNDEFINED);
-#endif
-#ifdef COGL_PIPELINE_VERTEND_FIXED
- if (pipeline->vertend == COGL_PIPELINE_VERTEND_FIXED)
- _cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_UNDEFINED);
-#endif
-
- /* To simplify things for the backends we are careful about how
- * we report STATE_LAYERS changes.
- *
- * All STATE_LAYERS changes with the exception of ->n_layers
- * will also result in layer_pre_change_notifications. For
- * backends that perform code generation for fragment processing
- * they typically need to understand the details of how layers
- * get changed to determine if they need to repeat codegen. It
- * doesn't help them to report a pipeline STATE_LAYERS change
- * for all layer changes since it's so broad, they really need
- * to wait for the layer change to be notified. What does help
- * though is to report a STATE_LAYERS change for a change in
- * ->n_layers because they typically do need to repeat codegen
- * in that case.
- *
- * This just ensures backends only get a single pipeline or
- * layer pre-change notification for any particular change.
- */
- if (pipeline->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
- _cogl_pipeline_fragends[pipeline->fragend]->pipeline_pre_change_notify)
- {
- const CoglPipelineFragend *fragend =
- _cogl_pipeline_fragends[pipeline->fragend];
-
- if (!from_layer_change)
- fragend->pipeline_pre_change_notify (pipeline, change, new_color);
- }
-
- if (pipeline->vertend != COGL_PIPELINE_VERTEND_UNDEFINED &&
- _cogl_pipeline_vertends[pipeline->vertend]->pipeline_pre_change_notify)
- {
- const CoglPipelineVertend *vertend =
- _cogl_pipeline_vertends[pipeline->vertend];
-
- /* To simplify things for the backends we are careful about how
- * we report STATE_LAYERS changes.
- *
- * All STATE_LAYERS changes with the exception of ->n_layers
- * will also result in layer_pre_change_notifications. For
- * backends that perform code generation for fragment processing
- * they typically need to understand the details of how layers
- * get changed to determine if they need to repeat codegen. It
- * doesn't help them to report a pipeline STATE_LAYERS change
- * for all layer changes since it's so broad, they really need
- * to wait for the layer change to be notified. What does help
- * though is to report a STATE_LAYERS change for a change in
- * ->n_layers because they typically do need to repeat codegen
- * in that case.
- *
- * This just ensures backends only get a single pipeline or
- * layer pre-change notification for any particular change.
- */
- if (!from_layer_change)
- vertend->pipeline_pre_change_notify (pipeline, change, new_color);
- }
-
- /* Notify all of the progends */
- if (!from_layer_change)
- for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
- if (_cogl_pipeline_progends[i]->pipeline_pre_change_notify)
- _cogl_pipeline_progends[i]->pipeline_pre_change_notify (pipeline,
- change,
- new_color);
-
- /* There may be an arbitrary tree of descendants of this pipeline;
- * any of which may indirectly depend on this pipeline as the
- * authority for some set of properties. (Meaning for example that
- * one of its descendants derives its color or blending state from
- * this pipeline.)
- *
- * We can't modify any property that this pipeline is the authority
- * for unless we create another pipeline to take its place first and
- * make sure descendants reference this new pipeline instead.
- */
-
- /* The simplest descendants to handle are weak pipelines; we simply
- * destroy them if we are modifying a pipeline they depend on. This
- * means weak pipelines never cause us to do a copy-on-write. */
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- destroy_weak_children_cb,
- NULL);
-
- /* If there are still children remaining though we'll need to
- * perform a copy-on-write and reparent the dependants as children
- * of the copy. */
- if (COGL_PIPELINE_NODE (pipeline)->has_children)
- {
- CoglPipeline *new_authority;
-
- COGL_STATIC_COUNTER (pipeline_copy_on_write_counter,
- "pipeline copy on write counter",
- "Increments each time a pipeline "
- "must be copied to allow modification",
- 0 /* no application private data */);
-
- COGL_COUNTER_INC (_cogl_uprof_context, pipeline_copy_on_write_counter);
-
- new_authority =
- cogl_pipeline_copy (_cogl_pipeline_get_parent (pipeline));
- _cogl_pipeline_set_static_breadcrumb (new_authority,
- "pre_change_notify:copy-on-write");
-
- /* We could explicitly walk the descendants, OR together the set
- * of differences that we determine this pipeline is the
- * authority on and only copy those differences copied across.
- *
- * Or, if we don't explicitly walk the descendants we at least
- * know that pipeline->differences represents the largest set of
- * differences that this pipeline could possibly be an authority
- * on.
- *
- * We do the later just because it's simplest, but we might need
- * to come back to this later...
- */
- _cogl_pipeline_copy_differences (new_authority, pipeline,
- pipeline->differences);
-
- /* Reparent the dependants of pipeline to be children of
- * new_authority instead... */
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- reparent_children_cb,
- new_authority);
-
- /* The children will keep the new authority alive so drop the
- * reference we got when copying... */
- cogl_object_unref (new_authority);
- }
-
- /* At this point we know we have a pipeline with no strong
- * dependants (though we may have some weak children) so we are now
- * free to modify the pipeline. */
-
- pipeline->age++;
-
- if (change & COGL_PIPELINE_STATE_NEEDS_BIG_STATE &&
- !pipeline->has_big_state)
- {
- pipeline->big_state = g_slice_new (CoglPipelineBigState);
- pipeline->has_big_state = TRUE;
- }
-
- /* Note: conceptually we have just been notified that a single
- * property value is about to change, but since some state-groups
- * contain multiple properties and 'pipeline' is about to take over
- * being the authority for the property's corresponding state-group
- * we need to maintain the integrity of the other property values
- * too.
- *
- * To ensure this we handle multi-property state-groups by copying
- * all the values from the old-authority to the new...
- *
- * We don't have to worry about non-sparse property groups since
- * we never take over being an authority for such properties so
- * they automatically maintain integrity.
- */
- if (change & COGL_PIPELINE_STATE_ALL_SPARSE &&
- !(pipeline->differences & change))
- {
- _cogl_pipeline_init_multi_property_sparse_state (pipeline, change);
- pipeline->differences |= change;
- }
-
- /* Each pipeline has a sorted cache of the layers it depends on
- * which will need updating via _cogl_pipeline_update_layers_cache
- * if a pipeline's layers are changed. */
- if (change == COGL_PIPELINE_STATE_LAYERS)
- recursively_free_layer_caches (pipeline);
-
- /* If the pipeline being changed is the same as the last pipeline we
- * flushed then we keep a track of the changes so we can try to
- * minimize redundant OpenGL calls if the same pipeline is flushed
- * again.
- */
- if (ctx->current_pipeline == pipeline)
- ctx->current_pipeline_changes_since_flush |= change;
-}
-
-
-static void
-_cogl_pipeline_add_layer_difference (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- gboolean inc_n_layers)
-{
- g_return_if_fail (layer->owner == NULL);
-
- layer->owner = pipeline;
- cogl_object_ref (layer);
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline,
- COGL_PIPELINE_STATE_LAYERS,
- NULL,
- FALSE);
-
- pipeline->differences |= COGL_PIPELINE_STATE_LAYERS;
-
- pipeline->layer_differences =
- g_list_prepend (pipeline->layer_differences, layer);
-
- if (inc_n_layers)
- pipeline->n_layers++;
-}
-
-/* NB: If you are calling this it's your responsibility to have
- * already called:
- * _cogl_pipeline_pre_change_notify (m, _CHANGE_LAYERS, NULL);
- */
-static void
-_cogl_pipeline_remove_layer_difference (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- gboolean dec_n_layers)
-{
- g_return_if_fail (layer->owner == pipeline);
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline,
- COGL_PIPELINE_STATE_LAYERS,
- NULL,
- FALSE);
-
- layer->owner = NULL;
- cogl_object_unref (layer);
-
- pipeline->differences |= COGL_PIPELINE_STATE_LAYERS;
-
- pipeline->layer_differences =
- g_list_remove (pipeline->layer_differences, layer);
-
- if (dec_n_layers)
- pipeline->n_layers--;
-}
-
-static void
-_cogl_pipeline_try_reverting_layers_authority (CoglPipeline *authority,
- CoglPipeline *old_authority)
-{
- if (authority->layer_differences == NULL &&
- _cogl_pipeline_get_parent (authority))
- {
- /* If the previous _STATE_LAYERS authority has the same
- * ->n_layers then we can revert to that being the authority
- * again. */
- if (!old_authority)
- {
- old_authority =
- _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority),
- COGL_PIPELINE_STATE_LAYERS);
- }
-
- if (old_authority->n_layers == authority->n_layers)
- authority->differences &= ~COGL_PIPELINE_STATE_LAYERS;
- }
-}
-
-
-static void
-handle_automatic_blend_enable (CoglPipeline *pipeline,
- CoglPipelineState change)
-{
- gboolean blend_enable =
- _cogl_pipeline_needs_blending_enabled (pipeline, change, NULL);
-
- if (blend_enable != pipeline->real_blend_enable)
- {
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be
- * modified.
- * - If the pipeline isn't currently an authority for the state
- * being changed, then initialize that state from the current
- * authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline,
- COGL_PIPELINE_STATE_REAL_BLEND_ENABLE,
- NULL,
- FALSE);
- pipeline->real_blend_enable = blend_enable;
- }
-}
-
-typedef struct
-{
- int keep_n;
- int current_pos;
- gboolean needs_pruning;
- int first_index_to_prune;
-} CoglPipelinePruneLayersInfo;
-
-static gboolean
-update_prune_layers_info_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglPipelinePruneLayersInfo *state = user_data;
-
- if (state->current_pos == state->keep_n)
- {
- state->needs_pruning = TRUE;
- state->first_index_to_prune = layer->index;
- return FALSE;
- }
- state->current_pos++;
- return TRUE;
-}
-
-void
-_cogl_pipeline_prune_to_n_layers (CoglPipeline *pipeline, int n)
-{
- CoglPipelinePruneLayersInfo state;
- gboolean notified_change = TRUE;
- GList *l;
- GList *next;
-
- state.keep_n = n;
- state.current_pos = 0;
- state.needs_pruning = FALSE;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- update_prune_layers_info_cb,
- &state);
-
- pipeline->n_layers = n;
-
- if (!state.needs_pruning)
- return;
-
- if (!(pipeline->differences & COGL_PIPELINE_STATE_LAYERS))
- return;
-
- /* It's possible that this pipeline owns some of the layers being
- * discarded, so we'll need to unlink them... */
- for (l = pipeline->layer_differences; l; l = next)
- {
- CoglPipelineLayer *layer = l->data;
- next = l->next; /* we're modifying the list we're iterating */
-
- if (layer->index > state.first_index_to_prune)
- {
- if (!notified_change)
- {
- /* - Flush journal primitives referencing the current
- * state.
- * - Make sure the pipeline has no dependants so it may
- * be modified.
- * - If the pipeline isn't currently an authority for
- * the state being changed, then initialize that state
- * from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline,
- COGL_PIPELINE_STATE_LAYERS,
- NULL,
- FALSE);
- notified_change = TRUE;
- }
-
- pipeline->layer_differences =
- g_list_delete_link (pipeline->layer_differences, l);
- }
- }
-}
-
-static void
-_cogl_pipeline_fragend_layer_change_notify (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- /* NB: Although layers can have private state associated with them
- * by multiple backends we know that a layer can't be *changed* if
- * it has multiple dependants so if we reach here we know we only
- * have a single owner and can only be associated with a single
- * backend that needs to be notified of the layer change...
- */
- if (owner->fragend != COGL_PIPELINE_FRAGEND_UNDEFINED &&
- _cogl_pipeline_fragends[owner->fragend]->layer_pre_change_notify)
- {
- const CoglPipelineFragend *fragend =
- _cogl_pipeline_fragends[owner->fragend];
- fragend->layer_pre_change_notify (owner, layer, change);
- }
-}
-
-static void
-_cogl_pipeline_vertend_layer_change_notify (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- /* NB: The comment in fragend_layer_change_notify applies here too */
- if (owner->vertend != COGL_PIPELINE_VERTEND_UNDEFINED &&
- _cogl_pipeline_vertends[owner->vertend]->layer_pre_change_notify)
- {
- const CoglPipelineVertend *vertend =
- _cogl_pipeline_vertends[owner->vertend];
- vertend->layer_pre_change_notify (owner, layer, change);
- }
-}
-
-static void
-_cogl_pipeline_progend_layer_change_notify (CoglPipeline *owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- int i;
-
- /* Give all of the progends a chance to notice that the layer has
- changed */
- for (i = 0; i < COGL_PIPELINE_N_PROGENDS; i++)
- if (_cogl_pipeline_progends[i]->layer_pre_change_notify)
- _cogl_pipeline_progends[i]->layer_pre_change_notify (owner,
- layer,
- change);
-}
-
-unsigned int
-_cogl_get_n_args_for_combine_func (CoglPipelineCombineFunc func)
-{
- switch (func)
- {
- case COGL_PIPELINE_COMBINE_FUNC_REPLACE:
- return 1;
- case COGL_PIPELINE_COMBINE_FUNC_MODULATE:
- case COGL_PIPELINE_COMBINE_FUNC_ADD:
- case COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED:
- case COGL_PIPELINE_COMBINE_FUNC_SUBTRACT:
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB:
- case COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA:
- return 2;
- case COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE:
- return 3;
- }
- return 0;
-}
-
-static void
-_cogl_pipeline_layer_init_multi_property_sparse_state (
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- CoglPipelineLayer *authority;
-
- /* Nothing to initialize in these cases since they are all comprised
- * of one member which we expect to immediately be overwritten. */
- if (!(change & COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY))
- return;
-
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- switch (change)
- {
- /* XXX: avoid using a default: label so we get a warning if we
- * don't explicitly handle a newly defined state-group here. */
- case COGL_PIPELINE_LAYER_STATE_UNIT:
- case COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET:
- case COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA:
- case COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS:
- case COGL_PIPELINE_LAYER_STATE_USER_MATRIX:
- case COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT:
- g_return_if_reached ();
-
- /* XXX: technically we could probably even consider these as
- * single property state-groups from the pov that currently the
- * corresponding property setters always update all of the values
- * at the same time. */
- case COGL_PIPELINE_LAYER_STATE_FILTERS:
- layer->min_filter = authority->min_filter;
- layer->mag_filter = authority->mag_filter;
- break;
- case COGL_PIPELINE_LAYER_STATE_WRAP_MODES:
- layer->wrap_mode_s = authority->wrap_mode_s;
- layer->wrap_mode_t = authority->wrap_mode_t;
- layer->wrap_mode_p = authority->wrap_mode_p;
- break;
- case COGL_PIPELINE_LAYER_STATE_COMBINE:
- {
- int n_args;
- int i;
- CoglPipelineLayerBigState *src_big_state = authority->big_state;
- CoglPipelineLayerBigState *dest_big_state = layer->big_state;
- GLint func = src_big_state->texture_combine_rgb_func;
-
- dest_big_state->texture_combine_rgb_func = func;
- n_args = _cogl_get_n_args_for_combine_func (func);
- for (i = 0; i < n_args; i++)
- {
- dest_big_state->texture_combine_rgb_src[i] =
- src_big_state->texture_combine_rgb_src[i];
- dest_big_state->texture_combine_rgb_op[i] =
- src_big_state->texture_combine_rgb_op[i];
- }
-
- func = src_big_state->texture_combine_alpha_func;
- dest_big_state->texture_combine_alpha_func = func;
- n_args = _cogl_get_n_args_for_combine_func (func);
- for (i = 0; i < n_args; i++)
- {
- dest_big_state->texture_combine_alpha_src[i] =
- src_big_state->texture_combine_alpha_src[i];
- dest_big_state->texture_combine_alpha_op[i] =
- src_big_state->texture_combine_alpha_op[i];
- }
- break;
- }
- }
-}
-
-/* NB: This function will allocate a new derived layer if you are
- * trying to change the state of a layer with dependants so you must
- * always check the return value.
- *
- * If a new layer is returned it will be owned by required_owner.
- *
- * required_owner can only by NULL for new, currently unowned layers
- * with no dependants.
- */
-static CoglPipelineLayer *
-_cogl_pipeline_layer_pre_change_notify (CoglPipeline *required_owner,
- CoglPipelineLayer *layer,
- CoglPipelineLayerState change)
-{
- CoglTextureUnit *unit;
-
- /* Identify the case where the layer is new with no owner or
- * dependants and so we don't need to do anything. */
- if (COGL_PIPELINE_NODE (layer)->has_children == FALSE &&
- layer->owner == NULL)
- goto init_layer_state;
-
- /* We only allow a NULL required_owner for new layers */
- g_return_val_if_fail (required_owner != NULL, layer);
-
- /* Chain up:
- * A modification of a layer is indirectly also a modification of
- * its owner so first make sure to flush the journal of any
- * references to the current owner state and if necessary perform
- * a copy-on-write for the required_owner if it has dependants.
- */
- _cogl_pipeline_pre_change_notify (required_owner,
- COGL_PIPELINE_STATE_LAYERS,
- NULL,
- TRUE);
-
- /* Unlike pipelines; layers are simply considered immutable once
- * they have dependants - either direct children, or another
- * pipeline as an owner.
- */
- if (COGL_PIPELINE_NODE (layer)->has_children ||
- layer->owner != required_owner)
- {
- CoglPipelineLayer *new = _cogl_pipeline_layer_copy (layer);
- if (layer->owner == required_owner)
- _cogl_pipeline_remove_layer_difference (required_owner, layer, FALSE);
- _cogl_pipeline_add_layer_difference (required_owner, new, FALSE);
- cogl_object_unref (new);
- layer = new;
- goto init_layer_state;
- }
-
- /* Note: At this point we know there is only one pipeline dependant on
- * this layer (required_owner), and there are no other layers
- * dependant on this layer so it's ok to modify it. */
-
- _cogl_pipeline_fragend_layer_change_notify (required_owner, layer, change);
- _cogl_pipeline_vertend_layer_change_notify (required_owner, layer, change);
- _cogl_pipeline_progend_layer_change_notify (required_owner, layer, change);
-
- /* If the layer being changed is the same as the last layer we
- * flushed to the corresponding texture unit then we keep a track of
- * the changes so we can try to minimize redundant OpenGL calls if
- * the same layer is flushed again.
- */
- unit = _cogl_get_texture_unit (_cogl_pipeline_layer_get_unit_index (layer));
- if (unit->layer == layer)
- unit->layer_changes_since_flush |= change;
-
-init_layer_state:
-
- if (required_owner)
- required_owner->age++;
-
- if (change & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE &&
- !layer->has_big_state)
- {
- layer->big_state = g_slice_new (CoglPipelineLayerBigState);
- layer->has_big_state = TRUE;
- }
-
- /* Note: conceptually we have just been notified that a single
- * property value is about to change, but since some state-groups
- * contain multiple properties and 'layer' is about to take over
- * being the authority for the property's corresponding state-group
- * we need to maintain the integrity of the other property values
- * too.
- *
- * To ensure this we handle multi-property state-groups by copying
- * all the values from the old-authority to the new...
- *
- * We don't have to worry about non-sparse property groups since
- * we never take over being an authority for such properties so
- * they automatically maintain integrity.
- */
- if (change & COGL_PIPELINE_LAYER_STATE_ALL_SPARSE &&
- !(layer->differences & change))
- {
- _cogl_pipeline_layer_init_multi_property_sparse_state (layer, change);
- layer->differences |= change;
- }
-
- return layer;
-}
-
-static void
-_cogl_pipeline_layer_unparent (CoglPipelineNode *layer)
-{
- /* Chain up */
- _cogl_pipeline_node_unparent_real (layer);
-}
-
-static void
-_cogl_pipeline_layer_set_parent (CoglPipelineLayer *layer,
- CoglPipelineLayer *parent)
-{
- /* Chain up */
- _cogl_pipeline_node_set_parent_real (COGL_PIPELINE_NODE (layer),
- COGL_PIPELINE_NODE (parent),
- _cogl_pipeline_layer_unparent,
- TRUE);
-}
-
-/* XXX: This is duplicated logic; the same as for
- * _cogl_pipeline_prune_redundant_ancestry it would be nice to find a
- * way to consolidate these functions! */
-static void
-_cogl_pipeline_layer_prune_redundant_ancestry (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *new_parent = _cogl_pipeline_layer_get_parent (layer);
-
- /* walk up past ancestors that are now redundant and potentially
- * reparent the layer. */
- while (_cogl_pipeline_layer_get_parent (new_parent) &&
- (new_parent->differences | layer->differences) ==
- layer->differences)
- new_parent = _cogl_pipeline_layer_get_parent (new_parent);
-
- _cogl_pipeline_layer_set_parent (layer, new_parent);
-}
-
-/*
- * XXX: consider special casing layer->unit_index so it's not a sparse
- * property so instead we can assume it's valid for all layer
- * instances.
- * - We would need to initialize ->unit_index in
- * _cogl_pipeline_layer_copy ().
- *
- * XXX: If you use this API you should consider that the given layer
- * might not be writeable and so a new derived layer will be allocated
- * and modified instead. The layer modified will be returned so you
- * can identify when this happens.
- */
-static CoglPipelineLayer *
-_cogl_pipeline_set_layer_unit (CoglPipeline *required_owner,
- CoglPipelineLayer *layer,
- int unit_index)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_UNIT;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, change);
- CoglPipelineLayer *new;
-
- if (authority->unit_index == unit_index)
- return layer;
-
- new =
- _cogl_pipeline_layer_pre_change_notify (required_owner,
- layer,
- change);
- if (new != layer)
- layer = new;
- else
- {
- /* If the layer we found is currently the authority on the state
- * we are changing see if we can revert to one of our ancestors
- * being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, change);
-
- if (old_authority->unit_index == unit_index)
- {
- layer->differences &= ~change;
- return layer;
- }
- }
- }
-
- layer->unit_index = unit_index;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= change;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
- return layer;
-}
-
-typedef struct
-{
- /* The layer we are trying to find */
- int layer_index;
-
- /* The layer we find or untouched if not found */
- CoglPipelineLayer *layer;
-
- /* If the layer can't be found then a new layer should be
- * inserted after this texture unit index... */
- int insert_after;
-
- /* When adding a layer we need the list of layers to shift up
- * to a new texture unit. When removing we need the list of
- * layers to shift down.
- *
- * Note: the list isn't sorted */
- CoglPipelineLayer **layers_to_shift;
- int n_layers_to_shift;
-
- /* When adding a layer we don't need a complete list of
- * layers_to_shift if we find a layer already corresponding to the
- * layer_index. */
- gboolean ignore_shift_layers_if_found;
-
-} CoglPipelineLayerInfo;
-
-/* Returns TRUE once we know there is nothing more to update */
-static gboolean
-update_layer_info (CoglPipelineLayer *layer,
- CoglPipelineLayerInfo *layer_info)
-{
- if (layer->index == layer_info->layer_index)
- {
- layer_info->layer = layer;
- if (layer_info->ignore_shift_layers_if_found)
- return TRUE;
- }
- else if (layer->index < layer_info->layer_index)
- {
- int unit_index = _cogl_pipeline_layer_get_unit_index (layer);
- layer_info->insert_after = unit_index;
- }
- else
- layer_info->layers_to_shift[layer_info->n_layers_to_shift++] =
- layer;
-
- return FALSE;
-}
-
-/* Returns FALSE to break out of a _foreach_layer () iteration */
-static gboolean
-update_layer_info_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- CoglPipelineLayerInfo *layer_info = user_data;
-
- if (update_layer_info (layer, layer_info))
- return FALSE; /* break */
- else
- return TRUE; /* continue */
-}
-
-static void
-_cogl_pipeline_get_layer_info (CoglPipeline *pipeline,
- CoglPipelineLayerInfo *layer_info)
-{
- /* Note: we are assuming this pipeline is a _STATE_LAYERS authority */
- int n_layers = pipeline->n_layers;
- int i;
-
- /* FIXME: _cogl_pipeline_foreach_layer_internal now calls
- * _cogl_pipeline_update_layers_cache anyway so this codepath is
- * pointless! */
- if (layer_info->ignore_shift_layers_if_found &&
- pipeline->layers_cache_dirty)
- {
- /* The expectation is that callers of
- * _cogl_pipeline_get_layer_info are likely to be modifying the
- * list of layers associated with a pipeline so in this case
- * where we don't have a cache of the layers and we don't
- * necessarily have to iterate all the layers of the pipeline we
- * use a foreach_layer callback instead of updating the cache
- * and iterating that as below. */
- _cogl_pipeline_foreach_layer_internal (pipeline,
- update_layer_info_cb,
- layer_info);
- return;
- }
-
- _cogl_pipeline_update_layers_cache (pipeline);
- for (i = 0; i < n_layers; i++)
- {
- CoglPipelineLayer *layer = pipeline->layers_cache[i];
-
- if (update_layer_info (layer, layer_info))
- return;
- }
-}
-
-static CoglPipelineLayer *
-_cogl_pipeline_get_layer (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS);
- CoglPipelineLayerInfo layer_info;
- CoglPipelineLayer *layer;
- int unit_index;
- int i;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- /* The layer index of the layer we want info about */
- layer_info.layer_index = layer_index;
-
- /* If a layer already exists with the given index this will be
- * updated. */
- layer_info.layer = NULL;
-
- /* If a layer isn't found for the given index we'll need to know
- * where to insert a new layer. */
- layer_info.insert_after = -1;
-
- /* If a layer can't be found then we'll need to insert a new layer
- * and bump up the texture unit for all layers with an index
- * > layer_index. */
- layer_info.layers_to_shift =
- g_alloca (sizeof (CoglPipelineLayer *) * authority->n_layers);
- layer_info.n_layers_to_shift = 0;
-
- /* If an exact match is found though we don't need a complete
- * list of layers with indices > layer_index... */
- layer_info.ignore_shift_layers_if_found = TRUE;
-
- _cogl_pipeline_get_layer_info (authority, &layer_info);
-
- if (layer_info.layer)
- return layer_info.layer;
-
- unit_index = layer_info.insert_after + 1;
- if (unit_index == 0)
- layer = _cogl_pipeline_layer_copy (ctx->default_layer_0);
- else
- {
- CoglPipelineLayer *new;
- layer = _cogl_pipeline_layer_copy (ctx->default_layer_n);
- new = _cogl_pipeline_set_layer_unit (NULL, layer, unit_index);
- /* Since we passed a newly allocated layer we wouldn't expect
- * _set_layer_unit() to have to allocate *another* layer. */
- g_assert (new == layer);
- }
- layer->index = layer_index;
-
- for (i = 0; i < layer_info.n_layers_to_shift; i++)
- {
- CoglPipelineLayer *shift_layer = layer_info.layers_to_shift[i];
-
- unit_index = _cogl_pipeline_layer_get_unit_index (shift_layer);
- _cogl_pipeline_set_layer_unit (pipeline, shift_layer, unit_index + 1);
- /* NB: shift_layer may not be writeable so _set_layer_unit()
- * will allocate a derived layer internally which will become
- * owned by pipeline. Check the return value if we need to do
- * anything else with this layer. */
- }
-
- _cogl_pipeline_add_layer_difference (pipeline, layer, TRUE);
-
- cogl_object_unref (layer);
-
- return layer;
-}
-
-CoglHandle
-_cogl_pipeline_layer_get_texture_real (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
-
- return authority->texture;
-}
-
-CoglHandle
-_cogl_pipeline_get_layer_texture (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipelineLayer *layer =
- _cogl_pipeline_get_layer (pipeline, layer_index);
- return _cogl_pipeline_layer_get_texture (layer);
-}
-
-static void
-_cogl_pipeline_prune_empty_layer_difference (CoglPipeline *layers_authority,
- CoglPipelineLayer *layer)
-{
- /* Find the GList link that references the empty layer */
- GList *link = g_list_find (layers_authority->layer_differences, layer);
- /* No pipeline directly owns the root node layer so this is safe... */
- CoglPipelineLayer *layer_parent = _cogl_pipeline_layer_get_parent (layer);
- CoglPipelineLayerInfo layer_info;
- CoglPipeline *old_layers_authority;
-
- g_return_if_fail (link != NULL);
-
- /* If the layer's parent doesn't have an owner then we can simply
- * take ownership ourselves and drop our reference on the empty
- * layer. We don't want to take ownership of the root node layer so
- * we also need to verify that the parent has a parent
- */
- if (layer_parent->index == layer->index && layer_parent->owner == NULL &&
- _cogl_pipeline_layer_get_parent (layer_parent) != NULL)
- {
- cogl_object_ref (layer_parent);
- layer_parent->owner = layers_authority;
- link->data = layer_parent;
- cogl_object_unref (layer);
- recursively_free_layer_caches (layers_authority);
- return;
- }
-
- /* Now we want to find the layer that would become the authority for
- * layer->index if we were to remove layer from
- * layers_authority->layer_differences
- */
-
- /* The layer index of the layer we want info about */
- layer_info.layer_index = layer->index;
-
- /* If a layer already exists with the given index this will be
- * updated. */
- layer_info.layer = NULL;
-
- /* If a layer can't be found then we'll need to insert a new layer
- * and bump up the texture unit for all layers with an index
- * > layer_index. */
- layer_info.layers_to_shift =
- g_alloca (sizeof (CoglPipelineLayer *) * layers_authority->n_layers);
- layer_info.n_layers_to_shift = 0;
-
- /* If an exact match is found though we don't need a complete
- * list of layers with indices > layer_index... */
- layer_info.ignore_shift_layers_if_found = TRUE;
-
- /* We know the default/root pipeline isn't a LAYERS authority so it's
- * safe to use the result of _cogl_pipeline_get_parent (layers_authority)
- * without checking it.
- */
- old_layers_authority =
- _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (layers_authority),
- COGL_PIPELINE_STATE_LAYERS);
-
- _cogl_pipeline_get_layer_info (old_layers_authority, &layer_info);
-
- /* If layer is the defining layer for the corresponding ->index then
- * we can't get rid of it. */
- if (!layer_info.layer)
- return;
-
- /* If the layer that would become the authority for layer->index is
- * _cogl_pipeline_layer_get_parent (layer) then we can simply remove the
- * layer difference. */
- if (layer_info.layer == _cogl_pipeline_layer_get_parent (layer))
- {
- _cogl_pipeline_remove_layer_difference (layers_authority, layer, FALSE);
- _cogl_pipeline_try_reverting_layers_authority (layers_authority,
- old_layers_authority);
- }
-}
-
-static void
-_cogl_pipeline_set_layer_texture_target (CoglPipeline *pipeline,
- int layer_index,
- GLenum target)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *new;
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- if (target == authority->target)
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, change);
-
- if (old_authority->target == target)
- {
- layer->differences &= ~change;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- goto changed;
- }
- }
- }
-
- layer->target = target;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= change;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
-changed:
-
- handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
-}
-
-static void
-_cogl_pipeline_set_layer_texture_data (CoglPipeline *pipeline,
- int layer_index,
- CoglHandle texture)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *new;
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- if (authority->texture == texture)
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, change);
-
- if (old_authority->texture == texture)
- {
- layer->differences &= ~change;
-
- if (layer->texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (layer->texture);
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- goto changed;
- }
- }
- }
-
- if (texture != COGL_INVALID_HANDLE)
- cogl_handle_ref (texture);
- if (layer == authority &&
- layer->texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (layer->texture);
- layer->texture = texture;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= change;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
-changed:
-
- handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
-}
-
-/* A convenience for querying the target of a given texture that
- * notably returns 0 for NULL textures - so we can say that a layer
- * with no associated CoglTexture will have a texture target of 0.
- */
-static GLenum
-get_texture_target (CoglHandle texture)
-{
- GLuint ignore_handle;
- GLenum gl_target;
-
- if (texture)
- cogl_texture_get_gl_texture (texture, &ignore_handle, &gl_target);
- else
- return 0;/* XXX: An invalid GL target enum */
-
- return gl_target;
-}
-
-void
-cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
- int layer_index,
- CoglHandle texture)
-{
- /* For the convenience of fragend code we separate texture state
- * into the "target" and the "data", and setting a layer texture
- * updates both of these properties.
- *
- * One example for why this is helpful is that the fragends may
- * cache programs they generate and want to re-use those programs
- * with all pipelines having equivalent fragment processing state.
- * For the sake of determining if pipelines have equivalent fragment
- * processing state we don't need to compare that the same
- * underlying texture objects are referenced by the pipelines but we
- * do need to see if they use the same texture targets. Making this
- * distinction is much simpler if they are in different state
- * groups.
- */
- _cogl_pipeline_set_layer_texture_target (pipeline, layer_index,
- get_texture_target (texture));
- _cogl_pipeline_set_layer_texture_data (pipeline, layer_index, texture);
-}
-
-typedef struct
-{
- int i;
- CoglPipeline *pipeline;
- unsigned long fallback_layers;
-} CoglPipelineFallbackState;
-
-static gboolean
-fallback_layer_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglPipelineFallbackState *state = user_data;
- CoglPipeline *pipeline = state->pipeline;
- CoglHandle texture = _cogl_pipeline_layer_get_texture (layer);
- GLenum gl_target;
- COGL_STATIC_COUNTER (layer_fallback_counter,
- "layer fallback counter",
- "Increments each time a layer's texture is "
- "forced to a fallback texture",
- 0 /* no application private data */);
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!(state->fallback_layers & 1<<state->i))
- return TRUE;
-
- COGL_COUNTER_INC (_cogl_uprof_context, layer_fallback_counter);
-
- if (G_LIKELY (texture != COGL_INVALID_HANDLE))
- cogl_texture_get_gl_texture (texture, NULL, &gl_target);
- else
- gl_target = GL_TEXTURE_2D;
-
- if (gl_target == GL_TEXTURE_2D)
- texture = ctx->default_gl_texture_2d_tex;
-#ifdef HAVE_COGL_GL
- else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
- texture = ctx->default_gl_texture_rect_tex;
-#endif
- else
- {
- g_warning ("We don't have a fallback texture we can use to fill "
- "in for an invalid pipeline layer, since it was "
- "using an unsupported texture target ");
- /* might get away with this... */
- texture = ctx->default_gl_texture_2d_tex;
- }
-
- cogl_pipeline_set_layer_texture (pipeline, layer->index, texture);
-
- state->i++;
-
- return TRUE;
-}
-
-void
-_cogl_pipeline_set_layer_wrap_modes (CoglPipeline *pipeline,
- CoglPipelineLayer *layer,
- CoglPipelineLayer *authority,
- CoglPipelineWrapModeInternal wrap_mode_s,
- CoglPipelineWrapModeInternal wrap_mode_t,
- CoglPipelineWrapModeInternal wrap_mode_p)
-{
- CoglPipelineLayer *new;
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
-
- if (authority->wrap_mode_s == wrap_mode_s &&
- authority->wrap_mode_t == wrap_mode_t &&
- authority->wrap_mode_p == wrap_mode_p)
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, change);
-
- if (old_authority->wrap_mode_s == wrap_mode_s &&
- old_authority->wrap_mode_t == wrap_mode_t &&
- old_authority->wrap_mode_p == wrap_mode_p)
- {
- layer->differences &= ~change;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- return;
- }
- }
- }
-
- layer->wrap_mode_s = wrap_mode_s;
- layer->wrap_mode_t = wrap_mode_t;
- layer->wrap_mode_p = wrap_mode_p;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= change;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-}
-
-static CoglPipelineWrapModeInternal
-public_to_internal_wrap_mode (CoglPipelineWrapMode mode)
-{
- return (CoglPipelineWrapModeInternal)mode;
-}
-
-static CoglPipelineWrapMode
-internal_to_public_wrap_mode (CoglPipelineWrapModeInternal internal_mode)
-{
- g_return_val_if_fail (internal_mode !=
- COGL_PIPELINE_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER,
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC);
- return (CoglPipelineWrapMode)internal_mode;
-}
-
-void
-cogl_pipeline_set_layer_wrap_mode_s (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineWrapModeInternal internal_mode =
- public_to_internal_wrap_mode (mode);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- _cogl_pipeline_set_layer_wrap_modes (pipeline, layer, authority,
- internal_mode,
- authority->wrap_mode_t,
- authority->wrap_mode_p);
-}
-
-void
-cogl_pipeline_set_layer_wrap_mode_t (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineWrapModeInternal internal_mode =
- public_to_internal_wrap_mode (mode);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- _cogl_pipeline_set_layer_wrap_modes (pipeline, layer, authority,
- authority->wrap_mode_s,
- internal_mode,
- authority->wrap_mode_p);
-}
-
-/* The rationale for naming the third texture coordinate 'p' instead
- of OpenGL's usual 'r' is that 'r' conflicts with the usual naming
- of the 'red' component when treating a vector as a color. Under
- GLSL this is awkward because the texture swizzling for a vector
- uses a single letter for each component and the names for colors,
- textures and positions are synonymous. GLSL works around this by
- naming the components of the texture s, t, p and q. Cogl already
- effectively already exposes this naming because it exposes GLSL so
- it makes sense to use that naming consistently. Another alternative
- could be u, v and w. This is what Blender and Direct3D use. However
- the w component conflicts with the w component of a position
- vertex. */
-void
-cogl_pipeline_set_layer_wrap_mode_p (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineWrapModeInternal internal_mode =
- public_to_internal_wrap_mode (mode);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- _cogl_pipeline_set_layer_wrap_modes (pipeline, layer, authority,
- authority->wrap_mode_s,
- authority->wrap_mode_t,
- internal_mode);
-}
-
-void
-cogl_pipeline_set_layer_wrap_mode (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineWrapModeInternal internal_mode =
- public_to_internal_wrap_mode (mode);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- _cogl_pipeline_set_layer_wrap_modes (pipeline, layer, authority,
- internal_mode,
- internal_mode,
- internal_mode);
- /* XXX: I wonder if we should really be duplicating the mode into
- * the 'r' wrap mode too? */
-}
-
-/* FIXME: deprecate this API */
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_s (CoglPipelineLayer *layer)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (_cogl_is_pipeline_layer (layer), FALSE);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- return internal_to_public_wrap_mode (authority->wrap_mode_s);
-}
-
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_s (CoglPipeline *pipeline, int layer_index)
-{
- CoglPipelineLayer *layer;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
- /* FIXME: we shouldn't ever construct a layer in a getter function */
-
- return _cogl_pipeline_layer_get_wrap_mode_s (layer);
-}
-
-/* FIXME: deprecate this API */
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_t (CoglPipelineLayer *layer)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (_cogl_is_pipeline_layer (layer), FALSE);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- return internal_to_public_wrap_mode (authority->wrap_mode_t);
-}
-
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_t (CoglPipeline *pipeline, int layer_index)
-{
- CoglPipelineLayer *layer;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
- /* FIXME: we shouldn't ever construct a layer in a getter function */
-
- return _cogl_pipeline_layer_get_wrap_mode_t (layer);
-}
-
-CoglPipelineWrapMode
-_cogl_pipeline_layer_get_wrap_mode_p (CoglPipelineLayer *layer)
-{
- CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_WRAP_MODES;
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer, change);
-
- return internal_to_public_wrap_mode (authority->wrap_mode_p);
-}
-
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_p (CoglPipeline *pipeline, int layer_index)
-{
- CoglPipelineLayer *layer;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- return _cogl_pipeline_layer_get_wrap_mode_p (layer);
-}
-
-void
-_cogl_pipeline_layer_get_wrap_modes (CoglPipelineLayer *layer,
- CoglPipelineWrapModeInternal *wrap_mode_s,
- CoglPipelineWrapModeInternal *wrap_mode_t,
- CoglPipelineWrapModeInternal *wrap_mode_p)
-{
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_WRAP_MODES);
-
- *wrap_mode_s = authority->wrap_mode_s;
- *wrap_mode_t = authority->wrap_mode_t;
- *wrap_mode_p = authority->wrap_mode_p;
-}
-
-gboolean
-cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
- int layer_index,
- gboolean enable,
- GError **error)
-{
- CoglPipelineLayerState change =
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *new;
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Don't allow point sprite coordinates to be enabled if the driver
- doesn't support it */
- if (enable && !cogl_features_available (COGL_FEATURE_POINT_SPRITE))
- {
- if (error)
- {
- g_set_error (error, COGL_ERROR, COGL_ERROR_UNSUPPORTED,
- "Point sprite texture coordinates are enabled "
- "for a layer but the GL driver does not support it.");
- }
- else
- {
- static gboolean warning_seen = FALSE;
- if (!warning_seen)
- g_warning ("Point sprite texture coordinates are enabled "
- "for a layer but the GL driver does not support it.");
- warning_seen = TRUE;
- }
-
- return FALSE;
- }
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- if (authority->big_state->point_sprite_coords == enable)
- return TRUE;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, change);
-
- if (old_authority->big_state->point_sprite_coords == enable)
- {
- layer->differences &= ~change;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- return TRUE;
- }
- }
- }
-
- layer->big_state->point_sprite_coords = enable;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= change;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
- return TRUE;
-}
-
-gboolean
-cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipelineLayerState change =
- COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
- /* FIXME: we shouldn't ever construct a layer in a getter function */
-
- authority = _cogl_pipeline_layer_get_authority (layer, change);
-
- return authority->big_state->point_sprite_coords;
-}
-
-typedef struct
-{
- CoglPipeline *pipeline;
- CoglHandle texture;
-} CoglPipelineOverrideLayerState;
-
-static gboolean
-override_layer_texture_cb (CoglPipelineLayer *layer, void *user_data)
-{
- CoglPipelineOverrideLayerState *state = user_data;
-
- cogl_pipeline_set_layer_texture (state->pipeline,
- layer->index,
- state->texture);
-
- return TRUE;
-}
-
-void
-_cogl_pipeline_apply_overrides (CoglPipeline *pipeline,
- CoglPipelineFlushOptions *options)
-{
- COGL_STATIC_COUNTER (apply_overrides_counter,
- "pipeline overrides counter",
- "Increments each time we have to apply "
- "override options to a pipeline",
- 0 /* no application private data */);
-
- COGL_COUNTER_INC (_cogl_uprof_context, apply_overrides_counter);
-
- if (options->flags & COGL_PIPELINE_FLUSH_DISABLE_MASK)
- {
- int i;
-
- /* NB: we can assume that once we see one bit to disable
- * a layer, all subsequent layers are also disabled. */
- for (i = 0; i < 32 && options->disable_layers & (1<<i); i++)
- ;
-
- _cogl_pipeline_prune_to_n_layers (pipeline, i);
- }
-
- if (options->flags & COGL_PIPELINE_FLUSH_FALLBACK_MASK)
- {
- CoglPipelineFallbackState state;
-
- state.i = 0;
- state.pipeline = pipeline;
- state.fallback_layers = options->fallback_layers;
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- fallback_layer_cb,
- &state);
- }
-
- if (options->flags & COGL_PIPELINE_FLUSH_LAYER0_OVERRIDE)
- {
- CoglPipelineOverrideLayerState state;
-
- _cogl_pipeline_prune_to_n_layers (pipeline, 1);
-
- /* NB: we are overriding the first layer, but we don't know
- * the user's given layer_index, which is why we use
- * _cogl_pipeline_foreach_layer_internal() here even though we know
- * there's only one layer. */
- state.pipeline = pipeline;
- state.texture = options->layer0_override_texture;
- _cogl_pipeline_foreach_layer_internal (pipeline,
- override_layer_texture_cb,
- &state);
- }
-}
-
-static gboolean
-_cogl_pipeline_layer_texture_target_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1,
- CoglPipelineEvalFlags flags)
-{
- return authority0->target == authority1->target;
-}
-
-static gboolean
-_cogl_pipeline_layer_texture_data_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1,
- CoglPipelineEvalFlags flags)
-{
- GLuint gl_handle0, gl_handle1;
-
- cogl_texture_get_gl_texture (authority0->texture, &gl_handle0, NULL);
- cogl_texture_get_gl_texture (authority1->texture, &gl_handle1, NULL);
-
- return gl_handle0 == gl_handle1;
-}
-
-/* Determine the mask of differences between two layers.
- *
- * XXX: If layers and pipelines could both be cast to a common Tree
- * type of some kind then we could have a unified
- * compare_differences() function.
- */
-unsigned long
-_cogl_pipeline_layer_compare_differences (CoglPipelineLayer *layer0,
- CoglPipelineLayer *layer1)
-{
- CoglPipelineLayer *node0;
- CoglPipelineLayer *node1;
- int len0;
- int len1;
- int len0_index;
- int len1_index;
- int count;
- int i;
- CoglPipelineLayer *common_ancestor = NULL;
- unsigned long layers_difference = 0;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- /* Algorithm:
- *
- * 1) Walk the ancestors of each layer to the root node, adding a
- * pointer to each ancester node to two GArrays:
- * ctx->pipeline0_nodes, and ctx->pipeline1_nodes.
- *
- * 2) Compare the arrays to find the nodes where they stop to
- * differ.
- *
- * 3) For each array now iterate from index 0 to the first node of
- * difference ORing that nodes ->difference mask into the final
- * pipeline_differences mask.
- */
-
- g_array_set_size (ctx->pipeline0_nodes, 0);
- g_array_set_size (ctx->pipeline1_nodes, 0);
- for (node0 = layer0; node0; node0 = _cogl_pipeline_layer_get_parent (node0))
- g_array_append_vals (ctx->pipeline0_nodes, &node0, 1);
- for (node1 = layer1; node1; node1 = _cogl_pipeline_layer_get_parent (node1))
- g_array_append_vals (ctx->pipeline1_nodes, &node1, 1);
-
- len0 = ctx->pipeline0_nodes->len;
- len1 = ctx->pipeline1_nodes->len;
- /* There's no point looking at the last entries since we know both
- * layers must have the same default layer as their root node. */
- len0_index = len0 - 2;
- len1_index = len1 - 2;
- count = MIN (len0, len1) - 1;
- for (i = 0; i < count; i++)
- {
- node0 = g_array_index (ctx->pipeline0_nodes,
- CoglPipelineLayer *, len0_index--);
- node1 = g_array_index (ctx->pipeline1_nodes,
- CoglPipelineLayer *, len1_index--);
- if (node0 != node1)
- {
- common_ancestor = _cogl_pipeline_layer_get_parent (node0);
- break;
- }
- }
-
- /* If we didn't already find the first the common_ancestor ancestor
- * that's because one pipeline is a direct descendant of the other
- * and in this case the first common ancestor is the last node we
- * looked at. */
- if (!common_ancestor)
- common_ancestor = node0;
-
- count = len0 - 1;
- for (i = 0; i < count; i++)
- {
- node0 = g_array_index (ctx->pipeline0_nodes, CoglPipelineLayer *, i);
- if (node0 == common_ancestor)
- break;
- layers_difference |= node0->differences;
- }
-
- count = len1 - 1;
- for (i = 0; i < count; i++)
- {
- node1 = g_array_index (ctx->pipeline1_nodes, CoglPipelineLayer *, i);
- if (node1 == common_ancestor)
- break;
- layers_difference |= node1->differences;
- }
-
- return layers_difference;
-}
-
-static gboolean
-_cogl_pipeline_layer_combine_state_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- CoglPipelineLayerBigState *big_state0 = authority0->big_state;
- CoglPipelineLayerBigState *big_state1 = authority1->big_state;
- int n_args;
- int i;
-
- if (big_state0->texture_combine_rgb_func !=
- big_state1->texture_combine_rgb_func)
- return FALSE;
-
- if (big_state0->texture_combine_alpha_func !=
- big_state1->texture_combine_alpha_func)
- return FALSE;
-
- n_args =
- _cogl_get_n_args_for_combine_func (big_state0->texture_combine_rgb_func);
- for (i = 0; i < n_args; i++)
- {
- if ((big_state0->texture_combine_rgb_src[i] !=
- big_state1->texture_combine_rgb_src[i]) ||
- (big_state0->texture_combine_rgb_op[i] !=
- big_state1->texture_combine_rgb_op[i]))
- return FALSE;
- }
-
- n_args =
- _cogl_get_n_args_for_combine_func (big_state0->texture_combine_alpha_func);
- for (i = 0; i < n_args; i++)
- {
- if ((big_state0->texture_combine_alpha_src[i] !=
- big_state1->texture_combine_alpha_src[i]) ||
- (big_state0->texture_combine_alpha_op[i] !=
- big_state1->texture_combine_alpha_op[i]))
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_layer_combine_constant_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- return memcmp (authority0->big_state->texture_combine_constant,
- authority1->big_state->texture_combine_constant,
- sizeof (float) * 4) == 0 ? TRUE : FALSE;
-}
-
-static gboolean
-_cogl_pipeline_layer_filters_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- if (authority0->mag_filter != authority1->mag_filter)
- return FALSE;
- if (authority0->min_filter != authority1->min_filter)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-compare_wrap_mode_equal (CoglPipelineWrapMode wrap_mode0,
- CoglPipelineWrapMode wrap_mode1)
-{
- /* We consider AUTOMATIC to be equivalent to CLAMP_TO_EDGE because
- the primitives code is expected to override this to something
- else if it wants it to be behave any other way */
- if (wrap_mode0 == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- wrap_mode0 = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
- if (wrap_mode1 == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- wrap_mode1 = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
-
- return wrap_mode0 == wrap_mode1;
-}
-
-static gboolean
-_cogl_pipeline_layer_wrap_modes_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- if (!compare_wrap_mode_equal (authority0->wrap_mode_s,
- authority1->wrap_mode_s) ||
- !compare_wrap_mode_equal (authority0->wrap_mode_t,
- authority1->wrap_mode_t) ||
- !compare_wrap_mode_equal (authority0->wrap_mode_p,
- authority1->wrap_mode_p))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_layer_user_matrix_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- CoglPipelineLayerBigState *big_state0 = authority0->big_state;
- CoglPipelineLayerBigState *big_state1 = authority1->big_state;
-
- if (!cogl_matrix_equal (&big_state0->matrix, &big_state1->matrix))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1)
-{
- CoglPipelineLayerBigState *big_state0 = authority0->big_state;
- CoglPipelineLayerBigState *big_state1 = authority1->big_state;
-
- return big_state0->point_sprite_coords == big_state1->point_sprite_coords;
-}
-
-typedef gboolean
-(*CoglPipelineLayerStateComparitor) (CoglPipelineLayer *authority0,
- CoglPipelineLayer *authority1);
-
-static gboolean
-layer_state_equal (CoglPipelineLayerStateIndex state_index,
- CoglPipelineLayer **authorities0,
- CoglPipelineLayer **authorities1,
- CoglPipelineLayerStateComparitor comparitor)
-{
- return comparitor (authorities0[state_index], authorities1[state_index]);
-}
-
-static void
-_cogl_pipeline_layer_resolve_authorities (CoglPipelineLayer *layer,
- unsigned long differences,
- CoglPipelineLayer **authorities)
-{
- unsigned long remaining = differences;
- CoglPipelineLayer *authority = layer;
-
- do
- {
- unsigned long found = authority->differences & remaining;
- int i;
-
- if (found == 0)
- continue;
-
- for (i = 0; TRUE; i++)
- {
- unsigned long state = (1L<<i);
-
- if (state & found)
- authorities[i] = authority;
- else if (state > found)
- break;
- }
-
- remaining &= ~found;
- if (remaining == 0)
- return;
- }
- while ((authority = _cogl_pipeline_layer_get_parent (authority)));
-
- g_assert (remaining == 0);
-}
-
-static gboolean
-_cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
- CoglPipelineLayer *layer1,
- unsigned long differences_mask,
- CoglPipelineEvalFlags flags)
-{
- unsigned long layers_difference;
- CoglPipelineLayer *authorities0[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
- CoglPipelineLayer *authorities1[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
-
- if (layer0 == layer1)
- return TRUE;
-
- layers_difference =
- _cogl_pipeline_layer_compare_differences (layer0, layer1);
-
- /* Only compare the sparse state groups requested by the caller... */
- layers_difference &= differences_mask;
-
- _cogl_pipeline_layer_resolve_authorities (layer0,
- layers_difference,
- authorities0);
- _cogl_pipeline_layer_resolve_authorities (layer1,
- layers_difference,
- authorities1);
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET)
- {
- CoglPipelineLayerStateIndex state_index =
- COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX;
- if (!_cogl_pipeline_layer_texture_target_equal (authorities0[state_index],
- authorities1[state_index],
- flags))
- return FALSE;
- }
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
- {
- CoglPipelineLayerStateIndex state_index =
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX;
- if (!_cogl_pipeline_layer_texture_data_equal (authorities0[state_index],
- authorities1[state_index],
- flags))
- return FALSE;
- }
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_combine_state_equal))
- return FALSE;
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_combine_constant_equal))
- return FALSE;
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_FILTERS &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_filters_equal))
- return FALSE;
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_WRAP_MODES &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_wrap_modes_equal))
- return FALSE;
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_USER_MATRIX &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_user_matrix_equal))
- return FALSE;
-
- if (layers_difference & COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS &&
- !layer_state_equal (COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
- authorities0, authorities1,
- _cogl_pipeline_layer_point_sprite_coords_equal))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_color_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- return cogl_color_equal (&authority0->color, &authority1->color);
-}
-
-static gboolean
-_cogl_pipeline_lighting_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- CoglPipelineLightingState *state0 = &authority0->big_state->lighting_state;
- CoglPipelineLightingState *state1 = &authority1->big_state->lighting_state;
-
- if (memcmp (state0->ambient, state1->ambient, sizeof (float) * 4) != 0)
- return FALSE;
- if (memcmp (state0->diffuse, state1->diffuse, sizeof (float) * 4) != 0)
- return FALSE;
- if (memcmp (state0->specular, state1->specular, sizeof (float) * 4) != 0)
- return FALSE;
- if (memcmp (state0->emission, state1->emission, sizeof (float) * 4) != 0)
- return FALSE;
- if (state0->shininess != state1->shininess)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_alpha_func_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- CoglPipelineAlphaFuncState *alpha_state0 =
- &authority0->big_state->alpha_state;
- CoglPipelineAlphaFuncState *alpha_state1 =
- &authority1->big_state->alpha_state;
-
- return alpha_state0->alpha_func == alpha_state1->alpha_func;
-}
-
-static gboolean
-_cogl_pipeline_alpha_func_reference_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- CoglPipelineAlphaFuncState *alpha_state0 =
- &authority0->big_state->alpha_state;
- CoglPipelineAlphaFuncState *alpha_state1 =
- &authority1->big_state->alpha_state;
-
- return (alpha_state0->alpha_func_reference ==
- alpha_state1->alpha_func_reference);
-}
-
-static gboolean
-_cogl_pipeline_blend_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- CoglPipelineBlendState *blend_state0 = &authority0->big_state->blend_state;
- CoglPipelineBlendState *blend_state1 = &authority1->big_state->blend_state;
-
-#ifndef HAVE_COGL_GLES
- if (blend_state0->blend_equation_rgb != blend_state1->blend_equation_rgb)
- return FALSE;
- if (blend_state0->blend_equation_alpha !=
- blend_state1->blend_equation_alpha)
- return FALSE;
- if (blend_state0->blend_src_factor_alpha !=
- blend_state1->blend_src_factor_alpha)
- return FALSE;
- if (blend_state0->blend_dst_factor_alpha !=
- blend_state1->blend_dst_factor_alpha)
- return FALSE;
-#endif
- if (blend_state0->blend_src_factor_rgb !=
- blend_state1->blend_src_factor_rgb)
- return FALSE;
- if (blend_state0->blend_dst_factor_rgb !=
- blend_state1->blend_dst_factor_rgb)
- return FALSE;
-#ifndef HAVE_COGL_GLES
- if (blend_state0->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
- blend_state0->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
- blend_state0->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
- blend_state0->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
- {
- if (!cogl_color_equal (&blend_state0->blend_constant,
- &blend_state1->blend_constant))
- return FALSE;
- }
-#endif
-
- return TRUE;
-}
-
-static gboolean
-_cogl_pipeline_depth_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- if (authority0->big_state->depth_state.depth_test_enabled == FALSE &&
- authority1->big_state->depth_state.depth_test_enabled == FALSE)
- return TRUE;
- else
- return memcmp (&authority0->big_state->depth_state,
- &authority1->big_state->depth_state,
- sizeof (CoglPipelineDepthState)) == 0;
-}
-
-static gboolean
-_cogl_pipeline_fog_state_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- CoglPipelineFogState *fog_state0 = &authority0->big_state->fog_state;
- CoglPipelineFogState *fog_state1 = &authority1->big_state->fog_state;
-
- if (fog_state0->enabled == fog_state1->enabled &&
- cogl_color_equal (&fog_state0->color, &fog_state1->color) &&
- fog_state0->mode == fog_state1->mode &&
- fog_state0->density == fog_state1->density &&
- fog_state0->z_near == fog_state1->z_near &&
- fog_state0->z_far == fog_state1->z_far)
- return TRUE;
- else
- return FALSE;
-}
-
-static gboolean
-_cogl_pipeline_point_size_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- return authority0->big_state->point_size == authority1->big_state->point_size;
-}
-
-static gboolean
-_cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- return (authority0->big_state->user_program ==
- authority1->big_state->user_program);
-}
-
-static gboolean
-_cogl_pipeline_layers_equal (CoglPipeline *authority0,
- CoglPipeline *authority1,
- unsigned long differences,
- CoglPipelineEvalFlags flags)
-{
- int i;
-
- if (authority0->n_layers != authority1->n_layers)
- return FALSE;
-
- _cogl_pipeline_update_layers_cache (authority0);
- _cogl_pipeline_update_layers_cache (authority1);
-
- for (i = 0; i < authority0->n_layers; i++)
- {
- if (!_cogl_pipeline_layer_equal (authority0->layers_cache[i],
- authority1->layers_cache[i],
- differences,
- flags))
- return FALSE;
- }
- return TRUE;
-}
-
-/* Determine the mask of differences between two pipelines */
-unsigned long
-_cogl_pipeline_compare_differences (CoglPipeline *pipeline0,
- CoglPipeline *pipeline1)
-{
- CoglPipeline *node0;
- CoglPipeline *node1;
- int len0;
- int len1;
- int len0_index;
- int len1_index;
- int count;
- int i;
- CoglPipeline *common_ancestor = NULL;
- unsigned long pipelines_difference = 0;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- /* Algorithm:
- *
- * 1) Walk the ancestors of each layer to the root node, adding a
- * pointer to each ancester node to two GArrays:
- * ctx->pipeline0_nodes, and ctx->pipeline1_nodes.
- *
- * 2) Compare the arrays to find the nodes where they stop to
- * differ.
- *
- * 3) For each array now iterate from index 0 to the first node of
- * difference ORing that nodes ->difference mask into the final
- * pipeline_differences mask.
- */
-
- g_array_set_size (ctx->pipeline0_nodes, 0);
- g_array_set_size (ctx->pipeline1_nodes, 0);
- for (node0 = pipeline0; node0; node0 = _cogl_pipeline_get_parent (node0))
- g_array_append_vals (ctx->pipeline0_nodes, &node0, 1);
- for (node1 = pipeline1; node1; node1 = _cogl_pipeline_get_parent (node1))
- g_array_append_vals (ctx->pipeline1_nodes, &node1, 1);
-
- len0 = ctx->pipeline0_nodes->len;
- len1 = ctx->pipeline1_nodes->len;
- /* There's no point looking at the last entries since we know both
- * layers must have the same default layer as their root node. */
- len0_index = len0 - 2;
- len1_index = len1 - 2;
- count = MIN (len0, len1) - 1;
- for (i = 0; i < count; i++)
- {
- node0 = g_array_index (ctx->pipeline0_nodes,
- CoglPipeline *, len0_index--);
- node1 = g_array_index (ctx->pipeline1_nodes,
- CoglPipeline *, len1_index--);
- if (node0 != node1)
- {
- common_ancestor = _cogl_pipeline_get_parent (node0);
- break;
- }
- }
-
- /* If we didn't already find the first the common_ancestor ancestor
- * that's because one pipeline is a direct descendant of the other
- * and in this case the first common ancestor is the last node we
- * looked at. */
- if (!common_ancestor)
- common_ancestor = node0;
-
- count = len0 - 1;
- for (i = 0; i < count; i++)
- {
- node0 = g_array_index (ctx->pipeline0_nodes, CoglPipeline *, i);
- if (node0 == common_ancestor)
- break;
- pipelines_difference |= node0->differences;
- }
-
- count = len1 - 1;
- for (i = 0; i < count; i++)
- {
- node1 = g_array_index (ctx->pipeline1_nodes, CoglPipeline *, i);
- if (node1 == common_ancestor)
- break;
- pipelines_difference |= node1->differences;
- }
-
- return pipelines_difference;
-
-}
-
-static gboolean
-simple_property_equal (CoglPipeline **authorities0,
- CoglPipeline **authorities1,
- unsigned long pipelines_difference,
- CoglPipelineStateIndex state_index,
- CoglPipelineStateComparitor comparitor)
-{
- if (pipelines_difference & (1L<<state_index))
- {
- if (!comparitor (authorities0[state_index], authorities1[state_index]))
- return FALSE;
- }
- return TRUE;
-}
-
-static void
-_cogl_pipeline_resolve_authorities (CoglPipeline *pipeline,
- unsigned long differences,
- CoglPipeline **authorities)
-{
- unsigned long remaining = differences;
- CoglPipeline *authority = pipeline;
-
- do
- {
- unsigned long found = authority->differences & remaining;
- int i;
-
- if (found == 0)
- continue;
-
- for (i = 0; TRUE; i++)
- {
- unsigned long state = (1L<<i);
-
- if (state & found)
- authorities[i] = authority;
- else if (state > found)
- break;
- }
-
- remaining &= ~found;
- if (remaining == 0)
- return;
- }
- while ((authority = _cogl_pipeline_get_parent (authority)));
-
- g_assert (remaining == 0);
-}
-
-/* Comparison of two arbitrary pipelines is done by:
- * 1) walking up the parents of each pipeline until a common
- * ancestor is found, and at each step ORing together the
- * difference masks.
- *
- * 2) using the final difference mask to determine which state
- * groups to compare.
- *
- * This is used, for example, by the Cogl journal to compare pipelines so that
- * it can split up geometry that needs different OpenGL state.
- *
- * XXX: When comparing texture layers, _cogl_pipeline_equal will actually
- * compare the underlying GL texture handle that the Cogl texture uses so that
- * atlas textures and sub textures will be considered equal if they point to
- * the same texture. This is useful for comparing pipelines in the journal but
- * it means that _cogl_pipeline_equal doesn't strictly compare whether the
- * pipelines are the same. If we needed those semantics we could perhaps add
- * another function or some flags to control the behaviour.
- *
- * XXX: Similarly when comparing the wrap modes,
- * COGL_PIPELINE_WRAP_MODE_AUTOMATIC is considered to be the same as
- * COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE because once they get to the
- * journal stage they act exactly the same.
- */
-gboolean
-_cogl_pipeline_equal (CoglPipeline *pipeline0,
- CoglPipeline *pipeline1,
- unsigned long differences,
- unsigned long layer_differences,
- CoglPipelineEvalFlags flags)
-{
- unsigned long pipelines_difference;
- CoglPipeline *authorities0[COGL_PIPELINE_STATE_SPARSE_COUNT];
- CoglPipeline *authorities1[COGL_PIPELINE_STATE_SPARSE_COUNT];
- gboolean ret;
-
- COGL_STATIC_TIMER (pipeline_equal_timer,
- "Mainloop", /* parent */
- "_cogl_pipeline_equal",
- "The time spent comparing cogl pipelines",
- 0 /* no application private data */);
-
- COGL_TIMER_START (_cogl_uprof_context, pipeline_equal_timer);
-
- if (pipeline0 == pipeline1)
- {
- ret = TRUE;
- goto done;
- }
-
- ret = FALSE;
-
- /* First check non-sparse properties */
-
- if (differences & COGL_PIPELINE_STATE_REAL_BLEND_ENABLE &&
- pipeline0->real_blend_enable != pipeline1->real_blend_enable)
- goto done;
-
- /* Then check sparse properties */
-
- pipelines_difference =
- _cogl_pipeline_compare_differences (pipeline0, pipeline1);
-
- /* Only compare the sparse state groups requested by the caller... */
- pipelines_difference &= differences;
-
- _cogl_pipeline_resolve_authorities (pipeline0,
- pipelines_difference,
- authorities0);
- _cogl_pipeline_resolve_authorities (pipeline1,
- pipelines_difference,
- authorities1);
-
- /* FIXME: we should resolve all the required authorities up front since
- * that should reduce some repeat ancestor traversals. */
-
- if (pipelines_difference & COGL_PIPELINE_STATE_COLOR)
- {
- CoglPipeline *authority0 = authorities0[COGL_PIPELINE_STATE_COLOR_INDEX];
- CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_COLOR_INDEX];
-
- if (!cogl_color_equal (&authority0->color, &authority1->color))
- goto done;
- }
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_LIGHTING_INDEX,
- _cogl_pipeline_lighting_state_equal))
- goto done;
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX,
- _cogl_pipeline_alpha_func_state_equal))
- goto done;
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX,
- _cogl_pipeline_alpha_func_reference_state_equal))
- goto done;
-
- /* We don't need to compare the detailed blending state if we know
- * blending is disabled for both pipelines. */
- if (pipeline0->real_blend_enable &&
- pipelines_difference & COGL_PIPELINE_STATE_BLEND)
- {
- CoglPipeline *authority0 = authorities0[COGL_PIPELINE_STATE_BLEND_INDEX];
- CoglPipeline *authority1 = authorities1[COGL_PIPELINE_STATE_BLEND_INDEX];
-
- if (!_cogl_pipeline_blend_state_equal (authority0, authority1))
- goto done;
- }
-
- /* XXX: we don't need to compare the BLEND_ENABLE state because it's
- * already reflected in ->real_blend_enable */
-#if 0
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_BLEND_INDEX,
- _cogl_pipeline_blend_enable_equal))
- return FALSE;
-#endif
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_DEPTH_INDEX,
- _cogl_pipeline_depth_state_equal))
- goto done;
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_FOG_INDEX,
- _cogl_pipeline_fog_state_equal))
- goto done;
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
- _cogl_pipeline_point_size_equal))
- goto done;
-
- if (!simple_property_equal (authorities0, authorities1,
- pipelines_difference,
- COGL_PIPELINE_STATE_USER_SHADER_INDEX,
- _cogl_pipeline_user_shader_equal))
- goto done;
-
- if (pipelines_difference & COGL_PIPELINE_STATE_LAYERS)
- {
- CoglPipelineStateIndex state_index = COGL_PIPELINE_STATE_LAYERS_INDEX;
- if (!_cogl_pipeline_layers_equal (authorities0[state_index],
- authorities1[state_index],
- layer_differences,
- flags))
- goto done;
- }
-
- ret = TRUE;
-done:
- COGL_TIMER_STOP (_cogl_uprof_context, pipeline_equal_timer);
- return ret;
-}
-
-void
-cogl_pipeline_get_color (CoglPipeline *pipeline,
- CoglColor *color)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
-
- *color = authority->color;
-}
-
-/* This is used heavily by the cogl journal when logging quads */
-void
-_cogl_pipeline_get_colorubv (CoglPipeline *pipeline,
- guint8 *color)
-{
- CoglPipeline *authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_COLOR);
-
- _cogl_color_get_rgba_4ubv (&authority->color, color);
-}
-
-static void
-_cogl_pipeline_prune_redundant_ancestry (CoglPipeline *pipeline)
-{
- CoglPipeline *new_parent = _cogl_pipeline_get_parent (pipeline);
-
- /* Before considering pruning redundant ancestry we check if this
- * pipeline is an authority for layer state and if so only consider
- * reparenting if it *owns* all the layers it depends on. NB: A
- * pipeline can be be a STATE_LAYERS authority but it may still
- * defer to its ancestors to define the state for some of its
- * layers.
- *
- * For example a pipeline that derives from a parent with 5 layers
- * can become a STATE_LAYERS authority by simply changing it's
- * ->n_layers count to 4 and in that case it can still defer to its
- * ancestors to define the state of those 4 layers.
- *
- * If a pipeline depends on any ancestors for layer state then we
- * immediatly bail out.
- */
- if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
- {
- if (pipeline->n_layers != g_list_length (pipeline->layer_differences))
- return;
- }
-
- /* walk up past ancestors that are now redundant and potentially
- * reparent the pipeline. */
- while (_cogl_pipeline_get_parent (new_parent) &&
- (new_parent->differences | pipeline->differences) ==
- pipeline->differences)
- new_parent = _cogl_pipeline_get_parent (new_parent);
-
- if (new_parent != _cogl_pipeline_get_parent (pipeline))
- {
- gboolean is_weak = _cogl_pipeline_is_weak (pipeline);
- _cogl_pipeline_set_parent (pipeline, new_parent, is_weak ? FALSE : TRUE);
- }
-}
-
-static void
-_cogl_pipeline_update_authority (CoglPipeline *pipeline,
- CoglPipeline *authority,
- CoglPipelineState state,
- CoglPipelineStateComparitor comparitor)
-{
- /* If we are the current authority see if we can revert to one of
- * our ancestors being the authority */
- if (pipeline == authority &&
- _cogl_pipeline_get_parent (authority) != NULL)
- {
- CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
- CoglPipeline *old_authority =
- _cogl_pipeline_get_authority (parent, state);
-
- if (comparitor (authority, old_authority))
- pipeline->differences &= ~state;
- }
- else if (pipeline != authority)
- {
- /* If we weren't previously the authority on this state then we
- * need to extended our differences mask and so it's possible
- * that some of our ancestry will now become redundant, so we
- * aim to reparent ourselves if that's true... */
- pipeline->differences |= state;
- _cogl_pipeline_prune_redundant_ancestry (pipeline);
- }
-}
-
-void
-cogl_pipeline_set_color (CoglPipeline *pipeline,
- const CoglColor *color)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_COLOR;
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- if (cogl_color_equal (color, &authority->color))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, color, FALSE);
-
- pipeline->color = *color;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_color_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha)
-{
- CoglColor color;
- cogl_color_init_from_4ub (&color, red, green, blue, alpha);
- cogl_pipeline_set_color (pipeline, &color);
-}
-
-void
-cogl_pipeline_set_color4f (CoglPipeline *pipeline,
- float red,
- float green,
- float blue,
- float alpha)
-{
- CoglColor color;
- cogl_color_init_from_4f (&color, red, green, blue, alpha);
- cogl_pipeline_set_color (pipeline, &color);
-}
-
-CoglPipelineBlendEnable
-_cogl_pipeline_get_blend_enabled (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_BLEND_ENABLE);
- return authority->blend_enable;
-}
-
-static gboolean
-_cogl_pipeline_blend_enable_equal (CoglPipeline *authority0,
- CoglPipeline *authority1)
-{
- return authority0->blend_enable == authority1->blend_enable ? TRUE : FALSE;
-}
-
-void
-_cogl_pipeline_set_blend_enabled (CoglPipeline *pipeline,
- CoglPipelineBlendEnable enable)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_BLEND_ENABLE;
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
- g_return_if_fail (enable > 1 &&
- "don't pass TRUE or FALSE to _set_blend_enabled!");
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- if (authority->blend_enable == enable)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->blend_enable = enable;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_blend_enable_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_get_ambient (CoglPipeline *pipeline,
- CoglColor *ambient)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
- cogl_color_init_from_4fv (ambient,
- authority->big_state->lighting_state.ambient);
-}
-
-void
-cogl_pipeline_set_ambient (CoglPipeline *pipeline,
- const CoglColor *ambient)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
- CoglPipeline *authority;
- CoglPipelineLightingState *lighting_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- lighting_state = &authority->big_state->lighting_state;
- if (cogl_color_equal (ambient, &lighting_state->ambient))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- lighting_state = &pipeline->big_state->lighting_state;
- lighting_state->ambient[0] = cogl_color_get_red_float (ambient);
- lighting_state->ambient[1] = cogl_color_get_green_float (ambient);
- lighting_state->ambient[2] = cogl_color_get_blue_float (ambient);
- lighting_state->ambient[3] = cogl_color_get_alpha_float (ambient);
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_lighting_state_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
- CoglColor *diffuse)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
- cogl_color_init_from_4fv (diffuse,
- authority->big_state->lighting_state.diffuse);
-}
-
-void
-cogl_pipeline_set_diffuse (CoglPipeline *pipeline,
- const CoglColor *diffuse)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
- CoglPipeline *authority;
- CoglPipelineLightingState *lighting_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- lighting_state = &authority->big_state->lighting_state;
- if (cogl_color_equal (diffuse, &lighting_state->diffuse))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- lighting_state = &pipeline->big_state->lighting_state;
- lighting_state->diffuse[0] = cogl_color_get_red_float (diffuse);
- lighting_state->diffuse[1] = cogl_color_get_green_float (diffuse);
- lighting_state->diffuse[2] = cogl_color_get_blue_float (diffuse);
- lighting_state->diffuse[3] = cogl_color_get_alpha_float (diffuse);
-
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_lighting_state_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline,
- const CoglColor *color)
-{
- cogl_pipeline_set_ambient (pipeline, color);
- cogl_pipeline_set_diffuse (pipeline, color);
-}
-
-void
-cogl_pipeline_get_specular (CoglPipeline *pipeline,
- CoglColor *specular)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
- cogl_color_init_from_4fv (specular,
- authority->big_state->lighting_state.specular);
-}
-
-void
-cogl_pipeline_set_specular (CoglPipeline *pipeline, const CoglColor *specular)
-{
- CoglPipeline *authority;
- CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
- CoglPipelineLightingState *lighting_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- lighting_state = &authority->big_state->lighting_state;
- if (cogl_color_equal (specular, &lighting_state->specular))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- lighting_state = &pipeline->big_state->lighting_state;
- lighting_state->specular[0] = cogl_color_get_red_float (specular);
- lighting_state->specular[1] = cogl_color_get_green_float (specular);
- lighting_state->specular[2] = cogl_color_get_blue_float (specular);
- lighting_state->specular[3] = cogl_color_get_alpha_float (specular);
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_lighting_state_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-float
-cogl_pipeline_get_shininess (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
- return authority->big_state->lighting_state.shininess;
-}
-
-void
-cogl_pipeline_set_shininess (CoglPipeline *pipeline,
- float shininess)
-{
- CoglPipeline *authority;
- CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
- CoglPipelineLightingState *lighting_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- if (shininess < 0.0)
- {
- g_warning ("Out of range shininess %f supplied for pipeline\n",
- shininess);
- return;
- }
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- lighting_state = &authority->big_state->lighting_state;
-
- if (lighting_state->shininess == shininess)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- lighting_state = &pipeline->big_state->lighting_state;
- lighting_state->shininess = shininess;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_lighting_state_equal);
-}
-
-void
-cogl_pipeline_get_emission (CoglPipeline *pipeline,
- CoglColor *emission)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LIGHTING);
-
- cogl_color_init_from_4fv (emission,
- authority->big_state->lighting_state.emission);
-}
-
-void
-cogl_pipeline_set_emission (CoglPipeline *pipeline, const CoglColor *emission)
-{
- CoglPipeline *authority;
- CoglPipelineState state = COGL_PIPELINE_STATE_LIGHTING;
- CoglPipelineLightingState *lighting_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- lighting_state = &authority->big_state->lighting_state;
- if (cogl_color_equal (emission, &lighting_state->emission))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- lighting_state = &pipeline->big_state->lighting_state;
- lighting_state->emission[0] = cogl_color_get_red_float (emission);
- lighting_state->emission[1] = cogl_color_get_green_float (emission);
- lighting_state->emission[2] = cogl_color_get_blue_float (emission);
- lighting_state->emission[3] = cogl_color_get_alpha_float (emission);
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_lighting_state_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-static void
-_cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
- CoglPipelineAlphaFunc alpha_func)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC;
- CoglPipeline *authority;
- CoglPipelineAlphaFuncState *alpha_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- alpha_state = &authority->big_state->alpha_state;
- if (alpha_state->alpha_func == alpha_func)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- alpha_state = &pipeline->big_state->alpha_state;
- alpha_state->alpha_func = alpha_func;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_alpha_func_state_equal);
-}
-
-static void
-_cogl_pipeline_set_alpha_test_function_reference (CoglPipeline *pipeline,
- float alpha_reference)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE;
- CoglPipeline *authority;
- CoglPipelineAlphaFuncState *alpha_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- alpha_state = &authority->big_state->alpha_state;
- if (alpha_state->alpha_func_reference == alpha_reference)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- alpha_state = &pipeline->big_state->alpha_state;
- alpha_state->alpha_func_reference = alpha_reference;
-
- _cogl_pipeline_update_authority
- (pipeline, authority, state,
- _cogl_pipeline_alpha_func_reference_state_equal);
-}
-
-void
-cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
- CoglPipelineAlphaFunc alpha_func,
- float alpha_reference)
-{
- _cogl_pipeline_set_alpha_test_function (pipeline, alpha_func);
- _cogl_pipeline_set_alpha_test_function_reference (pipeline, alpha_reference);
-}
-
-CoglPipelineAlphaFunc
-cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_ALPHA_FUNC);
-
- return authority->big_state->alpha_state.alpha_func;
-}
-
-float
-cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), 0.0f);
-
- authority =
- _cogl_pipeline_get_authority (pipeline,
- COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE);
-
- return authority->big_state->alpha_state.alpha_func_reference;
-}
-
-GLenum
-arg_to_gl_blend_factor (CoglBlendStringArgument *arg)
-{
- if (arg->source.is_zero)
- return GL_ZERO;
- if (arg->factor.is_one)
- return GL_ONE;
- else if (arg->factor.is_src_alpha_saturate)
- return GL_SRC_ALPHA_SATURATE;
- else if (arg->factor.source.info->type ==
- COGL_BLEND_STRING_COLOR_SOURCE_SRC_COLOR)
- {
- if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_SRC_COLOR;
- else
- return GL_SRC_COLOR;
- }
- else
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_SRC_ALPHA;
- else
- return GL_SRC_ALPHA;
- }
- }
- else if (arg->factor.source.info->type ==
- COGL_BLEND_STRING_COLOR_SOURCE_DST_COLOR)
- {
- if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_DST_COLOR;
- else
- return GL_DST_COLOR;
- }
- else
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_DST_ALPHA;
- else
- return GL_DST_ALPHA;
- }
- }
-#ifndef HAVE_COGL_GLES
- else if (arg->factor.source.info->type ==
- COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
- {
- if (arg->factor.source.mask != COGL_BLEND_STRING_CHANNEL_MASK_ALPHA)
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_CONSTANT_COLOR;
- else
- return GL_CONSTANT_COLOR;
- }
- else
- {
- if (arg->factor.source.one_minus)
- return GL_ONE_MINUS_CONSTANT_ALPHA;
- else
- return GL_CONSTANT_ALPHA;
- }
- }
-#endif
-
- g_warning ("Unable to determine valid blend factor from blend string\n");
- return GL_ONE;
-}
-
-void
-setup_blend_state (CoglBlendStringStatement *statement,
- GLenum *blend_equation,
- GLint *blend_src_factor,
- GLint *blend_dst_factor)
-{
-#ifndef HAVE_COGL_GLES
- switch (statement->function->type)
- {
- case COGL_BLEND_STRING_FUNCTION_ADD:
- *blend_equation = GL_FUNC_ADD;
- break;
- /* TODO - add more */
- default:
- g_warning ("Unsupported blend function given");
- *blend_equation = GL_FUNC_ADD;
- }
-#endif
-
- *blend_src_factor = arg_to_gl_blend_factor (&statement->args[0]);
- *blend_dst_factor = arg_to_gl_blend_factor (&statement->args[1]);
-}
-
-gboolean
-cogl_pipeline_set_blend (CoglPipeline *pipeline,
- const char *blend_description,
- GError **error)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
- CoglPipeline *authority;
- CoglBlendStringStatement statements[2];
- CoglBlendStringStatement *rgb;
- CoglBlendStringStatement *a;
- GError *internal_error = NULL;
- int count;
- CoglPipelineBlendState *blend_state;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- count =
- _cogl_blend_string_compile (blend_description,
- COGL_BLEND_STRING_CONTEXT_BLENDING,
- statements,
- &internal_error);
- if (!count)
- {
- if (error)
- g_propagate_error (error, internal_error);
- else
- {
- g_warning ("Cannot compile blend description: %s\n",
- internal_error->message);
- g_error_free (internal_error);
- }
- return FALSE;
- }
-
- if (count == 1)
- rgb = a = statements;
- else
- {
- rgb = &statements[0];
- a = &statements[1];
- }
-
- authority =
- _cogl_pipeline_get_authority (pipeline, state);
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- blend_state = &pipeline->big_state->blend_state;
-#ifndef HAVE_COGL_GLES
- setup_blend_state (rgb,
- &blend_state->blend_equation_rgb,
- &blend_state->blend_src_factor_rgb,
- &blend_state->blend_dst_factor_rgb);
- setup_blend_state (a,
- &blend_state->blend_equation_alpha,
- &blend_state->blend_src_factor_alpha,
- &blend_state->blend_dst_factor_alpha);
-#else
- setup_blend_state (rgb,
- NULL,
- &blend_state->blend_src_factor_rgb,
- &blend_state->blend_dst_factor_rgb);
-#endif
-
- /* If we are the current authority see if we can revert to one of our
- * ancestors being the authority */
- if (pipeline == authority &&
- _cogl_pipeline_get_parent (authority) != NULL)
- {
- CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
- CoglPipeline *old_authority =
- _cogl_pipeline_get_authority (parent, state);
-
- if (_cogl_pipeline_blend_state_equal (authority, old_authority))
- pipeline->differences &= ~state;
- }
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (pipeline != authority)
- {
- pipeline->differences |= state;
- _cogl_pipeline_prune_redundant_ancestry (pipeline);
- }
-
- handle_automatic_blend_enable (pipeline, state);
-
- return TRUE;
-}
-
-void
-cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
- const CoglColor *constant_color)
-{
-#ifndef HAVE_COGL_GLES
- CoglPipelineState state = COGL_PIPELINE_STATE_BLEND;
- CoglPipeline *authority;
- CoglPipelineBlendState *blend_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- blend_state = &authority->big_state->blend_state;
- if (cogl_color_equal (constant_color, &blend_state->blend_constant))
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- blend_state = &pipeline->big_state->blend_state;
- blend_state->blend_constant = *constant_color;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_blend_state_equal);
-
- handle_automatic_blend_enable (pipeline, state);
-#endif
-}
-
-CoglHandle
-cogl_pipeline_get_user_program (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), COGL_INVALID_HANDLE);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_USER_SHADER);
-
- return authority->big_state->user_program;
-}
-
-/* XXX: for now we don't mind if the program has vertex shaders
- * attached but if we ever make a similar API public we should only
- * allow attaching of programs containing fragment shaders. Eventually
- * we will have a CoglPipeline abstraction to also cover vertex
- * processing.
- */
-void
-cogl_pipeline_set_user_program (CoglPipeline *pipeline,
- CoglHandle program)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_USER_SHADER;
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- if (authority->big_state->user_program == program)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- if (program != COGL_INVALID_HANDLE)
- {
- _cogl_pipeline_set_fragend (pipeline, COGL_PIPELINE_FRAGEND_DEFAULT);
- _cogl_pipeline_set_vertend (pipeline, COGL_PIPELINE_VERTEND_DEFAULT);
- }
-
- /* If we are the current authority see if we can revert to one of our
- * ancestors being the authority */
- if (pipeline == authority &&
- _cogl_pipeline_get_parent (authority) != NULL)
- {
- CoglPipeline *parent = _cogl_pipeline_get_parent (authority);
- CoglPipeline *old_authority =
- _cogl_pipeline_get_authority (parent, state);
-
- if (old_authority->big_state->user_program == program)
- pipeline->differences &= ~state;
- }
- else if (pipeline != authority)
- {
- /* If we weren't previously the authority on this state then we
- * need to extended our differences mask and so it's possible
- * that some of our ancestry will now become redundant, so we
- * aim to reparent ourselves if that's true... */
- pipeline->differences |= state;
- _cogl_pipeline_prune_redundant_ancestry (pipeline);
- }
-
- if (program != COGL_INVALID_HANDLE)
- cogl_handle_ref (program);
- if (authority == pipeline &&
- pipeline->big_state->user_program != COGL_INVALID_HANDLE)
- cogl_handle_unref (pipeline->big_state->user_program);
- pipeline->big_state->user_program = program;
-
- handle_automatic_blend_enable (pipeline, state);
-}
-
-void
-cogl_pipeline_set_depth_test_enabled (CoglPipeline *pipeline,
- gboolean enable)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
- CoglPipeline *authority;
- CoglPipelineDepthState *depth_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- depth_state = &authority->big_state->depth_state;
- if (depth_state->depth_test_enabled == enable)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->depth_state.depth_test_enabled = enable;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_depth_state_equal);
-}
-
-gboolean
-cogl_pipeline_get_depth_test_enabled (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
-
- return authority->big_state->depth_state.depth_test_enabled;
-}
-
-void
-cogl_pipeline_set_depth_writing_enabled (CoglPipeline *pipeline,
- gboolean enable)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
- CoglPipeline *authority;
- CoglPipelineDepthState *depth_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- depth_state = &authority->big_state->depth_state;
- if (depth_state->depth_writing_enabled == enable)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->depth_state.depth_writing_enabled = enable;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_depth_state_equal);
-}
-
-gboolean
-cogl_pipeline_get_depth_writing_enabled (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), TRUE);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
-
- return authority->big_state->depth_state.depth_writing_enabled;
-}
-
-void
-cogl_pipeline_set_depth_test_function (CoglPipeline *pipeline,
- CoglDepthTestFunction function)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
- CoglPipeline *authority;
- CoglPipelineDepthState *depth_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- depth_state = &authority->big_state->depth_state;
- if (depth_state->depth_test_function == function)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->depth_state.depth_test_function = function;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_depth_state_equal);
-}
-
-CoglDepthTestFunction
-cogl_pipeline_get_depth_test_function (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline),
- COGL_DEPTH_TEST_FUNCTION_LESS);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
-
- return authority->big_state->depth_state.depth_test_function;
-}
-
-
-gboolean
-cogl_pipeline_set_depth_range (CoglPipeline *pipeline,
- float near_val,
- float far_val,
- GError **error)
-{
-#ifndef COGL_HAS_GLES
- CoglPipelineState state = COGL_PIPELINE_STATE_DEPTH;
- CoglPipeline *authority;
- CoglPipelineDepthState *depth_state;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- depth_state = &authority->big_state->depth_state;
- if (depth_state->depth_range_near == near_val &&
- depth_state->depth_range_far == far_val)
- return TRUE;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->depth_state.depth_range_near = near_val;
- pipeline->big_state->depth_state.depth_range_far = far_val;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_depth_state_equal);
- return TRUE;
-#else
- g_set_error (error,
- COGL_ERROR,
- COGL_ERROR_UNSUPPORTED,
- "glDepthRange not available on GLES 1");
- return FALSE;
-#endif
-}
-
-void
-cogl_pipeline_get_depth_range (CoglPipeline *pipeline,
- float *near_val,
- float *far_val)
-{
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_DEPTH);
-
- *near_val = authority->big_state->depth_state.depth_range_near;
- *far_val = authority->big_state->depth_state.depth_range_far;
-}
-
-static void
-_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
- const CoglPipelineFogState *fog_state)
-{
- CoglPipelineState state = COGL_PIPELINE_STATE_FOG;
- CoglPipeline *authority;
- CoglPipelineFogState *current_fog_state;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- current_fog_state = &authority->big_state->fog_state;
-
- if (current_fog_state->enabled == fog_state->enabled &&
- cogl_color_equal (¤t_fog_state->color, &fog_state->color) &&
- current_fog_state->mode == fog_state->mode &&
- current_fog_state->density == fog_state->density &&
- current_fog_state->z_near == fog_state->z_near &&
- current_fog_state->z_far == fog_state->z_far)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->fog_state = *fog_state;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_fog_state_equal);
-}
-
-unsigned long
-_cogl_pipeline_get_age (CoglPipeline *pipeline)
-{
- g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
- return pipeline->age;
-}
-
-static CoglPipelineLayer *
-_cogl_pipeline_layer_copy (CoglPipelineLayer *src)
-{
- CoglPipelineLayer *layer = g_slice_new (CoglPipelineLayer);
-
- _cogl_pipeline_node_init (COGL_PIPELINE_NODE (layer));
-
- layer->owner = NULL;
- layer->index = src->index;
- layer->differences = 0;
- layer->has_big_state = FALSE;
-
- _cogl_pipeline_layer_set_parent (layer, src);
-
- return _cogl_pipeline_layer_object_new (layer);
-}
-
-static void
-_cogl_pipeline_layer_free (CoglPipelineLayer *layer)
-{
- _cogl_pipeline_layer_unparent (COGL_PIPELINE_NODE (layer));
-
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA &&
- layer->texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (layer->texture);
-
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_NEEDS_BIG_STATE)
- g_slice_free (CoglPipelineLayerBigState, layer->big_state);
-
- g_slice_free (CoglPipelineLayer, layer);
-}
-
- /* If a layer has descendants we can't modify it freely
- *
- * If the layer is owned and the owner has descendants we can't
- * modify it freely.
- *
- * In both cases when we can't freely modify a layer we can either:
- * - create a new layer; splice it in to replace the layer so it can
- * be directly modified.
- * XXX: disadvantage is that we have to invalidate the layers_cache
- * for the owner and its descendants.
- * - create a new derived layer and modify that.
- */
-
- /* XXX: how is the caller expected to deal with ref-counting?
- *
- * If the layer can't be freely modified and we return a new layer
- * then that will effectively make the caller own a new reference
- * which doesn't happen if we simply modify the given layer.
- *
- * We could make it consistent by taking a reference on the layer if
- * we don't create a new one. At least this way the caller could
- * deal with it consistently, though the semantics are a bit
- * strange.
- *
- * Alternatively we could leave it to the caller to check
- * ...?
- */
-
-void
-_cogl_pipeline_init_default_layers (void)
-{
- CoglPipelineLayer *layer = g_slice_new0 (CoglPipelineLayer);
- CoglPipelineLayerBigState *big_state =
- g_slice_new0 (CoglPipelineLayerBigState);
- CoglPipelineLayer *new;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_pipeline_node_init (COGL_PIPELINE_NODE (layer));
-
- layer->index = 0;
-
- layer->differences = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
-
- layer->unit_index = 0;
-
- layer->texture = COGL_INVALID_HANDLE;
- layer->target = 0;
-
- layer->mag_filter = COGL_PIPELINE_FILTER_LINEAR;
- layer->min_filter = COGL_PIPELINE_FILTER_LINEAR;
-
- layer->wrap_mode_s = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
- layer->wrap_mode_t = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
- layer->wrap_mode_p = COGL_PIPELINE_WRAP_MODE_AUTOMATIC;
-
- layer->big_state = big_state;
- layer->has_big_state = TRUE;
-
- /* Choose the same default combine mode as OpenGL:
- * RGBA = MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
- big_state->texture_combine_rgb_func =
- COGL_PIPELINE_COMBINE_FUNC_MODULATE;
- big_state->texture_combine_rgb_src[0] =
- COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
- big_state->texture_combine_rgb_src[1] =
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
- big_state->texture_combine_rgb_op[0] =
- COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
- big_state->texture_combine_rgb_op[1] =
- COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
- big_state->texture_combine_alpha_func =
- COGL_PIPELINE_COMBINE_FUNC_MODULATE;
- big_state->texture_combine_alpha_src[0] =
- COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
- big_state->texture_combine_alpha_src[1] =
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
- big_state->texture_combine_alpha_op[0] =
- COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
- big_state->texture_combine_alpha_op[1] =
- COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
-
- big_state->point_sprite_coords = FALSE;
-
- cogl_matrix_init_identity (&big_state->matrix);
-
- ctx->default_layer_0 = _cogl_pipeline_layer_object_new (layer);
-
- /* TODO: we should make default_layer_n comprise of two
- * descendants of default_layer_0:
- * - the first descendant should change the texture combine
- * to what we expect is most commonly used for multitexturing
- * - the second should revert the above change.
- *
- * why? the documentation for how a new layer is initialized
- * doesn't say that layers > 0 have different defaults so unless
- * we change the documentation we can't use different defaults,
- * but if the user does what we expect and changes the
- * texture combine then we can revert the authority to the
- * first descendant which means we can maximize the number
- * of layers with a common ancestor.
- *
- * The main problem will be that we'll need to disable the
- * optimizations for flattening the ancestry when we make
- * the second descendant which reverts the state.
- */
- ctx->default_layer_n = _cogl_pipeline_layer_copy (layer);
- new = _cogl_pipeline_set_layer_unit (NULL, ctx->default_layer_n, 1);
- g_assert (new == ctx->default_layer_n);
- /* Since we passed a newly allocated layer we don't expect that
- * _set_layer_unit() will have to allocate *another* layer. */
-
- /* Finally we create a dummy dependant for ->default_layer_n which
- * effectively ensures that ->default_layer_n and ->default_layer_0
- * remain immutable.
- */
- ctx->dummy_layer_dependant =
- _cogl_pipeline_layer_copy (ctx->default_layer_n);
-}
-
-static void
-setup_texture_combine_state (CoglBlendStringStatement *statement,
- CoglPipelineCombineFunc *texture_combine_func,
- CoglPipelineCombineSource *texture_combine_src,
- CoglPipelineCombineOp *texture_combine_op)
-{
- int i;
-
- switch (statement->function->type)
- {
- case COGL_BLEND_STRING_FUNCTION_REPLACE:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_REPLACE;
- break;
- case COGL_BLEND_STRING_FUNCTION_MODULATE:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_MODULATE;
- break;
- case COGL_BLEND_STRING_FUNCTION_ADD:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_ADD;
- break;
- case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_ADD_SIGNED;
- break;
- case COGL_BLEND_STRING_FUNCTION_INTERPOLATE:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_INTERPOLATE;
- break;
- case COGL_BLEND_STRING_FUNCTION_SUBTRACT:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_SUBTRACT;
- break;
- case COGL_BLEND_STRING_FUNCTION_DOT3_RGB:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_DOT3_RGB;
- break;
- case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA:
- *texture_combine_func = COGL_PIPELINE_COMBINE_FUNC_DOT3_RGBA;
- break;
- }
-
- for (i = 0; i < statement->function->argc; i++)
- {
- CoglBlendStringArgument *arg = &statement->args[i];
-
- switch (arg->source.info->type)
- {
- case COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT:
- texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_CONSTANT;
- break;
- case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE:
- texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
- break;
- case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N:
- texture_combine_src[i] =
- COGL_PIPELINE_COMBINE_SOURCE_TEXTURE0 + arg->source.texture;
- break;
- case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY:
- texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_PRIMARY_COLOR;
- break;
- case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS:
- texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_PREVIOUS;
- break;
- default:
- g_warning ("Unexpected texture combine source");
- texture_combine_src[i] = COGL_PIPELINE_COMBINE_SOURCE_TEXTURE;
- }
-
- if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
- {
- if (statement->args[i].source.one_minus)
- texture_combine_op[i] =
- COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_COLOR;
- else
- texture_combine_op[i] = COGL_PIPELINE_COMBINE_OP_SRC_COLOR;
- }
- else
- {
- if (statement->args[i].source.one_minus)
- texture_combine_op[i] =
- COGL_PIPELINE_COMBINE_OP_ONE_MINUS_SRC_ALPHA;
- else
- texture_combine_op[i] = COGL_PIPELINE_COMBINE_OP_SRC_ALPHA;
- }
- }
-}
-
-gboolean
-cogl_pipeline_set_layer_combine (CoglPipeline *pipeline,
- int layer_index,
- const char *combine_description,
- GError **error)
-{
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_COMBINE;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *layer;
- CoglBlendStringStatement statements[2];
- CoglBlendStringStatement split[2];
- CoglBlendStringStatement *rgb;
- CoglBlendStringStatement *a;
- GError *internal_error = NULL;
- int count;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), FALSE);
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, state);
-
- count =
- _cogl_blend_string_compile (combine_description,
- COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE,
- statements,
- &internal_error);
- if (!count)
- {
- if (error)
- g_propagate_error (error, internal_error);
- else
- {
- g_warning ("Cannot compile combine description: %s\n",
- internal_error->message);
- g_error_free (internal_error);
- }
- return FALSE;
- }
-
- if (statements[0].mask == COGL_BLEND_STRING_CHANNEL_MASK_RGBA)
- {
- _cogl_blend_string_split_rgba_statement (statements,
- &split[0], &split[1]);
- rgb = &split[0];
- a = &split[1];
- }
- else
- {
- rgb = &statements[0];
- a = &statements[1];
- }
-
- /* FIXME: compare the new state with the current state! */
-
- /* possibly flush primitives referencing the current state... */
- layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state);
-
- setup_texture_combine_state (rgb,
- &layer->big_state->texture_combine_rgb_func,
- layer->big_state->texture_combine_rgb_src,
- layer->big_state->texture_combine_rgb_op);
-
- setup_texture_combine_state (a,
- &layer->big_state->texture_combine_alpha_func,
- layer->big_state->texture_combine_alpha_src,
- layer->big_state->texture_combine_alpha_op);
-
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent = _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, state);
-
- if (_cogl_pipeline_layer_combine_state_equal (authority,
- old_authority))
- {
- layer->differences &= ~state;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- goto changed;
- }
- }
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= state;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
-changed:
-
- handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
- return TRUE;
-}
-
-void
-cogl_pipeline_set_layer_combine_constant (CoglPipeline *pipeline,
- int layer_index,
- const CoglColor *constant_color)
-{
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *new;
- float color_as_floats[4];
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, state);
-
- color_as_floats[0] = cogl_color_get_red_float (constant_color);
- color_as_floats[1] = cogl_color_get_green_float (constant_color);
- color_as_floats[2] = cogl_color_get_blue_float (constant_color);
- color_as_floats[3] = cogl_color_get_alpha_float (constant_color);
-
- if (memcmp (authority->big_state->texture_combine_constant,
- color_as_floats, sizeof (float) * 4) == 0)
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, state);
- CoglPipelineLayerBigState *old_big_state = old_authority->big_state;
-
- if (memcmp (old_big_state->texture_combine_constant,
- color_as_floats, sizeof (float) * 4) == 0)
- {
- layer->differences &= ~state;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- goto changed;
- }
- }
- }
-
- memcpy (layer->big_state->texture_combine_constant,
- color_as_floats,
- sizeof (color_as_floats));
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= state;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-
-changed:
-
- handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
-}
-
-void
-_cogl_pipeline_get_layer_combine_constant (CoglPipeline *pipeline,
- int layer_index,
- float *constant)
-{
- CoglPipelineLayerState change =
- COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
- /* FIXME: we shouldn't ever construct a layer in a getter function */
-
- authority = _cogl_pipeline_layer_get_authority (layer, change);
- memcpy (constant, authority->big_state->texture_combine_constant,
- sizeof (float) * 4);
-}
-
-/* We should probably make a public API version of this that has a
- matrix out-param. For an internal API it's good to be able to avoid
- copying the matrix */
-const CoglMatrix *
-_cogl_pipeline_get_layer_matrix (CoglPipeline *pipeline, int layer_index)
-{
- CoglPipelineLayerState change =
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
-
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- authority = _cogl_pipeline_layer_get_authority (layer, change);
- return &authority->big_state->matrix;
-}
-
-void
-cogl_pipeline_set_layer_matrix (CoglPipeline *pipeline,
- int layer_index,
- const CoglMatrix *matrix)
-{
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_USER_MATRIX;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *new;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, state);
-
- if (cogl_matrix_equal (matrix, &authority->big_state->matrix))
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, state);
-
- if (cogl_matrix_equal (matrix, &old_authority->big_state->matrix))
- {
- layer->differences &= ~state;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- return;
- }
- }
- }
-
- layer->big_state->matrix = *matrix;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= state;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-}
-
-void
-cogl_pipeline_remove_layer (CoglPipeline *pipeline, int layer_index)
-{
- CoglPipeline *authority;
- CoglPipelineLayerInfo layer_info;
- int i;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS);
-
- /* The layer index of the layer we want info about */
- layer_info.layer_index = layer_index;
-
- /* This will be updated with a reference to the layer being removed
- * if it can be found. */
- layer_info.layer = NULL;
-
- /* This will be filled in with a list of layers that need to be
- * dropped down to a lower texture unit to fill the gap of the
- * removed layer. */
- layer_info.layers_to_shift =
- g_alloca (sizeof (CoglPipelineLayer *) * authority->n_layers);
- layer_info.n_layers_to_shift = 0;
-
- /* Unlike when we query layer info when adding a layer we must
- * always have a complete layers_to_shift list... */
- layer_info.ignore_shift_layers_if_found = FALSE;
-
- _cogl_pipeline_get_layer_info (authority, &layer_info);
-
- if (layer_info.layer == NULL)
- return;
-
- for (i = 0; i < layer_info.n_layers_to_shift; i++)
- {
- CoglPipelineLayer *shift_layer = layer_info.layers_to_shift[i];
- int unit_index = _cogl_pipeline_layer_get_unit_index (shift_layer);
- _cogl_pipeline_set_layer_unit (pipeline, shift_layer, unit_index - 1);
- /* NB: shift_layer may not be writeable so _set_layer_unit()
- * will allocate a derived layer internally which will become
- * owned by pipeline. Check the return value if we need to do
- * anything else with this layer. */
- }
-
- _cogl_pipeline_remove_layer_difference (pipeline, layer_info.layer, TRUE);
- _cogl_pipeline_try_reverting_layers_authority (pipeline, NULL);
-
- handle_automatic_blend_enable (pipeline, COGL_PIPELINE_STATE_LAYERS);
-}
-
-static gboolean
-prepend_layer_to_list_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- GList **layers = user_data;
-
- *layers = g_list_prepend (*layers, layer);
- return TRUE;
-}
-
-/* TODO: deprecate this API and replace it with
- * cogl_pipeline_foreach_layer
- * TODO: update the docs to note that if the user modifies any layers
- * then the list may become invalid.
- */
-const GList *
-_cogl_pipeline_get_layers (CoglPipeline *pipeline)
-{
- g_return_val_if_fail (cogl_is_pipeline (pipeline), NULL);
-
- if (!pipeline->deprecated_get_layers_list_dirty)
- g_list_free (pipeline->deprecated_get_layers_list);
-
- pipeline->deprecated_get_layers_list = NULL;
-
- _cogl_pipeline_foreach_layer_internal (pipeline,
- prepend_layer_to_list_cb,
- &pipeline->deprecated_get_layers_list);
- pipeline->deprecated_get_layers_list =
- g_list_reverse (pipeline->deprecated_get_layers_list);
-
- pipeline->deprecated_get_layers_list_dirty = 0;
-
- return pipeline->deprecated_get_layers_list;
-}
-
-int
-cogl_pipeline_get_n_layers (CoglPipeline *pipeline)
-{
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LAYERS);
-
- return authority->n_layers;
-}
-
-/* FIXME: deprecate and replace with
- * cogl_pipeline_get_layer_texture() instead. */
-CoglHandle
-_cogl_pipeline_layer_get_texture (CoglPipelineLayer *layer)
-{
- g_return_val_if_fail (_cogl_is_pipeline_layer (layer),
- COGL_INVALID_HANDLE);
-
- return _cogl_pipeline_layer_get_texture_real (layer);
-}
-
-gboolean
-_cogl_pipeline_layer_has_user_matrix (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
-
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_USER_MATRIX);
-
- /* If the authority is the default pipeline then no, otherwise yes */
- return _cogl_pipeline_layer_get_parent (authority) ? TRUE : FALSE;
-}
-
-void
-_cogl_pipeline_layer_get_filters (CoglPipelineLayer *layer,
- CoglPipelineFilter *min_filter,
- CoglPipelineFilter *mag_filter)
-{
- CoglPipelineLayer *authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_FILTERS);
-
- *min_filter = authority->min_filter;
- *mag_filter = authority->mag_filter;
-}
-
-void
-_cogl_pipeline_get_layer_filters (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineFilter *min_filter,
- CoglPipelineFilter *mag_filter)
-{
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_FILTERS);
-
- *min_filter = authority->min_filter;
- *mag_filter = authority->mag_filter;
-}
-
-CoglPipelineFilter
-_cogl_pipeline_get_layer_min_filter (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipelineFilter min_filter;
- CoglPipelineFilter mag_filter;
-
- _cogl_pipeline_get_layer_filters (pipeline, layer_index,
- &min_filter, &mag_filter);
- return min_filter;
-}
-
-CoglPipelineFilter
-_cogl_pipeline_get_layer_mag_filter (CoglPipeline *pipeline,
- int layer_index)
-{
- CoglPipelineFilter min_filter;
- CoglPipelineFilter mag_filter;
-
- _cogl_pipeline_get_layer_filters (pipeline, layer_index,
- &min_filter, &mag_filter);
- return mag_filter;
-}
-
-void
-_cogl_pipeline_layer_pre_paint (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *texture_authority;
-
- texture_authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA);
-
- if (texture_authority->texture != COGL_INVALID_HANDLE)
- {
- CoglTexturePrePaintFlags flags = 0;
- CoglPipelineFilter min_filter;
- CoglPipelineFilter mag_filter;
-
- _cogl_pipeline_layer_get_filters (layer, &min_filter, &mag_filter);
-
- if (min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST
- || min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST
- || min_filter == COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR
- || min_filter == COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR)
- flags |= COGL_TEXTURE_NEEDS_MIPMAP;
-
- _cogl_texture_pre_paint (texture_authority->texture, flags);
- }
-}
-
-void
-_cogl_pipeline_pre_paint_for_layer (CoglPipeline *pipeline,
- int layer_id)
-{
- CoglPipelineLayer *layer = _cogl_pipeline_get_layer (pipeline, layer_id);
- _cogl_pipeline_layer_pre_paint (layer);
-}
-
-CoglPipelineFilter
-_cogl_pipeline_layer_get_min_filter (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (_cogl_is_pipeline_layer (layer), 0);
-
- authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_FILTERS);
-
- return authority->min_filter;
-}
-
-CoglPipelineFilter
-_cogl_pipeline_layer_get_mag_filter (CoglPipelineLayer *layer)
-{
- CoglPipelineLayer *authority;
-
- g_return_val_if_fail (_cogl_is_pipeline_layer (layer), 0);
-
- authority =
- _cogl_pipeline_layer_get_authority (layer,
- COGL_PIPELINE_LAYER_STATE_FILTERS);
-
- return authority->mag_filter;
-}
-
-void
-cogl_pipeline_set_layer_filters (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineFilter min_filter,
- CoglPipelineFilter mag_filter)
-{
- CoglPipelineLayerState state = COGL_PIPELINE_LAYER_STATE_FILTERS;
- CoglPipelineLayer *layer;
- CoglPipelineLayer *authority;
- CoglPipelineLayer *new;
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- /* Note: this will ensure that the layer exists, creating one if it
- * doesn't already.
- *
- * Note: If the layer already existed it's possibly owned by another
- * pipeline. If the layer is created then it will be owned by
- * pipeline. */
- layer = _cogl_pipeline_get_layer (pipeline, layer_index);
-
- /* Now find the ancestor of the layer that is the authority for the
- * state we want to change */
- authority = _cogl_pipeline_layer_get_authority (layer, state);
-
- if (authority->min_filter == min_filter &&
- authority->mag_filter == mag_filter)
- return;
-
- new = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, state);
- if (new != layer)
- layer = new;
- else
- {
- /* If the original layer we found is currently the authority on
- * the state we are changing see if we can revert to one of our
- * ancestors being the authority. */
- if (layer == authority &&
- _cogl_pipeline_layer_get_parent (authority) != NULL)
- {
- CoglPipelineLayer *parent =
- _cogl_pipeline_layer_get_parent (authority);
- CoglPipelineLayer *old_authority =
- _cogl_pipeline_layer_get_authority (parent, state);
-
- if (old_authority->min_filter == min_filter &&
- old_authority->mag_filter == mag_filter)
- {
- layer->differences &= ~state;
-
- g_assert (layer->owner == pipeline);
- if (layer->differences == 0)
- _cogl_pipeline_prune_empty_layer_difference (pipeline,
- layer);
- return;
- }
- }
- }
-
- layer->min_filter = min_filter;
- layer->mag_filter = mag_filter;
-
- /* If we weren't previously the authority on this state then we need
- * to extended our differences mask and so it's possible that some
- * of our ancestry will now become redundant, so we aim to reparent
- * ourselves if that's true... */
- if (layer != authority)
- {
- layer->differences |= state;
- _cogl_pipeline_layer_prune_redundant_ancestry (layer);
- }
-}
-
-float
-cogl_pipeline_get_point_size (CoglHandle handle)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (handle);
- CoglPipeline *authority;
-
- g_return_val_if_fail (cogl_is_pipeline (handle), FALSE);
-
- authority =
- _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_POINT_SIZE);
-
- return authority->big_state->point_size;
-}
-
-void
-cogl_pipeline_set_point_size (CoglHandle handle,
- float point_size)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (handle);
- CoglPipelineState state = COGL_PIPELINE_STATE_POINT_SIZE;
- CoglPipeline *authority;
-
- g_return_if_fail (cogl_is_pipeline (handle));
-
- authority = _cogl_pipeline_get_authority (pipeline, state);
-
- if (authority->big_state->point_size == point_size)
- return;
-
- /* - Flush journal primitives referencing the current state.
- * - Make sure the pipeline has no dependants so it may be modified.
- * - If the pipeline isn't currently an authority for the state being
- * changed, then initialize that state from the current authority.
- */
- _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
-
- pipeline->big_state->point_size = point_size;
-
- _cogl_pipeline_update_authority (pipeline, authority, state,
- _cogl_pipeline_point_size_equal);
-}
-
-/* While a pipeline is referenced by the Cogl journal we can not allow
- * modifications, so this gives us a mechanism to track journal
- * references separately */
-CoglPipeline *
-_cogl_pipeline_journal_ref (CoglPipeline *pipeline)
-{
- pipeline->journal_ref_count++;
- return cogl_object_ref (pipeline);
-}
-
-void
-_cogl_pipeline_journal_unref (CoglPipeline *pipeline)
-{
- pipeline->journal_ref_count--;
- cogl_object_unref (pipeline);
-}
-
-void
-_cogl_pipeline_apply_legacy_state (CoglPipeline *pipeline)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* It was a mistake that we ever copied the OpenGL style API for
- * associating these things directly with the context when we
- * originally wrote Cogl. Until the corresponding deprecated APIs
- * can be removed though we now shoehorn the state changes through
- * the cogl_pipeline API instead.
- */
-
- /* A program explicitly set on the pipeline has higher precedence than
- * one associated with the context using cogl_program_use() */
- if (ctx->current_program &&
- cogl_pipeline_get_user_program (pipeline) == COGL_INVALID_HANDLE)
- cogl_pipeline_set_user_program (pipeline, ctx->current_program);
-
- if (ctx->legacy_depth_test_enabled)
- cogl_pipeline_set_depth_test_enabled (pipeline, TRUE);
-
- if (ctx->legacy_fog_state.enabled)
- _cogl_pipeline_set_fog_state (pipeline, &ctx->legacy_fog_state);
-}
-
-void
-_cogl_pipeline_set_static_breadcrumb (CoglPipeline *pipeline,
- const char *breadcrumb)
-{
- pipeline->has_static_breadcrumb = TRUE;
- pipeline->static_breadcrumb = breadcrumb;
-}
-
-typedef struct _HashState
-{
- unsigned long layer_differences;
- CoglPipelineEvalFlags flags;
- unsigned int hash;
-} HashState;
-
-static void
-_cogl_pipeline_layer_hash_unit_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- int unit = authority->unit_index;
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &unit, sizeof (unit));
-}
-
-static void
-_cogl_pipeline_layer_hash_texture_target_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- GLenum gl_target = authority->target;
-
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &gl_target, sizeof (gl_target));
-}
-
-static void
-_cogl_pipeline_layer_hash_texture_data_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- GLuint gl_handle;
-
- cogl_texture_get_gl_texture (authority->texture, &gl_handle, NULL);
-
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &gl_handle, sizeof (gl_handle));
-}
-
-static void
-_cogl_pipeline_layer_hash_filters_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- unsigned int hash = state->hash;
- hash = _cogl_util_one_at_a_time_hash (hash, &authority->mag_filter,
- sizeof (authority->mag_filter));
- hash = _cogl_util_one_at_a_time_hash (hash, &authority->min_filter,
- sizeof (authority->min_filter));
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_layer_hash_wrap_modes_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- unsigned int hash = state->hash;
- hash = _cogl_util_one_at_a_time_hash (hash, &authority->wrap_mode_s,
- sizeof (authority->wrap_mode_s));
- hash = _cogl_util_one_at_a_time_hash (hash, &authority->wrap_mode_t,
- sizeof (authority->wrap_mode_t));
- hash = _cogl_util_one_at_a_time_hash (hash, &authority->wrap_mode_p,
- sizeof (authority->wrap_mode_p));
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_layer_hash_combine_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- unsigned int hash = state->hash;
- CoglPipelineLayerBigState *b = authority->big_state;
- int n_args;
- int i;
-
- hash = _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_func,
- sizeof (b->texture_combine_rgb_func));
- n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_rgb_func);
- for (i = 0; i < n_args; i++)
- {
- hash =
- _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_src[i],
- sizeof (b->texture_combine_rgb_src[i]));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_rgb_op[i],
- sizeof (b->texture_combine_rgb_op[i]));
- }
-
- hash = _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_func,
- sizeof (b->texture_combine_alpha_func));
- n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_alpha_func);
- for (i = 0; i < n_args; i++)
- {
- hash =
- _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_src[i],
- sizeof (b->texture_combine_alpha_src[i]));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &b->texture_combine_alpha_op[i],
- sizeof (b->texture_combine_alpha_op[i]));
- }
-
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_layer_hash_combine_constant_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- CoglPipelineLayerBigState *b = authority->big_state;
- gboolean need_hash = FALSE;
- int n_args;
- int i;
-
- /* XXX: If the user also asked to hash the ALPHA_FUNC_STATE then it
- * would be nice if we could combine the n_args loops in this
- * function and _cogl_pipeline_layer_hash_combine_state.
- */
-
- n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_rgb_func);
- for (i = 0; i < n_args; i++)
- {
- if (b->texture_combine_rgb_src[i] ==
- COGL_PIPELINE_COMBINE_SOURCE_CONSTANT)
- {
- /* XXX: should we be careful to only hash the alpha
- * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */
- need_hash = TRUE;
- goto done;
- }
- }
-
- n_args = _cogl_get_n_args_for_combine_func (b->texture_combine_alpha_func);
- for (i = 0; i < n_args; i++)
- {
- if (b->texture_combine_alpha_src[i] ==
- COGL_PIPELINE_COMBINE_SOURCE_CONSTANT)
- {
- /* XXX: should we be careful to only hash the alpha
- * component in the COGL_PIPELINE_COMBINE_OP_SRC_ALPHA case? */
- need_hash = TRUE;
- goto done;
- }
- }
-
-done:
- if (need_hash)
- {
- float *constant = b->texture_combine_constant;
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, constant,
- sizeof (float) * 4);
- }
-}
-
-static void
-_cogl_pipeline_layer_hash_user_matrix_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- CoglPipelineLayerBigState *big_state = authority->big_state;
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, &big_state->matrix,
- sizeof (float) * 16);
-}
-
-static void
-_cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state)
-{
- CoglPipelineLayerBigState *big_state = authority->big_state;
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &big_state->point_sprite_coords,
- sizeof (big_state->point_sprite_coords));
-}
-
-typedef void (*LayerStateHashFunction) (CoglPipelineLayer *authority,
- CoglPipelineLayer **authorities,
- HashState *state);
-
-static LayerStateHashFunction
-layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT];
-
-/* XXX: We don't statically initialize the array of hash functions, so
- * we won't get caught out by later re-indexing the groups for some
- * reason. */
-void
-_cogl_pipeline_init_layer_state_hash_functions (void)
-{
- CoglPipelineLayerStateIndex _index;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_UNIT_INDEX] =
- _cogl_pipeline_layer_hash_unit_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_TARGET_INDEX] =
- _cogl_pipeline_layer_hash_texture_target_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA_INDEX] =
- _cogl_pipeline_layer_hash_texture_data_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_FILTERS_INDEX] =
- _cogl_pipeline_layer_hash_filters_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_WRAP_MODES_INDEX] =
- _cogl_pipeline_layer_hash_wrap_modes_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_COMBINE_INDEX] =
- _cogl_pipeline_layer_hash_combine_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX] =
- _cogl_pipeline_layer_hash_combine_constant_state;
- layer_state_hash_functions[COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX] =
- _cogl_pipeline_layer_hash_user_matrix_state;
- _index = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX;
- layer_state_hash_functions[_index] =
- _cogl_pipeline_layer_hash_point_sprite_state;
-
- /* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 9);
-}
-
-static gboolean
-_cogl_pipeline_hash_layer_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- HashState *state = user_data;
- unsigned long differences = state->layer_differences;
- CoglPipelineLayer *authorities[COGL_PIPELINE_LAYER_STATE_COUNT];
- unsigned long mask;
- int i;
-
- /* Theoretically we would hash non-sparse layer state here but
- * currently layers don't have any. */
-
- /* XXX: we resolve all the authorities here - not just those
- * corresponding to hash_state->layer_differences - because
- * the hashing of some state groups actually depends on the values
- * in other groups. For example we don't hash layer combine
- * constants if they are aren't referenced by the current layer
- * combine function.
- */
- mask = COGL_PIPELINE_LAYER_STATE_ALL_SPARSE;
- _cogl_pipeline_layer_resolve_authorities (layer,
- mask,
- authorities);
-
- /* So we go right ahead and hash the sparse state... */
- for (i = 0; i < COGL_PIPELINE_LAYER_STATE_COUNT; i++)
- {
- unsigned long current_state = (1L<<i);
-
- /* XXX: we are hashing the un-mixed hash values of all the
- * individual state groups; we should provide a means to test
- * the quality of the final hash values we are getting with this
- * approach... */
- if (differences & current_state)
- {
- CoglPipelineLayer *authority = authorities[i];
- layer_state_hash_functions[i] (authority, authorities, state);
- }
-
- if (current_state > differences)
- break;
- }
-
- return TRUE;
-}
-
-static void
-_cogl_pipeline_hash_color_state (CoglPipeline *authority,
- HashState *state)
-{
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, &authority->color,
- _COGL_COLOR_DATA_SIZE);
-}
-
-static void
-_cogl_pipeline_hash_blend_enable_state (CoglPipeline *authority,
- HashState *state)
-{
- guint8 blend_enable = authority->blend_enable;
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, &blend_enable, 1);
-}
-
-static void
-_cogl_pipeline_hash_layers_state (CoglPipeline *authority,
- HashState *state)
-{
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &authority->n_layers,
- sizeof (authority->n_layers));
- _cogl_pipeline_foreach_layer_internal (authority,
- _cogl_pipeline_hash_layer_cb,
- state);
-}
-
-static void
-_cogl_pipeline_hash_lighting_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineLightingState *lighting_state =
- &authority->big_state->lighting_state;
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, lighting_state,
- sizeof (CoglPipelineLightingState));
-}
-
-static void
-_cogl_pipeline_hash_alpha_func_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &alpha_state->alpha_func,
- sizeof (alpha_state->alpha_func));
-}
-
-static void
-_cogl_pipeline_hash_alpha_func_reference_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineAlphaFuncState *alpha_state = &authority->big_state->alpha_state;
- float ref = alpha_state->alpha_func_reference;
- state->hash =
- _cogl_util_one_at_a_time_hash (state->hash, &ref, sizeof (float));
-}
-
-static void
-_cogl_pipeline_hash_blend_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineBlendState *blend_state = &authority->big_state->blend_state;
- unsigned int hash;
-
- if (!authority->real_blend_enable)
- return;
-
- hash = state->hash;
-
-#ifndef HAVE_COGL_GLES
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_rgb,
- sizeof (blend_state->blend_equation_rgb));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_equation_alpha,
- sizeof (blend_state->blend_equation_alpha));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_alpha,
- sizeof (blend_state->blend_src_factor_alpha));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_alpha,
- sizeof (blend_state->blend_dst_factor_alpha));
-
- if (blend_state->blend_src_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
- blend_state->blend_src_factor_rgb == GL_CONSTANT_COLOR ||
- blend_state->blend_dst_factor_rgb == GL_ONE_MINUS_CONSTANT_COLOR ||
- blend_state->blend_dst_factor_rgb == GL_CONSTANT_COLOR)
- {
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_constant,
- sizeof (blend_state->blend_constant));
- }
-#endif
-
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_src_factor_rgb,
- sizeof (blend_state->blend_src_factor_rgb));
- hash =
- _cogl_util_one_at_a_time_hash (hash, &blend_state->blend_dst_factor_rgb,
- sizeof (blend_state->blend_dst_factor_rgb));
-
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_user_shader_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglHandle user_program = authority->big_state->user_program;
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, &user_program,
- sizeof (user_program));
-}
-
-static void
-_cogl_pipeline_hash_depth_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineDepthState *depth_state = &authority->big_state->depth_state;
- unsigned int hash = state->hash;
-
- if (depth_state->depth_test_enabled)
- {
- guint8 enabled = depth_state->depth_test_enabled;
- CoglDepthTestFunction function = depth_state->depth_test_function;
- hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
- hash = _cogl_util_one_at_a_time_hash (hash, &function, sizeof (function));
- }
-
- if (depth_state->depth_writing_enabled)
- {
- guint8 enabled = depth_state->depth_writing_enabled;
- float near_val = depth_state->depth_range_near;
- float far_val = depth_state->depth_range_far;
- hash = _cogl_util_one_at_a_time_hash (hash, &enabled, sizeof (enabled));
- hash = _cogl_util_one_at_a_time_hash (hash, &near_val, sizeof (near_val));
- hash = _cogl_util_one_at_a_time_hash (hash, &far_val, sizeof (far_val));
- }
-
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_fog_state (CoglPipeline *authority,
- HashState *state)
-{
- CoglPipelineFogState *fog_state = &authority->big_state->fog_state;
- unsigned long hash = state->hash;
-
- if (!fog_state->enabled)
- hash = _cogl_util_one_at_a_time_hash (hash, &fog_state->enabled,
- sizeof (fog_state->enabled));
- else
- hash = _cogl_util_one_at_a_time_hash (hash, &fog_state,
- sizeof (CoglPipelineFogState));
-
- state->hash = hash;
-}
-
-static void
-_cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
- HashState *state)
-{
- float point_size = authority->big_state->point_size;
- state->hash = _cogl_util_one_at_a_time_hash (state->hash, &point_size,
- sizeof (point_size));
-}
-
-typedef void (*StateHashFunction) (CoglPipeline *authority, HashState *state);
-
-static StateHashFunction
-state_hash_functions[COGL_PIPELINE_STATE_SPARSE_COUNT];
-
-/* We don't statically initialize the array of hash functions
- * so we won't get caught out by later re-indexing the groups for
- * some reason. */
-void
-_cogl_pipeline_init_state_hash_functions (void)
-{
- state_hash_functions[COGL_PIPELINE_STATE_COLOR_INDEX] =
- _cogl_pipeline_hash_color_state;
- state_hash_functions[COGL_PIPELINE_STATE_BLEND_ENABLE_INDEX] =
- _cogl_pipeline_hash_blend_enable_state;
- state_hash_functions[COGL_PIPELINE_STATE_LAYERS_INDEX] =
- _cogl_pipeline_hash_layers_state;
- state_hash_functions[COGL_PIPELINE_STATE_LIGHTING_INDEX] =
- _cogl_pipeline_hash_lighting_state;
- state_hash_functions[COGL_PIPELINE_STATE_ALPHA_FUNC_INDEX] =
- _cogl_pipeline_hash_alpha_func_state;
- state_hash_functions[COGL_PIPELINE_STATE_ALPHA_FUNC_REFERENCE_INDEX] =
- _cogl_pipeline_hash_alpha_func_reference_state;
- state_hash_functions[COGL_PIPELINE_STATE_BLEND_INDEX] =
- _cogl_pipeline_hash_blend_state;
- state_hash_functions[COGL_PIPELINE_STATE_USER_SHADER_INDEX] =
- _cogl_pipeline_hash_user_shader_state;
- state_hash_functions[COGL_PIPELINE_STATE_DEPTH_INDEX] =
- _cogl_pipeline_hash_depth_state;
- state_hash_functions[COGL_PIPELINE_STATE_FOG_INDEX] =
- _cogl_pipeline_hash_fog_state;
- state_hash_functions[COGL_PIPELINE_STATE_POINT_SIZE_INDEX] =
- _cogl_pipeline_hash_point_size_state;
-
- /* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 11);
-}
-
-unsigned int
-_cogl_pipeline_hash (CoglPipeline *pipeline,
- unsigned long differences,
- unsigned long layer_differences,
- CoglPipelineEvalFlags flags)
-{
- CoglPipeline *authorities[COGL_PIPELINE_STATE_SPARSE_COUNT];
- unsigned long mask;
- int i;
- HashState state;
- unsigned int final_hash = 0;
-
- state.hash = 0;
- state.layer_differences = layer_differences;
- state.flags = flags;
-
- /* hash non-sparse state */
-
- if (differences & COGL_PIPELINE_STATE_REAL_BLEND_ENABLE)
- {
- gboolean enable = pipeline->real_blend_enable;
- state.hash =
- _cogl_util_one_at_a_time_hash (state.hash, &enable, sizeof (enable));
- }
-
- /* hash sparse state */
-
- mask = differences & COGL_PIPELINE_STATE_ALL_SPARSE;
- _cogl_pipeline_resolve_authorities (pipeline, mask, authorities);
-
- for (i = 0; i < COGL_PIPELINE_STATE_SPARSE_COUNT; i++)
- {
- unsigned long current_state = (1L<<i);
-
- /* XXX: we are hashing the un-mixed hash values of all the
- * individual state groups; we should provide a means to test
- * the quality of the final hash values we are getting with this
- * approach... */
- if (differences & current_state)
- {
- CoglPipeline *authority = authorities[i];
- state_hash_functions[i] (authority, &state);
- final_hash = _cogl_util_one_at_a_time_hash (final_hash, &state.hash,
- sizeof (state.hash));
- }
-
- if (current_state > differences)
- break;
- }
-
- return _cogl_util_one_at_a_time_mix (final_hash);
-}
-
-typedef struct
-{
- int parent_id;
- int *node_id_ptr;
- GString *graph;
- int indent;
-} PrintDebugState;
-
-static gboolean
-dump_layer_cb (CoglPipelineNode *node, void *user_data)
-{
- CoglPipelineLayer *layer = COGL_PIPELINE_LAYER (node);
- PrintDebugState *state = user_data;
- int layer_id = *state->node_id_ptr;
- PrintDebugState state_out;
- GString *changes_label;
- gboolean changes = FALSE;
-
- if (state->parent_id >= 0)
- g_string_append_printf (state->graph, "%*slayer%p -> layer%p;\n",
- state->indent, "",
- layer->_parent.parent,
- layer);
-
- g_string_append_printf (state->graph,
- "%*slayer%p [label=\"layer=0x%p\\n"
- "ref count=%d\" "
- "color=\"blue\"];\n",
- state->indent, "",
- layer,
- layer,
- COGL_OBJECT (layer)->ref_count);
-
- changes_label = g_string_new ("");
- g_string_append_printf (changes_label,
- "%*slayer%p -> layer_state%d [weight=100];\n"
- "%*slayer_state%d [shape=box label=\"",
- state->indent, "",
- layer,
- layer_id,
- state->indent, "",
- layer_id);
-
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_UNIT)
- {
- changes = TRUE;
- g_string_append_printf (changes_label,
- "\\lunit=%u\\n",
- layer->unit_index);
- }
-
- if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
- {
- changes = TRUE;
- g_string_append_printf (changes_label,
- "\\ltexture=%p\\n",
- layer->texture);
- }
-
- if (changes)
- {
- g_string_append_printf (changes_label, "\"];\n");
- g_string_append (state->graph, changes_label->str);
- g_string_free (changes_label, TRUE);
- }
-
- state_out.parent_id = layer_id;
-
- state_out.node_id_ptr = state->node_id_ptr;
- (*state_out.node_id_ptr)++;
-
- state_out.graph = state->graph;
- state_out.indent = state->indent + 2;
-
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (layer),
- dump_layer_cb,
- &state_out);
-
- return TRUE;
-}
-
-static gboolean
-dump_layer_ref_cb (CoglPipelineLayer *layer, void *data)
-{
- PrintDebugState *state = data;
- int pipeline_id = *state->node_id_ptr;
-
- g_string_append_printf (state->graph,
- "%*spipeline_state%d -> layer%p;\n",
- state->indent, "",
- pipeline_id,
- layer);
-
- return TRUE;
-}
-
-static gboolean
-dump_pipeline_cb (CoglPipelineNode *node, void *user_data)
-{
- CoglPipeline *pipeline = COGL_PIPELINE (node);
- PrintDebugState *state = user_data;
- int pipeline_id = *state->node_id_ptr;
- PrintDebugState state_out;
- GString *changes_label;
- gboolean changes = FALSE;
- gboolean layers = FALSE;
-
- if (state->parent_id >= 0)
- g_string_append_printf (state->graph, "%*spipeline%d -> pipeline%d;\n",
- state->indent, "",
- state->parent_id,
- pipeline_id);
-
- g_string_append_printf (state->graph,
- "%*spipeline%d [label=\"pipeline=0x%p\\n"
- "ref count=%d\\n"
- "breadcrumb=\\\"%s\\\"\" color=\"red\"];\n",
- state->indent, "",
- pipeline_id,
- pipeline,
- COGL_OBJECT (pipeline)->ref_count,
- pipeline->has_static_breadcrumb ?
- pipeline->static_breadcrumb : "NULL");
-
- changes_label = g_string_new ("");
- g_string_append_printf (changes_label,
- "%*spipeline%d -> pipeline_state%d [weight=100];\n"
- "%*spipeline_state%d [shape=box label=\"",
- state->indent, "",
- pipeline_id,
- pipeline_id,
- state->indent, "",
- pipeline_id);
-
-
- if (pipeline->differences & COGL_PIPELINE_STATE_COLOR)
- {
- changes = TRUE;
- g_string_append_printf (changes_label,
- "\\lcolor=0x%02X%02X%02X%02X\\n",
- cogl_color_get_red_byte (&pipeline->color),
- cogl_color_get_green_byte (&pipeline->color),
- cogl_color_get_blue_byte (&pipeline->color),
- cogl_color_get_alpha_byte (&pipeline->color));
- }
-
- if (pipeline->differences & COGL_PIPELINE_STATE_BLEND)
- {
- const char *blend_enable_name;
-
- changes = TRUE;
-
- switch (pipeline->blend_enable)
- {
- case COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC:
- blend_enable_name = "AUTO";
- break;
- case COGL_PIPELINE_BLEND_ENABLE_ENABLED:
- blend_enable_name = "ENABLED";
- break;
- case COGL_PIPELINE_BLEND_ENABLE_DISABLED:
- blend_enable_name = "DISABLED";
- break;
- default:
- blend_enable_name = "UNKNOWN";
- }
- g_string_append_printf (changes_label,
- "\\lblend=%s\\n",
- blend_enable_name);
- }
-
- if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
- {
- changes = TRUE;
- layers = TRUE;
- g_string_append_printf (changes_label, "\\ln_layers=%d\\n",
- pipeline->n_layers);
- }
-
- if (changes)
- {
- g_string_append_printf (changes_label, "\"];\n");
- g_string_append (state->graph, changes_label->str);
- g_string_free (changes_label, TRUE);
- }
-
- if (layers)
- {
- g_list_foreach (pipeline->layer_differences,
- (GFunc)dump_layer_ref_cb,
- state);
- }
-
- state_out.parent_id = pipeline_id;
-
- state_out.node_id_ptr = state->node_id_ptr;
- (*state_out.node_id_ptr)++;
-
- state_out.graph = state->graph;
- state_out.indent = state->indent + 2;
-
- _cogl_pipeline_node_foreach_child (COGL_PIPELINE_NODE (pipeline),
- dump_pipeline_cb,
- &state_out);
-
- return TRUE;
-}
-
-void
-_cogl_debug_dump_pipelines_dot_file (const char *filename)
-{
- GString *graph;
- PrintDebugState layer_state;
- PrintDebugState pipeline_state;
- int layer_id = 0;
- int pipeline_id = 0;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!ctx->default_pipeline)
- return;
-
- graph = g_string_new ("");
- g_string_append_printf (graph, "digraph {\n");
-
- layer_state.graph = graph;
- layer_state.parent_id = -1;
- layer_state.node_id_ptr = &layer_id;
- layer_state.indent = 0;
- dump_layer_cb (ctx->default_layer_0, &layer_state);
-
- pipeline_state.graph = graph;
- pipeline_state.parent_id = -1;
- pipeline_state.node_id_ptr = &pipeline_id;
- pipeline_state.indent = 0;
- dump_pipeline_cb (ctx->default_pipeline, &pipeline_state);
-
- g_string_append_printf (graph, "}\n");
-
- if (filename)
- g_file_set_contents (filename, graph->str, -1, NULL);
- else
- g_print ("%s", graph->str);
-
- g_string_free (graph, TRUE);
-}
-
-typedef struct
-{
- int i;
- CoglPipelineLayer **layers;
-} AddLayersToArrayState;
-
-static gboolean
-add_layer_to_array_cb (CoglPipelineLayer *layer,
- void *user_data)
-{
- AddLayersToArrayState *state = user_data;
- state->layers[state->i++] = layer;
- return TRUE;
-}
-
-/* Determines if we need to handle the RGB and A texture combining
- * separately or is the same function used for both channel masks and
- * with the same arguments...
- */
-gboolean
-_cogl_pipeline_need_texture_combine_separate
- (CoglPipelineLayer *combine_authority)
-{
- CoglPipelineLayerBigState *big_state = combine_authority->big_state;
- int n_args;
- int i;
-
- if (big_state->texture_combine_rgb_func !=
- big_state->texture_combine_alpha_func)
- return TRUE;
-
- n_args = _cogl_get_n_args_for_combine_func (big_state->texture_combine_rgb_func);
-
- for (i = 0; i < n_args; i++)
- {
- if (big_state->texture_combine_rgb_src[i] !=
- big_state->texture_combine_alpha_src[i])
- return TRUE;
-
- /*
- * We can allow some variation of the source operands without
- * needing a separation...
- *
- * "A = REPLACE (CONSTANT[A])" + either of the following...
- * "RGB = REPLACE (CONSTANT[RGB])"
- * "RGB = REPLACE (CONSTANT[A])"
- *
- * can be combined as:
- * "RGBA = REPLACE (CONSTANT)" or
- * "RGBA = REPLACE (CONSTANT[A])" or
- *
- * And "A = REPLACE (1-CONSTANT[A])" + either of the following...
- * "RGB = REPLACE (1-CONSTANT)" or
- * "RGB = REPLACE (1-CONSTANT[A])"
- *
- * can be combined as:
- * "RGBA = REPLACE (1-CONSTANT)" or
- * "RGBA = REPLACE (1-CONSTANT[A])"
- */
- switch (big_state->texture_combine_alpha_op[i])
- {
- case GL_SRC_ALPHA:
- switch (big_state->texture_combine_rgb_op[i])
- {
- case GL_SRC_COLOR:
- case GL_SRC_ALPHA:
- break;
- default:
- return FALSE;
- }
- break;
- case GL_ONE_MINUS_SRC_ALPHA:
- switch (big_state->texture_combine_rgb_op[i])
- {
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_ONE_MINUS_SRC_ALPHA:
- break;
- default:
- return FALSE;
- }
- break;
- default:
- return FALSE; /* impossible */
- }
- }
-
- return FALSE;
-}
-
-/* This tries to find the oldest ancestor whose pipeline and layer
- state matches the given flags. This is mostly used to detect code
- gen authorities so that we can reduce the numer of programs
- generated */
-CoglPipeline *
-_cogl_pipeline_find_equivalent_parent (CoglPipeline *pipeline,
- CoglPipelineState pipeline_state,
- CoglPipelineLayerState layer_state)
-{
- CoglPipeline *authority0;
- CoglPipeline *authority1;
- int n_layers;
- CoglPipelineLayer **authority0_layers;
- CoglPipelineLayer **authority1_layers;
-
- /* Find the first pipeline that modifies state that affects the
- * state or any layer state... */
- authority0 = _cogl_pipeline_get_authority (pipeline,
- pipeline_state |
- COGL_PIPELINE_STATE_LAYERS);
-
- /* Find the next ancestor after that, that also modifies the
- * state... */
- if (_cogl_pipeline_get_parent (authority0))
- {
- authority1 =
- _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority0),
- pipeline_state |
- COGL_PIPELINE_STATE_LAYERS);
- }
- else
- return authority0;
-
- n_layers = cogl_pipeline_get_n_layers (authority0);
-
- for (;;)
- {
- AddLayersToArrayState state;
- int i;
-
- if (n_layers != cogl_pipeline_get_n_layers (authority1))
- return authority0;
-
- /* If the programs differ by anything that isn't part of the
- layer state then we can't continue */
- if (pipeline_state &&
- (_cogl_pipeline_compare_differences (authority0, authority1) &
- pipeline_state))
- return authority0;
-
- authority0_layers =
- g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
- state.i = 0;
- state.layers = authority0_layers;
- _cogl_pipeline_foreach_layer_internal (authority0,
- add_layer_to_array_cb,
- &state);
-
- authority1_layers =
- g_alloca (sizeof (CoglPipelineLayer *) * n_layers);
- state.i = 0;
- state.layers = authority1_layers;
- _cogl_pipeline_foreach_layer_internal (authority1,
- add_layer_to_array_cb,
- &state);
-
- for (i = 0; i < n_layers; i++)
- {
- unsigned long layer_differences;
-
- if (authority0_layers[i] == authority1_layers[i])
- continue;
-
- layer_differences =
- _cogl_pipeline_layer_compare_differences (authority0_layers[i],
- authority1_layers[i]);
-
- if (layer_differences & layer_state)
- return authority0;
- }
-
- /* Find the next ancestor after that, that also modifies state
- * affecting codegen... */
-
- if (!_cogl_pipeline_get_parent (authority1))
- break;
-
- authority0 = authority1;
- authority1 =
- _cogl_pipeline_get_authority (_cogl_pipeline_get_parent (authority1),
- pipeline_state |
- COGL_PIPELINE_STATE_LAYERS);
- if (authority1 == authority0)
- break;
- }
-
- return authority1;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_PIPELINE_H__
-#define __COGL_PIPELINE_H__
-
-G_BEGIN_DECLS
-
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-matrix.h>
-
-/**
- * SECTION:cogl-pipeline
- * @short_description: Functions for creating and manipulating the GPU
- * pipeline
- *
- * Cogl allows creating and manipulating objects representing the full
- * configuration of the GPU pipeline. In simplified terms the GPU
- * pipeline takes primitive geometry as the input, it first performs
- * vertex processing, allowing you to deform your geometry, then
- * rasterizes that (turning it from pure geometry into fragments) then
- * performs fragment processing including depth testing and texture
- * mapping. Finally it blends the result with the framebuffer.
- */
-
-typedef struct _CoglPipeline CoglPipeline;
-
-#define COGL_PIPELINE(OBJECT) ((CoglPipeline *)OBJECT)
-
-/**
- * CoglPipelineFilter:
- * @COGL_PIPELINE_FILTER_NEAREST: Measuring in manhatten distance from the,
- * current pixel center, use the nearest texture texel
- * @COGL_PIPELINE_FILTER_LINEAR: Use the weighted average of the 4 texels
- * nearest the current pixel center
- * @COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches the current pixel, and use the
- * %COGL_PIPELINE_FILTER_NEAREST criterion
- * @COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose
- * texel size most closely matches the current pixel, and use the
- * %COGL_PIPELINE_FILTER_LINEAR criterion
- * @COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely matches the current pixel, use
- * the %COGL_PIPELINE_FILTER_NEAREST criterion on each one and take
- * their weighted average
- * @COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels
- * whose texel size most closely matches the current pixel, use
- * the %COGL_PIPELINE_FILTER_LINEAR criterion on each one and take
- * their weighted average
- *
- * Texture filtering is used whenever the current pixel maps either to more
- * than one texture element (texel) or less than one. These filter enums
- * correspond to different strategies used to come up with a pixel color, by
- * possibly referring to multiple neighbouring texels and taking a weighted
- * average or simply using the nearest texel.
- */
-typedef enum {
- COGL_PIPELINE_FILTER_NEAREST = 0x2600,
- COGL_PIPELINE_FILTER_LINEAR = 0x2601,
- COGL_PIPELINE_FILTER_NEAREST_MIPMAP_NEAREST = 0x2700,
- COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST = 0x2701,
- COGL_PIPELINE_FILTER_NEAREST_MIPMAP_LINEAR = 0x2702,
- COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR = 0x2703
-} CoglPipelineFilter;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * CoglPipelineWrapMode:
- * @COGL_PIPELINE_WRAP_MODE_REPEAT: The texture will be repeated. This
- * is useful for example to draw a tiled background.
- * @COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE: The coordinates outside the
- * range 0→1 will sample copies of the edge pixels of the
- * texture. This is useful to avoid artifacts if only one copy of
- * the texture is being rendered.
- * @COGL_PIPELINE_WRAP_MODE_AUTOMATIC: Cogl will try to automatically
- * decide which of the above two to use. For cogl_rectangle(), it
- * will use repeat mode if any of the texture coordinates are
- * outside the range 0→1, otherwise it will use clamp to edge. For
- * cogl_polygon() it will always use repeat mode. For
- * cogl_vertex_buffer_draw() it will use repeat mode except for
- * layers that have point sprite coordinate generation enabled. This
- * is the default value.
- *
- * The wrap mode specifies what happens when texture coordinates
- * outside the range 0→1 are used. Note that if the filter mode is
- * anything but %COGL_PIPELINE_FILTER_NEAREST then texels outside the
- * range 0→1 might be used even when the coordinate is exactly 0 or 1
- * because OpenGL will try to sample neighbouring pixels. For example
- * if you are trying to render the full texture then you may get
- * artifacts around the edges when the pixels from the other side are
- * merged in if the wrap mode is set to repeat.
- *
- * Since: 2.0
- */
-/* GL_ALWAYS is just used here as a value that is known not to clash
- * with any valid GL wrap modes
- *
- * XXX: keep the values in sync with the CoglPipelineWrapModeInternal
- * enum so no conversion is actually needed.
- */
-typedef enum {
- COGL_PIPELINE_WRAP_MODE_REPEAT = 0x2901,
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE = 0x812F,
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC = 0x0207
-} CoglPipelineWrapMode;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * cogl_pipeline_new:
- *
- * Allocates and initializes a default simple pipeline that will color
- * a primitive white.
- *
- * Return value: a pointer to a new #CoglPipeline
- */
-CoglPipeline *
-cogl_pipeline_new (void);
-
-/**
- * cogl_pipeline_copy:
- * @source: a #CoglPipeline object to copy
- *
- * Creates a new pipeline with the configuration copied from the
- * source pipeline.
- *
- * We would strongly advise developers to always aim to use
- * cogl_pipeline_copy() instead of cogl_pipeline_new() whenever there will
- * be any similarity between two pipelines. Copying a pipeline helps Cogl
- * keep track of a pipelines ancestry which we may use to help minimize GPU
- * state changes.
- *
- * Returns: a pointer to the newly allocated #CoglPipeline
- *
- * Since: 2.0
- */
-CoglPipeline *
-cogl_pipeline_copy (CoglPipeline *source);
-
-/**
- * cogl_is_pipeline:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing pipeline object.
- *
- * Return value: %TRUE if the handle references a #CoglPipeline,
- * %FALSE otherwise
- */
-gboolean
-cogl_is_pipeline (CoglHandle handle);
-
-/**
- * cogl_pipeline_set_color:
- * @pipeline: A #CoglPipeline object
- * @color: The components of the color
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * Note that if you don't add any layers to the pipeline then the color
- * will be blended unmodified with the destination; the default blend
- * expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for
- * semi-transparent red. See cogl_color_premultiply().
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color (CoglPipeline *pipeline,
- const CoglColor *color);
-
-/**
- * cogl_pipeline_set_color4ub:
- * @pipeline: A #CoglPipeline object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * The default value is (0xff, 0xff, 0xff, 0xff)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color4ub (CoglPipeline *pipeline,
- guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha);
-
-/**
- * cogl_pipeline_set_color4f:
- * @pipeline: A #CoglPipeline object
- * @red: The red component
- * @green: The green component
- * @blue: The blue component
- * @alpha: The alpha component
- *
- * Sets the basic color of the pipeline, used when no lighting is enabled.
- *
- * The default value is (1.0, 1.0, 1.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_color4f (CoglPipeline *pipeline,
- float red,
- float green,
- float blue,
- float alpha);
-
-/**
- * cogl_pipeline_get_color:
- * @pipeline: A #CoglPipeline object
- * @color: (out): The location to store the color
- *
- * Retrieves the current pipeline color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_color (CoglPipeline *pipeline,
- CoglColor *color);
-
-/**
- * cogl_pipeline_set_ambient:
- * @pipeline: A #CoglPipeline object
- * @ambient: The components of the desired ambient color
- *
- * Sets the pipeline's ambient color, in the standard OpenGL lighting
- * model. The ambient color affects the overall color of the object.
- *
- * Since the diffuse color will be intense when the light hits the surface
- * directly, the ambient will be most apparent where the light hits at a
- * slant.
- *
- * The default value is (0.2, 0.2, 0.2, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_ambient (CoglPipeline *pipeline,
- const CoglColor *ambient);
-
-/**
- * cogl_pipeline_get_ambient:
- * @pipeline: A #CoglPipeline object
- * @ambient: The location to store the ambient color
- *
- * Retrieves the current ambient color for @pipeline
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_ambient (CoglPipeline *pipeline,
- CoglColor *ambient);
-
-/**
- * cogl_pipeline_set_diffuse:
- * @pipeline: A #CoglPipeline object
- * @diffuse: The components of the desired diffuse color
- *
- * Sets the pipeline's diffuse color, in the standard OpenGL lighting
- * model. The diffuse color is most intense where the light hits the
- * surface directly - perpendicular to the surface.
- *
- * The default value is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_diffuse (CoglPipeline *pipeline,
- const CoglColor *diffuse);
-
-/**
- * cogl_pipeline_get_diffuse:
- * @pipeline: A #CoglPipeline object
- * @diffuse: The location to store the diffuse color
- *
- * Retrieves the current diffuse color for @pipeline
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_diffuse (CoglPipeline *pipeline,
- CoglColor *diffuse);
-
-/**
- * cogl_pipeline_set_ambient_and_diffuse:
- * @pipeline: A #CoglPipeline object
- * @color: The components of the desired ambient and diffuse colors
- *
- * Conveniently sets the diffuse and ambient color of @pipeline at the same
- * time. See cogl_pipeline_set_ambient() and cogl_pipeline_set_diffuse().
- *
- * The default ambient color is (0.2, 0.2, 0.2, 1.0)
- *
- * The default diffuse color is (0.8, 0.8, 0.8, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_ambient_and_diffuse (CoglPipeline *pipeline,
- const CoglColor *color);
-
-/**
- * cogl_pipeline_set_specular:
- * @pipeline: A #CoglPipeline object
- * @specular: The components of the desired specular color
- *
- * Sets the pipeline's specular color, in the standard OpenGL lighting
- * model. The intensity of the specular color depends on the viewport
- * position, and is brightest along the lines of reflection.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_specular (CoglPipeline *pipeline,
- const CoglColor *specular);
-
-/**
- * cogl_pipeline_get_specular:
- * @pipeline: A #CoglPipeline object
- * @specular: The location to store the specular color
- *
- * Retrieves the pipelines current specular color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_specular (CoglPipeline *pipeline,
- CoglColor *specular);
-
-/**
- * cogl_pipeline_set_shininess:
- * @pipeline: A #CoglPipeline object
- * @shininess: The desired shininess; must be >= 0.0
- *
- * Sets the shininess of the pipeline, in the standard OpenGL lighting
- * model, which determines the size of the specular highlights. A
- * higher @shininess will produce smaller highlights which makes the
- * object appear more shiny.
- *
- * The default value is 0.0
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_shininess (CoglPipeline *pipeline,
- float shininess);
-
-/**
- * cogl_pipeline_get_shininess:
- * @pipeline: A #CoglPipeline object
- *
- * Retrieves the pipelines current emission color.
- *
- * Return value: The pipelines current shininess value
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_shininess (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_emission:
- * @pipeline: A #CoglPipeline object
- * @emission: The components of the desired emissive color
- *
- * Sets the pipeline's emissive color, in the standard OpenGL lighting
- * model. It will look like the surface is a light source emitting this
- * color.
- *
- * The default value is (0.0, 0.0, 0.0, 1.0)
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_emission (CoglPipeline *pipeline,
- const CoglColor *emission);
-
-/**
- * cogl_pipeline_get_emission:
- * @pipeline: A #CoglPipeline object
- * @emission: The location to store the emission color
- *
- * Retrieves the pipelines current emission color.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_get_emission (CoglPipeline *pipeline,
- CoglColor *emission);
-
-/**
- * CoglPipelineAlphaFunc:
- * @COGL_PIPELINE_ALPHA_FUNC_NEVER: Never let the fragment through.
- * @COGL_PIPELINE_ALPHA_FUNC_LESS: Let the fragment through if the incoming
- * alpha value is less than the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_EQUAL: Let the fragment through if the incoming
- * alpha value equals the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_LEQUAL: Let the fragment through if the incoming
- * alpha value is less than or equal to the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_GREATER: Let the fragment through if the incoming
- * alpha value is greater than the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL: Let the fragment through if the incoming
- * alpha value does not equal the reference alpha value
- * @COGL_PIPELINE_ALPHA_FUNC_GEQUAL: Let the fragment through if the incoming
- * alpha value is greater than or equal to the reference alpha value.
- * @COGL_PIPELINE_ALPHA_FUNC_ALWAYS: Always let the fragment through.
- *
- * Alpha testing happens before blending primitives with the framebuffer and
- * gives an opportunity to discard fragments based on a comparison with the
- * incoming alpha value and a reference alpha value. The #CoglPipelineAlphaFunc
- * determines how the comparison is done.
- */
-typedef enum {
- COGL_PIPELINE_ALPHA_FUNC_NEVER = 0x0200,
- COGL_PIPELINE_ALPHA_FUNC_LESS = 0x0201,
- COGL_PIPELINE_ALPHA_FUNC_EQUAL = 0x0202,
- COGL_PIPELINE_ALPHA_FUNC_LEQUAL = 0x0203,
- COGL_PIPELINE_ALPHA_FUNC_GREATER = 0x0204,
- COGL_PIPELINE_ALPHA_FUNC_NOTEQUAL = 0x0205,
- COGL_PIPELINE_ALPHA_FUNC_GEQUAL = 0x0206,
- COGL_PIPELINE_ALPHA_FUNC_ALWAYS = 0x0207
-} CoglPipelineAlphaFunc;
-/* NB: these values come from the equivalents in gl.h */
-
-/**
- * cogl_pipeline_set_alpha_test_function:
- * @pipeline: A #CoglPipeline object
- * @alpha_func: A @CoglPipelineAlphaFunc constant
- * @alpha_reference: A reference point that the chosen alpha function uses
- * to compare incoming fragments to.
- *
- * Before a primitive is blended with the framebuffer, it goes through an
- * alpha test stage which lets you discard fragments based on the current
- * alpha value. This function lets you change the function used to evaluate
- * the alpha channel, and thus determine which fragments are discarded
- * and which continue on to the blending stage.
- *
- * The default is %COGL_PIPELINE_ALPHA_FUNC_ALWAYS
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_alpha_test_function (CoglPipeline *pipeline,
- CoglPipelineAlphaFunc alpha_func,
- float alpha_reference);
-
-/**
- * cogl_pipeline_get_alpha_test_function:
- * @pipeline: A #CoglPipeline object
- *
- * Return value: The alpha test function of @pipeline.
- *
- * Since: 2.0
- */
-CoglPipelineAlphaFunc
-cogl_pipeline_get_alpha_test_function (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_get_alpha_test_reference:
- * @pipeline: A #CoglPipeline object
- *
- * Return value: The alpha test reference value of @pipeline.
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_alpha_test_reference (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_blend:
- * @pipeline: A #CoglPipeline object
- * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
- * describing the desired blend function.
- * @error: return location for a #GError that may report lack of driver
- * support if you give separate blend string statements for the alpha
- * channel and RGB channels since some drivers, or backends such as
- * GLES 1.1, don't support this feature. May be %NULL, in which case a
- * warning will be printed out using GLib's logging facilities if an
- * error is encountered.
- *
- * If not already familiar; please refer <link linkend="cogl-Blend-Strings">here</link>
- * for an overview of what blend strings are, and their syntax.
- *
- * Blending occurs after the alpha test function, and combines fragments with
- * the framebuffer.
-
- * Currently the only blend function Cogl exposes is ADD(). So any valid
- * blend statements will be of the form:
- *
- * |[
- * <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>))
- * ]|
- *
- * <warning>The brackets around blend factors are currently not
- * optional!</warning>
- *
- * This is the list of source-names usable as blend factors:
- * <itemizedlist>
- * <listitem><para>SRC_COLOR: The color of the in comming fragment</para></listitem>
- * <listitem><para>DST_COLOR: The color of the framebuffer</para></listitem>
- * <listitem><para>CONSTANT: The constant set via cogl_pipeline_set_blend_constant()</para></listitem>
- * </itemizedlist>
- *
- * The source names can be used according to the
- * <link linkend="cogl-Blend-String-syntax">color-source and factor syntax</link>,
- * so for example "(1-SRC_COLOR[A])" would be a valid factor, as would
- * "(CONSTANT[RGB])"
- *
- * These can also be used as factors:
- * <itemizedlist>
- * <listitem>0: (0, 0, 0, 0)</listitem>
- * <listitem>1: (1, 1, 1, 1)</listitem>
- * <listitem>SRC_ALPHA_SATURATE_FACTOR: (f,f,f,1) where f = MIN(SRC_COLOR[A],1-DST_COLOR[A])</listitem>
- * </itemizedlist>
- *
- * <note>Remember; all color components are normalized to the range [0, 1]
- * before computing the result of blending.</note>
- *
- * <example id="cogl-Blend-Strings-blend-unpremul">
- * <title>Blend Strings/1</title>
- * <para>Blend a non-premultiplied source over a destination with
- * premultiplied alpha:</para>
- * <programlisting>
- * "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
- * "A = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- * </programlisting>
- * </example>
- *
- * <example id="cogl-Blend-Strings-blend-premul">
- * <title>Blend Strings/2</title>
- * <para>Blend a premultiplied source over a destination with
- * premultiplied alpha</para>
- * <programlisting>
- * "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
- * </programlisting>
- * </example>
- *
- * The default blend string is:
- * |[
- * RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))
- * ]|
- *
- * That gives normal alpha-blending when the calculated color for the pipeline
- * is in premultiplied form.
- *
- * Return value: %TRUE if the blend string was successfully parsed, and the
- * described blending is supported by the underlying driver/hardware. If
- * there was an error, %FALSE is returned and @error is set accordingly (if
- * present).
- *
- * Since: 2.0
- */
-gboolean
-cogl_pipeline_set_blend (CoglPipeline *pipeline,
- const char *blend_string,
- GError **error);
-
-/**
- * cogl_pipeline_set_blend_constant:
- * @pipeline: A #CoglPipeline object
- * @constant_color: The constant color you want
- *
- * When blending is setup to reference a CONSTANT blend factor then
- * blending will depend on the constant set with this function.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_blend_constant (CoglPipeline *pipeline,
- const CoglColor *constant_color);
-
-/**
- * cogl_pipeline_set_point_size:
- * @pipeline: a #CoglHandle to a pipeline.
- * @point_size: the new point size.
- *
- * Changes the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API. Note that typically the GPU will
- * only support a limited minimum and maximum range of point sizes. If
- * the chosen point size is outside that range then the nearest value
- * within that range will be used instead. The size of a point is in
- * screen space so it will be the same regardless of any
- * transformations. The default point size is 1.0.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_point_size (CoglHandle pipeline,
- float point_size);
-
-/**
- * cogl_pipeline_get_point_size:
- * @pipeline: a #CoglHandle to a pipeline.
- *
- * Get the size of points drawn when %COGL_VERTICES_MODE_POINTS is
- * used with the vertex buffer API.
- *
- * Return value: the point size of the pipeline.
- *
- * Since: 2.0
- */
-float
-cogl_pipeline_get_point_size (CoglHandle pipeline);
-
-/**
- * cogl_pipeline_get_user_program:
- * @pipeline: a #CoglPipeline object.
- *
- * Queries what user program has been associated with the given
- * @pipeline using cogl_pipeline_set_user_program().
- *
- * Return value: The current user program or %COGL_INVALID_HANDLE.
- *
- * Since: 2.0
- */
-CoglHandle
-cogl_pipeline_get_user_program (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_user_program:
- * @pipeline: a #CoglPipeline object.
- * @program: A #CoglHandle to a linked CoglProgram
- *
- * Associates a linked CoglProgram with the given pipeline so that the
- * program can take full control of vertex and/or fragment processing.
- *
- * This is an example of how it can be used to associate an ARBfp
- * program with a #CoglPipeline:
- * |[
- * CoglHandle shader;
- * CoglHandle program;
- * CoglPipeline *pipeline;
- *
- * shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
- * cogl_shader_source (shader,
- * "!!ARBfp1.0\n"
- * "MOV result.color,fragment.color;\n"
- * "END\n");
- * cogl_shader_compile (shader);
- *
- * program = cogl_create_program ();
- * cogl_program_attach_shader (program, shader);
- * cogl_program_link (program);
- *
- * pipeline = cogl_pipeline_new ();
- * cogl_pipeline_set_user_program (pipeline, program);
- *
- * cogl_set_source_color4ub (0xff, 0x00, 0x00, 0xff);
- * cogl_rectangle (0, 0, 100, 100);
- * ]|
- *
- * It is possibly worth keeping in mind that this API is not part of
- * the long term design for how we want to expose shaders to Cogl
- * developers (We are planning on deprecating the cogl_program and
- * cogl_shader APIs in favour of a "snippet" framework) but in the
- * meantime we hope this will handle most practical GLSL and ARBfp
- * requirements.
- *
- * Also remember you need to check for either the
- * %COGL_FEATURE_SHADERS_GLSL or %COGL_FEATURE_SHADERS_ARBFP before
- * using the cogl_program or cogl_shader API.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_user_program (CoglPipeline *pipeline,
- CoglHandle program);
-
-/**
- * cogl_pipeline_set_layer:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the index of the layer
- * @texture: a #CoglHandle for the layer object
- *
- * In addition to the standard OpenGL lighting model a Cogl pipeline may have
- * one or more layers comprised of textures that can be blended together in
- * order, with a number of different texture combine modes. This function
- * defines a new texture layer.
- *
- * The index values of multiple layers do not have to be consecutive; it is
- * only their relative order that is important.
- *
- * <note>In the future, we may define other types of pipeline layers, such
- * as purely GLSL based layers.</note>
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_texture (CoglPipeline *pipeline,
- int layer_index,
- CoglHandle texture);
-
-/**
- * cogl_pipeline_remove_layer:
- * @pipeline: A #CoglPipeline object
- * @layer_index: Specifies the layer you want to remove
- *
- * This function removes a layer from your pipeline
- */
-void
-cogl_pipeline_remove_layer (CoglPipeline *pipeline,
- int layer_index);
-
-/**
- * cogl_pipeline_set_layer_combine:
- * @pipeline: A #CoglPipeline object
- * @layer_index: Specifies the layer you want define a combine function for
- * @blend_string: A <link linkend="cogl-Blend-Strings">Cogl blend string</link>
- * describing the desired texture combine function.
- * @error: A #GError that may report parse errors or lack of GPU/driver
- * support. May be %NULL, in which case a warning will be printed out if an
- * error is encountered.
- *
- * If not already familiar; you can refer
- * <link linkend="cogl-Blend-Strings">here</link> for an overview of what blend
- * strings are and there syntax.
- *
- * These are all the functions available for texture combining:
- * <itemizedlist>
- * <listitem>REPLACE(arg0) = arg0</listitem>
- * <listitem>MODULATE(arg0, arg1) = arg0 x arg1</listitem>
- * <listitem>ADD(arg0, arg1) = arg0 + arg1</listitem>
- * <listitem>ADD_SIGNED(arg0, arg1) = arg0 + arg1 - 0.5</listitem>
- * <listitem>INTERPOLATE(arg0, arg1, arg2) = arg0 x arg2 + arg1 x (1 - arg2)</listitem>
- * <listitem>SUBTRACT(arg0, arg1) = arg0 - arg1</listitem>
- * <listitem>
- * <programlisting>
- * DOT3_RGB(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
- * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
- * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
- * </programlisting>
- * </listitem>
- * <listitem>
- * <programlisting>
- * DOT3_RGBA(arg0, arg1) = 4 x ((arg0[R] - 0.5)) * (arg1[R] - 0.5) +
- * (arg0[G] - 0.5)) * (arg1[G] - 0.5) +
- * (arg0[B] - 0.5)) * (arg1[B] - 0.5))
- * </programlisting>
- * </listitem>
- * </itemizedlist>
- *
- * Refer to the
- * <link linkend="cogl-Blend-String-syntax">color-source syntax</link> for
- * describing the arguments. The valid source names for texture combining
- * are:
- * <variablelist>
- * <varlistentry>
- * <term>TEXTURE</term>
- * <listitem>Use the color from the current texture layer</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>TEXTURE_0, TEXTURE_1, etc</term>
- * <listitem>Use the color from the specified texture layer</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>CONSTANT</term>
- * <listitem>Use the color from the constant given with
- * cogl_pipeline_set_layer_constant()</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>PRIMARY</term>
- * <listitem>Use the color of the pipeline as set with
- * cogl_pipeline_set_color()</listitem>
- * </varlistentry>
- * <varlistentry>
- * <term>PREVIOUS</term>
- * <listitem>Either use the texture color from the previous layer, or
- * if this is layer 0, use the color of the pipeline as set with
- * cogl_pipeline_set_color()</listitem>
- * </varlistentry>
- * </variablelist>
- *
- * <refsect2 id="cogl-Layer-Combine-Examples">
- * <title>Layer Combine Examples</title>
- * <para>This is effectively what the default blending is:</para>
- * <informalexample><programlisting>
- * RGBA = MODULATE (PREVIOUS, TEXTURE)
- * </programlisting></informalexample>
- * <para>This could be used to cross-fade between two images, using
- * the alpha component of a constant as the interpolator. The constant
- * color is given by calling cogl_pipeline_set_layer_constant.</para>
- * <informalexample><programlisting>
- * RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A])
- * </programlisting></informalexample>
- * </refsect2>
- *
- * <note>You can't give a multiplication factor for arguments as you can
- * with blending.</note>
- *
- * Return value: %TRUE if the blend string was successfully parsed, and the
- * described texture combining is supported by the underlying driver and
- * or hardware. On failure, %FALSE is returned and @error is set
- *
- * Since: 2.0
- */
-gboolean
-cogl_pipeline_set_layer_combine (CoglPipeline *pipeline,
- int layer_index,
- const char *blend_string,
- GError **error);
-
-/**
- * cogl_pipeline_set_layer_combine_constant:
- * @pipeline: A #CoglPipeline object
- * @layer_index: Specifies the layer you want to specify a constant used
- * for texture combining
- * @constant: The constant color you want
- *
- * When you are using the 'CONSTANT' color source in a layer combine
- * description then you can use this function to define its value.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_combine_constant (CoglPipeline *pipeline,
- int layer_index,
- const CoglColor *constant);
-
-/**
- * cogl_pipeline_set_layer_matrix:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the index for the layer inside @pipeline
- * @matrix: the transformation matrix for the layer
- *
- * This function lets you set a matrix that can be used to e.g. translate
- * and rotate a single layer of a pipeline used to fill your geometry.
- */
-void
-cogl_pipeline_set_layer_matrix (CoglPipeline *pipeline,
- int layer_index,
- const CoglMatrix *matrix);
-
-/**
- * cogl_pipeline_get_n_layers:
- * @pipeline: A #CoglPipeline object
- *
- * Retrieves the number of layers defined for the given @pipeline
- *
- * Return value: the number of layers
- *
- * Since: 2.0
- */
-int
-cogl_pipeline_get_n_layers (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_layer_filters:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- * @min_filter: the filter used when scaling a texture down.
- * @mag_filter: the filter used when magnifying a texture.
- *
- * Changes the decimation and interpolation filters used when a texture is
- * drawn at other scales than 100%.
- */
-void
-cogl_pipeline_set_layer_filters (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineFilter min_filter,
- CoglPipelineFilter mag_filter);
-
-/**
- * cogl_pipeline_set_layer_point_sprite_coords_enabled:
- * @pipeline: a #CoglHandle to a pipeline.
- * @layer_index: the layer number to change.
- * @enable: whether to enable point sprite coord generation.
- * @error: A return location for a GError, or NULL to ignore errors.
- *
- * When rendering points, if @enable is %TRUE then the texture
- * coordinates for this layer will be replaced with coordinates that
- * vary from 0.0 to 1.0 across the primitive. The top left of the
- * point will have the coordinates 0.0,0.0 and the bottom right will
- * have 1.0,1.0. If @enable is %FALSE then the coordinates will be
- * fixed for the entire point.
- *
- * This function will only work if %COGL_FEATURE_POINT_SPRITE is
- * available. If the feature is not available then the function will
- * return %FALSE and set @error.
- *
- * Return value: %TRUE if the function succeeds, %FALSE otherwise.
- * Since: 2.0
- */
-gboolean
-cogl_pipeline_set_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
- int layer_index,
- gboolean enable,
- GError **error);
-
-/**
- * cogl_pipeline_get_layer_point_sprite_coords_enabled:
- * @pipeline: a #CoglHandle to a pipeline.
- * @layer_index: the layer number to check.
- *
- * Gets whether point sprite coordinate generation is enabled for this
- * texture layer.
- *
- * Return value: whether the texture coordinates will be replaced with
- * point sprite coordinates.
- *
- * Since: 2.0
- */
-gboolean
-cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
- int layer_index);
-
-/**
- * cogl_pipeline_get_layer_wrap_mode_s:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 's' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 's' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_s (CoglPipeline *pipeline,
- int layer_index);
-
-/**
- * cogl_pipeline_set_layer_wrap_mode_s:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 's' coordinate of texture lookups on this layer.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_wrap_mode_s (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode);
-
-/**
- * cogl_pipeline_get_layer_wrap_mode_t:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 't' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 't' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_t (CoglPipeline *pipeline,
- int layer_index);
-
-
-/**
- * cogl_pipeline_set_layer_wrap_mode_t:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 't' coordinate of texture lookups on this layer.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_wrap_mode_t (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode);
-
-/**
- * cogl_pipeline_get_layer_wrap_mode_p:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- *
- * Returns the wrap mode for the 'p' coordinate of texture lookups on this
- * layer.
- *
- * Return value: the wrap mode for the 'p' coordinate of texture lookups on
- * this layer.
- *
- * Since: 1.6
- */
-CoglPipelineWrapMode
-cogl_pipeline_get_layer_wrap_mode_p (CoglPipeline *pipeline,
- int layer_index);
-
-/**
- * cogl_pipeline_set_layer_wrap_mode_p:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for the 'p' coordinate of texture lookups on
- * this layer. 'p' is the third coordinate.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_wrap_mode_p (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode);
-
-/**
- * cogl_pipeline_set_layer_wrap_mode:
- * @pipeline: A #CoglPipeline object
- * @layer_index: the layer number to change.
- * @mode: the new wrap mode
- *
- * Sets the wrap mode for all three coordinates of texture lookups on
- * this layer. This is equivalent to calling
- * cogl_pipeline_set_layer_wrap_mode_s(),
- * cogl_pipeline_set_layer_wrap_mode_t() and
- * cogl_pipeline_set_layer_wrap_mode_p() separately.
- *
- * Since: 2.0
- */
-void
-cogl_pipeline_set_layer_wrap_mode (CoglPipeline *pipeline,
- int layer_index,
- CoglPipelineWrapMode mode);
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-
-/**
- * cogl_pipeline_set_depth_test_enabled:
- * @pipeline: A #CoglPipeline object
- * @enable: The enable state you want
- *
- * Enables or disables depth testing according to the value of
- * @enable.
- *
- * If depth testing is enable then the #CoglDepthTestFunction set
- * using cogl_pipeline_set_depth_test_function() us used to evaluate
- * the depth value of incoming fragments against the corresponding
- * value stored in the current depth buffer, and if the test passes
- * then the fragments depth value is used to update the depth buffer.
- * (unless you have disabled depth writing via
- * cogl_pipeline_set_depth_writing_enabled ())
- *
- * By default depth testing is disabled.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_set_depth_test_enabled (CoglPipeline *pipeline,
- gboolean enable);
-
-/**
- * cogl_pipeline_get_depth_test_enabled:
- * @pipeline: A #CoglPipeline object
- *
- * Gets the current depth test enabled state as previously set by
- * cogl_pipeline_set_depth_test_enabled().
- *
- * Returns: The pipeline's current depth test enabled state.
- * Since: 2.0
- * Stability: Unstable
- */
-gboolean
-cogl_pipeline_get_depth_test_enabled (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_depth_writing_enabled:
- * @pipeline: A #CoglPipeline object
- * @enable: The enable state you want
- *
- * Enables or disables depth buffer writing according to the value of
- * @enable. Normally when depth testing is enabled and the comparison
- * between a fragment's depth value and the corresponding depth buffer
- * value passes then the fragment's depth is written to the depth
- * buffer unless writing is disabled here.
- *
- * By default depth writing is enabled
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_set_depth_writing_enabled (CoglPipeline *pipeline,
- gboolean enable);
-
-/**
- * cogl_pipeline_get_depth_writing_enabled:
- * @pipeline: A #CoglPipeline object
- *
- * Gets the depth writing enable state as set by the corresponding
- * cogl_pipeline_set_depth_writing_enabled.
- *
- * Returns: The current depth writing enable state
- * Since: 2.0
- * Stability: Unstable
- */
-gboolean
-cogl_pipeline_get_depth_writing_enabled (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_depth_test_function:
- * @pipeline: A #CoglPipeline object
- * @function: The #CoglDepthTestFunction to set
- *
- * Sets the #CoglDepthTestFunction used to compare the depth value of
- * an incoming fragment against the corresponding value in the current
- * depth buffer.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_set_depth_test_function (CoglPipeline *pipeline,
- CoglDepthTestFunction function);
-
-/**
- * cogl_pipeline_get_depth_test_function:
- * @pipeline: A #CoglPipeline object
- *
- * Gets the current depth test enable state as previously set via
- * cogl_pipeline_set_depth_test_enabled().
- *
- * Returns: The current depth test enable state.
- * Since: 2.0
- * Stability: Unstable
- */
-CoglDepthTestFunction
-cogl_pipeline_get_depth_test_function (CoglPipeline *pipeline);
-
-/**
- * cogl_pipeline_set_depth_range:
- * @pipeline: A #CoglPipeline object
- * @near_val: The near component of the desired depth range which will be
- * clamped to the range [0, 1]
- * @far_val: The far component of the desired depth range which will be
- * clamped to the range [0, 1]
- * @error: location to store an error of type #CoglError
- *
- * Sets the range to map depth values in normalized device coordinates
- * to before writing out to a depth buffer.
- *
- * After your geometry has be transformed, clipped and had perspective
- * division applied placing it in normalized device
- * coordinates all depth values between the near and far z clipping
- * planes are in the range -1 to 1. Before writing any depth value to
- * the depth buffer though the value is mapped into the range [0, 1].
- *
- * With this function you can change the range which depth values are
- * mapped too although the range must still lye within the range [0,
- * 1].
- *
- * If your driver does not support this feature (for example you are
- * using GLES 1 drivers) then this will return %FALSE and set an error
- * if @error isn't NULL. You can check ahead of time for the
- * %COGL_FEATURE_DEPTH_RANGE feature with cogl_features_available() to
- * know if this function will succeed.
- *
- * By default normalized device coordinate depth values are mapped to
- * the full range of depth buffer values, [0, 1].
- *
- * Returns: %TRUE if driver support is available else %FALSE.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-gboolean
-cogl_pipeline_set_depth_range (CoglPipeline *pipeline,
- float near_val,
- float far_val,
- GError **error);
-
-/**
- * cogl_pipeline_get_depth_range_mapping:
- * @pipeline: A #CoglPipeline object
- * @near_val: A pointer to store the near component of the depth range
- * @far_val: A pointer to store the far component of the depth range
- *
- * Gets the current range to which normalized depth values are mapped
- * before writing to the depth buffer. This corresponds to the range
- * set with cogl_pipeline_set_depth_range().
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_get_depth_range (CoglPipeline *pipeline,
- float *near_val,
- float *far_val);
-
-/**
- * CoglPipelineLayerCallback:
- * @pipeline: The #CoglPipeline whos layers are being iterated
- * @layer_index: The current layer index
- * @user_data: The private data passed to cogl_pipeline_foreach_layer()
- *
- * The callback prototype used with cogl_pipeline_foreach_layer() for
- * iterating all the layers of a @pipeline.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-typedef gboolean (*CoglPipelineLayerCallback) (CoglPipeline *pipeline,
- int layer_index,
- void *user_data);
-
-/**
- * cogl_pipeline_foreach_layer:
- * @pipeline: A #CoglPipeline object
- * @callback: A #CoglPipelineLayerCallback to be called for each layer
- * index
- * @user_data: Private data that will be passed to the callback
- *
- * Iterates all the layer indices of the given @pipeline.
- *
- * Since: 2.0
- * Stability: Unstable
- */
-void
-cogl_pipeline_foreach_layer (CoglPipeline *pipeline,
- CoglPipelineLayerCallback callback,
- void *user_data);
-
-#endif /* COGL_ENABLE_EXPERIMENTAL_API */
-
-G_END_DECLS
-
-#endif /* __COGL_PIPELINE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PIXEL_ARRAY_PRIVATE_H__
-#define __COGL_PIXEL_ARRAY_PRIVATE_H__
-
-#include "cogl-handle.h"
-#include "cogl-buffer-private.h"
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-#define COGL_PIXEL_ARRAY(array) ((CoglPixelArray *)(array))
-
-struct _CoglPixelArray
-{
- CoglBuffer _parent;
-
- CoglPixelFormat format;
- unsigned int width;
- unsigned int height;
- unsigned int stride;
-};
-
-GQuark
-_cogl_handle_pixel_array_get_type (void);
-
-G_END_DECLS
-
-#endif /* __COGL_PIXEL_ARRAY_PRIVATE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-/* For an overview of the functionality implemented here, please see
- * cogl-pixel-array.h, which contains the gtk-doc section overview for the
- * Pixel Buffers API.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-context-private.h"
-#include "cogl-object.h"
-#include "cogl-pixel-array-private.h"
-#include "cogl-pixel-array.h"
-
-/*
- * GL/GLES compatibility defines for the buffer API:
- */
-
-#if defined (HAVE_COGL_GL)
-
-#define glGenBuffers ctx->drv.pf_glGenBuffers
-#define glBindBuffer ctx->drv.pf_glBindBuffer
-#define glBufferData ctx->drv.pf_glBufferData
-#define glBufferSubData ctx->drv.pf_glBufferSubData
-#define glGetBufferSubData ctx->drv.pf_glGetBufferSubData
-#define glDeleteBuffers ctx->drv.pf_glDeleteBuffers
-#define glMapBuffer ctx->drv.pf_glMapBuffer
-#define glUnmapBuffer ctx->drv.pf_glUnmapBuffer
-
-#ifndef GL_PIXEL_UNPACK_BUFFER
-#define GL_PIXEL_UNPACK_BUFFER GL_PIXEL_UNPACK_BUFFER_ARB
-#endif
-
-#ifndef GL_PIXEL_PACK_BUFFER
-#define GL_PIXEL_PACK_BUFFER GL_PIXEL_PACK_BUFFER_ARB
-#endif
-
-#endif
-
-static void
-_cogl_pixel_array_free (CoglPixelArray *buffer);
-
-COGL_BUFFER_DEFINE (PixelArray, pixel_array)
-
-static CoglPixelArray *
-_cogl_pixel_array_new (unsigned int size)
-{
- CoglPixelArray *pixel_array = g_slice_new0 (CoglPixelArray);
- CoglBuffer *buffer = COGL_BUFFER (pixel_array);
- gboolean use_malloc;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- if (!cogl_features_available (COGL_FEATURE_PBOS))
- use_malloc = TRUE;
- else
- use_malloc = FALSE;
-
- /* parent's constructor */
- _cogl_buffer_initialize (buffer,
- size,
- use_malloc,
- COGL_BUFFER_BIND_TARGET_PIXEL_UNPACK,
- COGL_BUFFER_USAGE_HINT_TEXTURE,
- COGL_BUFFER_UPDATE_HINT_STATIC);
-
- /* return COGL_INVALID_HANDLE; */
- return _cogl_pixel_array_object_new (pixel_array);
-}
-
-CoglPixelArray *
-cogl_pixel_array_new_with_size (unsigned int width,
- unsigned int height,
- CoglPixelFormat format,
- unsigned int *rowstride)
-{
- CoglPixelArray *buffer;
- CoglPixelArray *pixel_array;
- unsigned int stride;
-
- /* creating a buffer to store "any" format does not make sense */
- if (G_UNLIKELY (format == COGL_PIXEL_FORMAT_ANY))
- return COGL_INVALID_HANDLE;
-
- /* for now we fallback to cogl_pixel_array_new, later, we could ask
- * libdrm a tiled buffer for instance */
- stride = width * _cogl_get_format_bpp (format);
- if (rowstride)
- *rowstride = stride;
-
- buffer = _cogl_pixel_array_new (height * stride);
- if (G_UNLIKELY (buffer == COGL_INVALID_HANDLE))
- return COGL_INVALID_HANDLE;
-
- pixel_array = COGL_PIXEL_ARRAY (buffer);
- pixel_array->width = width;
- pixel_array->height = height;
- pixel_array->format = format;
- pixel_array->stride = stride;
-
- return buffer;
-}
-
-static void
-_cogl_pixel_array_free (CoglPixelArray *buffer)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* parent's destructor */
- _cogl_buffer_fini (COGL_BUFFER (buffer));
-
- g_slice_free (CoglPixelArray, buffer);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Damien Lespiau <damien.lespiau@intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_PIXEL_ARRAY_H__
-#define __COGL_PIXEL_ARRAY_H__
-
-#include <glib.h>
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/* All of the cogl-pixel-array API is currently experimental so we
- * suffix the actual symbols with _EXP so if somone is monitoring for
- * ABI changes it will hopefully be clearer to them what's going on if
- * any of the symbols dissapear at a later date.
- */
-
-#define cogl_pixel_array_new cogl_pixel_array_new_EXP
-#define cogl_pixel_array_new_with_size cogl_pixel_array_new_with_size_EXP
-#define cogl_is_pixel_array cogl_is_pixel_array_EXP
-#if 0
-#define cogl_pixel_array_set_region cogl_pixel_array_set_region_EXP
-#endif
-
-typedef struct _CoglPixelArray CoglPixelArray;
-
-/**
- * cogl_pixel_array_new_with_size:
- * @width: width of the pixel array in pixels
- * @height: height of the pixel array in pixels
- * @format: the format of the pixels the array will store
- * @stride: if not %NULL the function will return the stride of the array
- * in bytes
- *
- * Creates a new array to store pixel data.
- *
- * <note>COGL will try its best to provide a hardware array you can map,
- * write into and effectively do a zero copy upload when creating a texture
- * from it with cogl_texture_new_from_buffer(). For various reasons, such
- * arrays are likely to have a stride larger than width * bytes_per_pixel. The
- * user must take the stride into account when writing into it.</note>
- *
- * Return value: a #CoglPixelArray representing the newly created array or
- * %NULL on failure
- *
- * Since: 1.2
- * Stability: Unstable
- */
-CoglPixelArray *
-cogl_pixel_array_new_with_size (unsigned int width,
- unsigned int height,
- CoglPixelFormat format,
- unsigned int *stride);
-
-/**
- * cogl_is_pixel_array:
- * @object: a #CoglObject to test
- *
- * Checks whether @handle is a pixel array.
- *
- * Return value: %TRUE if the @handle is a pixel array, and %FALSE
- * otherwise
- *
- * Since: 1.2
- * Stability: Unstable
- */
-gboolean
-cogl_is_pixel_array (void *object);
-
-#if 0
-/*
- * cogl_pixel_array_set_region:
- * @array: the #CoglHandle of a pixel array
- * @data: pixel data to upload to @array
- * @src_width: width in pixels of the region to update
- * @src_height: height in pixels of the region to update
- * @src_rowstride: row stride in bytes of the source array
- * @dst_x: upper left destination horizontal coordinate
- * @dst_y: upper left destination vertical coordinate
- *
- * Uploads new data into a pixel array. The source data pointed by @data can
- * have a different stride than @array in which case the function will do the
- * right thing for you. For performance reasons, it is recommended for the
- * source data to have the same stride than @array.
- *
- * Return value: %TRUE if the upload succeeded, %FALSE otherwise
- *
- * Since: 1.2
- * Stability: Unstable
- */
-gboolean
-cogl_pixel_array_set_region (CoglHandle array,
- guint8 *data,
- unsigned int src_width,
- unsigned int src_height,
- unsigned int src_rowstride,
- unsigned int dst_x,
- unsigned int dst_y);
-#endif
-
-G_END_DECLS
-
-#endif /* __COGL_PIXEL_ARRAY_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __COGL_POINT_INT_POLYGON_PRIVATE_H
-#define __COGL_POINT_INT_POLYGON_PRIVATE_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-int
-_cogl_util_point_in_screen_poly (float point_x,
- float point_y,
- void *vertices,
- size_t stride,
- int n_vertices);
-
-G_END_DECLS
-
-#endif /* __COGL_POINT_INT_POLYGON_PRIVATE_H */
-
+++ /dev/null
-/*
- * Point Inclusion in Polygon Test
- *
- * Copyright (c) 1970-2003, Wm. Randolph Franklin
- * Copyright (C) 2011 Intel Corporation.
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimers.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice in the documentation and/or other materials
- * provided with the distribution.
- * 3. The name of W. Randolph Franklin may not be used to endorse or
- * promote products derived from this Software without specific
- * prior written permission.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Note:
- * The algorithm for this point_in_poly() function was learnt from:
- * http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-util.h"
-
-#include <glib.h>
-
-/* We've made a notable change to the original algorithm referenced
- * above to make sure we have reliable results for screen aligned
- * rectangles even though there may be some numerical in-precision in
- * how the vertices of the polygon were calculated.
- *
- * We've avoided introducing an epsilon factor to the comparisons
- * since we feel there's a risk of changing some semantics in ways that
- * might not be desirable. One of those is that if you transform two
- * polygons which share an edge and test a point close to that edge
- * then this algorithm will currently give a positive result for only
- * one polygon.
- *
- * Another concern is the way this algorithm resolves the corner case
- * where the horizontal ray being cast to count edge crossings may
- * cross directly through a vertex. The solution is based on the "idea
- * of Simulation of Simplicity" and "pretends to shift the ray
- * infinitesimally down so that it either clearly intersects, or
- * clearly doesn't touch". I'm not familiar with the idea myself so I
- * expect a misplaced epsilon is likely to break that aspect of the
- * algorithm.
- *
- * The simple solution we've gone for is to pixel align the polygon
- * vertices which should eradicate most noise due to in-precision.
- */
-int
-_cogl_util_point_in_screen_poly (float point_x,
- float point_y,
- void *vertices,
- size_t stride,
- int n_vertices)
-{
- int i, j, c = 0;
-
- for (i = 0, j = n_vertices - 1; i < n_vertices; j = i++)
- {
- float vert_xi = *(float *)((guint8 *)vertices + i * stride);
- float vert_xj = *(float *)((guint8 *)vertices + j * stride);
- float vert_yi = *(float *)((guint8 *)vertices + i * stride +
- sizeof (float));
- float vert_yj = *(float *)((guint8 *)vertices + j * stride +
- sizeof (float));
-
- vert_xi = COGL_UTIL_NEARBYINT (vert_xi);
- vert_xj = COGL_UTIL_NEARBYINT (vert_xj);
- vert_yi = COGL_UTIL_NEARBYINT (vert_yi);
- vert_yj = COGL_UTIL_NEARBYINT (vert_yj);
-
- if (((vert_yi > point_y) != (vert_yj > point_y)) &&
- (point_x < (vert_xj - vert_xi) * (point_y - vert_yi) /
- (vert_yj - vert_yi) + vert_xi) )
- c = !c;
- }
-
- return c;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_PRIMITIVE_PRIVATE_H
-#define __COGL_PRIMITIVE_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-vertex-array-private.h"
-
-struct _CoglPrimitive
-{
- CoglObject _parent;
-
- CoglVerticesMode mode;
- int first_vertex;
- int n_vertices;
- CoglIndices *indices;
- GArray *attributes;
-
- int immutable_ref;
-};
-
-CoglPrimitive *
-_cogl_primitive_immutable_ref (CoglPrimitive *primitive);
-
-void
-_cogl_primitive_immutable_unref (CoglPrimitive *primitive);
-
-#endif /* __COGL_PRIMITIVE_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-object-private.h"
-#include "cogl-primitive.h"
-#include "cogl-primitive-private.h"
-#include "cogl-attribute-private.h"
-
-#include <stdarg.h>
-
-static void _cogl_primitive_free (CoglPrimitive *primitive);
-
-COGL_OBJECT_DEFINE (Primitive, primitive);
-
-/* XXX: should we have an n_attributes arg instead of NULL terminating? */
-CoglPrimitive *
-cogl_primitive_new_with_attributes_array (CoglVerticesMode mode,
- int n_vertices,
- CoglAttribute **attributes)
-{
- CoglPrimitive *primitive = g_slice_new (CoglPrimitive);
- int i;
-
- primitive->mode = mode;
- primitive->first_vertex = 0;
- primitive->n_vertices = n_vertices;
- primitive->indices = NULL;
- primitive->attributes =
- g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
- primitive->immutable_ref = 0;
-
- for (i = 0; attributes[i]; i++)
- {
- CoglAttribute *attribute = attributes[i];
- cogl_object_ref (attribute);
-
- g_return_val_if_fail (cogl_is_attribute (attribute), NULL);
-
- g_array_append_val (primitive->attributes, attribute);
- }
-
- return _cogl_primitive_object_new (primitive);
-}
-
-/* This is just an internal convenience wrapper around
- new_with_attributes that also unrefs the attributes. It is just
- used for the builtin struct constructors */
-static CoglPrimitive *
-_cogl_primitive_new_with_attributes_array_unref (CoglVerticesMode mode,
- int n_vertices,
- CoglAttribute **attributes)
-{
- CoglPrimitive *primitive;
- int i;
-
- primitive = cogl_primitive_new_with_attributes_array (mode,
- n_vertices,
- attributes);
-
- for (i = 0; attributes[i]; i++)
- cogl_object_unref (attributes[i]);
-
- return primitive;
-}
-
-CoglPrimitive *
-cogl_primitive_new (CoglVerticesMode mode,
- int n_vertices,
- ...)
-{
- va_list ap;
- int n_attributes;
- CoglAttribute **attributes;
- int i;
- CoglAttribute *attribute;
-
- va_start (ap, n_vertices);
- for (n_attributes = 0; va_arg (ap, CoglAttribute *); n_attributes++)
- ;
- va_end (ap);
-
- attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
- attributes[n_attributes] = NULL;
-
- va_start (ap, n_vertices);
- for (i = 0; (attribute = va_arg (ap, CoglAttribute *)); i++)
- attributes[i] = attribute;
- va_end (ap);
-
- return cogl_primitive_new_with_attributes_array (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2), data);
- CoglAttribute *attributes[2];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP2),
- offsetof (CoglVertexP2, x),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p3 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3), data);
- CoglAttribute *attributes[2];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP3),
- offsetof (CoglVertexP3, x),
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2C4 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2C4), data);
- CoglAttribute *attributes[3];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP2C4),
- offsetof (CoglVertexP2C4, x),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglVertexP2C4),
- offsetof (CoglVertexP2C4, r),
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
- attributes[2] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p3c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3C4 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3C4), data);
- CoglAttribute *attributes[3];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP3C4),
- offsetof (CoglVertexP3C4, x),
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglVertexP3C4),
- offsetof (CoglVertexP3C4, r),
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
- attributes[2] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p2t2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2T2 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2T2), data);
- CoglAttribute *attributes[3];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP2T2),
- offsetof (CoglVertexP2T2, x),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglVertexP2T2),
- offsetof (CoglVertexP2T2, s),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p3t2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3T2 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3T2), data);
- CoglAttribute *attributes[3];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP3T2),
- offsetof (CoglVertexP3T2, x),
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglVertexP3T2),
- offsetof (CoglVertexP3T2, s),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p2t2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2T2C4 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP2T2C4), data);
- CoglAttribute *attributes[4];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP2T2C4),
- offsetof (CoglVertexP2T2C4, x),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglVertexP2T2C4),
- offsetof (CoglVertexP2T2C4, s),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] = cogl_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglVertexP2T2C4),
- offsetof (CoglVertexP2T2C4, r),
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
- attributes[3] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-CoglPrimitive *
-cogl_primitive_new_p3t2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3T2C4 *data)
-{
- CoglVertexArray *array =
- cogl_vertex_array_new (n_vertices * sizeof (CoglVertexP3T2C4), data);
- CoglAttribute *attributes[4];
-
- attributes[0] = cogl_attribute_new (array,
- "cogl_position_in",
- sizeof (CoglVertexP3T2C4),
- offsetof (CoglVertexP3T2C4, x),
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = cogl_attribute_new (array,
- "cogl_tex_coord0_in",
- sizeof (CoglVertexP3T2C4),
- offsetof (CoglVertexP3T2C4, s),
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[2] = cogl_attribute_new (array,
- "cogl_color_in",
- sizeof (CoglVertexP3T2C4),
- offsetof (CoglVertexP3T2C4, r),
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
- attributes[3] = NULL;
-
- cogl_object_unref (array);
-
- return _cogl_primitive_new_with_attributes_array_unref (mode, n_vertices,
- attributes);
-}
-
-static void
-free_attributes_list (CoglPrimitive *primitive)
-{
- int i;
-
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- cogl_object_unref (attribute);
- }
- g_array_set_size (primitive->attributes, 0);
-}
-
-static void
-_cogl_primitive_free (CoglPrimitive *primitive)
-{
- free_attributes_list (primitive);
-
- g_array_free (primitive->attributes, TRUE);
-
- g_slice_free (CoglPrimitive, primitive);
-}
-
-static void
-warn_about_midscene_changes (void)
-{
- static gboolean seen = FALSE;
- if (!seen)
- {
- g_warning ("Mid-scene modification of buffers has "
- "undefined results\n");
- seen = TRUE;
- }
-}
-
-void
-cogl_primitive_set_attributes (CoglPrimitive *primitive,
- CoglAttribute **attributes)
-{
- int i;
-
- g_return_if_fail (cogl_is_primitive (primitive));
-
- if (G_UNLIKELY (primitive->immutable_ref))
- {
- warn_about_midscene_changes ();
- return;
- }
-
- free_attributes_list (primitive);
-
- g_array_set_size (primitive->attributes, 0);
- for (i = 0; attributes[i]; i++)
- {
- cogl_object_ref (attributes[i]);
- g_return_if_fail (cogl_is_attribute (attributes[i]));
- g_array_append_val (primitive->attributes, attributes[i]);
- }
-}
-
-int
-cogl_primitive_get_first_vertex (CoglPrimitive *primitive)
-{
- g_return_val_if_fail (cogl_is_primitive (primitive), 0);
-
- return primitive->first_vertex;
-}
-
-void
-cogl_primitive_set_first_vertex (CoglPrimitive *primitive,
- int first_vertex)
-{
- g_return_if_fail (cogl_is_primitive (primitive));
-
- if (G_UNLIKELY (primitive->immutable_ref))
- {
- warn_about_midscene_changes ();
- return;
- }
-
- primitive->first_vertex = first_vertex;
-}
-
-int
-cogl_primitive_get_n_vertices (CoglPrimitive *primitive)
-{
- g_return_val_if_fail (cogl_is_primitive (primitive), 0);
-
- return primitive->n_vertices;
-}
-
-void
-cogl_primitive_set_n_vertices (CoglPrimitive *primitive,
- int n_vertices)
-{
- g_return_if_fail (cogl_is_primitive (primitive));
-
- primitive->n_vertices = n_vertices;
-}
-
-CoglVerticesMode
-cogl_primitive_get_mode (CoglPrimitive *primitive)
-{
- g_return_val_if_fail (cogl_is_primitive (primitive), 0);
-
- return primitive->mode;
-}
-
-void
-cogl_primitive_set_mode (CoglPrimitive *primitive,
- CoglVerticesMode mode)
-{
- g_return_if_fail (cogl_is_primitive (primitive));
-
- if (G_UNLIKELY (primitive->immutable_ref))
- {
- warn_about_midscene_changes ();
- return;
- }
-
- primitive->mode = mode;
-}
-
-void
-cogl_primitive_set_indices (CoglPrimitive *primitive,
- CoglIndices *indices)
-{
- g_return_if_fail (cogl_is_primitive (primitive));
-
- if (G_UNLIKELY (primitive->immutable_ref))
- {
- warn_about_midscene_changes ();
- return;
- }
-
- if (indices)
- cogl_object_ref (indices);
- if (primitive->indices)
- cogl_object_unref (primitive->indices);
- primitive->indices = indices;
-}
-
-CoglPrimitive *
-_cogl_primitive_immutable_ref (CoglPrimitive *primitive)
-{
- int i;
-
- g_return_val_if_fail (cogl_is_primitive (primitive), NULL);
-
- primitive->immutable_ref++;
-
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- _cogl_attribute_immutable_ref (attribute);
- }
-
- return primitive;
-}
-
-void
-_cogl_primitive_immutable_unref (CoglPrimitive *primitive)
-{
- int i;
-
- g_return_if_fail (cogl_is_primitive (primitive));
- g_return_if_fail (primitive->immutable_ref > 0);
-
- primitive->immutable_ref--;
-
- for (i = 0; i < primitive->attributes->len; i++)
- {
- CoglAttribute *attribute =
- g_array_index (primitive->attributes, CoglAttribute *, i);
- _cogl_attribute_immutable_unref (attribute);
- }
-}
-
-/* XXX: cogl_draw_primitive() ? */
-void
-cogl_primitive_draw (CoglPrimitive *primitive)
-{
- CoglAttribute **attributes =
- (CoglAttribute **)primitive->attributes->data;
-
- if (primitive->indices)
- cogl_draw_indexed_attributes_array (primitive->mode,
- primitive->first_vertex,
- primitive->n_vertices,
- primitive->indices,
- attributes);
- else
- cogl_draw_attributes_array (primitive->mode,
- primitive->first_vertex,
- primitive->n_vertices,
- attributes);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_PRIMITIVE_H__
-#define __COGL_PRIMITIVE_H__
-
-#include <cogl/cogl-vertex-buffer.h> /* for CoglVerticesMode */
-#include <cogl/cogl-attribute.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-primitive
- * @short_description: Functions for creating, manipulating and drawing
- * primitives
- *
- * FIXME
- */
-
-typedef struct _CoglPrimitive CoglPrimitive;
-
-/**
- * CoglVertexP2:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v2_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y;
-} CoglVertexP2;
-
-/**
- * CoglVertexP3:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @z: The z component of a position attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v3_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y, z;
-} CoglVertexP3;
-
-/**
- * CoglVertexP2C4:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @r: The red component of a color attribute
- * @b: The green component of a color attribute
- * @g: The blue component of a color attribute
- * @a: The alpha component of a color attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v2c4_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y;
- guint8 r, g, b, a;
-} CoglVertexP2C4;
-
-/**
- * CoglVertexP3C4:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @z: The z component of a position attribute
- * @r: The red component of a color attribute
- * @b: The green component of a color attribute
- * @g: The blue component of a color attribute
- * @a: The alpha component of a color attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v3c4_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y, z;
- guint8 r, g, b, a;
-} CoglVertexP3C4;
-
-/**
- * CoglVertexP2T2:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @s: The s component of a texture coordinate attribute
- * @t: The t component of a texture coordinate attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v2t2_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y;
- float s, t;
-} CoglVertexP2T2;
-
-/**
- * CoglVertexP3T2:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @z: The z component of a position attribute
- * @s: The s component of a texture coordinate attribute
- * @t: The t component of a texture coordinate attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v3t2_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y, z;
- float s, t;
-} CoglVertexP3T2;
-
-
-/**
- * CoglVertexP2T2C4:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @s: The s component of a texture coordinate attribute
- * @t: The t component of a texture coordinate attribute
- * @r: The red component of a color attribute
- * @b: The green component of a color attribute
- * @g: The blue component of a color attribute
- * @a: The alpha component of a color attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v3t2c4_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y;
- float s, t;
- guint8 r, g, b, a;
-} CoglVertexP2T2C4;
-
-/**
- * CoglVertexP3T2C4:
- * @x: The x component of a position attribute
- * @y: The y component of a position attribute
- * @z: The z component of a position attribute
- * @s: The s component of a texture coordinate attribute
- * @t: The t component of a texture coordinate attribute
- * @r: The red component of a color attribute
- * @b: The green component of a color attribute
- * @g: The blue component of a color attribute
- * @a: The alpha component of a color attribute
- *
- * A convenience vertex definition that can be used with
- * cogl_primitive_new_with_v3t2c4_attributes().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-typedef struct
-{
- float x, y, z;
- float s, t;
- guint8 r, g, b, a;
-} CoglVertexP3T2C4;
-
-/**
- * cogl_primitive_new:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @Varargs: A %NULL terminated list of attributes
- *
- * Combines a set of #CoglAttribute<!-- -->s with a specific draw @mode
- * and defines a vertex count so a #CoglPrimitive object can be retained and
- * drawn later with no addition information required.
- *
- * Returns: A newly allocated #CoglPrimitive object
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new (CoglVerticesMode mode,
- int n_vertices,
- ...);
-
-/* XXX: how about just: cogl_primitive_new_with_attributes () ? */
-CoglPrimitive *
-cogl_primitive_new_with_attributes_array (CoglVerticesMode mode,
- int n_vertices,
- CoglAttribute **attributes);
-
-/**
- * cogl_primitive_new_p2:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP2 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position
- * attribute with a #CoglAttribute and upload your data.
- *
- * For example to draw a convex polygon you can do:
- * |[
- * CoglVertexP2 triangle[] =
- * {
- * { 0, 300 },
- * { 150, 0, },
- * { 300, 300 }
- * };
- * prim = cogl_primitive_new_p2 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2 *data);
-
-/**
- * cogl_primitive_new_p3:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP3 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position
- * attribute with a #CoglAttribute and upload your data.
- *
- * For example to draw a convex polygon you can do:
- * |[
- * CoglVertexP3 triangle[] =
- * {
- * { 0, 300, 0 },
- * { 150, 0, 0 },
- * { 300, 300, 0 }
- * };
- * prim = cogl_primitive_new_p3 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p3 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3 *data);
-
-/**
- * cogl_primitive_new_p2c4:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP2C4 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position
- * and color attributes with #CoglAttribute<!-- -->s and upload
- * your data.
- *
- * For example to draw a convex polygon with a linear gradient you
- * can do:
- * |[
- * CoglVertexP2C4 triangle[] =
- * {
- * { 0, 300, 0xff, 0x00, 0x00, 0xff },
- * { 150, 0, 0x00, 0xff, 0x00, 0xff },
- * { 300, 300, 0xff, 0x00, 0x00, 0xff }
- * };
- * prim = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2C4 *data);
-
-/**
- * cogl_primitive_new_p3c4:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP3C4 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position
- * and color attributes with #CoglAttribute<!-- -->s and upload
- * your data.
- *
- * For example to draw a convex polygon with a linear gradient you
- * can do:
- * |[
- * CoglVertexP3C4 triangle[] =
- * {
- * { 0, 300, 0, 0xff, 0x00, 0x00, 0xff },
- * { 150, 0, 0, 0x00, 0xff, 0x00, 0xff },
- * { 300, 300, 0, 0xff, 0x00, 0x00, 0xff }
- * };
- * prim = cogl_primitive_new_p3c4 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p3c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3C4 *data);
-
-/**
- * cogl_primitive_new_p2t2:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP2T2 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position and
- * texture coordinate attributes with #CoglAttribute<!-- -->s and
- * upload your data.
- *
- * For example to draw a convex polygon with texture mapping you can
- * do:
- * |[
- * CoglVertexP2T2 triangle[] =
- * {
- * { 0, 300, 0.0, 1.0},
- * { 150, 0, 0.5, 0.0},
- * { 300, 300, 1.0, 1.0}
- * };
- * prim = cogl_primitive_new_p2t2 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p2t2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2T2 *data);
-
-/**
- * cogl_primitive_new_p3t2:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP3T2 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position and
- * texture coordinate attributes with #CoglAttribute<!-- -->s and
- * upload your data.
- *
- * For example to draw a convex polygon with texture mapping you can
- * do:
- * |[
- * CoglVertexP3T2 triangle[] =
- * {
- * { 0, 300, 0, 0.0, 1.0},
- * { 150, 0, 0, 0.5, 0.0},
- * { 300, 300, 0, 1.0, 1.0}
- * };
- * prim = cogl_primitive_new_p3t2 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p3t2 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3T2 *data);
-
-/**
- * cogl_primitive_new_p2t2c4:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP2T2C4 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position, texture
- * coordinate and color attributes with #CoglAttribute<!-- -->s and
- * upload your data.
- *
- * For example to draw a convex polygon with texture mapping and a
- * linear gradient you can do:
- * |[
- * CoglVertexP2T2C4 triangle[] =
- * {
- * { 0, 300, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff},
- * { 150, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff},
- * { 300, 300, 1.0, 1.0, 0xff, 0x00, 0x00, 0xff}
- * };
- * prim = cogl_primitive_new_p2t2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p2t2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP2T2C4 *data);
-
-/**
- * cogl_primitive_new_p3t2c4:
- * @mode: A #CoglVerticesMode defining how to draw the vertices
- * @n_vertices: The number of vertices to process when drawing
- * @data: An array of #CoglVertexP3T2C4 vertices
- *
- * Provides a convenient way to describe a primitive, such as a single
- * triangle strip or a triangle fan, that will internally allocate the
- * necessary #CoglVertexArray storage, describe the position, texture
- * coordinate and color attributes with #CoglAttribute<!-- -->s and
- * upload your data.
- *
- * For example to draw a convex polygon with texture mapping and a
- * linear gradient you can do:
- * |[
- * CoglVertexP3T2C4 triangle[] =
- * {
- * { 0, 300, 0, 0.0, 1.0, 0xff, 0x00, 0x00, 0xff},
- * { 150, 0, 0, 0.5, 0.0, 0x00, 0xff, 0x00, 0xff},
- * { 300, 300, 0, 1.0, 1.0, 0xff, 0x00, 0x00, 0xff}
- * };
- * prim = cogl_primitive_new_p3t2c4 (COGL_VERTICES_MODE_TRIANGLE_FAN,
- * 3, triangle);
- * cogl_primitive_draw (prim);
- * ]|
- *
- * <note>The primitive API doesn't support drawing with sliced
- * textures (since switching between slices implies changing state and
- * so that implies multiple primitives need to be submitted). You
- * should pass the %COGL_TEXTURE_NO_SLICING flag to all textures that
- * might be used while drawing with this API. If your hardware doesn't
- * support non-power of two textures (For example you are using GLES
- * 1.1) then you will need to make sure your assets are resized to a
- * power-of-two size (though they don't have to be square)</note>
- *
- * Return value: A newly allocated #CoglPrimitive with a reference of
- * 1. This can be freed using cogl_object_unref().
- *
- * Since: 1.6
- * Stability: Unstable
- */
-CoglPrimitive *
-cogl_primitive_new_p3t2c4 (CoglVerticesMode mode,
- int n_vertices,
- const CoglVertexP3T2C4 *data);
-int
-cogl_primitive_get_first_vertex (CoglPrimitive *primitive);
-
-void
-cogl_primitive_set_first_vertex (CoglPrimitive *primitive,
- int first_vertex);
-
-int
-cogl_primitive_get_n_vertices (CoglPrimitive *primitive);
-
-void
-cogl_primitive_set_n_vertices (CoglPrimitive *primitive,
- int n_vertices);
-
-CoglVerticesMode
-cogl_primitive_get_mode (CoglPrimitive *primitive);
-
-void
-cogl_primitive_set_mode (CoglPrimitive *primitive,
- CoglVerticesMode mode);
-
-/**
- * cogl_primitive_set_attributes:
- * @primitive: A #CoglPrimitive object
- * @attributes: A %NULL terminated array of #CoglAttribute
- * pointers
- *
- * Replaces all the attributes of the given #CoglPrimitive object.
- *
- * Since: 1.6
- * Stability: Unstable
- */
-void
-cogl_primitive_set_attributes (CoglPrimitive *primitive,
- CoglAttribute **attributes);
-
-
-void
-cogl_primitive_set_indices (CoglPrimitive *primitive,
- CoglIndices *indices);
-
-/**
- * cogl_primitive_draw:
- * @primitive: A #CoglPrimitive object
- *
- * Draw the given @primitive with the current source material.
- *
- * Since: 1.6
- * Stability: Unstable
- */
-void
-cogl_primitive_draw (CoglPrimitive *primitive);
-
-/**
- * cogl_is_primitive:
- * @object: A #CoglObject
- *
- * Gets whether the given object references a #CoglPrimitive.
- *
- * Returns: %TRUE if the handle references a #CoglPrimitive,
- * %FALSE otherwise
- *
- * Since: 1.6
- * Stability: Unstable
- */
-gboolean
-cogl_is_primitive (void *object);
-
-G_END_DECLS
-
-#endif /* __COGL_PRIMITIVE_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PRIMITIVES_PRIVATE_H
-#define __COGL_PRIMITIVES_PRIVATE_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/* Draws a rectangle without going through the journal so that it will
- be flushed immediately. This should only be used in situations
- where the code may be called while the journal is already being
- flushed. In that case using the journal would go wrong */
-void
-_cogl_rectangle_immediate (float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-G_END_DECLS
-
-#endif /* __COGL_PRIMITIVES_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-vertex-buffer-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-attribute-private.h"
-
-#include <string.h>
-#include <math.h>
-
-#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
-
-#ifdef HAVE_COGL_GL
-#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
-#endif
-
-
-typedef struct _TextureSlicedQuadState
-{
- CoglPipeline *pipeline;
- CoglHandle main_texture;
- float tex_virtual_origin_x;
- float tex_virtual_origin_y;
- float quad_origin_x;
- float quad_origin_y;
- float v_to_q_scale_x;
- float v_to_q_scale_y;
- float quad_len_x;
- float quad_len_y;
- gboolean flipped_x;
- gboolean flipped_y;
-} TextureSlicedQuadState;
-
-typedef struct _TextureSlicedPolygonState
-{
- const CoglTextureVertex *vertices;
- int n_vertices;
- int stride;
- CoglAttribute **attributes;
-} TextureSlicedPolygonState;
-
-static void
-log_quad_sub_textures_cb (CoglHandle texture_handle,
- const float *subtexture_coords,
- const float *virtual_coords,
- void *user_data)
-{
- TextureSlicedQuadState *state = user_data;
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglHandle texture_override;
- float quad_coords[4];
-
-#define TEX_VIRTUAL_TO_QUAD(V, Q, AXIS) \
- do { \
- Q = V - state->tex_virtual_origin_##AXIS; \
- Q *= state->v_to_q_scale_##AXIS; \
- if (state->flipped_##AXIS) \
- Q = state->quad_len_##AXIS - Q; \
- Q += state->quad_origin_##AXIS; \
- } while (0);
-
- TEX_VIRTUAL_TO_QUAD (virtual_coords[0], quad_coords[0], x);
- TEX_VIRTUAL_TO_QUAD (virtual_coords[1], quad_coords[1], y);
-
- TEX_VIRTUAL_TO_QUAD (virtual_coords[2], quad_coords[2], x);
- TEX_VIRTUAL_TO_QUAD (virtual_coords[3], quad_coords[3], y);
-
-#undef TEX_VIRTUAL_TO_QUAD
-
- COGL_NOTE (DRAW,
- "~~~~~ slice\n"
- "qx1: %f\t"
- "qy1: %f\n"
- "qx2: %f\t"
- "qy2: %f\n"
- "tx1: %f\t"
- "ty1: %f\n"
- "tx2: %f\t"
- "ty2: %f\n",
- quad_coords[0], quad_coords[1],
- quad_coords[2], quad_coords[3],
- subtexture_coords[0], subtexture_coords[1],
- subtexture_coords[2], subtexture_coords[3]);
-
- /* We only need to override the texture if it's different from the
- main texture */
- if (texture_handle == state->main_texture)
- texture_override = COGL_INVALID_HANDLE;
- else
- texture_override = texture_handle;
-
- _cogl_journal_log_quad (framebuffer->journal,
- quad_coords,
- state->pipeline,
- 1, /* one layer */
- texture_override, /* replace the layer0 texture */
- subtexture_coords,
- 4);
-}
-
-typedef struct _ValidateFirstLayerState
-{
- CoglPipeline *override_pipeline;
-} ValidateFirstLayerState;
-
-static gboolean
-validate_first_layer_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- ValidateFirstLayerState *state = user_data;
- CoglPipelineWrapMode clamp_to_edge =
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
-
- /* We can't use hardware repeat so we need to set clamp to edge
- * otherwise it might pull in edge pixels from the other side. By
- * default WRAP_MODE_AUTOMATIC becomes CLAMP_TO_EDGE so we only need
- * to override if the wrap mode is repeat.
- */
- if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_REPEAT)
- {
- if (!state->override_pipeline)
- state->override_pipeline = cogl_pipeline_copy (pipeline);
- cogl_pipeline_set_layer_wrap_mode_s (pipeline, layer_index,
- clamp_to_edge);
- }
- if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_REPEAT)
- {
- if (!state->override_pipeline)
- state->override_pipeline = cogl_pipeline_copy (pipeline);
- cogl_pipeline_set_layer_wrap_mode_t (pipeline, layer_index,
- clamp_to_edge);
- }
-
- return FALSE;
-}
-
-/* This path doesn't currently support multitexturing but is used for
- * CoglTextures that don't support repeating using the GPU so we need to
- * manually emit extra geometry to fake the repeating. This includes:
- *
- * - CoglTexture2DSliced: when made of > 1 slice or if the users given
- * texture coordinates require repeating,
- * - CoglTexture2DAtlas: if the users given texture coordinates require
- * repeating,
- * - CoglTextureRectangle: if the users given texture coordinates require
- * repeating,
- * - CoglTexturePixmap: if the users given texture coordinates require
- * repeating
- */
-/* TODO: support multitexturing */
-static void
-_cogl_texture_quad_multiple_primitives (CoglHandle tex_handle,
- CoglPipeline *pipeline,
- gboolean clamp_s,
- gboolean clamp_t,
- const float *position,
- float tx_1,
- float ty_1,
- float tx_2,
- float ty_2)
-{
- TextureSlicedQuadState state;
- gboolean tex_virtual_flipped_x;
- gboolean tex_virtual_flipped_y;
- gboolean quad_flipped_x;
- gboolean quad_flipped_y;
- ValidateFirstLayerState validate_first_layer_state;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* If the wrap mode is clamp to edge then we'll recursively draw the
- stretched part and replace the coordinates */
- if (clamp_s && tx_1 != tx_2)
- {
- float *replacement_position = g_newa (float, 4);
- float old_tx_1 = tx_1, old_tx_2 = tx_2;
-
- memcpy (replacement_position, position, sizeof (float) * 4);
-
- tx_1 = CLAMP (tx_1, 0.0f, 1.0f);
- tx_2 = CLAMP (tx_2, 0.0f, 1.0f);
-
- if (old_tx_1 != tx_1)
- {
- /* Draw the left part of the quad as a stretched copy of tx_1 */
- float tmp_position[] =
- { position[0], position[1],
- (position[0] +
- (position[2] - position[0]) *
- (tx_1 - old_tx_1) / (old_tx_2 - old_tx_1)),
- position[3] };
- _cogl_texture_quad_multiple_primitives (tex_handle, pipeline,
- FALSE, clamp_t,
- tmp_position,
- tx_1, ty_1, tx_1, ty_2);
- replacement_position[0] = tmp_position[2];
- }
-
- if (old_tx_2 != tx_2)
- {
- /* Draw the right part of the quad as a stretched copy of tx_2 */
- float tmp_position[] =
- { (position[0] +
- (position[2] - position[0]) *
- (tx_2 - old_tx_1) / (old_tx_2 - old_tx_1)),
- position[1], position[2], position[3] };
- _cogl_texture_quad_multiple_primitives (tex_handle, pipeline,
- FALSE, clamp_t,
- tmp_position,
- tx_2, ty_1, tx_2, ty_2);
- replacement_position[2] = tmp_position[0];
- }
-
- /* If there's no main part left then we don't need to continue */
- if (tx_1 == tx_2)
- return;
-
- position = replacement_position;
- }
-
- if (clamp_t && ty_1 != ty_2)
- {
- float *replacement_position = g_newa (float, 4);
- float old_ty_1 = ty_1, old_ty_2 = ty_2;
-
- memcpy (replacement_position, position, sizeof (float) * 4);
-
- ty_1 = CLAMP (ty_1, 0.0f, 1.0f);
- ty_2 = CLAMP (ty_2, 0.0f, 1.0f);
-
- if (old_ty_1 != ty_1)
- {
- /* Draw the top part of the quad as a stretched copy of ty_1 */
- float tmp_position[] =
- { position[0], position[1], position[2],
- (position[1] +
- (position[3] - position[1]) *
- (ty_1 - old_ty_1) / (old_ty_2 - old_ty_1)) };
- _cogl_texture_quad_multiple_primitives (tex_handle, pipeline,
- clamp_s, FALSE,
- tmp_position,
- tx_1, ty_1, tx_2, ty_1);
- replacement_position[1] = tmp_position[3];
- }
-
- if (old_ty_2 != ty_2)
- {
- /* Draw the bottom part of the quad as a stretched copy of ty_2 */
- float tmp_position[] =
- { position[0],
- (position[1] +
- (position[3] - position[1]) *
- (ty_2 - old_ty_1) / (old_ty_2 - old_ty_1)),
- position[2], position[3] };
- _cogl_texture_quad_multiple_primitives (tex_handle, pipeline,
- clamp_s, FALSE,
- tmp_position,
- tx_1, ty_2, tx_2, ty_2);
- replacement_position[3] = tmp_position[1];
- }
-
- /* If there's no main part left then we don't need to continue */
- if (ty_1 == ty_2)
- return;
-
- position = replacement_position;
- }
-
- validate_first_layer_state.override_pipeline = NULL;
- cogl_pipeline_foreach_layer (pipeline,
- validate_first_layer_cb,
- &validate_first_layer_state);
-
- state.main_texture = tex_handle;
-
- if (validate_first_layer_state.override_pipeline)
- state.pipeline = validate_first_layer_state.override_pipeline;
- else
- state.pipeline = pipeline;
-
- /* Get together the data we need to transform the virtual texture
- * coordinates of each slice into quad coordinates...
- *
- * NB: We need to consider that the quad coordinates and the texture
- * coordinates may be inverted along the x or y axis, and must preserve the
- * inversions when we emit the final geometry.
- */
-
-#define X0 0
-#define Y0 1
-#define X1 2
-#define Y1 3
-
- tex_virtual_flipped_x = (tx_1 > tx_2) ? TRUE : FALSE;
- tex_virtual_flipped_y = (ty_1 > ty_2) ? TRUE : FALSE;
- state.tex_virtual_origin_x = tex_virtual_flipped_x ? tx_2 : tx_1;
- state.tex_virtual_origin_y = tex_virtual_flipped_y ? ty_2 : ty_1;
-
- quad_flipped_x = (position[X0] > position[X1]) ? TRUE : FALSE;
- quad_flipped_y = (position[Y0] > position[Y1]) ? TRUE : FALSE;
- state.quad_origin_x = quad_flipped_x ? position[X1] : position[X0];
- state.quad_origin_y = quad_flipped_y ? position[Y1] : position[Y0];
-
- /* flatten the two forms of coordinate inversion into one... */
- state.flipped_x = tex_virtual_flipped_x ^ quad_flipped_x;
- state.flipped_y = tex_virtual_flipped_y ^ quad_flipped_y;
-
- /* We use the _len_AXIS naming here instead of _width and _height because
- * log_quad_slice_cb uses a macro with symbol concatenation to handle both
- * axis, so this is more convenient... */
- state.quad_len_x = fabs (position[X1] - position[X0]);
- state.quad_len_y = fabs (position[Y1] - position[Y0]);
-
-#undef X0
-#undef Y0
-#undef X1
-#undef Y1
-
- state.v_to_q_scale_x = fabs (state.quad_len_x / (tx_2 - tx_1));
- state.v_to_q_scale_y = fabs (state.quad_len_y / (ty_2 - ty_1));
-
- _cogl_texture_foreach_sub_texture_in_region (tex_handle,
- tx_1, ty_1, tx_2, ty_2,
- log_quad_sub_textures_cb,
- &state);
-
- if (validate_first_layer_state.override_pipeline)
- cogl_object_unref (validate_first_layer_state.override_pipeline);
-}
-
-typedef struct _ValidateTexCoordsState
-{
- int i;
- int n_layers;
- const float *user_tex_coords;
- int user_tex_coords_len;
- float *final_tex_coords;
- CoglPipeline *override_pipeline;
- gboolean needs_multiple_primitives;
-} ValidateTexCoordsState;
-
-/*
- * Validate the texture coordinates for this rectangle.
- */
-static gboolean
-validate_tex_coords_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- ValidateTexCoordsState *state = user_data;
- CoglHandle texture;
- const float *in_tex_coords;
- float *out_tex_coords;
- float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
- CoglTransformResult transform_result;
-
- state->i++;
-
- texture = _cogl_pipeline_get_layer_texture (pipeline, layer_index);
-
- /* NB: NULL textures are handled by _cogl_pipeline_flush_gl_state */
- if (!texture)
- return TRUE;
-
- /* FIXME: we should be able to avoid this copying when no
- * transform is required by the texture backend and the user
- * has supplied enough coordinates for all the layers.
- */
-
- /* If the user didn't supply texture coordinates for this layer
- then use the default coords */
- if (state->i >= state->user_tex_coords_len / 4)
- in_tex_coords = default_tex_coords;
- else
- in_tex_coords = &state->user_tex_coords[state->i * 4];
-
- out_tex_coords = &state->final_tex_coords[state->i * 4];
-
- memcpy (out_tex_coords, in_tex_coords, sizeof (float) * 4);
-
- /* Convert the texture coordinates to GL.
- */
- transform_result =
- _cogl_texture_transform_quad_coords_to_gl (texture,
- out_tex_coords);
- /* If the texture has waste or we are using GL_TEXTURE_RECT we
- * can't handle texture repeating so we can't use the layer if
- * repeating is required.
- *
- * NB: We already know that no texture matrix is being used if the
- * texture doesn't support hardware repeat.
- */
- if (transform_result == COGL_TRANSFORM_SOFTWARE_REPEAT)
- {
- if (state->i == 0)
- {
- if (state->n_layers > 1)
- {
- static gboolean warning_seen = FALSE;
- if (!warning_seen)
- g_warning ("Skipping layers 1..n of your material since "
- "the first layer doesn't support hardware "
- "repeat (e.g. because of waste or use of "
- "GL_TEXTURE_RECTANGLE_ARB) and you supplied "
- "texture coordinates outside the range [0,1]."
- "Falling back to software repeat assuming "
- "layer 0 is the most important one keep");
- warning_seen = TRUE;
- }
-
- if (state->override_pipeline)
- cogl_object_unref (state->override_pipeline);
- state->needs_multiple_primitives = TRUE;
- return FALSE;
- }
- else
- {
- static gboolean warning_seen = FALSE;
- if (!warning_seen)
- g_warning ("Skipping layer %d of your material "
- "since you have supplied texture coords "
- "outside the range [0,1] but the texture "
- "doesn't support hardware repeat (e.g. "
- "because of waste or use of "
- "GL_TEXTURE_RECTANGLE_ARB). This isn't "
- "supported with multi-texturing.", state->i);
- warning_seen = TRUE;
-
- cogl_pipeline_set_layer_texture (texture, layer_index, NULL);
- }
- }
-
- /* By default WRAP_MODE_AUTOMATIC becomes to CLAMP_TO_EDGE. If
- the texture coordinates need repeating then we'll override
- this to GL_REPEAT. Otherwise we'll leave it at CLAMP_TO_EDGE
- so that it won't blend in pixels from the opposite side when
- the full texture is drawn with GL_LINEAR filter mode */
- if (transform_result == COGL_TRANSFORM_HARDWARE_REPEAT)
- {
- if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- if (!state->override_pipeline)
- state->override_pipeline = cogl_pipeline_copy (pipeline);
- cogl_pipeline_set_layer_wrap_mode_s (state->override_pipeline,
- layer_index,
- COGL_PIPELINE_WRAP_MODE_REPEAT);
- }
- if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- if (!state->override_pipeline)
- state->override_pipeline = cogl_pipeline_copy (pipeline);
- cogl_pipeline_set_layer_wrap_mode_t (state->override_pipeline,
- layer_index,
- COGL_PIPELINE_WRAP_MODE_REPEAT);
- }
- }
-
- return TRUE;
-}
-
-/* This path supports multitexturing but only when each of the layers is
- * handled with a single GL texture. Also if repeating is necessary then
- * _cogl_texture_can_hardware_repeat() must return TRUE.
- * This includes layers made from:
- *
- * - CoglTexture2DSliced: if only comprised of a single slice with optional
- * waste, assuming the users given texture coordinates don't require
- * repeating.
- * - CoglTexture{1D,2D,3D}: always.
- * - CoglTexture2DAtlas: assuming the users given texture coordinates don't
- * require repeating.
- * - CoglTextureRectangle: assuming the users given texture coordinates don't
- * require repeating.
- * - CoglTexturePixmap: assuming the users given texture coordinates don't
- * require repeating.
- */
-static gboolean
-_cogl_multitexture_quad_single_primitive (const float *position,
- CoglPipeline *pipeline,
- const float *user_tex_coords,
- int user_tex_coords_len)
-{
- int n_layers = cogl_pipeline_get_n_layers (pipeline);
- ValidateTexCoordsState state;
- float *final_tex_coords = alloca (sizeof (float) * 4 * n_layers);
- CoglFramebuffer *framebuffer;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- state.i = -1;
- state.n_layers = n_layers;
- state.user_tex_coords = user_tex_coords;
- state.user_tex_coords_len = user_tex_coords_len;
- state.final_tex_coords = final_tex_coords;
- state.override_pipeline = NULL;
- state.needs_multiple_primitives = FALSE;
-
- cogl_pipeline_foreach_layer (pipeline,
- validate_tex_coords_cb,
- &state);
-
- if (state.needs_multiple_primitives)
- return FALSE;
-
- if (state.override_pipeline)
- pipeline = state.override_pipeline;
-
- framebuffer = cogl_get_draw_framebuffer ();
- _cogl_journal_log_quad (framebuffer->journal,
- position,
- pipeline,
- n_layers,
- COGL_INVALID_HANDLE, /* no texture override */
- final_tex_coords,
- n_layers * 4);
-
- if (state.override_pipeline)
- cogl_object_unref (state.override_pipeline);
-
- return TRUE;
-}
-
-typedef struct _ValidateLayerState
-{
- int i;
- int first_layer;
- CoglPipeline *override_source;
- gboolean all_use_sliced_quad_fallback;
-} ValidateLayerState;
-
-static gboolean
-_cogl_rectangles_validate_layer_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- ValidateLayerState *state = user_data;
- CoglHandle texture;
-
- state->i++;
-
- /* We need to ensure the mipmaps are ready before deciding
- * anything else about the texture because the texture storage
- * could completely change if it needs to be migrated out of the
- * atlas and will affect how we validate the layer.
- *
- * FIXME: this needs to be generalized. There could be any
- * number of things that might require a shuffling of the
- * underlying texture storage. We could add two mechanisms to
- * generalize this a bit...
- *
- * 1) add a _cogl_pipeline_layer_update_storage() function that
- * would for instance consider if mipmapping is necessary and
- * potentially migrate the texture from an atlas.
- *
- * 2) allow setting of transient primitive-flags on a pipeline
- * that may affect the outcome of _update_storage(). One flag
- * could indicate that we expect to sample beyond the bounds of
- * the texture border.
- *
- * flags = COGL_PIPELINE_PRIMITIVE_FLAG_VALID_BORDERS;
- * _cogl_pipeline_layer_assert_primitive_flags (layer, flags)
- * _cogl_pipeline_layer_update_storage (layer)
- * enqueue primitive in journal
- *
- * when the primitive is dequeued and drawn we should:
- * _cogl_pipeline_flush_gl_state (pipeline)
- * draw primitive
- * _cogl_pipeline_unassert_primitive_flags (layer, flags);
- *
- * _cogl_pipeline_layer_update_storage should take into
- * consideration all the asserted primitive requirements. (E.g.
- * there could be multiple primitives in the journal - or in a
- * renderlist in the future - that need mipmaps or that need
- * valid contents beyond their borders (for cogl_polygon)
- * meaning they can't work with textures in an atas, so
- * _cogl_pipeline_layer_update_storage would pass on these
- * requirements to the texture atlas backend which would make
- * sure the referenced texture is migrated out of the atlas and
- * mipmaps are generated.)
- */
- _cogl_pipeline_pre_paint_for_layer (pipeline, layer_index);
-
- texture = _cogl_pipeline_get_layer_texture (pipeline, layer_index);
-
- /* COGL_INVALID_HANDLE textures are handled by
- * _cogl_pipeline_flush_gl_state */
- if (texture == COGL_INVALID_HANDLE)
- return TRUE;
-
- if (state->i == 0)
- state->first_layer = layer_index;
-
- /* XXX:
- * For now, if the first layer is sliced then all other layers are
- * ignored since we currently don't support multi-texturing with
- * sliced textures. If the first layer is not sliced then any other
- * layers found to be sliced will be skipped. (with a warning)
- *
- * TODO: Add support for multi-texturing rectangles with sliced
- * textures if no texture matrices are in use.
- */
- if (cogl_texture_is_sliced (texture))
- {
- if (state->i == 0)
- {
- static gboolean warning_seen = FALSE;
-
- if (!state->override_source)
- state->override_source = cogl_pipeline_copy (pipeline);
- _cogl_pipeline_prune_to_n_layers (state->override_source, 1);
- state->all_use_sliced_quad_fallback = TRUE;
-
- if (!warning_seen)
- g_warning ("Skipping layers 1..n of your pipeline since "
- "the first layer is sliced. We don't currently "
- "support any multi-texturing with sliced "
- "textures but assume layer 0 is the most "
- "important to keep");
- warning_seen = TRUE;
-
- return FALSE;
- }
- else
- {
- static gboolean warning_seen = FALSE;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!warning_seen)
- g_warning ("Skipping layer %d of your pipeline consisting of "
- "a sliced texture (unsuported for multi texturing)",
- state->i);
- warning_seen = TRUE;
-
- /* Note: currently only 2D textures can be sliced. */
- cogl_pipeline_set_layer_texture (pipeline, layer_index,
- ctx->default_gl_texture_2d_tex);
- return TRUE;
- }
- }
-
-#ifdef COGL_ENABLE_DEBUG
- /* If the texture can't be repeated with the GPU (e.g. because it has
- * waste or if using GL_TEXTURE_RECTANGLE_ARB) then if a texture matrix
- * is also in use we don't know if the result will end up trying
- * to texture from the waste area.
- *
- * Note: we check can_hardware_repeat() first since it's cheaper.
- *
- * Note: cases where the texture coordinates will require repeating
- * will be caught by later validation.
- */
- if (!_cogl_texture_can_hardware_repeat (texture) &&
- _cogl_pipeline_layer_has_user_matrix (pipeline, layer_index))
- {
- static gboolean warning_seen = FALSE;
- if (!warning_seen)
- g_warning ("layer %d of your pipeline uses a custom "
- "texture matrix but because the texture doesn't "
- "support hardware repeating you may see artefacts "
- "due to sampling beyond the texture's bounds.",
- state->i);
- warning_seen = TRUE;
- }
-#endif
-
- return TRUE;
-}
-
-struct _CoglMutiTexturedRect
-{
- const float *position; /* x0,y0,x1,y1 */
- const float *tex_coords; /* (tx0,ty0,tx1,ty1)(tx0,ty0,tx1,ty1)(... */
- int tex_coords_len; /* number of floats in tex_coords? */
-};
-
-static void
-_cogl_rectangles_with_multitexture_coords (
- struct _CoglMutiTexturedRect *rects,
- int n_rects)
-{
- CoglPipeline *pipeline;
- ValidateLayerState state;
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- pipeline = cogl_get_source ();
-
- /*
- * Validate all the layers of the current source pipeline...
- */
- state.i = -1;
- state.first_layer = 0;
- state.override_source = NULL;
- state.all_use_sliced_quad_fallback = FALSE;
- cogl_pipeline_foreach_layer (pipeline,
- _cogl_rectangles_validate_layer_cb,
- &state);
-
- if (state.override_source)
- pipeline = state.override_source;
-
- /*
- * Emit geometry for each of the rectangles...
- */
-
- for (i = 0; i < n_rects; i++)
- {
- CoglHandle texture;
- const float default_tex_coords[4] = {0.0, 0.0, 1.0, 1.0};
- const float *tex_coords;
- gboolean clamp_s, clamp_t;
-
- if (!state.all_use_sliced_quad_fallback)
- {
- gboolean success =
- _cogl_multitexture_quad_single_primitive (rects[i].position,
- pipeline,
- rects[i].tex_coords,
- rects[i].tex_coords_len);
-
- /* NB: If _cogl_multitexture_quad_single_primitive fails then it
- * means the user tried to use texture repeat with a texture that
- * can't be repeated by the GPU (e.g. due to waste or use of
- * GL_TEXTURE_RECTANGLE_ARB) */
- if (success)
- continue;
- }
-
- /* If multitexturing failed or we are drawing with a sliced texture
- * then we only support a single layer so we pluck out the texture
- * from the first pipeline layer... */
- texture = _cogl_pipeline_get_layer_texture (pipeline, state.first_layer);
-
- if (rects[i].tex_coords)
- tex_coords = rects[i].tex_coords;
- else
- tex_coords = default_tex_coords;
-
- clamp_s = (cogl_pipeline_get_layer_wrap_mode_s (pipeline,
- state.first_layer) ==
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
- clamp_t = (cogl_pipeline_get_layer_wrap_mode_t (pipeline,
- state.first_layer) ==
- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-
- COGL_NOTE (DRAW, "Drawing Tex Quad (Multi-Prim Mode)");
-
- _cogl_texture_quad_multiple_primitives (texture,
- pipeline,
- clamp_s, clamp_t,
- rects[i].position,
- tex_coords[0],
- tex_coords[1],
- tex_coords[2],
- tex_coords[3]);
- }
-
- if (state.override_source)
- cogl_object_unref (pipeline);
-}
-
-void
-cogl_rectangles (const float *verts,
- unsigned int n_rects)
-{
- struct _CoglMutiTexturedRect *rects;
- int i;
-
- /* XXX: All the cogl_rectangle* APIs normalize their input into an array of
- * _CoglMutiTexturedRect rectangles and pass these on to our work horse;
- * _cogl_rectangles_with_multitexture_coords.
- */
-
- rects = g_alloca (n_rects * sizeof (struct _CoglMutiTexturedRect));
-
- for (i = 0; i < n_rects; i++)
- {
- rects[i].position = &verts[i * 4];
- rects[i].tex_coords = NULL;
- rects[i].tex_coords_len = 0;
- }
-
- _cogl_rectangles_with_multitexture_coords (rects, n_rects);
-}
-
-void
-cogl_rectangles_with_texture_coords (const float *verts,
- unsigned int n_rects)
-{
- struct _CoglMutiTexturedRect *rects;
- int i;
-
- /* XXX: All the cogl_rectangle* APIs normalize their input into an array of
- * _CoglMutiTexturedRect rectangles and pass these on to our work horse;
- * _cogl_rectangles_with_multitexture_coords.
- */
-
- rects = g_alloca (n_rects * sizeof (struct _CoglMutiTexturedRect));
-
- for (i = 0; i < n_rects; i++)
- {
- rects[i].position = &verts[i * 8];
- rects[i].tex_coords = &verts[i * 8 + 4];
- rects[i].tex_coords_len = 4;
- }
-
- _cogl_rectangles_with_multitexture_coords (rects, n_rects);
-}
-
-void
-cogl_rectangle_with_texture_coords (float x_1,
- float y_1,
- float x_2,
- float y_2,
- float tx_1,
- float ty_1,
- float tx_2,
- float ty_2)
-{
- const float position[4] = {x_1, y_1, x_2, y_2};
- const float tex_coords[4] = {tx_1, ty_1, tx_2, ty_2};
- struct _CoglMutiTexturedRect rect;
-
- /* XXX: All the cogl_rectangle* APIs normalize their input into an array of
- * _CoglMutiTexturedRect rectangles and pass these on to our work horse;
- * _cogl_rectangles_with_multitexture_coords.
- */
-
- rect.position = position;
- rect.tex_coords = tex_coords;
- rect.tex_coords_len = 4;
-
- _cogl_rectangles_with_multitexture_coords (&rect, 1);
-}
-
-void
-cogl_rectangle_with_multitexture_coords (float x_1,
- float y_1,
- float x_2,
- float y_2,
- const float *user_tex_coords,
- int user_tex_coords_len)
-{
- const float position[4] = {x_1, y_1, x_2, y_2};
- struct _CoglMutiTexturedRect rect;
-
- /* XXX: All the cogl_rectangle* APIs normalize their input into an array of
- * _CoglMutiTexturedRect rectangles and pass these on to our work horse;
- * _cogl_rectangles_with_multitexture_coords.
- */
-
- rect.position = position;
- rect.tex_coords = user_tex_coords;
- rect.tex_coords_len = user_tex_coords_len;
-
- _cogl_rectangles_with_multitexture_coords (&rect, 1);
-}
-
-void
-cogl_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- const float position[4] = {x_1, y_1, x_2, y_2};
- struct _CoglMutiTexturedRect rect;
-
- /* XXX: All the cogl_rectangle* APIs normalize their input into an array of
- * _CoglMutiTexturedRect rectangles and pass these on to our work horse;
- * _cogl_rectangles_with_multitexture_coords.
- */
-
- rect.position = position;
- rect.tex_coords = NULL;
- rect.tex_coords_len = 0;
-
- _cogl_rectangles_with_multitexture_coords (&rect, 1);
-}
-
-void
-_cogl_rectangle_immediate (float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- /* Draw a rectangle using the vertex array API to avoid going
- through the journal. This should only be used in cases where the
- code might be called while the journal is already being flushed
- such as when flushing the clip state */
- float vertices[8] =
- {
- x_1, y_1,
- x_1, y_2,
- x_2, y_1,
- x_2, y_2
- };
- CoglVertexArray *vertex_array;
- CoglAttribute *attributes[2];
-
- vertex_array = cogl_vertex_array_new (sizeof (vertices), vertices);
- attributes[0] = cogl_attribute_new (vertex_array,
- "cogl_position_in",
- sizeof (float) * 2, /* stride */
- 0, /* offset */
- 2, /* n_components */
- COGL_ATTRIBUTE_TYPE_FLOAT);
- attributes[1] = NULL;
-
- _cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_STRIP,
- 0, /* first_index */
- 4, /* n_vertices */
- attributes,
- COGL_DRAW_SKIP_JOURNAL_FLUSH |
- COGL_DRAW_SKIP_PIPELINE_VALIDATION |
- COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
-
-
- cogl_object_unref (attributes[0]);
- cogl_object_unref (vertex_array);
-}
-
-typedef struct _AppendTexCoordsState
-{
- const CoglTextureVertex *vertices_in;
- int vertex;
- int layer;
- float *vertices_out;
-} AppendTexCoordsState;
-
-gboolean
-append_tex_coord_attributes_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- AppendTexCoordsState *state = user_data;
- CoglHandle tex_handle;
- float tx, ty;
- float *t;
-
- tx = state->vertices_in[state->vertex].tx;
- ty = state->vertices_in[state->vertex].ty;
-
- /* COGL_INVALID_HANDLE textures will be handled in
- * _cogl_pipeline_flush_layers_gl_state but there is no need to worry
- * about scaling texture coordinates in this case */
- tex_handle = _cogl_pipeline_get_layer_texture (pipeline, layer_index);
- if (tex_handle != COGL_INVALID_HANDLE)
- _cogl_texture_transform_coords_to_gl (tex_handle, &tx, &ty);
-
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- t = state->vertices_out + 3 + 2 * state->layer;
- t[0] = tx;
- t[1] = ty;
-
- state->layer++;
-
- return TRUE;
-}
-
-typedef struct _ValidateState
-{
- CoglPipeline *original_pipeline;
- CoglPipeline *pipeline;
-} ValidateState;
-
-static gboolean
-_cogl_polygon_validate_layer_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- ValidateState *state = user_data;
-
- /* By default COGL_PIPELINE_WRAP_MODE_AUTOMATIC becomes
- * GL_CLAMP_TO_EDGE but we want the polygon API to use GL_REPEAT to
- * maintain compatibility with previous releases
- */
-
- if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- if (state->original_pipeline == state->pipeline)
- state->pipeline = cogl_pipeline_copy (pipeline);
-
- cogl_pipeline_set_layer_wrap_mode_s (state->pipeline, layer_index,
- COGL_PIPELINE_WRAP_MODE_REPEAT);
- }
-
- if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) ==
- COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- if (state->original_pipeline == state->pipeline)
- state->pipeline = cogl_pipeline_copy (pipeline);
-
- cogl_pipeline_set_layer_wrap_mode_t (state->pipeline, layer_index,
- COGL_PIPELINE_WRAP_MODE_REPEAT);
- }
-
- return TRUE;
-}
-
-void
-cogl_polygon (const CoglTextureVertex *vertices,
- unsigned int n_vertices,
- gboolean use_color)
-{
- CoglPipeline *pipeline;
- ValidateState validate_state;
- int n_layers;
- int n_attributes;
- CoglAttribute **attributes;
- int i;
- unsigned int stride;
- gsize stride_bytes;
- CoglVertexArray *vertex_array;
- float *v;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- pipeline = cogl_get_source ();
-
- validate_state.original_pipeline = pipeline;
- validate_state.pipeline = pipeline;
- cogl_pipeline_foreach_layer (pipeline,
- _cogl_polygon_validate_layer_cb,
- &validate_state);
- pipeline = validate_state.pipeline;
-
- n_layers = cogl_pipeline_get_n_layers (pipeline);
-
- n_attributes = 1 + n_layers + (use_color ? 1 : 0);
- attributes = g_alloca (sizeof (CoglAttribute *) * (n_attributes + 1));
- attributes[n_attributes] = NULL;
-
- /* Our data is arranged like:
- * [X, Y, Z, TX0, TY0, TX1, TY1..., R, G, B, A,...] */
- stride = 3 + (2 * n_layers) + (use_color ? 1 : 0);
- stride_bytes = stride * sizeof (float);
-
- /* Make sure there is enough space in the global vertex array. This
- * is used so we can render the polygon with a single call to OpenGL
- * but still support any number of vertices */
- g_array_set_size (ctx->polygon_vertices, n_vertices * stride);
-
- vertex_array = cogl_vertex_array_new (n_vertices * stride_bytes, NULL);
-
- attributes[0] = cogl_attribute_new (vertex_array,
- "cogl_position_in",
- stride_bytes,
- 0,
- 3,
- COGL_ATTRIBUTE_TYPE_FLOAT);
-
- for (i = 0; i < n_layers; i++)
- {
- const char *names[] = {
- "cogl_tex_coord0_in",
- "cogl_tex_coord1_in",
- "cogl_tex_coord2_in",
- "cogl_tex_coord3_in",
- "cogl_tex_coord4_in",
- "cogl_tex_coord5_in",
- "cogl_tex_coord6_in",
- "cogl_tex_coord7_in"
- };
- char *name = i < 8 ? (char *)names[i] :
- g_strdup_printf ("cogl_tex_coord%d_in", i);
-
- attributes[i + 1] = cogl_attribute_new (vertex_array,
- name,
- stride_bytes,
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- 12 + 8 * i,
- 2,
- COGL_ATTRIBUTE_TYPE_FLOAT);
- }
-
- if (use_color)
- {
- attributes[n_attributes - 1] =
- cogl_attribute_new (vertex_array,
- "cogl_color_in",
- stride_bytes,
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- 12 + 8 * n_layers,
- 4,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
- }
-
- /* Convert the vertices into an array of float vertex attributes */
- v = (float *)ctx->polygon_vertices->data;
- for (i = 0; i < n_vertices; i++)
- {
- AppendTexCoordsState append_tex_coords_state;
- guint8 *c;
-
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- v[0] = vertices[i].x;
- v[1] = vertices[i].y;
- v[2] = vertices[i].z;
-
- append_tex_coords_state.vertices_in = vertices;
- append_tex_coords_state.vertex = i;
- append_tex_coords_state.layer = 0;
- append_tex_coords_state.vertices_out = v;
- cogl_pipeline_foreach_layer (pipeline,
- append_tex_coord_attributes_cb,
- &append_tex_coords_state);
-
- if (use_color)
- {
- /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
- c = (guint8 *) (v + 3 + 2 * n_layers);
- c[0] = cogl_color_get_red_byte (&vertices[i].color);
- c[1] = cogl_color_get_green_byte (&vertices[i].color);
- c[2] = cogl_color_get_blue_byte (&vertices[i].color);
- c[3] = cogl_color_get_alpha_byte (&vertices[i].color);
- }
-
- v += stride;
- }
-
- v = (float *)ctx->polygon_vertices->data;
- cogl_buffer_set_data (COGL_BUFFER (vertex_array),
- 0,
- v,
- ctx->polygon_vertices->len * sizeof (float));
-
- cogl_push_source (pipeline);
-
- cogl_draw_attributes_array (COGL_VERTICES_MODE_TRIANGLE_FAN,
- 0, n_vertices,
- attributes);
-
- cogl_pop_source ();
-
- if (pipeline != validate_state.original_pipeline)
- cogl_object_unref (pipeline);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PRIMITIVES_H
-#define __COGL_PRIMITIVES_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-primitives
- * @short_description: Functions that draw various primitive 3D shapes
- *
- * The primitives API provides utilities for drawing some
- * common 3D shapes in a more convenient way than the CoglVertexBuffer
- * API provides.
- */
-
-/**
- * cogl_rectangle:
- * @x_1: X coordinate of the top-left corner
- * @y_1: Y coordinate of the top-left corner
- * @x_2: X coordinate of the bottom-right corner
- * @y_2: Y coordinate of the bottom-right corner
- *
- * Fills a rectangle at the given coordinates with the current source material
- **/
-void
-cogl_rectangle (float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-/**
- * cogl_rectangle_with_texture_coords:
- * @x1: x coordinate upper left on screen.
- * @y1: y coordinate upper left on screen.
- * @x2: x coordinate lower right on screen.
- * @y2: y coordinate lower right on screen.
- * @tx1: x part of texture coordinate to use for upper left pixel
- * @ty1: y part of texture coordinate to use for upper left pixel
- * @tx2: x part of texture coordinate to use for lower right pixel
- * @ty2: y part of texture coordinate to use for left pixel
- *
- * Draw a rectangle using the current material and supply texture coordinates
- * to be used for the first texture layer of the material. To draw the entire
- * texture pass in @tx1=0.0 @ty1=0.0 @tx2=1.0 @ty2=1.0.
- *
- * Since: 1.0
- */
-void
-cogl_rectangle_with_texture_coords (float x1,
- float y1,
- float x2,
- float y2,
- float tx1,
- float ty1,
- float tx2,
- float ty2);
-
-/**
- * cogl_rectangle_with_multitexture_coords:
- * @x1: x coordinate upper left on screen.
- * @y1: y coordinate upper left on screen.
- * @x2: x coordinate lower right on screen.
- * @y2: y coordinate lower right on screen.
- * @tex_coords: (in) (array) (transfer none): An array containing groups of
- * 4 float values: [tx1, ty1, tx2, ty2] that are interpreted as two texture
- * coordinates; one for the upper left texel, and one for the lower right
- * texel. Each value should be between 0.0 and 1.0, where the coordinate
- * (0.0, 0.0) represents the top left of the texture, and (1.0, 1.0) the
- * bottom right.
- * @tex_coords_len: The length of the tex_coords array. (e.g. for one layer
- * and one group of texture coordinates, this would be 4)
- *
- * This function draws a rectangle using the current source material to
- * texture or fill with. As a material may contain multiple texture layers
- * this interface lets you supply texture coordinates for each layer of the
- * material.
- *
- * The first pair of coordinates are for the first layer (with the smallest
- * layer index) and if you supply less texture coordinates than there are
- * layers in the current source material then default texture coordinates
- * (0.0, 0.0, 1.0, 1.0) are generated.
- *
- * Since: 1.0
- */
-void
-cogl_rectangle_with_multitexture_coords (float x1,
- float y1,
- float x2,
- float y2,
- const float *tex_coords,
- int tex_coords_len);
-
-/**
- * cogl_rectangles_with_texture_coords:
- * @verts: (in) (array) (transfer none): an array of vertices
- * @n_rects: number of rectangles to draw
- *
- * Draws a series of rectangles in the same way that
- * cogl_rectangle_with_texture_coords() does. In some situations it can give a
- * significant performance boost to use this function rather than
- * calling cogl_rectangle_with_texture_coords() separately for each rectangle.
- *
- * @verts should point to an array of #float<!-- -->s with
- * @n_rects * 8 elements. Each group of 8 values corresponds to the
- * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same
- * meaning as in cogl_rectangle_with_texture_coords().
- *
- * Since: 0.8.6
- */
-void
-cogl_rectangles_with_texture_coords (const float *verts,
- unsigned int n_rects);
-
-/**
- * cogl_rectangles:
- * @verts: (in) (array) (transfer none): an array of vertices
- * @n_rects: number of rectangles to draw
- *
- * Draws a series of rectangles in the same way that
- * cogl_rectangle() does. In some situations it can give a
- * significant performance boost to use this function rather than
- * calling cogl_rectangle() separately for each rectangle.
- *
- * @verts should point to an array of #float<!-- -->s with
- * @n_rects * 4 elements. Each group of 4 values corresponds to the
- * parameters x1, y1, x2, and y2, and have the same
- * meaning as in cogl_rectangle().
- *
- * Since: 1.0
- */
-void
-cogl_rectangles (const float *verts,
- unsigned int n_rects);
-
-/**
- * cogl_polygon:
- * @vertices: An array of #CoglTextureVertex structs
- * @n_vertices: The length of the vertices array
- * @use_color: %TRUE if the color member of #CoglTextureVertex should be used
- *
- * Draws a convex polygon using the current source material to fill / texture
- * with according to the texture coordinates passed.
- *
- * If @use_color is %TRUE then the color will be changed for each vertex using
- * the value specified in the color member of #CoglTextureVertex. This can be
- * used for example to make the texture fade out by setting the alpha value of
- * the color.
- *
- * All of the texture coordinates must be in the range [0,1] and repeating the
- * texture is not supported.
- *
- * Because of the way this function is implemented it will currently
- * only work if either the texture is not sliced or the backend is not
- * OpenGL ES and the minifying and magnifying functions are both set
- * to COGL_MATERIAL_FILTER_NEAREST.
- *
- * Since: 1.0
- */
-void
-cogl_polygon (const CoglTextureVertex *vertices,
- unsigned int n_vertices,
- gboolean use_color);
-
-G_END_DECLS
-
-#endif /* __COGL_PRIMITIVES_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PRIVATE_H__
-#define __COGL_PRIVATE_H__
-
-G_BEGIN_DECLS
-
-gboolean
-_cogl_gl_check_version (GError **error);
-
-void
-_cogl_gl_update_features (CoglContext *context);
-
-gboolean
-_cogl_check_extension (const char *name, const char *ext);
-
-void
-_cogl_clear (const CoglColor *color, unsigned long buffers);
-
-void
-_cogl_read_pixels_with_rowstride (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels,
- int rowstride);
-
-G_END_DECLS
-
-#endif /* __COGL_PRIVATE_H__ */
+++ /dev/null
-
-#ifdef COGL_ENABLE_PROFILE
-
-#include "cogl-profile.h"
-#include "cogl-debug.h"
-
-#include <stdlib.h>
-
-UProfContext *_cogl_uprof_context;
-
-static gboolean
-debug_option_getter (void *user_data)
-{
- unsigned int shift = GPOINTER_TO_UINT (user_data);
- return COGL_DEBUG_ENABLED (shift);
-}
-
-static void
-debug_option_setter (gboolean value, void *user_data)
-{
- unsigned int shift = GPOINTER_TO_UINT (user_data);
-
- if (value)
- COGL_DEBUG_SET_FLAG (shift);
- else
- COGL_DEBUG_CLEAR_FLAG (shift);
-}
-
-static void
-print_exit_report (void)
-{
- if (getenv ("COGL_PROFILE_OUTPUT_REPORT"))
- {
- UProfReport *report = uprof_report_new ("Cogl report");
- uprof_report_add_context (report, _cogl_uprof_context);
- uprof_report_print (report);
- uprof_report_unref (report);
- }
- uprof_context_unref (_cogl_uprof_context);
-}
-
-void
-_cogl_uprof_init (void)
-{
- _cogl_uprof_context = uprof_context_new ("Cogl");
-#define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \
- G_STMT_START { \
- int shift = COGL_DEBUG_ ## MASK_NAME; \
- uprof_context_add_boolean_option (_cogl_uprof_context, \
- GROUP, \
- NAME, \
- NAME_FORMATTED, \
- DESCRIPTION, \
- debug_option_getter, \
- debug_option_setter, \
- GUINT_TO_POINTER (shift)); \
- } G_STMT_END;
-
-#include "cogl-debug-options.h"
-#undef OPT
-
- g_atexit (print_exit_report);
-}
-
-void
-_cogl_profile_trace_message (const char *format, ...)
-{
- va_list ap;
-
- va_start (ap, format);
- g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, format, ap);
- va_end (ap);
-
- if (_cogl_uprof_context)
- uprof_context_vtrace_message (_cogl_uprof_context, format, ap);
-}
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PROFILE_H__
-#define __COGL_PROFILE_H__
-
-
-#ifdef COGL_ENABLE_PROFILE
-
-#include <uprof.h>
-
-extern UProfContext *_cogl_uprof_context;
-
-#define COGL_STATIC_TIMER UPROF_STATIC_TIMER
-#define COGL_STATIC_COUNTER UPROF_STATIC_COUNTER
-#define COGL_COUNTER_INC UPROF_COUNTER_INC
-#define COGL_COUNTER_DEC UPROF_COUNTER_DEC
-#define COGL_TIMER_START UPROF_TIMER_START
-#define COGL_TIMER_STOP UPROF_TIMER_STOP
-
-void
-_cogl_uprof_init (void);
-
-void
-_cogl_profile_trace_message (const char *format, ...);
-
-#else
-
-#define COGL_STATIC_TIMER(A,B,C,D,E) extern void _cogl_dummy_decl (void)
-#define COGL_STATIC_COUNTER(A,B,C,D) extern void _cogl_dummy_decl (void)
-#define COGL_COUNTER_INC(A,B) G_STMT_START{ (void)0; }G_STMT_END
-#define COGL_COUNTER_DEC(A,B) G_STMT_START{ (void)0; }G_STMT_END
-#define COGL_TIMER_START(A,B) G_STMT_START{ (void)0; }G_STMT_END
-#define COGL_TIMER_STOP(A,B) G_STMT_START{ (void)0; }G_STMT_END
-
-#define _cogl_profile_trace_message g_message
-
-#endif
-
-#endif /* __COGL_PROFILE_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_PROGRAM_H
-#define __COGL_PROGRAM_H
-
-#include "cogl-handle.h"
-#include "cogl-internal.h"
-#include "cogl-shader-private.h"
-
-typedef struct _CoglProgram CoglProgram;
-
-struct _CoglProgram
-{
- CoglHandleObject _parent;
-
- GSList *attached_shaders;
-
- GArray *custom_uniforms;
-
- /* An age counter that changes whenever the list of shaders is modified */
- unsigned int age;
-};
-
-typedef struct _CoglProgramUniform CoglProgramUniform;
-
-struct _CoglProgramUniform
-{
- char *name;
- CoglBoxedValue value;
- /* The cached GL location for this uniform. This is only valid
- between calls to _cogl_program_dirty_all_uniforms */
- GLint location;
- /* Whether we have a location yet */
- unsigned int location_valid : 1;
- /* Whether the uniform value has changed since the last time the
- uniforms were flushed */
- unsigned int dirty : 1;
-};
-
-CoglProgram *_cogl_program_pointer_from_handle (CoglHandle handle);
-
-/* Internal function to flush the custom uniforms for the given use
- program. This assumes the target GL program is already bound. The
- gl_program still needs to be passed so that CoglProgram can query
- the uniform locations. gl_program_changed should be set to TRUE if
- we are flushing the uniforms against a different GL program from
- the last time it was flushed. This will cause it to requery all of
- the locations and assume that all uniforms are dirty */
-void
-_cogl_program_flush_uniforms (CoglProgram *program,
- GLuint gl_program,
- gboolean gl_program_changed);
-
-CoglShaderLanguage
-_cogl_program_get_language (CoglHandle handle);
-
-gboolean
-_cogl_program_has_fragment_shader (CoglHandle handle);
-
-gboolean
-_cogl_program_has_vertex_shader (CoglHandle handle);
-
-#endif /* __COGL_PROGRAM_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-
-#include "cogl-shader-private.h"
-#include "cogl-program-private.h"
-
-#include <string.h>
-
-static void _cogl_program_free (CoglProgram *program);
-
-COGL_HANDLE_DEFINE (Program, program);
-COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (program);
-
-/* A CoglProgram is effectively just a list of shaders that will be
- used together and a set of values for the custom uniforms. No
- actual GL program is created - instead this is the responsibility
- of the GLSL material backend. The uniform values are collected in
- an array and then flushed whenever the material backend requests
- it. */
-
-#ifndef HAVE_COGL_GLES2
-
-#define glGetUniformLocation ctx->drv.pf_glGetUniformLocation
-#define glUniform1f ctx->drv.pf_glUniform1f
-#define glUniform2f ctx->drv.pf_glUniform2f
-#define glUniform3f ctx->drv.pf_glUniform3f
-#define glUniform4f ctx->drv.pf_glUniform4f
-#define glUniform1fv ctx->drv.pf_glUniform1fv
-#define glUniform2fv ctx->drv.pf_glUniform2fv
-#define glUniform3fv ctx->drv.pf_glUniform3fv
-#define glUniform4fv ctx->drv.pf_glUniform4fv
-#define glUniform1i ctx->drv.pf_glUniform1i
-#define glUniform2i ctx->drv.pf_glUniform2i
-#define glUniform3i ctx->drv.pf_glUniform3i
-#define glUniform4i ctx->drv.pf_glUniform4i
-#define glUniform1iv ctx->drv.pf_glUniform1iv
-#define glUniform2iv ctx->drv.pf_glUniform2iv
-#define glUniform3iv ctx->drv.pf_glUniform3iv
-#define glUniform4iv ctx->drv.pf_glUniform4iv
-#define glUniformMatrix2fv ctx->drv.pf_glUniformMatrix2fv
-#define glUniformMatrix3fv ctx->drv.pf_glUniformMatrix3fv
-#define glUniformMatrix4fv ctx->drv.pf_glUniformMatrix4fv
-#define glProgramLocalParameter4fv ctx->drv.pf_glProgramLocalParameter4fv
-
-#endif /* HAVE_COGL_GLES2 */
-
-static void
-_cogl_program_free (CoglProgram *program)
-{
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Unref all of the attached shaders */
- g_slist_foreach (program->attached_shaders, (GFunc) cogl_handle_unref, NULL);
- /* Destroy the list */
- g_slist_free (program->attached_shaders);
-
- for (i = 0; i < program->custom_uniforms->len; i++)
- {
- CoglProgramUniform *uniform =
- &g_array_index (program->custom_uniforms, CoglProgramUniform, i);
-
- g_free (uniform->name);
-
- if (uniform->value.count > 1)
- g_free (uniform->value.v.array);
- }
-
- g_array_free (program->custom_uniforms, TRUE);
-
- g_slice_free (CoglProgram, program);
-}
-
-CoglHandle
-cogl_create_program (void)
-{
- CoglProgram *program;
-
- program = g_slice_new0 (CoglProgram);
-
- program->custom_uniforms =
- g_array_new (FALSE, FALSE, sizeof (CoglProgramUniform));
- program->age = 0;
-
- return _cogl_program_handle_new (program);
-}
-
-void
-cogl_program_attach_shader (CoglHandle program_handle,
- CoglHandle shader_handle)
-{
- CoglProgram *program;
- CoglShader *shader;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!cogl_is_program (program_handle) || !cogl_is_shader (shader_handle))
- return;
-
- program = _cogl_program_pointer_from_handle (program_handle);
- shader = _cogl_shader_pointer_from_handle (shader_handle);
-
- /* Only one shader is allowed if the type is ARBfp */
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- g_return_if_fail (program->attached_shaders == NULL);
- else if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
- g_return_if_fail (_cogl_program_get_language (program) ==
- COGL_SHADER_LANGUAGE_GLSL);
-#endif
-
- program->attached_shaders
- = g_slist_prepend (program->attached_shaders,
- cogl_handle_ref (shader_handle));
-
- program->age++;
-}
-
-void
-cogl_program_link (CoglHandle handle)
-{
- /* There's no point in linking the program here because it will have
- to be relinked with a different fixed functionality shader
- whenever the settings change */
-}
-
-void
-cogl_program_use (CoglHandle handle)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (handle == COGL_INVALID_HANDLE ||
- cogl_is_program (handle));
-
- if (ctx->current_program == 0 && handle != 0)
- ctx->legacy_state_set++;
- else if (handle == 0 && ctx->current_program != 0)
- ctx->legacy_state_set--;
-
- if (handle != COGL_INVALID_HANDLE)
- cogl_handle_ref (handle);
- if (ctx->current_program != COGL_INVALID_HANDLE)
- cogl_handle_unref (ctx->current_program);
- ctx->current_program = handle;
-}
-
-int
-cogl_program_get_uniform_location (CoglHandle handle,
- const char *uniform_name)
-{
- int i;
- CoglProgram *program;
- CoglProgramUniform *uniform;
-
- if (!cogl_is_program (handle))
- return -1;
-
- program = _cogl_program_pointer_from_handle (handle);
-
- /* We can't just ask the GL program object for the uniform location
- directly because it will change every time the program is linked
- with a different shader. Instead we make our own mapping of
- uniform numbers and cache the names */
- for (i = 0; i < program->custom_uniforms->len; i++)
- {
- uniform = &g_array_index (program->custom_uniforms,
- CoglProgramUniform, i);
-
- if (!strcmp (uniform->name, uniform_name))
- return i;
- }
-
- /* Create a new uniform with the given name */
- g_array_set_size (program->custom_uniforms,
- program->custom_uniforms->len + 1);
- uniform = &g_array_index (program->custom_uniforms,
- CoglProgramUniform,
- program->custom_uniforms->len - 1);
-
- uniform->name = g_strdup (uniform_name);
- memset (&uniform->value, 0, sizeof (CoglBoxedValue));
- uniform->dirty = TRUE;
- uniform->location_valid = FALSE;
-
- return program->custom_uniforms->len - 1;
-}
-
-static void
-cogl_program_uniform_x (CoglHandle handle,
- int uniform_no,
- int size,
- int count,
- CoglBoxedType type,
- gsize value_size,
- gconstpointer value,
- gboolean transpose)
-{
- CoglProgram *program = handle;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (cogl_is_program (handle));
- g_return_if_fail (program != NULL);
-
- if (uniform_no >= 0 && uniform_no < program->custom_uniforms->len &&
- size >= 1 && size <= 4 && count >= 1)
- {
- CoglProgramUniform *uniform =
- &g_array_index (program->custom_uniforms,
- CoglProgramUniform, uniform_no);
-
- if (count == 1)
- {
- if (uniform->value.count > 1)
- g_free (uniform->value.v.array);
-
- memcpy (uniform->value.v.float_value, value, value_size);
- }
- else
- {
- if (uniform->value.count > 1)
- {
- if (uniform->value.count != count ||
- uniform->value.size != size ||
- uniform->value.type != type)
- {
- g_free (uniform->value.v.array);
- uniform->value.v.array = g_malloc (count * value_size);
- }
- }
- else
- uniform->value.v.array = g_malloc (count * value_size);
-
- memcpy (uniform->value.v.array, value, count * value_size);
- }
-
- uniform->value.type = type;
- uniform->value.size = size;
- uniform->value.count = count;
- uniform->dirty = TRUE;
- }
-}
-
-void
-cogl_program_uniform_1f (int uniform_no,
- float value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_program_uniform_x (ctx->current_program,
- uniform_no, 1, 1, COGL_BOXED_FLOAT,
- sizeof (float), &value, FALSE);
-}
-
-void
-cogl_program_set_uniform_1f (CoglHandle handle,
- int uniform_location,
- float value)
-{
- cogl_program_uniform_x (handle,
- uniform_location, 1, 1, COGL_BOXED_FLOAT,
- sizeof (float), &value, FALSE);
-}
-
-void
-cogl_program_uniform_1i (int uniform_no,
- int value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_program_uniform_x (ctx->current_program,
- uniform_no, 1, 1, COGL_BOXED_INT,
- sizeof (int), &value, FALSE);
-}
-
-void
-cogl_program_set_uniform_1i (CoglHandle handle,
- int uniform_location,
- int value)
-{
- cogl_program_uniform_x (handle,
- uniform_location, 1, 1, COGL_BOXED_INT,
- sizeof (int), &value, FALSE);
-}
-
-void
-cogl_program_uniform_float (int uniform_no,
- int size,
- int count,
- const GLfloat *value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_program_uniform_x (ctx->current_program,
- uniform_no, size, count, COGL_BOXED_FLOAT,
- sizeof (float) * size, value, FALSE);
-}
-
-void
-cogl_program_set_uniform_float (CoglHandle handle,
- int uniform_location,
- int n_components,
- int count,
- const float *value)
-{
- cogl_program_uniform_x (handle,
- uniform_location, n_components, count,
- COGL_BOXED_FLOAT,
- sizeof (float) * n_components, value, FALSE);
-}
-
-void
-cogl_program_uniform_int (int uniform_no,
- int size,
- int count,
- const GLint *value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_program_uniform_x (ctx->current_program,
- uniform_no, size, count, COGL_BOXED_INT,
- sizeof (int) * size, value, FALSE);
-}
-
-void
-cogl_program_set_uniform_int (CoglHandle handle,
- int uniform_location,
- int n_components,
- int count,
- const int *value)
-{
- cogl_program_uniform_x (handle,
- uniform_location, n_components, count,
- COGL_BOXED_INT,
- sizeof (int) * n_components, value, FALSE);
-}
-
-void
-cogl_program_set_uniform_matrix (CoglHandle handle,
- int uniform_location,
- int dimensions,
- int count,
- gboolean transpose,
- const float *value)
-{
- g_return_if_fail (cogl_is_program (handle));
-
- cogl_program_uniform_x (handle,
- uniform_location, dimensions, count,
- COGL_BOXED_MATRIX,
- sizeof (float) * dimensions * dimensions,
- value,
- transpose);
-}
-
-void
-cogl_program_uniform_matrix (int uniform_no,
- int size,
- int count,
- gboolean transpose,
- const float *value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
- cogl_program_set_uniform_matrix (ctx->current_program,
- uniform_no, size, count, transpose, value);
-}
-
-#ifndef HAVE_COGL_GLES
-
-/* ARBfp local parameters can be referenced like:
- *
- * "program.local[5]"
- * ^14char offset (after whitespace is stripped)
- */
-static int
-get_local_param_index (const char *uniform_name)
-{
- char *input = g_strdup (uniform_name);
- int i;
- char *p = input;
- char *endptr;
- int _index;
-
- for (i = 0; input[i] != '\0'; i++)
- if (input[i] != '_' && input[i] != '\t')
- *p++ = input[i];
- input[i] = '\0';
-
- g_return_val_if_fail (strncmp ("program.local[", input, 14) == 0, -1);
-
- _index = g_ascii_strtoull (input + 14, &endptr, 10);
- g_return_val_if_fail (endptr != input + 14, -1);
- g_return_val_if_fail (*endptr == ']', -1);
-
- g_return_val_if_fail (_index >= 0, -1);
-
- g_free (input);
-
- return _index;
-}
-
-static void
-_cogl_program_flush_uniform_glsl (GLint location,
- CoglBoxedValue *value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- switch (value->type)
- {
- case COGL_BOXED_NONE:
- break;
-
- case COGL_BOXED_INT:
- {
- int *ptr;
-
- if (value->count == 1)
- ptr = value->v.int_value;
- else
- ptr = value->v.int_array;
-
- switch (value->size)
- {
- case 1: glUniform1iv (location, value->count, ptr); break;
- case 2: glUniform2iv (location, value->count, ptr); break;
- case 3: glUniform3iv (location, value->count, ptr); break;
- case 4: glUniform4iv (location, value->count, ptr); break;
- }
- }
- break;
-
- case COGL_BOXED_FLOAT:
- {
- float *ptr;
-
- if (value->count == 1)
- ptr = value->v.float_value;
- else
- ptr = value->v.float_array;
-
- switch (value->size)
- {
- case 1: glUniform1fv (location, value->count, ptr); break;
- case 2: glUniform2fv (location, value->count, ptr); break;
- case 3: glUniform3fv (location, value->count, ptr); break;
- case 4: glUniform4fv (location, value->count, ptr); break;
- }
- }
- break;
-
- case COGL_BOXED_MATRIX:
- {
- float *ptr;
-
- if (value->count == 1)
- ptr = value->v.matrix;
- else
- ptr = value->v.float_array;
-
- switch (value->size)
- {
- case 2:
- glUniformMatrix2fv (location, value->count, value->transpose, ptr);
- break;
- case 3:
- glUniformMatrix3fv (location, value->count, value->transpose, ptr);
- break;
- case 4:
- glUniformMatrix4fv (location, value->count, value->transpose, ptr);
- break;
- }
- }
- break;
- }
-}
-
-#endif /* HAVE_COGL_GLES */
-
-#ifdef HAVE_COGL_GL
-
-static void
-_cogl_program_flush_uniform_arbfp (GLint location,
- CoglBoxedValue *value)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (value->type != COGL_BOXED_NONE)
- {
- g_return_if_fail (value->type == COGL_BOXED_FLOAT);
- g_return_if_fail (value->size == 4);
- g_return_if_fail (value->count == 1);
-
- GE( glProgramLocalParameter4fv (GL_FRAGMENT_PROGRAM_ARB, location,
- value->v.float_value) );
- }
-}
-
-#endif /* HAVE_COGL_GL */
-
-void
-_cogl_program_flush_uniforms (CoglProgram *program,
- GLuint gl_program,
- gboolean gl_program_changed)
-{
-#ifdef HAVE_COGL_GLES
-
- g_return_if_reached ();
-
-#else /* HAVE_COGL_GLES */
-
- CoglProgramUniform *uniform;
- int i;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (i = 0; i < program->custom_uniforms->len; i++)
- {
- uniform = &g_array_index (program->custom_uniforms,
- CoglProgramUniform, i);
-
- if (gl_program_changed || uniform->dirty)
- {
- if (gl_program_changed || !uniform->location_valid)
- {
- if (_cogl_program_get_language (program) ==
- COGL_SHADER_LANGUAGE_GLSL)
- uniform->location =
- glGetUniformLocation (gl_program, uniform->name);
- else
- uniform->location =
- get_local_param_index (uniform->name);
-
- uniform->location_valid = TRUE;
- }
-
- /* If the uniform isn't really in the program then there's
- no need to actually set it */
- if (uniform->location != -1)
- {
- switch (_cogl_program_get_language (program))
- {
- case COGL_SHADER_LANGUAGE_GLSL:
- _cogl_program_flush_uniform_glsl (uniform->location,
- &uniform->value);
- break;
-
-#ifdef HAVE_COGL_GL
- case COGL_SHADER_LANGUAGE_ARBFP:
- _cogl_program_flush_uniform_arbfp (uniform->location,
- &uniform->value);
- break;
-#endif
- }
- }
-
- uniform->dirty = FALSE;
- }
- }
-
-#endif /* HAVE_COGL_GLES */
-}
-
-CoglShaderLanguage
-_cogl_program_get_language (CoglHandle handle)
-{
- CoglProgram *program = handle;
-
- /* Use the language of the first shader */
-
- if (program->attached_shaders)
- {
- CoglShader *shader = program->attached_shaders->data;
- return shader->language;
- }
- else
- return COGL_SHADER_LANGUAGE_GLSL;
-}
-
-static gboolean
-_cogl_program_has_shader_type (CoglProgram *program,
- CoglShaderType type)
-{
- GSList *l;
-
- for (l = program->attached_shaders; l; l = l->next)
- {
- CoglShader *shader = l->data;
-
- if (shader->type == type)
- return TRUE;
- }
-
- return FALSE;
-}
-
-gboolean
-_cogl_program_has_fragment_shader (CoglHandle handle)
-{
- return _cogl_program_has_shader_type (handle, COGL_SHADER_TYPE_FRAGMENT);
-}
-
-gboolean
-_cogl_program_has_vertex_shader (CoglHandle handle)
-{
- return _cogl_program_has_shader_type (handle, COGL_SHADER_TYPE_VERTEX);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-
-#include "cogl-rectangle-map.h"
-#include "cogl-debug.h"
-
-/* Implements a data structure which keeps track of unused
- sub-rectangles within a larger rectangle using a binary tree
- structure. The algorithm for this is based on the description here:
-
- http://www.blackpawn.com/texts/lightmaps/default.html
-*/
-
-#ifdef COGL_ENABLE_DEBUG
-
-/* The cairo header is only used for debugging to generate an image of
- the atlas */
-#include <cairo.h>
-
-static void _cogl_rectangle_map_dump_image (CoglRectangleMap *map);
-
-#endif /* COGL_ENABLE_DEBUG */
-
-typedef struct _CoglRectangleMapNode CoglRectangleMapNode;
-typedef struct _CoglRectangleMapStackEntry CoglRectangleMapStackEntry;
-
-typedef void (* CoglRectangleMapInternalForeachCb) (CoglRectangleMapNode *node,
- void *data);
-
-typedef enum
-{
- COGL_RECTANGLE_MAP_BRANCH,
- COGL_RECTANGLE_MAP_FILLED_LEAF,
- COGL_RECTANGLE_MAP_EMPTY_LEAF
-} CoglRectangleMapNodeType;
-
-struct _CoglRectangleMap
-{
- CoglRectangleMapNode *root;
-
- unsigned int n_rectangles;
-
- unsigned int space_remaining;
-
- GDestroyNotify value_destroy_func;
-
- /* Stack used for walking the structure. This is only used during
- the lifetime of a single function call but it is kept here as an
- optimisation to avoid reallocating it every time it is needed */
- GArray *stack;
-};
-
-struct _CoglRectangleMapNode
-{
- CoglRectangleMapNodeType type;
-
- CoglRectangleMapEntry rectangle;
-
- unsigned int largest_gap;
-
- CoglRectangleMapNode *parent;
-
- union
- {
- /* Fields used when this is a branch */
- struct
- {
- CoglRectangleMapNode *left;
- CoglRectangleMapNode *right;
- } branch;
-
- /* Field used when this is a filled leaf */
- void *data;
- } d;
-};
-
-struct _CoglRectangleMapStackEntry
-{
- /* The node to search */
- CoglRectangleMapNode *node;
- /* Index of next branch of this node to explore. Basically either 0
- to go left or 1 to go right */
- gboolean next_index;
-};
-
-static CoglRectangleMapNode *
-_cogl_rectangle_map_node_new (void)
-{
- return g_slice_new (CoglRectangleMapNode);
-}
-
-static void
-_cogl_rectangle_map_node_free (CoglRectangleMapNode *node)
-{
- g_slice_free (CoglRectangleMapNode, node);
-}
-
-CoglRectangleMap *
-_cogl_rectangle_map_new (unsigned int width,
- unsigned int height,
- GDestroyNotify value_destroy_func)
-{
- CoglRectangleMap *map = g_new (CoglRectangleMap, 1);
- CoglRectangleMapNode *root = _cogl_rectangle_map_node_new ();
-
- root->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- root->parent = NULL;
- root->rectangle.x = 0;
- root->rectangle.y = 0;
- root->rectangle.width = width;
- root->rectangle.height = height;
- root->largest_gap = width * height;
-
- map->root = root;
- map->n_rectangles = 0;
- map->value_destroy_func = value_destroy_func;
- map->space_remaining = width * height;
-
- map->stack = g_array_new (FALSE, FALSE, sizeof (CoglRectangleMapStackEntry));
-
- return map;
-}
-
-static void
-_cogl_rectangle_map_stack_push (GArray *stack,
- CoglRectangleMapNode *node,
- gboolean next_index)
-{
- CoglRectangleMapStackEntry *new_entry;
-
- g_array_set_size (stack, stack->len + 1);
-
- new_entry = &g_array_index (stack, CoglRectangleMapStackEntry,
- stack->len - 1);
-
- new_entry->node = node;
- new_entry->next_index = next_index;
-}
-
-static void
-_cogl_rectangle_map_stack_pop (GArray *stack)
-{
- g_array_set_size (stack, stack->len - 1);
-}
-
-static CoglRectangleMapStackEntry *
-_cogl_rectangle_map_stack_get_top (GArray *stack)
-{
- return &g_array_index (stack, CoglRectangleMapStackEntry,
- stack->len - 1);
-}
-
-static CoglRectangleMapNode *
-_cogl_rectangle_map_node_split_horizontally (CoglRectangleMapNode *node,
- unsigned int left_width)
-{
- /* Splits the node horizontally (according to emacs' definition, not
- vim) by converting it to a branch and adding two new leaf
- nodes. The leftmost branch will have the width left_width and
- will be returned. If the node is already just the right size it
- won't do anything */
-
- CoglRectangleMapNode *left_node, *right_node;
-
- if (node->rectangle.width == left_width)
- return node;
-
- left_node = _cogl_rectangle_map_node_new ();
- left_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- left_node->parent = node;
- left_node->rectangle.x = node->rectangle.x;
- left_node->rectangle.y = node->rectangle.y;
- left_node->rectangle.width = left_width;
- left_node->rectangle.height = node->rectangle.height;
- left_node->largest_gap = (left_node->rectangle.width *
- left_node->rectangle.height);
- node->d.branch.left = left_node;
-
- right_node = _cogl_rectangle_map_node_new ();
- right_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- right_node->parent = node;
- right_node->rectangle.x = node->rectangle.x + left_width;
- right_node->rectangle.y = node->rectangle.y;
- right_node->rectangle.width = node->rectangle.width - left_width;
- right_node->rectangle.height = node->rectangle.height;
- right_node->largest_gap = (right_node->rectangle.width *
- right_node->rectangle.height);
- node->d.branch.right = right_node;
-
- node->type = COGL_RECTANGLE_MAP_BRANCH;
-
- return left_node;
-}
-
-static CoglRectangleMapNode *
-_cogl_rectangle_map_node_split_vertically (CoglRectangleMapNode *node,
- unsigned int top_height)
-{
- /* Splits the node vertically (according to emacs' definition, not
- vim) by converting it to a branch and adding two new leaf
- nodes. The topmost branch will have the height top_height and
- will be returned. If the node is already just the right size it
- won't do anything */
-
- CoglRectangleMapNode *top_node, *bottom_node;
-
- if (node->rectangle.height == top_height)
- return node;
-
- top_node = _cogl_rectangle_map_node_new ();
- top_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- top_node->parent = node;
- top_node->rectangle.x = node->rectangle.x;
- top_node->rectangle.y = node->rectangle.y;
- top_node->rectangle.width = node->rectangle.width;
- top_node->rectangle.height = top_height;
- top_node->largest_gap = (top_node->rectangle.width *
- top_node->rectangle.height);
- node->d.branch.left = top_node;
-
- bottom_node = _cogl_rectangle_map_node_new ();
- bottom_node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- bottom_node->parent = node;
- bottom_node->rectangle.x = node->rectangle.x;
- bottom_node->rectangle.y = node->rectangle.y + top_height;
- bottom_node->rectangle.width = node->rectangle.width;
- bottom_node->rectangle.height = node->rectangle.height - top_height;
- bottom_node->largest_gap = (bottom_node->rectangle.width *
- bottom_node->rectangle.height);
- node->d.branch.right = bottom_node;
-
- node->type = COGL_RECTANGLE_MAP_BRANCH;
-
- return top_node;
-}
-
-#ifdef COGL_ENABLE_DEBUG
-
-static unsigned int
-_cogl_rectangle_map_verify_recursive (CoglRectangleMapNode *node)
-{
- /* This is just used for debugging the data structure. It
- recursively walks the tree to verify that the largest gap values
- all add up */
-
- switch (node->type)
- {
- case COGL_RECTANGLE_MAP_BRANCH:
- {
- int sum =
- _cogl_rectangle_map_verify_recursive (node->d.branch.left) +
- _cogl_rectangle_map_verify_recursive (node->d.branch.right);
- g_assert (node->largest_gap ==
- MAX (node->d.branch.left->largest_gap,
- node->d.branch.right->largest_gap));
- return sum;
- }
-
- case COGL_RECTANGLE_MAP_EMPTY_LEAF:
- g_assert (node->largest_gap ==
- node->rectangle.width * node->rectangle.height);
- return 0;
-
- case COGL_RECTANGLE_MAP_FILLED_LEAF:
- g_assert (node->largest_gap == 0);
- return 1;
- }
-
- return 0;
-}
-
-static unsigned int
-_cogl_rectangle_map_get_space_remaining_recursive (CoglRectangleMapNode *node)
-{
- /* This is just used for debugging the data structure. It
- recursively walks the tree to verify that the remaining space
- value adds up */
-
- switch (node->type)
- {
- case COGL_RECTANGLE_MAP_BRANCH:
- {
- CoglRectangleMapNode *l = node->d.branch.left;
- CoglRectangleMapNode *r = node->d.branch.right;
-
- return (_cogl_rectangle_map_get_space_remaining_recursive (l) +
- _cogl_rectangle_map_get_space_remaining_recursive (r));
- }
-
- case COGL_RECTANGLE_MAP_EMPTY_LEAF:
- return node->rectangle.width * node->rectangle.height;
-
- case COGL_RECTANGLE_MAP_FILLED_LEAF:
- return 0;
- }
-
- return 0;
-}
-
-static void
-_cogl_rectangle_map_verify (CoglRectangleMap *map)
-{
- unsigned int actual_n_rectangles =
- _cogl_rectangle_map_verify_recursive (map->root);
- unsigned int actual_space_remaining =
- _cogl_rectangle_map_get_space_remaining_recursive (map->root);
-
- g_assert_cmpuint (actual_n_rectangles, ==, map->n_rectangles);
- g_assert_cmpuint (actual_space_remaining, ==, map->space_remaining);
-}
-
-#endif /* COGL_ENABLE_DEBUG */
-
-gboolean
-_cogl_rectangle_map_add (CoglRectangleMap *map,
- unsigned int width,
- unsigned int height,
- void *data,
- CoglRectangleMapEntry *rectangle)
-{
- unsigned int rectangle_size = width * height;
- /* Stack of nodes to search in */
- GArray *stack = map->stack;
- CoglRectangleMapNode *found_node = NULL;
-
- /* Zero-sized rectangles break the algorithm for removing rectangles
- so we'll disallow them */
- g_return_val_if_fail (width > 0 && height > 0, FALSE);
-
- /* Start with the root node */
- g_array_set_size (stack, 0);
- _cogl_rectangle_map_stack_push (stack, map->root, FALSE);
-
- /* Depth-first search for an empty node that is big enough */
- while (stack->len > 0)
- {
- CoglRectangleMapStackEntry *stack_top;
- CoglRectangleMapNode *node;
- int next_index;
-
- /* Pop an entry off the stack */
- stack_top = _cogl_rectangle_map_stack_get_top (stack);
- node = stack_top->node;
- next_index = stack_top->next_index;
- _cogl_rectangle_map_stack_pop (stack);
-
- /* Regardless of the type of the node, there's no point
- descending any further if the new rectangle won't fit within
- it */
- if (node->rectangle.width >= width &&
- node->rectangle.height >= height &&
- node->largest_gap >= rectangle_size)
- {
- if (node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
- {
- /* We've found a node we can use */
- found_node = node;
- break;
- }
- else if (node->type == COGL_RECTANGLE_MAP_BRANCH)
- {
- if (next_index)
- /* Try the right branch */
- _cogl_rectangle_map_stack_push (stack,
- node->d.branch.right,
- 0);
- else
- {
- /* Make sure we remember to try the right branch once
- we've finished descending the left branch */
- _cogl_rectangle_map_stack_push (stack,
- node,
- 1);
- /* Try the left branch */
- _cogl_rectangle_map_stack_push (stack,
- node->d.branch.left,
- 0);
- }
- }
- }
- }
-
- if (found_node)
- {
- CoglRectangleMapNode *node;
-
- /* Split according to whichever axis will leave us with the
- largest space */
- if (found_node->rectangle.width - width >
- found_node->rectangle.height - height)
- {
- found_node =
- _cogl_rectangle_map_node_split_horizontally (found_node, width);
- found_node =
- _cogl_rectangle_map_node_split_vertically (found_node, height);
- }
- else
- {
- found_node =
- _cogl_rectangle_map_node_split_vertically (found_node, height);
- found_node =
- _cogl_rectangle_map_node_split_horizontally (found_node, width);
- }
-
- found_node->type = COGL_RECTANGLE_MAP_FILLED_LEAF;
- found_node->d.data = data;
- found_node->largest_gap = 0;
- if (rectangle)
- *rectangle = found_node->rectangle;
-
- /* Walk back up the tree and update the stored largest gap for
- the node's sub tree */
- for (node = found_node->parent; node; node = node->parent)
- {
- /* This node is a parent so it should always be a branch */
- g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH);
-
- node->largest_gap = MAX (node->d.branch.left->largest_gap,
- node->d.branch.right->largest_gap);
- }
-
- /* There is now an extra rectangle in the map */
- map->n_rectangles++;
- /* and less space */
- map->space_remaining -= rectangle_size;
-
-#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE)))
- {
- _cogl_rectangle_map_dump_image (map);
- /* Dumping the rectangle map is really slow so we might as well
- verify the space remaining here as it is also quite slow */
- _cogl_rectangle_map_verify (map);
- }
-#endif
-
- return TRUE;
- }
- else
- return FALSE;
-}
-
-void
-_cogl_rectangle_map_remove (CoglRectangleMap *map,
- const CoglRectangleMapEntry *rectangle)
-{
- CoglRectangleMapNode *node = map->root;
- unsigned int rectangle_size = rectangle->width * rectangle->height;
-
- /* We can do a binary-chop down the search tree to find the rectangle */
- while (node->type == COGL_RECTANGLE_MAP_BRANCH)
- {
- CoglRectangleMapNode *left_node = node->d.branch.left;
-
- /* If and only if the rectangle is in the left node then the x,y
- position of the rectangle will be within the node's
- rectangle */
- if (rectangle->x < left_node->rectangle.x + left_node->rectangle.width &&
- rectangle->y < left_node->rectangle.y + left_node->rectangle.height)
- /* Go left */
- node = left_node;
- else
- /* Go right */
- node = node->d.branch.right;
- }
-
- /* Make sure we found the right node */
- if (node->type != COGL_RECTANGLE_MAP_FILLED_LEAF ||
- node->rectangle.x != rectangle->x ||
- node->rectangle.y != rectangle->y ||
- node->rectangle.width != rectangle->width ||
- node->rectangle.height != rectangle->height)
- /* This should only happen if someone tried to remove a rectangle
- that was not in the map so something has gone wrong */
- g_return_if_reached ();
- else
- {
- /* Convert the node back to an empty node */
- if (map->value_destroy_func)
- map->value_destroy_func (node->d.data);
- node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
- node->largest_gap = rectangle_size;
-
- /* Walk back up the tree combining branch nodes that have two
- empty leaves back into a single empty leaf */
- for (node = node->parent; node; node = node->parent)
- {
- /* This node is a parent so it should always be a branch */
- g_assert (node->type == COGL_RECTANGLE_MAP_BRANCH);
-
- if (node->d.branch.left->type == COGL_RECTANGLE_MAP_EMPTY_LEAF &&
- node->d.branch.right->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
- {
- _cogl_rectangle_map_node_free (node->d.branch.left);
- _cogl_rectangle_map_node_free (node->d.branch.right);
- node->type = COGL_RECTANGLE_MAP_EMPTY_LEAF;
-
- node->largest_gap = (node->rectangle.width *
- node->rectangle.height);
- }
- else
- break;
- }
-
- /* Reduce the amount of space remaining in all of the parents
- further up the chain */
- for (; node; node = node->parent)
- node->largest_gap = MAX (node->d.branch.left->largest_gap,
- node->d.branch.right->largest_gap);
-
- /* There is now one less rectangle */
- g_assert (map->n_rectangles > 0);
- map->n_rectangles--;
- /* and more space */
- map->space_remaining += rectangle_size;
- }
-
-#ifdef COGL_ENABLE_DEBUG
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DUMP_ATLAS_IMAGE)))
- {
- _cogl_rectangle_map_dump_image (map);
- /* Dumping the rectangle map is really slow so we might as well
- verify the space remaining here as it is also quite slow */
- _cogl_rectangle_map_verify (map);
- }
-#endif
-}
-
-unsigned int
-_cogl_rectangle_map_get_width (CoglRectangleMap *map)
-{
- return map->root->rectangle.width;
-}
-
-unsigned int
-_cogl_rectangle_map_get_height (CoglRectangleMap *map)
-{
- return map->root->rectangle.height;
-}
-
-unsigned int
-_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map)
-{
- return map->space_remaining;
-}
-
-unsigned int
-_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map)
-{
- return map->n_rectangles;
-}
-
-static void
-_cogl_rectangle_map_internal_foreach (CoglRectangleMap *map,
- CoglRectangleMapInternalForeachCb func,
- void *data)
-{
- /* Stack of nodes to search in */
- GArray *stack = map->stack;
-
- /* Start with the root node */
- g_array_set_size (stack, 0);
- _cogl_rectangle_map_stack_push (stack, map->root, 0);
-
- /* Iterate all nodes depth-first */
- while (stack->len > 0)
- {
- CoglRectangleMapStackEntry *stack_top =
- _cogl_rectangle_map_stack_get_top (stack);
- CoglRectangleMapNode *node = stack_top->node;
-
- switch (node->type)
- {
- case COGL_RECTANGLE_MAP_BRANCH:
- if (stack_top->next_index == 0)
- {
- /* Next time we come back to this node, go to the right */
- stack_top->next_index = 1;
-
- /* Explore the left branch next */
- _cogl_rectangle_map_stack_push (stack,
- node->d.branch.left,
- 0);
- }
- else if (stack_top->next_index == 1)
- {
- /* Next time we come back to this node, stop processing it */
- stack_top->next_index = 2;
-
- /* Explore the right branch next */
- _cogl_rectangle_map_stack_push (stack,
- node->d.branch.right,
- 0);
- }
- else
- {
- /* We're finished with this node so we can call the callback */
- func (node, data);
- _cogl_rectangle_map_stack_pop (stack);
- }
- break;
-
- default:
- /* Some sort of leaf node, just call the callback */
- func (node, data);
- _cogl_rectangle_map_stack_pop (stack);
- break;
- }
- }
-
- /* The stack should now be empty */
- g_assert (stack->len == 0);
-}
-
-typedef struct _CoglRectangleMapForeachClosure
-{
- CoglRectangleMapCallback callback;
- void *data;
-} CoglRectangleMapForeachClosure;
-
-static void
-_cogl_rectangle_map_foreach_cb (CoglRectangleMapNode *node, void *data)
-{
- CoglRectangleMapForeachClosure *closure = data;
-
- if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
- closure->callback (&node->rectangle, node->d.data, closure->data);
-}
-
-void
-_cogl_rectangle_map_foreach (CoglRectangleMap *map,
- CoglRectangleMapCallback callback,
- void *data)
-{
- CoglRectangleMapForeachClosure closure;
-
- closure.callback = callback;
- closure.data = data;
-
- _cogl_rectangle_map_internal_foreach (map,
- _cogl_rectangle_map_foreach_cb,
- &closure);
-}
-
-static void
-_cogl_rectangle_map_free_cb (CoglRectangleMapNode *node, void *data)
-{
- CoglRectangleMap *map = data;
-
- if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF && map->value_destroy_func)
- map->value_destroy_func (node->d.data);
-
- _cogl_rectangle_map_node_free (node);
-}
-
-void
-_cogl_rectangle_map_free (CoglRectangleMap *map)
-{
- _cogl_rectangle_map_internal_foreach (map,
- _cogl_rectangle_map_free_cb,
- map);
-
- g_array_free (map->stack, TRUE);
-
- g_free (map);
-}
-
-#ifdef COGL_ENABLE_DEBUG
-
-static void
-_cogl_rectangle_map_dump_image_cb (CoglRectangleMapNode *node, void *data)
-{
- cairo_t *cr = data;
-
- if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF ||
- node->type == COGL_RECTANGLE_MAP_EMPTY_LEAF)
- {
- /* Fill the rectangle using a different colour depending on
- whether the rectangle is used */
- if (node->type == COGL_RECTANGLE_MAP_FILLED_LEAF)
- cairo_set_source_rgb (cr, 0.0, 0.0, 1.0);
- else
- cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
-
- cairo_rectangle (cr,
- node->rectangle.x,
- node->rectangle.y,
- node->rectangle.width,
- node->rectangle.height);
-
- cairo_fill_preserve (cr);
-
- /* Draw a white outline around the rectangle */
- cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
- cairo_stroke (cr);
- }
-}
-
-static void
-_cogl_rectangle_map_dump_image (CoglRectangleMap *map)
-{
- /* This dumps a png to help visualize the map. Each leaf rectangle
- is drawn with a white outline. Unused leaves are filled in black
- and used leaves are blue */
-
- cairo_surface_t *surface =
- cairo_image_surface_create (CAIRO_FORMAT_RGB24,
- _cogl_rectangle_map_get_width (map),
- _cogl_rectangle_map_get_height (map));
- cairo_t *cr = cairo_create (surface);
-
- _cogl_rectangle_map_internal_foreach (map,
- _cogl_rectangle_map_dump_image_cb,
- cr);
-
- cairo_destroy (cr);
-
- cairo_surface_write_to_png (surface, "cogl-rectangle-map-dump.png");
-
- cairo_surface_destroy (surface);
-}
-
-#endif /* COGL_ENABLE_DEBUG */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __COGL_RECTANGLE_MAP_H
-#define __COGL_RECTANGLE_MAP_H
-
-#include <glib.h>
-
-typedef struct _CoglRectangleMap CoglRectangleMap;
-typedef struct _CoglRectangleMapEntry CoglRectangleMapEntry;
-
-typedef void (* CoglRectangleMapCallback) (const CoglRectangleMapEntry *entry,
- void *rectangle_data,
- void *user_data);
-
-struct _CoglRectangleMapEntry
-{
- unsigned int x, y;
- unsigned int width, height;
-};
-
-CoglRectangleMap *
-_cogl_rectangle_map_new (unsigned int width,
- unsigned int height,
- GDestroyNotify value_destroy_func);
-
-gboolean
-_cogl_rectangle_map_add (CoglRectangleMap *map,
- unsigned int width,
- unsigned int height,
- void *data,
- CoglRectangleMapEntry *rectangle);
-
-void
-_cogl_rectangle_map_remove (CoglRectangleMap *map,
- const CoglRectangleMapEntry *rectangle);
-
-unsigned int
-_cogl_rectangle_map_get_width (CoglRectangleMap *map);
-
-unsigned int
-_cogl_rectangle_map_get_height (CoglRectangleMap *map);
-
-unsigned int
-_cogl_rectangle_map_get_remaining_space (CoglRectangleMap *map);
-
-unsigned int
-_cogl_rectangle_map_get_n_rectangles (CoglRectangleMap *map);
-
-void
-_cogl_rectangle_map_foreach (CoglRectangleMap *map,
- CoglRectangleMapCallback callback,
- void *data);
-
-void
-_cogl_rectangle_map_free (CoglRectangleMap *map);
-
-#endif /* __COGL_RECTANGLE_MAP_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_RENDERER_GLX_PRIVATE_H
-#define __COGL_RENDERER_GLX_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-renderer-xlib-private.h"
-
-typedef struct _CoglRendererGLX
-{
- CoglRendererXlib _parent;
-
- int glx_major;
- int glx_minor;
-
- int glx_error_base;
- int glx_event_base;
-
- gboolean is_direct;
-
- /* Vblank stuff */
- int dri_fd;
-
- /* Function pointers for GLX specific extensions */
-#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
-
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- ret (APIENTRY * pf_ ## name) args;
-
-#define COGL_WINSYS_FEATURE_END()
-
-#include "cogl-winsys-glx-feature-functions.h"
-
-#undef COGL_WINSYS_FEATURE_BEGIN
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#undef COGL_WINSYS_FEATURE_END
-} CoglRendererGLX;
-
-#endif /* __COGL_RENDERER_GLX_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_RENDERER_PRIVATE_H
-#define __COGL_RENDERER_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-winsys-private.h"
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include <X11/Xlib.h>
-#endif
-
-struct _CoglRenderer
-{
- CoglObject _parent;
- gboolean connected;
- const CoglWinsysVtable *winsys_vtable;
-#ifdef COGL_HAS_XLIB_SUPPORT
- Display *foreign_xdpy;
-#endif
- /* List of callback functions that will be given every native event */
- GSList *event_filters;
- void *winsys;
-};
-
-#endif /* __COGL_RENDERER_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_RENDERER_X11_PRIVATE_H
-#define __COGL_RENDERER_X11_PRIVATE_H
-
-typedef struct _CoglRendererX11
-{
- int damage_base;
-} CoglRendererX11;
-
-#endif /* __COGL_RENDERER_X11_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_RENDERER_XLIB_PRIVATE_H
-#define __COGL_RENDERER_XLIB_PRIVATE_H
-
-#include "cogl-object-private.h"
-#include "cogl-xlib-private.h"
-#include "cogl-renderer-x11-private.h"
-
-typedef struct _CoglRendererXlib
-{
- CoglRendererX11 _parent;
-
- Display *xdpy;
-
- /* Current top of the XError trap state stack. The actual memory for
- these is expected to be allocated on the stack by the caller */
- CoglXlibTrapState *trap_state;
-} CoglRendererXlib;
-
-gboolean
-_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error);
-
-void
-_cogl_renderer_xlib_disconnect (CoglRenderer *renderer);
-
-/*
- * cogl_renderer_xlib_trap_errors:
- * @state: A temporary place to store data for the trap.
- *
- * Traps every X error until _cogl_xlib_untrap_errors() called. You
- * should allocate an uninitialised CoglXlibTrapState struct on the
- * stack to pass to this function. The same pointer should later be
- * passed to _cogl_xlib_untrap_errors(). Calls to
- * _cogl_xlib_trap_errors() can be nested as long as
- * _cogl_xlib_untrap_errors() is called with the corresponding state
- * pointers in reverse order.
- */
-void
-_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
- CoglXlibTrapState *state);
-
-/*
- * cogl_renderer_xlib_untrap_errors:
- * @state: The state that was passed to _cogl_xlib_trap_errors().
- *
- * Removes the X error trap and returns the current status.
- *
- * Return value: the trapped error code, or 0 for success
- */
-int
-_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
- CoglXlibTrapState *state);
-
-#endif /* __COGL_RENDERER_XLIB_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-object.h"
-
-#include "cogl-renderer-private.h"
-#include "cogl-renderer-xlib-private.h"
-#include "cogl-renderer-x11-private.h"
-#include "cogl-winsys-private.h"
-
-#include <X11/Xlib.h>
-#include <X11/extensions/Xdamage.h>
-
-static char *_cogl_x11_display_name = NULL;
-static GList *_cogl_xlib_renderers = NULL;
-
-static void
-register_xlib_renderer (CoglRenderer *renderer)
-{
- GList *l;
-
- for (l = _cogl_xlib_renderers; l; l = l->next)
- if (l->data == renderer)
- return;
-
- _cogl_xlib_renderers = g_list_prepend (_cogl_xlib_renderers, renderer);
-}
-
-static void
-unregister_xlib_renderer (CoglRenderer *renderer)
-{
- _cogl_xlib_renderers = g_list_remove (_cogl_xlib_renderers, renderer);
-}
-
-static CoglRenderer *
-get_renderer_for_xdisplay (Display *xdpy)
-{
- GList *l;
-
- for (l = _cogl_xlib_renderers; l; l = l->next)
- {
- CoglRenderer *renderer = l->data;
- CoglRendererXlib *xlib_renderer = renderer->winsys;
-
- if (xlib_renderer->xdpy == xdpy)
- return renderer;
- }
-
- return NULL;
-}
-
-static int
-error_handler (Display *xdpy,
- XErrorEvent *error)
-{
- CoglRenderer *renderer;
- CoglRendererXlib *xlib_renderer;
-
- renderer = get_renderer_for_xdisplay (xdpy);
-
- xlib_renderer = renderer->winsys;
- g_assert (xlib_renderer->trap_state);
-
- xlib_renderer->trap_state->trapped_error_code = error->error_code;
-
- return 0;
-}
-
-void
-_cogl_renderer_xlib_trap_errors (CoglRenderer *renderer,
- CoglXlibTrapState *state)
-{
- CoglRendererXlib *xlib_renderer;
-
- xlib_renderer = renderer->winsys;
-
- state->trapped_error_code = 0;
- state->old_error_handler = XSetErrorHandler (error_handler);
-
- state->old_state = xlib_renderer->trap_state;
- xlib_renderer->trap_state = state;
-}
-
-int
-_cogl_renderer_xlib_untrap_errors (CoglRenderer *renderer,
- CoglXlibTrapState *state)
-{
- CoglRendererXlib *xlib_renderer;
-
- xlib_renderer = renderer->winsys;
- g_assert (state == xlib_renderer->trap_state);
-
- XSetErrorHandler (state->old_error_handler);
-
- xlib_renderer->trap_state = state->old_state;
-
- return state->trapped_error_code;
-}
-
-static Display *
-assert_xlib_display (CoglRenderer *renderer, GError **error)
-{
- Display *xdpy = cogl_renderer_xlib_get_foreign_display (renderer);
- CoglRendererXlib *xlib_renderer = renderer->winsys;
-
- /* A foreign display may have already been set... */
- if (xdpy)
- {
- xlib_renderer->xdpy = xdpy;
- return xdpy;
- }
-
- xdpy = XOpenDisplay (_cogl_x11_display_name);
- if (xdpy == NULL)
- {
- g_set_error (error,
- COGL_RENDERER_ERROR,
- COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN,
- "Failed to open X Display %s", _cogl_x11_display_name);
- return NULL;
- }
-
- xlib_renderer->xdpy = xdpy;
- return xdpy;
-}
-
-gboolean
-_cogl_renderer_xlib_connect (CoglRenderer *renderer, GError **error)
-{
- CoglRendererXlib *xlib_renderer = renderer->winsys;
- CoglRendererX11 *x11_renderer = renderer->winsys;
- int damage_error;
-
- if (!assert_xlib_display (renderer, error))
- return FALSE;
-
- /* Check whether damage events are supported on this display */
- if (!XDamageQueryExtension (xlib_renderer->xdpy,
- &x11_renderer->damage_base,
- &damage_error))
- x11_renderer->damage_base = -1;
-
- xlib_renderer->trap_state = NULL;
-
- register_xlib_renderer (renderer);
-
- return TRUE;
-}
-
-void
-_cogl_renderer_xlib_disconnect (CoglRenderer *renderer)
-{
- CoglRendererXlib *xlib_renderer = renderer->winsys;
-
- if (!renderer->foreign_xdpy)
- XCloseDisplay (xlib_renderer->xdpy);
-
- unregister_xlib_renderer (renderer);
-}
-
-Display *
-cogl_renderer_xlib_get_display (CoglRenderer *renderer)
-{
- CoglRendererXlib *xlib_renderer;
-
- g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
-
- xlib_renderer = renderer->winsys;
-
- return xlib_renderer->xdpy;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-object.h"
-
-#include "cogl-renderer.h"
-#include "cogl-renderer-private.h"
-#include "cogl-display-private.h"
-#include "cogl-winsys-private.h"
-
-#ifdef COGL_HAS_FULL_WINSYS
-
-#ifdef COGL_HAS_GLX_SUPPORT
-extern const CoglWinsysVtable *_cogl_winsys_glx_get_vtable (void);
-#endif
-#ifdef COGL_HAS_EGL_SUPPORT
-extern const CoglWinsysVtable *_cogl_winsys_egl_get_vtable (void);
-#endif
-
-typedef const CoglWinsysVtable *(*CoglWinsysVtableGetter) (void);
-
-static CoglWinsysVtableGetter _cogl_winsys_vtable_getters[] =
-{
-#ifdef COGL_HAS_GLX_SUPPORT
- _cogl_winsys_glx_get_vtable,
-#endif
-#ifdef COGL_HAS_EGL_SUPPORT
- _cogl_winsys_egl_get_vtable
-#endif
-};
-
-#endif /* COGL_HAS_FULL_WINSYS */
-
-static void _cogl_renderer_free (CoglRenderer *renderer);
-
-COGL_OBJECT_DEFINE (Renderer, renderer);
-
-typedef struct _CoglNativeFilterClosure
-{
- CoglNativeFilterFunc func;
- void *data;
-} CoglNativeFilterClosure;
-
-GQuark
-cogl_renderer_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-renderer-error-quark");
-}
-
-static const CoglWinsysVtable *
-_cogl_renderer_get_winsys (CoglRenderer *renderer)
-{
- return renderer->winsys_vtable;
-}
-
-static void
-native_filter_closure_free (CoglNativeFilterClosure *closure)
-{
- g_slice_free (CoglNativeFilterClosure, closure);
-}
-
-static void
-_cogl_renderer_free (CoglRenderer *renderer)
-{
-#ifdef COGL_HAS_FULL_WINSYS
- const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
- winsys->renderer_disconnect (renderer);
-#endif
-
- g_slist_foreach (renderer->event_filters,
- (GFunc) native_filter_closure_free,
- NULL);
- g_slist_free (renderer->event_filters);
-
- g_free (renderer);
-}
-
-CoglRenderer *
-cogl_renderer_new (void)
-{
- CoglRenderer *renderer = g_new0 (CoglRenderer, 1);
-
- renderer->connected = FALSE;
- renderer->event_filters = NULL;
-
- return _cogl_renderer_object_new (renderer);
-}
-
-#if COGL_HAS_XLIB_SUPPORT
-void
-cogl_renderer_xlib_set_foreign_display (CoglRenderer *renderer,
- Display *xdisplay)
-{
- g_return_if_fail (cogl_is_renderer (renderer));
-
- /* NB: Renderers are considered immutable once connected */
- g_return_if_fail (!renderer->connected);
-
- renderer->foreign_xdpy = xdisplay;
-}
-
-Display *
-cogl_renderer_xlib_get_foreign_display (CoglRenderer *renderer)
-{
- g_return_val_if_fail (cogl_is_renderer (renderer), NULL);
-
- return renderer->foreign_xdpy;
-}
-#endif /* COGL_HAS_XLIB_SUPPORT */
-
-gboolean
-cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
- CoglOnscreenTemplate *onscreen_template,
- GError **error)
-{
-#ifdef COGL_HAS_FULL_WINSYS
- CoglDisplay *display;
- const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
-
- if (!winsys->renderer_connect (renderer, error))
- return FALSE;
-
- display = cogl_display_new (renderer, onscreen_template);
- if (!cogl_display_setup (display, error))
- {
- cogl_object_unref (display);
- return FALSE;
- }
-
- cogl_object_unref (display);
-#endif
- return TRUE;
-}
-
-/* Final connection API */
-
-gboolean
-cogl_renderer_connect (CoglRenderer *renderer, GError **error)
-{
-#ifdef COGL_HAS_FULL_WINSYS
- int i;
- char *renderer_name = getenv ("COGL_RENDERER");
-#endif
- GString *error_message;
-
- if (renderer->connected)
- return TRUE;
-
-#ifdef COGL_HAS_FULL_WINSYS
- error_message = g_string_new ("");
- for (i = 0; i < G_N_ELEMENTS (_cogl_winsys_vtable_getters); i++)
- {
- const CoglWinsysVtable *winsys = _cogl_winsys_vtable_getters[i]();
- GError *tmp_error = NULL;
-
- if (renderer_name && strcmp (winsys->name, renderer_name) != 0)
- continue;
-
- if (!winsys->renderer_connect (renderer, &tmp_error))
- {
- g_string_append_c (error_message, '\n');
- g_string_append (error_message, tmp_error->message);
- g_error_free (tmp_error);
- }
- else
- {
- renderer->winsys_vtable = winsys;
- renderer->connected = TRUE;
- g_string_free (error_message, TRUE);
- return TRUE;
- }
- }
-
- if (!renderer->connected)
- {
- renderer->winsys_vtable = NULL;
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "Failed to connected to any renderer: %s",
- error_message->str);
- g_string_free (error_message, TRUE);
- return FALSE;
- }
-
- return TRUE;
-#else
- renderer->connected = TRUE;
- return TRUE;
-#endif
-}
-
-CoglFilterReturn
-cogl_renderer_handle_native_event (CoglRenderer *renderer,
- void *event)
-{
- GSList *l, *next;
-
- /* Pass the event on to all of the registered filters in turn */
- for (l = renderer->event_filters; l; l = next)
- {
- CoglNativeFilterClosure *closure = l->data;
-
- /* The next pointer is taken now so that we can handle the
- closure being removed during emission */
- next = l->next;
-
- if (closure->func (event, closure->data) == COGL_FILTER_REMOVE)
- return COGL_FILTER_REMOVE;
- }
-
- /* If the backend for the renderer also wants to see the events, it
- should just register its own filter */
-
- return COGL_FILTER_CONTINUE;
-}
-
-void
-cogl_renderer_add_native_filter (CoglRenderer *renderer,
- CoglNativeFilterFunc func,
- void *data)
-{
- CoglNativeFilterClosure *closure;
-
- closure = g_slice_new (CoglNativeFilterClosure);
- closure->func = func;
- closure->data = data;
-
- renderer->event_filters = g_slist_prepend (renderer->event_filters, closure);
-}
-
-void
-cogl_renderer_remove_native_filter (CoglRenderer *renderer,
- CoglNativeFilterFunc func,
- void *data)
-{
- GSList *l, *prev = NULL;
-
- for (l = renderer->event_filters; l; prev = l, l = l->next)
- {
- CoglNativeFilterClosure *closure = l->data;
-
- if (closure->func == func && closure->data == data)
- {
- native_filter_closure_free (closure);
- if (prev)
- prev->next = g_slist_delete_link (prev->next, l);
- else
- renderer->event_filters =
- g_slist_delete_link (renderer->event_filters, l);
- break;
- }
- }
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_RENDERER_H__
-#define __COGL_RENDERER_H__
-
-#include <glib.h>
-
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-onscreen-template.h>
-
-#ifdef COGL_HAS_XLIB
-#include <X11/Xlib.h>
-#endif
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-renderer
- * @short_description:
- *
- */
-
-#define cogl_renderer_error_quark cogl_renderer_error_quark_EXP
-
-#define COGL_RENDERER_ERROR cogl_renderer_error_quark ()
-GQuark
-cogl_renderer_error_quark (void);
-
-typedef struct _CoglRenderer CoglRenderer;
-
-#define cogl_is_renderer cogl_is_renderer_EXP
-gboolean
-cogl_is_renderer (void *object);
-
-#define cogl_renderer_new cogl_renderer_new_EXP
-CoglRenderer *
-cogl_renderer_new (void);
-
-/* optional configuration APIs */
-
-#define cogl_renderer_handle_native_event cogl_renderer_handle_native_event_EXP
-/*
- * cogl_renderer_handle_native_event:
- * @event: pointer to native event structure
- *
- * This function processes a single event; it can be used to hook into
- * external event retrieval (for example that done by Clutter or
- * GDK). The type of the structure that event points to depends on the
- * window system used for the renderer. On an xlib renderer it would
- * be a pointer to an XEvent or an a Windows renderer it would be a
- * pointer to a MSG struct.
- *
- * Return value: #CoglFilterReturn. %COGL_FILTER_REMOVE indicates that
- * Cogl has internally handled the event and the caller should do no
- * further processing. %COGL_FILTER_CONTINUE indicates that Cogl is
- * either not interested in the event, or has used the event to update
- * internal state without taking any exclusive action.
- */
-CoglFilterReturn
-cogl_renderer_handle_native_event (CoglRenderer *renderer,
- void *event);
-
-#define cogl_renderer_add_native_filter cogl_renderer_add_native_filter_EXP
-/*
- * _cogl_renderer_add_native_filter:
- *
- * Adds a callback function that will receive all native events. The
- * function can stop further processing of the event by return
- * %COGL_FILTER_REMOVE. What is considered a native event depends on
- * the type of renderer used. An xlib based renderer would pass all
- * XEvents whereas a Windows based renderer would pass MSGs.
- */
-void
-cogl_renderer_add_native_filter (CoglRenderer *renderer,
- CoglNativeFilterFunc func,
- void *data);
-
-#define cogl_renderer_remove_native_filter \
- cogl_renderer_remove_native_filter_EXP
-/*
- * _cogl_renderer_remove_native_filter:
- *
- * Removes a callback that was previously added with
- * _cogl_renderer_add_native_filter().
- */
-void
-cogl_renderer_remove_native_filter (CoglRenderer *renderer,
- CoglNativeFilterFunc func,
- void *data);
-
-#ifdef COGL_HAS_XLIB
-
-#define cogl_renderer_xlib_get_foreign_display \
- cogl_renderer_xlib_get_foreign_display_EXP
-/*
- * cogl_renderer_xlib_get_foreign_display:
- *
- * Return value: the foreign Xlib display that will be used by any Xlib based
- * winsys backend. The display needs to be set with
- * cogl_renderer_xlib_set_foreign_display() before this function is called.
- */
-Display *
-cogl_renderer_xlib_get_foreign_display (CoglRenderer *renderer);
-
-#define cogl_renderer_xlib_set_foreign_display \
- cogl_renderer_xlib_set_foreign_display_EXP
-/*
- * cogl_renderer_xlib_set_foreign_display:
- *
- * Sets a foreign Xlib display that Cogl will use for and Xlib based winsys
- * backend.
- */
-void
-cogl_renderer_xlib_set_foreign_display (CoglRenderer *renderer,
- Display *display);
-
-#define cogl_renderer_xlib_get_display cogl_renderer_xlib_get_display_EXP
-Display *
-cogl_renderer_xlib_get_display (CoglRenderer *renderer);
-
-#endif /* COGL_HAS_XLIB */
-
-#define cogl_renderer_check_onscreen_template \
- cogl_renderer_check_onscreen_template_EXP
-gboolean
-cogl_renderer_check_onscreen_template (CoglRenderer *renderer,
- CoglOnscreenTemplate *onscreen_template,
- GError **error);
-
-/* Final connection API */
-
-#define cogl_renderer_connect cogl_renderer_connect_EXP
-gboolean
-cogl_renderer_connect (CoglRenderer *renderer, GError **error);
-
-G_END_DECLS
-
-#endif /* __COGL_RENDERER_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_SHADER_BOILERPLATE_H
-#define __COGL_SHADER_BOILERPLATE_H
-
-#include "cogl.h"
-
-
-#ifndef HAVE_COGL_GLES2
-
-#define _COGL_COMMON_SHADER_BOILERPLATE \
- "#define COGL_VERSION 100\n" \
- "\n" \
- "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
- "#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix\n" \
- "#define cogl_projection_matrix gl_ProjectionMatrix\n" \
- "#define cogl_texture_matrix gl_TextureMatrix\n" \
- "\n"
-
-#define _COGL_VERTEX_SHADER_BOILERPLATE \
- _COGL_COMMON_SHADER_BOILERPLATE \
- "#define cogl_position_in gl_Vertex\n" \
- "#define cogl_color_in gl_Color\n" \
- "#define cogl_tex_coord_in gl_MultiTexCoord0\n" \
- "#define cogl_tex_coord0_in gl_MultiTexCoord0\n" \
- "#define cogl_tex_coord1_in gl_MultiTexCoord1\n" \
- "#define cogl_tex_coord2_in gl_MultiTexCoord2\n" \
- "#define cogl_tex_coord3_in gl_MultiTexCoord3\n" \
- "#define cogl_tex_coord4_in gl_MultiTexCoord4\n" \
- "#define cogl_tex_coord5_in gl_MultiTexCoord5\n" \
- "#define cogl_tex_coord6_in gl_MultiTexCoord6\n" \
- "#define cogl_tex_coord7_in gl_MultiTexCoord7\n" \
- "#define cogl_normal_in gl_Normal\n" \
- "\n" \
- "#define cogl_position_out gl_Position\n" \
- "#define cogl_point_size_out gl_PointSize\n" \
- "#define cogl_color_out gl_FrontColor\n" \
- "#define cogl_tex_coord_out gl_TexCoord\n"
-
-#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
- _COGL_COMMON_SHADER_BOILERPLATE \
- "#define cogl_color_in gl_Color\n" \
- "#define cogl_tex_coord_in gl_TexCoord\n" \
- "\n" \
- "#define cogl_color_out gl_FragColor\n" \
- "#define cogl_depth_out gl_FragDepth\n" \
- "\n" \
- "#define cogl_front_facing gl_FrontFacing\n"
-#if 0
- /* GLSL 1.2 has a bottom left origin, though later versions
- * allow use of an origin_upper_left keyword which would be
- * more appropriate for Cogl. */
- "#define coglFragCoord gl_FragCoord\n"
-#endif
-
-#else /* HAVE_COGL_GLES2 */
-
-#define _COGL_COMMON_SHADER_BOILERPLATE \
- "#define COGL_VERSION 100\n" \
- "\n" \
- "uniform mat4 cogl_modelview_matrix;\n" \
- "uniform mat4 cogl_modelview_projection_matrix;\n" \
- "uniform mat4 cogl_projection_matrix;\n" \
- "uniform float cogl_point_size_in;\n"
-
-/* This declares all of the variables that we might need. This is
- working on the assumption that the compiler will optimise them out
- if they are not actually used. The GLSL spec for GLES at least
- implies that this will happen for varyings but it doesn't
- explicitly so for attributes */
-#define _COGL_VERTEX_SHADER_BOILERPLATE \
- _COGL_COMMON_SHADER_BOILERPLATE \
- "#define cogl_color_out _cogl_color\n" \
- "varying vec4 _cogl_color;\n" \
- "#define cogl_tex_coord_out _cogl_tex_coord\n" \
- "#define cogl_position_out gl_Position\n" \
- "#define cogl_point_size_out gl_PointSize\n" \
- "\n" \
- "attribute vec4 cogl_color_in;\n" \
- "attribute vec4 cogl_position_in;\n" \
- "#define cogl_tex_coord_in cogl_tex_coord0_in;\n" \
- "attribute vec3 cogl_normal_in;\n"
-
-#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
- "#if __VERSION__ == 100\n" \
- "precision highp float;\n" \
- "#endif\n" \
- _COGL_COMMON_SHADER_BOILERPLATE \
- "\n" \
- "varying vec4 _cogl_color;\n" \
- "\n" \
- "#define cogl_color_in _cogl_color\n" \
- "#define cogl_tex_coord_in _cogl_tex_coord\n" \
- "\n" \
- "#define cogl_color_out gl_FragColor\n" \
- "#define cogl_depth_out gl_FragDepth\n" \
- "\n" \
- "#define cogl_front_facing gl_FrontFacing\n"
-
-#endif /* HAVE_COGL_GLES2 */
-
-#endif /* __COGL_SHADER_BOILERPLATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_SHADER_H
-#define __COGL_SHADER_H
-
-#include "cogl-handle.h"
-
-typedef struct _CoglShader CoglShader;
-
-typedef enum
-{
- COGL_SHADER_LANGUAGE_GLSL,
-#ifdef HAVE_COGL_GL
- COGL_SHADER_LANGUAGE_ARBFP
-#endif
-} CoglShaderLanguage;
-
-struct _CoglShader
-{
- CoglHandleObject _parent;
- GLuint gl_handle;
- int n_tex_coord_attribs;
- CoglShaderType type;
- CoglShaderLanguage language;
- char *source;
-};
-
-CoglShader *_cogl_shader_pointer_from_handle (CoglHandle handle);
-
-void
-_cogl_shader_compile_real (CoglHandle handle, int n_tex_coord_attribs);
-
-CoglShaderLanguage
-_cogl_program_get_language (CoglHandle handle);
-
-void
-_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
- GLenum shader_gl_type,
- int n_tex_coord_attribs,
- GLsizei count_in,
- const char **strings_in,
- const GLint *lengths_in);
-
-#endif /* __COGL_SHADER_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-shader-private.h"
-#include "cogl-shader-boilerplate.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-
-#include <glib.h>
-
-#include <string.h>
-
-#ifdef HAVE_COGL_GL
-#define glCreateShader ctx->drv.pf_glCreateShader
-#define glGetShaderiv ctx->drv.pf_glGetShaderiv
-#define glGetShaderInfoLog ctx->drv.pf_glGetShaderInfoLog
-#define glCompileShader ctx->drv.pf_glCompileShader
-#define glShaderSource ctx->drv.pf_glShaderSource
-#define glDeleteShader ctx->drv.pf_glDeleteShader
-#define glProgramString ctx->drv.pf_glProgramString
-#define glBindProgram ctx->drv.pf_glBindProgram
-#define glDeletePrograms ctx->drv.pf_glDeletePrograms
-#define glGenPrograms ctx->drv.pf_glGenPrograms
-#define GET_CONTEXT _COGL_GET_CONTEXT
-#else
-#define GET_CONTEXT(CTXVAR,RETVAL) G_STMT_START { } G_STMT_END
-#endif
-
-static void _cogl_shader_free (CoglShader *shader);
-
-COGL_HANDLE_DEFINE (Shader, shader);
-COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (shader);
-
-static void
-_cogl_shader_free (CoglShader *shader)
-{
-#ifndef HAVE_COGL_GLES
-
- /* Frees shader resources but its handle is not
- released! Do that separately before this! */
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- {
- if (shader->gl_handle)
- GE (glDeletePrograms (1, &shader->gl_handle));
- }
- else
-#endif
- if (shader->gl_handle)
- GE (glDeleteShader (shader->gl_handle));
-
-#endif /* HAVE_COGL_GLES */
-
- g_slice_free (CoglShader, shader);
-}
-
-CoglHandle
-cogl_create_shader (CoglShaderType type)
-{
- CoglShader *shader;
-
- GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- switch (type)
- {
- case COGL_SHADER_TYPE_VERTEX:
- case COGL_SHADER_TYPE_FRAGMENT:
- break;
- default:
- g_warning ("Unexpected shader type (0x%08lX) given to "
- "cogl_create_shader", (unsigned long) type);
- return COGL_INVALID_HANDLE;
- }
-
- shader = g_slice_new (CoglShader);
- shader->language = COGL_SHADER_LANGUAGE_GLSL;
- shader->gl_handle = 0;
-#ifdef HAVE_COGL_GLES2
- shader->n_tex_coord_attribs = 0;
-#endif
- shader->type = type;
-
- return _cogl_shader_handle_new (shader);
-}
-
-static void
-delete_shader (CoglShader *shader)
-{
-#ifndef HAVE_COGL_GLES
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- {
- if (shader->gl_handle)
- GE (glDeletePrograms (1, &shader->gl_handle));
- }
- else
-#endif
- {
- if (shader->gl_handle)
- GE (glDeleteShader (shader->gl_handle));
- }
-
- shader->gl_handle = 0;
-
-#endif /* HAVE_COGL_GLES */
-}
-
-void
-cogl_shader_source (CoglHandle handle,
- const char *source)
-{
- CoglShader *shader;
- CoglShaderLanguage language;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!cogl_is_shader (handle))
- return;
-
- shader = _cogl_shader_pointer_from_handle (handle);
-
-#ifdef HAVE_COGL_GL
- if (strncmp (source, "!!ARBfp1.0", 10) == 0)
- language = COGL_SHADER_LANGUAGE_ARBFP;
- else
-#endif
- language = COGL_SHADER_LANGUAGE_GLSL;
-
- /* Delete the old object if the language is changing... */
- if (G_UNLIKELY (language != shader->language) &&
- shader->gl_handle)
- delete_shader (shader);
-
- shader->source = g_strdup (source);
-
- shader->language = language;
-}
-
-void
-cogl_shader_compile (CoglHandle handle)
-{
-#ifdef HAVE_COGL_GL
- CoglShader *shader = handle;
-#endif
-
- if (!cogl_is_shader (handle))
- return;
-
-#ifdef HAVE_COGL_GL
- _cogl_shader_compile_real (shader, 0 /* ignored */);
-#endif
-
- /* XXX: For GLES2 we don't actually compile anything until the
- * shader gets used so we have an opportunity to add some
- * boilerplate to the shader.
- *
- * At the end of the day this is obviously a badly designed API
- * given that we are having to lie to the user. It was a mistake to
- * so thinly wrap the OpenGL shader API and the current plan is to
- * replace it with a pipeline snippets API. */
-}
-
-void
-_cogl_shader_set_source_with_boilerplate (GLuint shader_gl_handle,
- GLenum shader_gl_type,
- int n_tex_coord_attribs,
- GLsizei count_in,
- const char **strings_in,
- const GLint *lengths_in)
-{
-#ifndef HAVE_COGL_GLES
-
- static const char vertex_boilerplate[] = _COGL_VERTEX_SHADER_BOILERPLATE;
- static const char fragment_boilerplate[] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
-
- const char **strings = g_alloca (sizeof (char *) * (count_in + 3));
- GLint *lengths = g_alloca (sizeof (GLint) * (count_in + 3));
- int count = 0;
-#ifdef HAVE_COGL_GLES2
- char *tex_coord_declarations = NULL;
-#endif
-
- GET_CONTEXT (ctx, NO_RETVAL);
-
-#ifdef HAVE_COGL_GLES2
- if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
- {
- static const char texture_3d_extension[] =
- "#extension GL_OES_texture_3D : enable\n";
- strings[count] = texture_3d_extension;
- lengths[count++] = sizeof (texture_3d_extension) - 1;
- }
-#endif
-
- if (shader_gl_type == GL_VERTEX_SHADER)
- {
- strings[count] = vertex_boilerplate;
- lengths[count++] = sizeof (vertex_boilerplate) - 1;
- }
- else if (shader_gl_type == GL_FRAGMENT_SHADER)
- {
- strings[count] = fragment_boilerplate;
- lengths[count++] = sizeof (fragment_boilerplate) - 1;
- }
-
-#ifdef HAVE_COGL_GLES2
- if (n_tex_coord_attribs)
- {
- GString *declarations = g_string_new (NULL);
-
- g_string_append_printf (declarations,
- "varying vec4 _cogl_tex_coord[%d];\n",
- n_tex_coord_attribs);
-
- if (shader_gl_type == GL_VERTEX_SHADER)
- {
- int i;
-
- g_string_append_printf (declarations,
- "uniform mat4 cogl_texture_matrix[%d];\n",
- n_tex_coord_attribs);
-
- for (i = 0; i < n_tex_coord_attribs; i++)
- g_string_append_printf (declarations,
- "attribute vec4 cogl_tex_coord%d_in;\n",
- i);
- }
-
- tex_coord_declarations = g_string_free (declarations, FALSE);
- strings[count] = tex_coord_declarations;
- lengths[count++] = -1; /* null terminated */
- }
-#endif
-
- memcpy (strings + count, strings_in, sizeof (char *) * count_in);
- if (lengths_in)
- memcpy (lengths + count, lengths_in, sizeof (GLint) * count_in);
- else
- {
- int i;
-
- for (i = 0; i < count_in; i++)
- lengths[count + i] = -1; /* null terminated */
- }
- count += count_in;
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
- {
- GString *buf = g_string_new (NULL);
- int i;
-
- g_string_append_printf (buf,
- "%s shader:\n",
- shader_gl_type == GL_VERTEX_SHADER ?
- "vertex" : "fragment");
- for (i = 0; i < count; i++)
- if (lengths[i] != -1)
- g_string_append_len (buf, strings[i], lengths[i]);
- else
- g_string_append (buf, strings[i]);
-
- g_message ("%s", buf->str);
-
- g_string_free (buf, TRUE);
- }
-
- GE( glShaderSource (shader_gl_handle, count,
- (const char **) strings, lengths) );
-
-#ifdef HAVE_COGL_GLES2
- g_free (tex_coord_declarations);
-#endif
-
-#endif /* HAVE_COGL_GLES */
-}
-
-void
-_cogl_shader_compile_real (CoglHandle handle,
- int n_tex_coord_attribs)
-{
-#ifndef HAVE_COGL_GLES
-
- CoglShader *shader = handle;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- {
-#ifdef COGL_GL_DEBUG
- GLenum gl_error;
-#endif
-
- if (shader->gl_handle)
- return;
-
- GE (glGenPrograms (1, &shader->gl_handle));
-
- GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
-
- if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_SHOW_SOURCE)))
- g_message ("user ARBfp program:\n%s", shader->source);
-
-#ifdef COGL_GL_DEBUG
- while ((gl_error = glGetError ()) != GL_NO_ERROR)
- ;
-#endif
- glProgramString (GL_FRAGMENT_PROGRAM_ARB,
- GL_PROGRAM_FORMAT_ASCII_ARB,
- strlen (shader->source),
- shader->source);
-#ifdef COGL_GL_DEBUG
- gl_error = glGetError ();
- if (gl_error != GL_NO_ERROR)
- {
- g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
- G_STRLOC,
- gl_error,
- shader->source,
- glGetString (GL_PROGRAM_ERROR_STRING_ARB));
- }
-#endif
- }
- else
-#endif
- {
- GLenum gl_type;
-
- if (shader->gl_handle
-#ifdef HAVE_COGL_GLES2
- && shader->n_tex_coord_attribs >= n_tex_coord_attribs
-#endif
- )
- return;
-
- if (shader->gl_handle)
- delete_shader (shader);
-
- switch (shader->type)
- {
- case COGL_SHADER_TYPE_VERTEX:
- gl_type = GL_VERTEX_SHADER;
- break;
- case COGL_SHADER_TYPE_FRAGMENT:
- gl_type = GL_FRAGMENT_SHADER;
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- shader->gl_handle = glCreateShader (gl_type);
-
- _cogl_shader_set_source_with_boilerplate (shader->gl_handle,
- gl_type,
- n_tex_coord_attribs,
- 1,
- (const char **) &shader->source,
- NULL);
-
- GE (glCompileShader (shader->gl_handle));
-
-#ifdef HAVE_COGL_GLES2
- shader->n_tex_coord_attribs = n_tex_coord_attribs;
-#endif
-
-#ifdef COGL_GL_DEBUG
- if (!cogl_shader_is_compiled (handle))
- {
- char *log = cogl_shader_get_info_log (handle);
- g_warning ("Failed to compile GLSL program:\nsrc:\n%s\nerror:\n%s\n",
- shader->source,
- log);
- }
-#endif
- }
-
-#endif /* HAVE_COGL_GLES */
-}
-
-char *
-cogl_shader_get_info_log (CoglHandle handle)
-{
-#ifdef HAVE_COGL_GLES
-
- return NULL;
-
-#else /* HAVE_COGL_GLES */
-
- CoglShader *shader;
-
- GET_CONTEXT (ctx, NULL);
-
- if (!cogl_is_shader (handle))
- return NULL;
-
- shader = _cogl_shader_pointer_from_handle (handle);
-
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- {
- /* ARBfp exposes a program error string, but since cogl_program
- * doesn't have any API to query an error log it is not currently
- * exposed. */
- return g_strdup ("");
- }
- else
-#endif
- {
- char buffer[512];
- int len = 0;
-
- /* We don't normally compile the shader when the user calls
- * cogl_shader_compile() because we want to be able to add
- * boilerplate code that depends on how it ends up finally being
- * used.
- *
- * Here we force an early compile if the user is interested in
- * log information to increase the chance that the log will be
- * useful! We have to guess the number of texture coordinate
- * attributes that may be used (normally less than 4) since that
- * affects the boilerplate.
- */
- if (!shader->gl_handle)
- _cogl_shader_compile_real (handle, 4);
-
- glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
- buffer[len] = '\0';
- return g_strdup (buffer);
- }
-
-#endif /* HAVE_COGL_GLES */
-}
-
-CoglShaderType
-cogl_shader_get_type (CoglHandle handle)
-{
- CoglShader *shader;
-
- GET_CONTEXT (ctx, COGL_SHADER_TYPE_VERTEX);
-
- if (!cogl_is_shader (handle))
- {
- g_warning ("Non shader handle type passed to cogl_shader_get_type");
- return COGL_SHADER_TYPE_VERTEX;
- }
-
- shader = _cogl_shader_pointer_from_handle (handle);
- return shader->type;
-}
-
-gboolean
-cogl_shader_is_compiled (CoglHandle handle)
-{
-#ifdef HAVE_COGL_GLES
-
- return FALSE;
-
-#else /* HAVE_COGL_GLES */
-
- GLint status;
- CoglShader *shader;
-
- GET_CONTEXT (ctx, FALSE);
-
- if (!cogl_is_shader (handle))
- return FALSE;
-
- shader = _cogl_shader_pointer_from_handle (handle);
-
-#ifdef HAVE_COGL_GL
- if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
- return TRUE;
- else
-#endif
- {
- /* FIXME: We currently have an arbitrary limit of 4 texture
- * coordinate attributes since our API means we have to add
- * some boilerplate to the users GLSL program (for GLES2)
- * before we actually know how many attributes are in use.
- *
- * 4 will probably be enough (or at least that limitation should
- * be enough until we can replace this API with the pipeline
- * snippets API) but if it isn't then the shader won't compile,
- * through no fault of the user.
- *
- * To some extent this is just a symptom of bad API design; it
- * was a mistake for Cogl to so thinly wrap the OpenGL shader
- * API. Eventually we plan for this whole API will be deprecated
- * by the pipeline snippets framework.
- */
- if (!shader->gl_handle)
- _cogl_shader_compile_real (handle, 4);
-
- GE (glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
- if (status == GL_TRUE)
- return TRUE;
- else
- return FALSE;
- }
-
-#endif /* HAVE_COGL_GLES */
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_SHADER_H__
-#define __COGL_SHADER_H__
-
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-defines.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-shaders
- * @short_description: Fuctions for accessing the programmable GL pipeline
- *
- * COGL allows accessing the GL programmable pipeline in order to create
- * vertex and fragment shaders.
- *
- * The only supported format is GLSL shaders.
- */
-
-/**
- * CoglShaderType:
- * @COGL_SHADER_TYPE_VERTEX: A program for proccessing vertices
- * @COGL_SHADER_TYPE_FRAGMENT: A program for processing fragments
- *
- * Types of shaders
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_SHADER_TYPE_VERTEX,
- COGL_SHADER_TYPE_FRAGMENT
-} CoglShaderType;
-
-/**
- * cogl_create_shader:
- * @shader_type: COGL_SHADER_TYPE_VERTEX or COGL_SHADER_TYPE_FRAGMENT.
- *
- * Create a new shader handle, use #cogl_shader_source to set the source code
- * to be used on it.
- *
- * Returns: a new shader handle.
- */
-CoglHandle
-cogl_create_shader (CoglShaderType shader_type);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_shader_ref:
- * @handle: A #CoglHandle to a shader.
- *
- * Add an extra reference to a shader.
- *
- * Returns: @handle
- */
-CoglHandle
-cogl_shader_ref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-/**
- * cogl_shader_unref:
- * @handle: A #CoglHandle to a shader.
- *
- * Removes a reference to a shader. If it was the last reference the
- * shader object will be destroyed.
- */
-void
-cogl_shader_unref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_is_shader:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing shader object.
- *
- * Returns: %TRUE if the handle references a shader,
- * %FALSE otherwise
- */
-gboolean cogl_is_shader (CoglHandle handle);
-
-/**
- * cogl_shader_source:
- * @shader: #CoglHandle for a shader.
- * @source: GLSL shader source.
- *
- * Replaces the current GLSL source associated with a shader with a new
- * one.
- */
-void
-cogl_shader_source (CoglHandle shader,
- const char *source);
-/**
- * cogl_shader_compile:
- * @handle: #CoglHandle for a shader.
- *
- * Compiles the shader, no return value, but the shader is now ready for
- * linking into a program.
- */
-void
-cogl_shader_compile (CoglHandle handle);
-
-/**
- * cogl_shader_get_info_log:
- * @handle: #CoglHandle for a shader.
- *
- * Retrieves the information log for a coglobject, can be used in conjunction
- * with cogl_shader_get_parameteriv() to retrieve the compiler warnings/error
- * messages that caused a shader to not compile correctly, mainly useful for
- * debugging purposes.
- *
- * Return value: a newly allocated string containing the info log. Use
- * g_free() to free it
- */
-char *
-cogl_shader_get_info_log (CoglHandle handle);
-
-/**
- * cogl_shader_get_type:
- * @handle: #CoglHandle for a shader.
- *
- * Retrieves the type of a shader #CoglHandle
- *
- * Return value: %COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor
- * or %COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor
- */
-CoglShaderType
-cogl_shader_get_type (CoglHandle handle);
-
-/**
- * cogl_shader_is_compiled:
- * @handle: #CoglHandle for a shader.
- *
- * Retrieves whether a shader #CoglHandle has been compiled
- *
- * Return value: %TRUE if the shader object has sucessfully be compiled
- */
-gboolean
-cogl_shader_is_compiled (CoglHandle handle);
-
-/**
- * cogl_create_program:
- *
- * Create a new cogl program object that can be used to replace parts of the GL
- * rendering pipeline with custom code.
- *
- * Returns: a new cogl program.
- */
-CoglHandle
-cogl_create_program (void);
-
-/**
- * cogl_program_ref:
- * @handle: A #CoglHandle to a program.
- *
- * Add an extra reference to a program.
- *
- * Returns: @handle
- */
-CoglHandle
-cogl_program_ref (CoglHandle handle);
-
-/**
- * cogl_program_unref:
- * @handle: A #CoglHandle to a program.
- *
- * Removes a reference to a program. If it was the last reference the
- * program object will be destroyed.
- */
-void
-cogl_program_unref (CoglHandle handle);
-
-/**
- * cogl_is_program:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing program object.
- *
- * Returns: %TRUE if the handle references a program,
- * %FALSE otherwise
- */
-gboolean
-cogl_is_program (CoglHandle handle);
-
-/**
- * cogl_program_attach_shader:
- * @program_handle: a #CoglHandle for a shdaer program.
- * @shader_handle: a #CoglHandle for a vertex of fragment shader.
- *
- * Attaches a shader to a program object, a program can have one vertex shader
- * and one fragment shader attached.
- */
-void
-cogl_program_attach_shader (CoglHandle program_handle,
- CoglHandle shader_handle);
-
-
-/**
- * cogl_program_link:
- * @handle: a #CoglHandle for a shader program.
- *
- * Links a program making it ready for use.
- */
-void
-cogl_program_link (CoglHandle handle);
-
-/**
- * cogl_program_use:
- * @handle: a #CoglHandle for a shader program or %COGL_INVALID_HANDLE.
- *
- * Activate a specific shader program replacing that part of the GL
- * rendering pipeline, if passed in %COGL_INVALID_HANDLE the default
- * behavior of GL is reinstated.
- */
-void
-cogl_program_use (CoglHandle handle);
-
-/**
- * cogl_program_get_uniform_location:
- * @handle: a #CoglHandle for a shader program.
- * @uniform_name: the name of a uniform.
- *
- * Retrieve the location (offset) of a uniform variable in a shader program,
- * a uniform is a variable that is constant for all vertices/fragments for a
- * shader object and is possible to modify as an external parameter.
- *
- * Return value: the offset of a uniform in a specified program.
- * This uniform can be set using cogl_program_uniform_1f() when the
- * program is in use.
- */
-int
-cogl_program_get_uniform_location (CoglHandle handle,
- const char *uniform_name);
-
-/**
- * cogl_program_set_uniform_1f:
- * @program: A #CoglHandle for a linked program
- * @uniform_location: the uniform location retrieved from
- * cogl_program_get_uniform_location().
- * @value: the new value of the uniform.
- *
- * Changes the value of a floating point uniform for the given linked
- * @program.
- *
- * Since: 1.4
- */
-void
-cogl_program_set_uniform_1f (CoglHandle program,
- int uniform_location,
- float value);
-
-/**
- * cogl_program_set_uniform_1i:
- * @program: A #CoglHandle for a linked program
- * @uniform_location: the uniform location retrieved from
- * cogl_program_get_uniform_location().
- * @value: the new value of the uniform.
- *
- * Changes the value of an integer uniform for the given linked
- * @program.
- *
- * Since: 1.4
- */
-void
-cogl_program_set_uniform_1i (CoglHandle program,
- int uniform_location,
- int value);
-
-/**
- * cogl_program_set_uniform_float:
- * @program: A #CoglHandle for a linked program
- * @uniform_location: the uniform location retrieved from
- * cogl_program_get_uniform_location().
- * @n_components: The number of components for the uniform. For
- * example with glsl you'd use 3 for a vec3 or 4 for a vec4.
- * @count: For uniform arrays this is the array length otherwise just
- * pass 1
- * @value: (array length=count): the new value of the uniform[s].
- *
- * Changes the value of a float vector uniform, or uniform array for
- * the given linked @program.
- *
- * Since: 1.4
- */
-void
-cogl_program_set_uniform_float (CoglHandle program,
- int uniform_location,
- int n_components,
- int count,
- const float *value);
-
-/**
- * cogl_program_set_uniform_int:
- * @program: A #CoglHandle for a linked program
- * @uniform_location: the uniform location retrieved from
- * cogl_program_get_uniform_location().
- * @n_components: The number of components for the uniform. For
- * example with glsl you'd use 3 for a vec3 or 4 for a vec4.
- * @count: For uniform arrays this is the array length otherwise just
- * pass 1
- * @value: (array length=count): the new value of the uniform[s].
- *
- * Changes the value of a int vector uniform, or uniform array for
- * the given linked @program.
- *
- * Since: 1.4
- */
-void
-cogl_program_set_uniform_int (CoglHandle program,
- int uniform_location,
- int n_components,
- int count,
- const int *value);
-
-/**
- * cogl_program_set_uniform_matrix:
- * @program: A #CoglHandle for a linked program
- * @uniform_location: the uniform location retrieved from
- * cogl_program_get_uniform_location().
- * @dimensions: The dimensions of the matrix. So for for example pass
- * 2 for a 2x2 matrix or 3 for 3x3.
- * @count: For uniform arrays this is the array length otherwise just
- * pass 1
- * @transpose: Whether to transpose the matrix when setting the uniform.
- * @value: (array length=count): the new value of the uniform.
- *
- * Changes the value of a matrix uniform, or uniform array in the
- * given linked @program.
- *
- * Since: 1.4
- */
-void
-cogl_program_set_uniform_matrix (CoglHandle program,
- int uniform_location,
- int dimensions,
- int count,
- gboolean transpose,
- const float *value);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_program_uniform_1f:
- * @uniform_no: the uniform to set.
- * @value: the new value of the uniform.
- *
- * Changes the value of a floating point uniform in the currently
- * used (see cogl_program_use()) shader program.
- *
- * Deprecated: 1.4: Use cogl_program_set_uniform_1f() instead.
- */
-void
-cogl_program_uniform_1f (int uniform_no,
- float value) G_GNUC_DEPRECATED;
-
-/**
- * cogl_program_uniform_1i:
- * @uniform_no: the uniform to set.
- * @value: the new value of the uniform.
- *
- * Changes the value of an integer uniform in the currently
- * used (see cogl_program_use()) shader program.
- *
- * Deprecated: 1.4: Use cogl_program_set_uniform_1i() instead.
- */
-void
-cogl_program_uniform_1i (int uniform_no,
- int value) G_GNUC_DEPRECATED;
-
-/**
- * cogl_program_uniform_float:
- * @uniform_no: the uniform to set.
- * @size: Size of float vector.
- * @count: Size of array of uniforms.
- * @value: (array length=count): the new value of the uniform.
- *
- * Changes the value of a float vector uniform, or uniform array in the
- * currently used (see cogl_program_use()) shader program.
- *
- * Deprecated: 1.4: Use cogl_program_set_uniform_float() instead.
- */
-void
-cogl_program_uniform_float (int uniform_no,
- int size,
- int count,
- const float *value) G_GNUC_DEPRECATED;
-
-/**
- * cogl_program_uniform_int:
- * @uniform_no: the uniform to set.
- * @size: Size of int vector.
- * @count: Size of array of uniforms.
- * @value: (array length=count): the new value of the uniform.
- *
- * Changes the value of a int vector uniform, or uniform array in the
- * currently used (see cogl_program_use()) shader program.
- */
-void
-cogl_program_uniform_int (int uniform_no,
- int size,
- int count,
- const int *value) G_GNUC_DEPRECATED;
-
-/**
- * cogl_program_uniform_matrix:
- * @uniform_no: the uniform to set.
- * @size: Size of matrix.
- * @count: Size of array of uniforms.
- * @transpose: Whether to transpose the matrix when setting the uniform.
- * @value: (array length=count): the new value of the uniform.
- *
- * Changes the value of a matrix uniform, or uniform array in the
- * currently used (see cogl_program_use()) shader program. The @size
- * parameter is used to determine the square size of the matrix.
- */
-void
-cogl_program_uniform_matrix (int uniform_no,
- int size,
- int count,
- gboolean transpose,
- const float *value) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-G_END_DECLS
-
-#endif /* __COGL_SHADER_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "math.h"
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-spans.h"
-
-void
-_cogl_span_iter_update (CoglSpanIter *iter)
-{
- /* Pick current span */
- iter->span = &g_array_index (iter->array, CoglSpan, iter->index);
-
- /* Offset next position by span size */
- iter->next_pos = iter->pos +
- (float)(iter->span->size - iter->span->waste);
-
- /* Check if span intersects the area to cover */
- if (iter->next_pos <= iter->cover_start ||
- iter->pos >= iter->cover_end)
- {
- /* Intersection undefined */
- iter->intersects = FALSE;
- return;
- }
-
- iter->intersects = TRUE;
-
- /* Clip start position to coverage area */
- if (iter->pos < iter->cover_start)
- iter->intersect_start = iter->cover_start;
- else
- iter->intersect_start = iter->pos;
-
- /* Clip end position to coverage area */
- if (iter->next_pos > iter->cover_end)
- iter->intersect_end = iter->cover_end;
- else
- iter->intersect_end = iter->next_pos;
-}
-
-void
-_cogl_span_iter_begin (CoglSpanIter *iter,
- GArray *spans,
- float normalize_factor,
- float cover_start,
- float cover_end)
-{
- float cover_start_normalized;
-
- iter->index = 0;
- iter->span = NULL;
-
- iter->array = spans;
-
- /* We always iterate in a positive direction from the origin. If
- * iter->flipped == TRUE that means whoever is using this API should
- * interpreted the current span as extending in the opposite direction. I.e.
- * it extends to the left if iterating the X axis, or up if the Y axis. */
- if (cover_start > cover_end)
- {
- float tmp = cover_start;
- cover_start = cover_end;
- cover_end = tmp;
- iter->flipped = TRUE;
- }
- else
- iter->flipped = FALSE;
-
- /* The texture spans cover the normalized texture coordinate space ranging
- * from [0,1] but to help support repeating of sliced textures we allow
- * iteration of any range so we need to relate the start of the range to the
- * nearest point equivalent to 0.
- */
- cover_start_normalized = cover_start / normalize_factor;
- iter->origin = floorf (cover_start_normalized) * normalize_factor;
-
- iter->cover_start = cover_start;
- iter->cover_end = cover_end;
- iter->pos = iter->origin;
-
- /* Update intersection */
- _cogl_span_iter_update (iter);
-}
-
-void
-_cogl_span_iter_next (CoglSpanIter *iter)
-{
- /* Move current position */
- iter->pos = iter->next_pos;
-
- /* Pick next slice (wrap when last reached) */
- iter->index = (iter->index + 1) % iter->array->len;
-
- /* Update intersection */
- _cogl_span_iter_update (iter);
-}
-
-gboolean
-_cogl_span_iter_end (CoglSpanIter *iter)
-{
- /* End reached when whole area covered */
- return iter->pos >= iter->cover_end;
-}
-
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_SPANS_PRIVATE_H
-#define __COGL_SPANS_PRIVATE_H
-
-#include "cogl-handle.h"
-
-typedef struct _CoglSpan
-{
- int start;
- int size;
- int waste;
-} CoglSpan;
-
-typedef struct _CoglSpanIter
-{
- int index;
- GArray *array;
- CoglSpan *span;
- float pos;
- float next_pos;
- float origin;
- float cover_start;
- float cover_end;
- float intersect_start;
- float intersect_end;
- float intersect_start_local;
- float intersect_end_local;
- gboolean intersects;
- gboolean flipped;
-} CoglSpanIter;
-
-void
-_cogl_span_iter_update (CoglSpanIter *iter);
-
-void
-_cogl_span_iter_begin (CoglSpanIter *iter,
- GArray *spans,
- float normalize_factor,
- float cover_start,
- float cover_end);
-
-void
-_cogl_span_iter_next (CoglSpanIter *iter);
-
-gboolean
-_cogl_span_iter_end (CoglSpanIter *iter);
-
-#endif /* __COGL_SPANS_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_SUB_TEXTURE_H
-#define __COGL_SUB_TEXTURE_H
-
-#include "cogl-handle.h"
-#include "cogl-texture-private.h"
-
-#define COGL_SUB_TEXTURE(tex) ((CoglSubTexture *) tex)
-
-typedef struct _CoglSubTexture CoglSubTexture;
-
-struct _CoglSubTexture
-{
- CoglTexture _parent;
-
- /* This is the texture that was passed in to
- _cogl_sub_texture_new. If this is also a sub texture then we will
- use the full texture from that to render instead of making a
- chain. However we want to preserve the next texture in case the
- user is expecting us to keep a reference and also so that we can
- later add a cogl_sub_texture_get_full_texture() function. */
- CoglHandle next_texture;
- /* This is the texture that will actually be used to draw. It will
- point to the end of the chain if a sub texture of a sub texture
- is created */
- CoglHandle full_texture;
-
- /* The region represented by this sub-texture. This is the region of
- full_texture which won't necessarily be the same as the region
- passed to _cogl_sub_texture_new if next_texture is actually
- already a sub texture */
- int sub_x;
- int sub_y;
- int sub_width;
- int sub_height;
-};
-
-GQuark
-_cogl_handle_sub_texture_get_type (void);
-
-CoglHandle
-_cogl_sub_texture_new (CoglHandle next_texture,
- int sub_x,
- int sub_y,
- int sub_width,
- int sub_height);
-
-#endif /* __COGL_SUB_TEXTURE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-sub-texture-private.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-texture-driver.h"
-
-#include <string.h>
-#include <math.h>
-
-static void _cogl_sub_texture_free (CoglSubTexture *sub_tex);
-
-COGL_TEXTURE_INTERNAL_DEFINE (SubTexture, sub_texture);
-
-static const CoglTextureVtable cogl_sub_texture_vtable;
-
-static void
-_cogl_sub_texture_map_range (float *t1, float *t2,
- int sub_offset,
- int sub_size,
- int full_size)
-{
- float t1_frac, t1_int, t2_frac, t2_int;
-
- t1_frac = modff (*t1, &t1_int);
- t2_frac = modff (*t2, &t2_int);
-
- if (t1_frac < 0.0f)
- {
- t1_frac += 1.0f;
- t1_int -= 1.0f;
- }
- if (t2_frac < 0.0f)
- {
- t2_frac += 1.0f;
- t2_int -= 1.0f;
- }
-
- /* If one of the coordinates is zero we need to make sure it is
- still greater than the other coordinate if it was originally so
- we'll flip it to the other side */
- if (*t1 < *t2)
- {
- if (t2_frac == 0.0f)
- {
- t2_frac = 1.0f;
- t2_int -= 1.0f;
- }
- }
- else
- {
- if (t1_frac == 0.0f)
- {
- t1_frac = 1.0f;
- t1_int -= 1.0f;
- }
- }
-
- /* Convert the fractional part leaving the integer part intact */
- t1_frac = (sub_offset + t1_frac * sub_size) / full_size;
- *t1 = t1_frac + t1_int;
-
- t2_frac = (sub_offset + t2_frac * sub_size) / full_size;
- *t2 = t2_frac + t2_int;
-}
-
-static void
-_cogl_sub_texture_map_quad (CoglSubTexture *sub_tex,
- float *coords)
-{
- unsigned int full_width = cogl_texture_get_width (sub_tex->full_texture);
- unsigned int full_height = cogl_texture_get_height (sub_tex->full_texture);
-
- _cogl_sub_texture_map_range (coords + 0, coords + 2,
- sub_tex->sub_x, sub_tex->sub_width,
- full_width);
- _cogl_sub_texture_map_range (coords + 1, coords + 3,
- sub_tex->sub_y, sub_tex->sub_height,
- full_height);
-}
-
-/* Maps from the texture coordinates of the full texture to the
- texture coordinates of the sub texture */
-static float
-_cogl_sub_texture_unmap_coord (float t,
- int sub_offset,
- int sub_size,
- int full_size)
-{
- float frac_part, int_part;
-
- /* Convert the fractional part leaving the integer part in tact */
- frac_part = modff (t, &int_part);
-
- if (cogl_util_float_signbit (frac_part))
- frac_part = ((1.0f + frac_part) * full_size -
- sub_offset - sub_size) / sub_size;
- else
- frac_part = (frac_part * full_size - sub_offset) / sub_size;
-
- return frac_part + int_part;
-}
-
-static void
-_cogl_sub_texture_unmap_coords (CoglSubTexture *sub_tex,
- float *s,
- float *t)
-{
- unsigned int full_width = cogl_texture_get_width (sub_tex->full_texture);
- unsigned int full_height = cogl_texture_get_height (sub_tex->full_texture);
-
- *s = _cogl_sub_texture_unmap_coord (*s, sub_tex->sub_x, sub_tex->sub_width,
- full_width);
- *t = _cogl_sub_texture_unmap_coord (*t, sub_tex->sub_y, sub_tex->sub_height,
- full_height);
-}
-
-typedef struct _CoglSubTextureForeachData
-{
- CoglSubTexture *sub_tex;
- CoglTextureSliceCallback callback;
- void *user_data;
-} CoglSubTextureForeachData;
-
-static void
-_cogl_sub_texture_foreach_cb (CoglHandle handle,
- const float *slice_coords,
- const float *full_virtual_coords,
- void *user_data)
-{
- CoglSubTextureForeachData *data = user_data;
- float virtual_coords[4];
-
- memcpy (virtual_coords, full_virtual_coords, sizeof (virtual_coords));
- /* Convert the virtual coords from the full-texture space to the sub
- texture space */
- _cogl_sub_texture_unmap_coords (data->sub_tex,
- &virtual_coords[0],
- &virtual_coords[1]);
- _cogl_sub_texture_unmap_coords (data->sub_tex,
- &virtual_coords[2],
- &virtual_coords[3]);
-
- data->callback (handle,
- slice_coords, virtual_coords,
- data->user_data);
-}
-
-static void
-_cogl_sub_texture_manual_repeat_cb (const float *coords,
- void *user_data)
-{
- CoglSubTextureForeachData *data = user_data;
- float mapped_coords[4];
-
- memcpy (mapped_coords, coords, sizeof (mapped_coords));
-
- _cogl_sub_texture_map_quad (data->sub_tex, mapped_coords);
-
- _cogl_texture_foreach_sub_texture_in_region (data->sub_tex->full_texture,
- mapped_coords[0],
- mapped_coords[1],
- mapped_coords[2],
- mapped_coords[3],
- _cogl_sub_texture_foreach_cb,
- user_data);
-}
-
-static void
-_cogl_sub_texture_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
- CoglSubTextureForeachData data;
-
- data.sub_tex = sub_tex;
- data.callback = callback;
- data.user_data = user_data;
-
- _cogl_texture_iterate_manual_repeats (_cogl_sub_texture_manual_repeat_cb,
- virtual_tx_1, virtual_ty_1,
- virtual_tx_2, virtual_ty_2,
- &data);
-}
-
-static void
-_cogl_sub_texture_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- _cogl_texture_set_wrap_mode_parameters (sub_tex->full_texture,
- wrap_mode_s,
- wrap_mode_t,
- wrap_mode_p);
-}
-
-static void
-_cogl_sub_texture_free (CoglSubTexture *sub_tex)
-{
- cogl_handle_unref (sub_tex->next_texture);
- cogl_handle_unref (sub_tex->full_texture);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (sub_tex));
-}
-
-CoglHandle
-_cogl_sub_texture_new (CoglHandle next_texture,
- int sub_x, int sub_y,
- int sub_width, int sub_height)
-{
- CoglHandle full_texture;
- CoglSubTexture *sub_tex;
- CoglTexture *tex;
- unsigned int next_width, next_height;
-
- next_width = cogl_texture_get_width (next_texture);
- next_height = cogl_texture_get_height (next_texture);
-
- /* The region must specify a non-zero subset of the full texture */
- g_return_val_if_fail (sub_x >= 0 && sub_y >= 0, COGL_INVALID_HANDLE);
- g_return_val_if_fail (sub_width > 0 && sub_height > 0, COGL_INVALID_HANDLE);
- g_return_val_if_fail (sub_x + sub_width <= next_width, COGL_INVALID_HANDLE);
- g_return_val_if_fail (sub_y + sub_height <= next_height, COGL_INVALID_HANDLE);
-
- sub_tex = g_new (CoglSubTexture, 1);
-
- tex = COGL_TEXTURE (sub_tex);
-
- _cogl_texture_init (tex, &cogl_sub_texture_vtable);
-
- /* If the next texture is also a sub texture we can avoid one level
- of indirection by referencing the full texture of that texture
- instead. */
- if (_cogl_is_sub_texture (next_texture))
- {
- CoglSubTexture *other_sub_tex =
- _cogl_sub_texture_pointer_from_handle (next_texture);
- full_texture = other_sub_tex->full_texture;
- sub_x += other_sub_tex->sub_x;
- sub_y += other_sub_tex->sub_y;
- }
- else
- full_texture = next_texture;
-
- sub_tex->next_texture = cogl_handle_ref (next_texture);
- sub_tex->full_texture = cogl_handle_ref (full_texture);
-
- sub_tex->sub_x = sub_x;
- sub_tex->sub_y = sub_y;
- sub_tex->sub_width = sub_width;
- sub_tex->sub_height = sub_height;
-
- return _cogl_sub_texture_handle_new (sub_tex);
-}
-
-static int
-_cogl_sub_texture_get_max_waste (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return cogl_texture_get_max_waste (sub_tex->full_texture);
-}
-
-static gboolean
-_cogl_sub_texture_is_sliced (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return cogl_texture_is_sliced (sub_tex->full_texture);
-}
-
-static gboolean
-_cogl_sub_texture_can_hardware_repeat (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- /* We can hardware repeat if the subtexture actually represents all of the
- of the full texture */
- return (sub_tex->sub_width ==
- cogl_texture_get_width (sub_tex->full_texture) &&
- sub_tex->sub_height ==
- cogl_texture_get_height (sub_tex->full_texture) &&
- _cogl_texture_can_hardware_repeat (sub_tex->full_texture));
-}
-
-static void
-_cogl_sub_texture_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- /* This won't work if the sub texture is not the size of the full
- texture and the coordinates are outside the range [0,1] */
- *s = ((*s * sub_tex->sub_width + sub_tex->sub_x) /
- cogl_texture_get_width (sub_tex->full_texture));
- *t = ((*t * sub_tex->sub_height + sub_tex->sub_y) /
- cogl_texture_get_height (sub_tex->full_texture));
-
- _cogl_texture_transform_coords_to_gl (sub_tex->full_texture, s, t);
-}
-
-static CoglTransformResult
-_cogl_sub_texture_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
- int i;
-
- /* We can't support repeating with this method. In this case
- cogl-primitives will resort to manual repeating */
- for (i = 0; i < 4; i++)
- if (coords[i] < 0.0f || coords[i] > 1.0f)
- return COGL_TRANSFORM_SOFTWARE_REPEAT;
-
- _cogl_sub_texture_map_quad (sub_tex, coords);
-
- return _cogl_texture_transform_quad_coords_to_gl (sub_tex->full_texture,
- coords);
-}
-
-static gboolean
-_cogl_sub_texture_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return cogl_texture_get_gl_texture (sub_tex->full_texture,
- out_gl_handle,
- out_gl_target);
-}
-
-static void
-_cogl_sub_texture_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- _cogl_texture_set_filters (sub_tex->full_texture, min_filter, mag_filter);
-}
-
-static void
-_cogl_sub_texture_pre_paint (CoglTexture *tex,
- CoglTexturePrePaintFlags flags)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- _cogl_texture_pre_paint (sub_tex->full_texture, flags);
-}
-
-static void
-_cogl_sub_texture_ensure_non_quad_rendering (CoglTexture *tex)
-{
-}
-
-static gboolean
-_cogl_sub_texture_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return _cogl_texture_set_region_from_bitmap (sub_tex->full_texture,
- src_x, src_y,
- dst_x + sub_tex->sub_x,
- dst_y + sub_tex->sub_y,
- dst_width, dst_height,
- bmp);
-}
-
-static CoglPixelFormat
-_cogl_sub_texture_get_format (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return cogl_texture_get_format (sub_tex->full_texture);
-}
-
-static GLenum
-_cogl_sub_texture_get_gl_format (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return _cogl_texture_get_gl_format (sub_tex->full_texture);
-}
-
-static int
-_cogl_sub_texture_get_width (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return sub_tex->sub_width;
-}
-
-static int
-_cogl_sub_texture_get_height (CoglTexture *tex)
-{
- CoglSubTexture *sub_tex = COGL_SUB_TEXTURE (tex);
-
- return sub_tex->sub_height;
-}
-
-static const CoglTextureVtable
-cogl_sub_texture_vtable =
- {
- _cogl_sub_texture_set_region,
- NULL, /* get_data */
- _cogl_sub_texture_foreach_sub_texture_in_region,
- _cogl_sub_texture_get_max_waste,
- _cogl_sub_texture_is_sliced,
- _cogl_sub_texture_can_hardware_repeat,
- _cogl_sub_texture_transform_coords_to_gl,
- _cogl_sub_texture_transform_quad_coords_to_gl,
- _cogl_sub_texture_get_gl_texture,
- _cogl_sub_texture_set_filters,
- _cogl_sub_texture_pre_paint,
- _cogl_sub_texture_ensure_non_quad_rendering,
- _cogl_sub_texture_set_wrap_mode_parameters,
- _cogl_sub_texture_get_format,
- _cogl_sub_texture_get_gl_format,
- _cogl_sub_texture_get_width,
- _cogl_sub_texture_get_height,
- NULL /* is_foreign */
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_SWAP_CHAIN_PRIVATE_H
-#define __COGL_SWAP_CHAIN_PRIVATE_H
-
-#include "cogl-object-private.h"
-
-struct _CoglSwapChain
-{
- CoglObject _parent;
-
- gboolean has_alpha;
-
- int length;
-};
-
-#endif /* __COGL_SWAP_CHAIN_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-object.h"
-
-#include "cogl-swap-chain-private.h"
-
-static void _cogl_swap_chain_free (CoglSwapChain *swap_chain);
-
-COGL_OBJECT_DEFINE (SwapChain, swap_chain);
-
-GQuark
-cogl_swap_chain_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-swap-chain-error-quark");
-}
-
-static void
-_cogl_swap_chain_free (CoglSwapChain *swap_chain)
-{
- g_slice_free (CoglSwapChain, swap_chain);
-}
-
-CoglSwapChain *
-cogl_swap_chain_new (void)
-{
- CoglSwapChain *swap_chain = g_slice_new0 (CoglSwapChain);
-
- swap_chain->length = -1; /* no preference */
-
- return _cogl_swap_chain_object_new (swap_chain);
-}
-
-void
-cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain,
- gboolean has_alpha)
-{
- swap_chain->has_alpha = has_alpha;
-}
-
-void
-cogl_swap_chain_set_length (CoglSwapChain *swap_chain,
- int length)
-{
- swap_chain->length = length;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_SWAP_CHAIN_H__
-#define __COGL_SWAP_CHAIN_H__
-
-G_BEGIN_DECLS
-
-typedef struct _CoglSwapChain CoglSwapChain;
-
-#define cogl_swap_chain_new cogl_swap_chain_new_EXP
-CoglSwapChain *
-cogl_swap_chain_new (void);
-
-#define cogl_swap_chain_set_has_alpha cogl_swap_chain_set_has_alpha_EXP
-void
-cogl_swap_chain_set_has_alpha (CoglSwapChain *swap_chain,
- gboolean has_alpha);
-
-#define cogl_swap_chain_set_length cogl_swap_chain_set_length_EXP
-void
-cogl_swap_chain_set_length (CoglSwapChain *swap_chain,
- int length);
-
-G_END_DECLS
-
-#endif /* __COGL_SWAP_CHAIN_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_2D_H
-#define __COGL_TEXTURE_2D_H
-
-#include "cogl-handle.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-texture-private.h"
-
-#define COGL_TEXTURE_2D(tex) ((CoglTexture2D *) tex)
-
-typedef struct _CoglTexture2D CoglTexture2D;
-
-struct _CoglTexture2D
-{
- CoglTexture _parent;
-
- /* The internal format of the GL texture represented as a
- CoglPixelFormat */
- CoglPixelFormat format;
- /* The internal format of the GL texture represented as a GL enum */
- GLenum gl_format;
- /* The texture object number */
- GLuint gl_texture;
- int width;
- int height;
- GLenum min_filter;
- GLenum mag_filter;
- GLint wrap_mode_s;
- GLint wrap_mode_t;
- gboolean auto_mipmap;
- gboolean mipmaps_dirty;
- gboolean is_foreign;
-
- CoglTexturePixel first_pixel;
-};
-
-GQuark
-_cogl_handle_texture_2d_get_type (void);
-
-gboolean
-_cogl_is_texture_2d (CoglHandle object);
-
-CoglHandle
-_cogl_texture_2d_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_texture_2d_new_from_foreign (GLuint gl_handle,
- GLuint width,
- GLuint height,
- CoglPixelFormat format);
-
-/*
- * _cogl_texture_2d_externally_modified:
- * @handle: A handle to a 2D texture
- *
- * This should be called whenever the texture is modified other than
- * by using cogl_texture_set_region. It will cause the mipmaps to be
- * invalidated
- */
-void
-_cogl_texture_2d_externally_modified (CoglHandle handle);
-
-/*
- * _cogl_texture_2d_copy_from_framebuffer:
- * @handle: A handle to a 2D texture
- * @dst_x: X-position to store the image within the texture
- * @dst_y: Y-position to store the image within the texture
- * @src_x: X-position to within the framebuffer to read from
- * @src_y: Y-position to within the framebuffer to read from
- * @width: width of the rectangle to copy
- * @height: height of the rectangle to copy
- *
- * This copies a portion of the current read framebuffer into the
- * texture.
- */
-void
-_cogl_texture_2d_copy_from_framebuffer (CoglHandle handle,
- int dst_x,
- int dst_y,
- int src_x,
- int src_y,
- int width,
- int height);
-
-#endif /* __COGL_TEXTURE_2D_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_2D_SLICED_H
-#define __COGL_TEXTURE_2D_SLICED_H
-
-#include "cogl-bitmap-private.h"
-#include "cogl-handle.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-texture-private.h"
-
-#define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex)
-
-typedef struct _CoglTexture2DSliced CoglTexture2DSliced;
-
-struct _CoglTexture2DSliced
-{
- CoglTexture _parent;
- GArray *slice_x_spans;
- GArray *slice_y_spans;
- GArray *slice_textures;
- int max_waste;
-
- int width;
- int height;
-};
-
-GQuark
-_cogl_handle_texture_2d_sliced_get_type (void);
-
-CoglHandle
-_cogl_texture_2d_sliced_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
- GLenum gl_target,
- GLuint width,
- GLuint height,
- GLuint x_pot_waste,
- GLuint y_pot_waste,
- CoglPixelFormat format);
-
-CoglHandle
-_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-#endif /* __COGL_TEXTURE_2D_SLICED_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Matthew Allum <mallum@openedhand.com>
- * Neil Roberts <neil@linux.intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-bitmap.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-2d-sliced-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-spans.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-static void _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds);
-
-COGL_TEXTURE_INTERNAL_DEFINE (Texture2DSliced, texture_2d_sliced);
-
-static const CoglTextureVtable cogl_texture_2d_sliced_vtable;
-
-typedef struct
-{
- CoglTexture2DSliced *tex;
- CoglSpan *x_span;
- CoglSpan *y_span;
-
- CoglTextureSliceCallback callback;
- void *user_data;
-} ForeachData;
-
-static void
-_cogl_texture_2d_sliced_foreach_cb (CoglHandle handle,
- const float *slice_coords,
- const float *virtual_coords_in,
- void *user_data)
-{
- float virtual_coords_out[4];
- ForeachData *data = user_data;
-
- /* Convert the virtual coordinates of the texture slice back to
- coordinates in the space of the outer texture */
- virtual_coords_out[0] = (virtual_coords_in[0] * data->x_span->size +
- data->x_span->start) / data->tex->width;
- virtual_coords_out[1] = (virtual_coords_in[1] * data->y_span->size +
- data->y_span->start) / data->tex->height;
- virtual_coords_out[2] = (virtual_coords_in[2] * data->x_span->size +
- data->x_span->start) / data->tex->width;
- virtual_coords_out[3] = (virtual_coords_in[3] * data->y_span->size +
- data->y_span->start) / data->tex->height;
-
- data->callback (handle,
- slice_coords,
- virtual_coords_out,
- data->user_data);
-}
-
-/* To differentiate between texture coordinates of a specific, real, slice
- * texture and the texture coordinates of the composite, sliced texture, the
- * coordinates of the sliced texture are called "virtual" coordinates and the
- * coordinates of slices are called "slice" coordinates. */
-/* This function lets you iterate all the slices that lie within the given
- * virtual coordinates of the parent sliced texture. */
-/* Note: no guarantee is given about the order in which the slices will be
- * visited */
-static void
-_cogl_texture_2d_sliced_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- float width = tex_2ds->width;
- float height = tex_2ds->height;
- CoglSpanIter iter_x;
- CoglSpanIter iter_y;
- ForeachData data;
-
- data.tex = COGL_TEXTURE_2D_SLICED (tex);
- data.callback = callback;
- data.user_data = user_data;
-
- /* Slice spans are stored in denormalized coordinates, and this is what
- * the _cogl_span_iter_* funcs expect to be given, so we scale the given
- * virtual coordinates by the texture size to denormalize.
- */
- /* XXX: I wonder if it's worth changing how we store spans so we can avoid
- * the need to denormalize here */
- virtual_tx_1 *= width;
- virtual_ty_1 *= height;
- virtual_tx_2 *= width;
- virtual_ty_2 *= height;
-
- /* Iterate the y axis of the virtual rectangle */
- for (_cogl_span_iter_begin (&iter_y,
- tex_2ds->slice_y_spans,
- height,
- virtual_ty_1,
- virtual_ty_2);
- !_cogl_span_iter_end (&iter_y);
- _cogl_span_iter_next (&iter_y))
- {
- float y_intersect_start = iter_y.intersect_start;
- float y_intersect_end = iter_y.intersect_end;
- float slice_ty1;
- float slice_ty2;
-
- /* Discard slices out of rectangle early */
- if (!iter_y.intersects)
- continue;
-
- if (iter_y.flipped)
- {
- y_intersect_start = iter_y.intersect_end;
- y_intersect_end = iter_y.intersect_start;
- }
-
- /* Localize slice texture coordinates */
- slice_ty1 = y_intersect_start - iter_y.pos;
- slice_ty2 = y_intersect_end - iter_y.pos;
-
- /* Normalize slice texture coordinates */
- slice_ty1 /= iter_y.span->size;
- slice_ty2 /= iter_y.span->size;
-
- data.y_span = iter_y.span;
-
- /* Iterate the x axis of the virtual rectangle */
- for (_cogl_span_iter_begin (&iter_x,
- tex_2ds->slice_x_spans,
- width,
- virtual_tx_1,
- virtual_tx_2);
- !_cogl_span_iter_end (&iter_x);
- _cogl_span_iter_next (&iter_x))
- {
- float x_intersect_start = iter_x.intersect_start;
- float x_intersect_end = iter_x.intersect_end;
- float slice_tx1;
- float slice_tx2;
- CoglHandle slice_tex;
-
- /* Discard slices out of rectangle early */
- if (!iter_x.intersects)
- continue;
-
- if (iter_x.flipped)
- {
- x_intersect_start = iter_x.intersect_end;
- x_intersect_end = iter_x.intersect_start;
- }
-
- /* Localize slice texture coordinates */
- slice_tx1 = x_intersect_start - iter_x.pos;
- slice_tx2 = x_intersect_end - iter_x.pos;
-
- /* Normalize slice texture coordinates */
- slice_tx1 /= iter_x.span->size;
- slice_tx2 /= iter_x.span->size;
-
- data.x_span = iter_x.span;
-
- /* Pluck out the cogl texture for this slice */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle,
- iter_y.index * iter_x.array->len +
- iter_x.index);
-
- _cogl_texture_foreach_sub_texture_in_region
- (slice_tex,
- slice_tx1, slice_ty1, slice_tx2, slice_ty2,
- _cogl_texture_2d_sliced_foreach_cb,
- &data);
- }
- }
-}
-
-static guint8 *
-_cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds,
- CoglPixelFormat format)
-{
- CoglSpan *last_x_span;
- CoglSpan *last_y_span;
- guint8 *waste_buf = NULL;
-
- /* If the texture has any waste then allocate a buffer big enough to
- fill the gaps */
- last_x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan,
- tex_2ds->slice_x_spans->len - 1);
- last_y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan,
- tex_2ds->slice_y_spans->len - 1);
- if (last_x_span->waste > 0 || last_y_span->waste > 0)
- {
- int bpp = _cogl_get_format_bpp (format);
- CoglSpan *first_x_span
- = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0);
- CoglSpan *first_y_span
- = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0);
- unsigned int right_size = first_y_span->size * last_x_span->waste;
- unsigned int bottom_size = first_x_span->size * last_y_span->waste;
-
- waste_buf = g_malloc (MAX (right_size, bottom_size) * bpp);
- }
-
- return waste_buf;
-}
-
-static void
-_cogl_texture_2d_sliced_set_waste (CoglTexture2DSliced *tex_2ds,
- CoglBitmap *source_bmp,
- CoglHandle slice_tex,
- guint8 *waste_buf,
- CoglSpan *x_span,
- CoglSpan *y_span,
- CoglSpanIter *x_iter,
- CoglSpanIter *y_iter,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y)
-{
- gboolean need_x, need_y;
-
- /* If the x_span is sliced and the upload touches the
- rightmost pixels then fill the waste with copies of the
- pixels */
- need_x = x_span->waste > 0 &&
- x_iter->intersect_end - x_iter->pos >= x_span->size - x_span->waste;
-
- /* same for the bottom-most pixels */
- need_y = y_span->waste > 0 &&
- y_iter->intersect_end - y_iter->pos >= y_span->size - y_span->waste;
-
- if (need_x || need_y)
- {
- int bmp_rowstride = _cogl_bitmap_get_rowstride (source_bmp);
- CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
- int bpp = _cogl_get_format_bpp (source_format);
- guint8 *bmp_data;
- const guint8 *src;
- guint8 *dst;
- unsigned int wy, wx;
- CoglBitmap *waste_bmp;
-
- bmp_data = _cogl_bitmap_map (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- if (bmp_data == NULL)
- return;
-
- if (need_x)
- {
- src = (bmp_data + ((src_y + (int) y_iter->intersect_start - dst_y) *
- bmp_rowstride) +
- (src_x + x_span->start + x_span->size -
- x_span->waste - dst_x - 1) * bpp);
-
- dst = waste_buf;
-
- for (wy = 0;
- wy < y_iter->intersect_end - y_iter->intersect_start;
- wy++)
- {
- for (wx = 0; wx < x_span->waste; wx++)
- {
- memcpy (dst, src, bpp);
- dst += bpp;
- }
- src += bmp_rowstride;
- }
-
- waste_bmp =
- _cogl_bitmap_new_from_data (waste_buf,
- source_format,
- x_span->waste,
- y_iter->intersect_end -
- y_iter->intersect_start,
- x_span->waste * bpp,
- NULL,
- NULL);
-
- _cogl_texture_set_region_from_bitmap (slice_tex,
- 0, /* src_x */
- 0, /* src_y */
- /* dst_x */
- x_span->size - x_span->waste,
- y_iter->intersect_start -
- y_span->start, /* dst_y */
- x_span->waste, /* dst_width */
- /* dst_height */
- y_iter->intersect_end -
- y_iter->intersect_start,
- waste_bmp);
-
- cogl_object_unref (waste_bmp);
- }
-
- if (need_y)
- {
- unsigned int copy_width, intersect_width;
-
- src = (bmp_data + ((src_x + (int) x_iter->intersect_start - dst_x) *
- bpp) +
- (src_y + y_span->start + y_span->size - y_span->waste
- - dst_y - 1) * bmp_rowstride);
-
- dst = waste_buf;
-
- if (x_iter->intersect_end - x_iter->pos
- >= x_span->size - x_span->waste)
- copy_width = x_span->size + x_iter->pos - x_iter->intersect_start;
- else
- copy_width = x_iter->intersect_end - x_iter->intersect_start;
-
- intersect_width = x_iter->intersect_end - x_iter->intersect_start;
-
- for (wy = 0; wy < y_span->waste; wy++)
- {
- memcpy (dst, src, intersect_width * bpp);
- dst += intersect_width * bpp;
-
- for (wx = intersect_width; wx < copy_width; wx++)
- {
- memcpy (dst, dst - bpp, bpp);
- dst += bpp;
- }
- }
-
- waste_bmp =
- _cogl_bitmap_new_from_data (waste_buf,
- source_format,
- copy_width,
- y_span->waste,
- copy_width * bpp,
- NULL,
- NULL);
-
- _cogl_texture_set_region_from_bitmap (slice_tex,
- 0, /* src_x */
- 0, /* src_y */
- /* dst_x */
- x_iter->intersect_start -
- x_iter->pos,
- /* dst_y */
- y_span->size - y_span->waste,
- copy_width, /* dst_width */
- y_span->waste, /* dst_height */
- waste_bmp);
-
- cogl_object_unref (waste_bmp);
- }
-
- _cogl_bitmap_unmap (source_bmp);
- }
-}
-
-static gboolean
-_cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds,
- CoglBitmap *bmp)
-{
- CoglSpan *x_span;
- CoglSpan *y_span;
- CoglHandle slice_tex;
- int x, y;
- guint8 *waste_buf;
- CoglPixelFormat bmp_format;
-
- bmp_format = _cogl_bitmap_get_format (bmp);
-
- waste_buf = _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds,
- bmp_format);
-
- /* Iterate vertical slices */
- for (y = 0; y < tex_2ds->slice_y_spans->len; ++y)
- {
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y);
-
- /* Iterate horizontal slices */
- for (x = 0; x < tex_2ds->slice_x_spans->len; ++x)
- {
- int slice_num = y * tex_2ds->slice_x_spans->len + x;
- CoglSpanIter x_iter, y_iter;
-
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x);
-
- /* Pick the gl texture object handle */
- slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglHandle, slice_num);
-
- _cogl_texture_set_region_from_bitmap (slice_tex,
- x_span->start, /* src x */
- y_span->start, /* src y */
- 0, /* dst x */
- 0, /* dst y */
- x_span->size -
- x_span->waste, /* width */
- y_span->size -
- y_span->waste, /* height */
- bmp);
-
- /* Set up a fake iterator that covers the whole slice */
- x_iter.intersect_start = x_span->start;
- x_iter.intersect_end = (x_span->start +
- x_span->size -
- x_span->waste);
- x_iter.pos = x_span->start;
-
- y_iter.intersect_start = y_span->start;
- y_iter.intersect_end = (y_span->start +
- y_span->size -
- y_span->waste);
- y_iter.pos = y_span->start;
-
- _cogl_texture_2d_sliced_set_waste (tex_2ds,
- bmp,
- slice_tex,
- waste_buf,
- x_span, y_span,
- &x_iter, &y_iter,
- 0, /* src_x */
- 0, /* src_y */
- 0, /* dst_x */
- 0); /* dst_y */
- }
- }
-
- if (waste_buf)
- g_free (waste_buf);
-
- return TRUE;
-}
-
-static gboolean
-_cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height,
- CoglBitmap *source_bmp,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- CoglSpan *x_span;
- CoglSpan *y_span;
- CoglSpanIter x_iter;
- CoglSpanIter y_iter;
- CoglHandle slice_tex;
- int source_x = 0, source_y = 0;
- int inter_w = 0, inter_h = 0;
- int local_x = 0, local_y = 0;
- guint8 *waste_buf;
- CoglPixelFormat source_format;
-
- source_format = _cogl_bitmap_get_format (source_bmp);
-
- waste_buf =
- _cogl_texture_2d_sliced_allocate_waste_buffer (tex_2ds, source_format);
-
- /* Iterate vertical spans */
- for (source_y = src_y,
- _cogl_span_iter_begin (&y_iter,
- tex_2ds->slice_y_spans,
- tex_2ds->height,
- dst_y,
- dst_y + height);
-
- !_cogl_span_iter_end (&y_iter);
-
- _cogl_span_iter_next (&y_iter),
- source_y += inter_h )
- {
- /* Discard slices out of the subregion early */
- if (!y_iter.intersects)
- {
- inter_h = 0;
- continue;
- }
-
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan,
- y_iter.index);
-
- /* Iterate horizontal spans */
- for (source_x = src_x,
- _cogl_span_iter_begin (&x_iter,
- tex_2ds->slice_x_spans,
- tex_2ds->width,
- dst_x,
- dst_x + width);
-
- !_cogl_span_iter_end (&x_iter);
-
- _cogl_span_iter_next (&x_iter),
- source_x += inter_w )
- {
- int slice_num;
-
- /* Discard slices out of the subregion early */
- if (!x_iter.intersects)
- {
- inter_w = 0;
- continue;
- }
-
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan,
- x_iter.index);
-
- /* Pick intersection width and height */
- inter_w = (x_iter.intersect_end - x_iter.intersect_start);
- inter_h = (y_iter.intersect_end - y_iter.intersect_start);
-
- /* Localize intersection top-left corner to slice*/
- local_x = (x_iter.intersect_start - x_iter.pos);
- local_y = (y_iter.intersect_start - y_iter.pos);
-
- slice_num = y_iter.index * tex_2ds->slice_x_spans->len + x_iter.index;
-
- /* Pick slice texture */
- slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglHandle, slice_num);
-
- _cogl_texture_set_region_from_bitmap (slice_tex,
- source_x,
- source_y,
- local_x, /* dst x */
- local_y, /* dst y */
- inter_w, /* width */
- inter_h, /* height */
- source_bmp);
-
- _cogl_texture_2d_sliced_set_waste (tex_2ds,
- source_bmp,
- slice_tex,
- waste_buf,
- x_span, y_span,
- &x_iter, &y_iter,
- src_x, src_y,
- dst_x, dst_y);
- }
- }
-
- g_free (waste_buf);
-
- return TRUE;
-}
-
-static int
-_cogl_rect_slices_for_size (int size_to_fill,
- int max_span_size,
- int max_waste,
- GArray *out_spans)
-{
- int n_spans = 0;
- CoglSpan span;
-
- /* Init first slice span */
- span.start = 0;
- span.size = max_span_size;
- span.waste = 0;
-
- /* Repeat until whole area covered */
- while (size_to_fill >= span.size)
- {
- /* Add another slice span of same size */
- if (out_spans)
- g_array_append_val (out_spans, span);
- span.start += span.size;
- size_to_fill -= span.size;
- n_spans++;
- }
-
- /* Add one last smaller slice span */
- if (size_to_fill > 0)
- {
- span.size = size_to_fill;
- if (out_spans)
- g_array_append_val (out_spans, span);
- n_spans++;
- }
-
- return n_spans;
-}
-
-static int
-_cogl_pot_slices_for_size (int size_to_fill,
- int max_span_size,
- int max_waste,
- GArray *out_spans)
-{
- int n_spans = 0;
- CoglSpan span;
-
- /* Init first slice span */
- span.start = 0;
- span.size = max_span_size;
- span.waste = 0;
-
- /* Fix invalid max_waste */
- if (max_waste < 0)
- max_waste = 0;
-
- while (TRUE)
- {
- /* Is the whole area covered? */
- if (size_to_fill > span.size)
- {
- /* Not yet - add a span of this size */
- if (out_spans)
- g_array_append_val (out_spans, span);
-
- span.start += span.size;
- size_to_fill -= span.size;
- n_spans++;
- }
- else if (span.size - size_to_fill <= max_waste)
- {
- /* Yes and waste is small enough */
- /* Pick the next power of two up from size_to_fill. This can
- sometimes be less than the span.size that would be chosen
- otherwise */
- span.size = _cogl_util_next_p2 (size_to_fill);
- span.waste = span.size - size_to_fill;
- if (out_spans)
- g_array_append_val (out_spans, span);
-
- return ++n_spans;
- }
- else
- {
- /* Yes but waste is too large */
- while (span.size - size_to_fill > max_waste)
- {
- span.size /= 2;
- g_assert (span.size > 0);
- }
- }
- }
-
- /* Can't get here */
- return 0;
-}
-
-static void
-_cogl_texture_2d_sliced_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- int i;
-
- /* Pass the set wrap mode on to all of the child textures */
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglHandle,
- i);
-
- _cogl_texture_set_wrap_mode_parameters (slice_tex,
- wrap_mode_s,
- wrap_mode_t,
- wrap_mode_p);
- }
-}
-
-static gboolean
-_cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds,
- int width, int height,
- CoglPixelFormat format,
- CoglTextureFlags flags)
-{
- int max_width;
- int max_height;
- CoglHandle *slice_textures;
- int n_x_slices;
- int n_y_slices;
- int n_slices;
- int x, y;
- CoglSpan *x_span;
- CoglSpan *y_span;
- GLenum gl_intformat;
- GLenum gl_type;
-
- int (*slices_for_size) (int, int, int, GArray*);
-
- /* Initialize size of largest slice according to supported features */
- if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
- {
- max_width = width;
- max_height = height;
- slices_for_size = _cogl_rect_slices_for_size;
- }
- else
- {
- max_width = _cogl_util_next_p2 (width);
- max_height = _cogl_util_next_p2 (height);
- slices_for_size = _cogl_pot_slices_for_size;
- }
-
- _cogl_pixel_format_to_gl (format, &gl_intformat, NULL, &gl_type);
-
- /* Negative number means no slicing forced by the user */
- if (tex_2ds->max_waste <= -1)
- {
- CoglSpan span;
-
- /* Check if size supported else bail out */
- if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
- gl_intformat,
- gl_type,
- max_width,
- max_height))
- {
- return FALSE;
- }
-
- n_x_slices = 1;
- n_y_slices = 1;
-
- /* Init span arrays */
- tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan),
- 1);
-
- tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan),
- 1);
-
- /* Add a single span for width and height */
- span.start = 0;
- span.size = max_width;
- span.waste = max_width - width;
- g_array_append_val (tex_2ds->slice_x_spans, span);
-
- span.size = max_height;
- span.waste = max_height - height;
- g_array_append_val (tex_2ds->slice_y_spans, span);
- }
- else
- {
- /* Decrease the size of largest slice until supported by GL */
- while (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
- gl_intformat,
- gl_type,
- max_width,
- max_height))
- {
- /* Alternate between width and height */
- if (max_width > max_height)
- max_width /= 2;
- else
- max_height /= 2;
-
- if (max_width == 0 || max_height == 0)
- return FALSE;
- }
-
- /* Determine the slices required to cover the bitmap area */
- n_x_slices = slices_for_size (width,
- max_width, tex_2ds->max_waste,
- NULL);
-
- n_y_slices = slices_for_size (height,
- max_height, tex_2ds->max_waste,
- NULL);
-
- /* Init span arrays with reserved size */
- tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan),
- n_x_slices);
-
- tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan),
- n_y_slices);
-
- /* Fill span arrays with info */
- slices_for_size (width,
- max_width, tex_2ds->max_waste,
- tex_2ds->slice_x_spans);
-
- slices_for_size (height,
- max_height, tex_2ds->max_waste,
- tex_2ds->slice_y_spans);
- }
-
- /* Init and resize GL handle array */
- n_slices = n_x_slices * n_y_slices;
-
- tex_2ds->slice_textures = g_array_sized_new (FALSE, FALSE,
- sizeof (CoglHandle),
- n_slices);
-
- g_array_set_size (tex_2ds->slice_textures, n_slices);
-
- /* Generate a "working set" of GL texture objects
- * (some implementations might supported faster
- * re-binding between textures inside a set) */
- slice_textures = (CoglHandle *) tex_2ds->slice_textures->data;
-
- /* Init each GL texture object */
- for (y = 0; y < n_y_slices; ++y)
- {
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y);
-
- for (x = 0; x < n_x_slices; ++x)
- {
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x);
-
- COGL_NOTE (SLICING, "CREATE SLICE (%d,%d)\tsize (%d,%d)",
- x, y,
- x_span->size - x_span->waste,
- y_span->size - y_span->waste);
-
- slice_textures[y * n_x_slices + x] =
- cogl_texture_new_with_size (x_span->size, y_span->size,
- COGL_TEXTURE_NO_ATLAS | flags,
- format);
- }
- }
-
- return TRUE;
-}
-
-static void
-_cogl_texture_2d_sliced_slices_free (CoglTexture2DSliced *tex_2ds)
-{
- if (tex_2ds->slice_x_spans != NULL)
- g_array_free (tex_2ds->slice_x_spans, TRUE);
-
- if (tex_2ds->slice_y_spans != NULL)
- g_array_free (tex_2ds->slice_y_spans, TRUE);
-
- if (tex_2ds->slice_textures != NULL)
- {
- int i;
-
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- CoglHandle slice_tex =
- g_array_index (tex_2ds->slice_textures, CoglHandle, i);
- cogl_handle_unref (slice_tex);
- }
-
- g_array_free (tex_2ds->slice_textures, TRUE);
- }
-}
-
-static void
-_cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds)
-{
- _cogl_texture_2d_sliced_slices_free (tex_2ds);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (tex_2ds));
-}
-
-static gboolean
-_cogl_texture_2d_sliced_init_base (CoglTexture2DSliced *tex_2ds,
- int width,
- int height,
- CoglPixelFormat internal_format,
- CoglTextureFlags flags)
-{
- CoglTexture *tex = COGL_TEXTURE (tex_2ds);
-
- _cogl_texture_init (tex, &cogl_texture_2d_sliced_vtable);
-
- tex_2ds->slice_x_spans = NULL;
- tex_2ds->slice_y_spans = NULL;
- tex_2ds->slice_textures = NULL;
-
- /* Create slices for the given format and size */
- if (!_cogl_texture_2d_sliced_slices_create (tex_2ds,
- width,
- height,
- internal_format,
- flags))
- return FALSE;
-
- tex_2ds->width = width;
- tex_2ds->height = height;
-
- return TRUE;
-}
-
-CoglHandle
-_cogl_texture_2d_sliced_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture2DSliced *tex_2ds;
-
- /* Since no data, we need some internal format */
- if (internal_format == COGL_PIXEL_FORMAT_ANY)
- internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
-
- /* Init texture with empty bitmap */
- tex_2ds = g_new (CoglTexture2DSliced, 1);
-
- if ((flags & COGL_TEXTURE_NO_SLICING))
- tex_2ds->max_waste = -1;
- else
- tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
-
- if (!_cogl_texture_2d_sliced_init_base (tex_2ds,
- width, height,
- internal_format,
- flags))
- {
- _cogl_texture_2d_sliced_free (tex_2ds);
- return COGL_INVALID_HANDLE;
- }
-
- return _cogl_texture_2d_sliced_handle_new (tex_2ds);
-}
-
-CoglHandle
-_cogl_texture_2d_sliced_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture2DSliced *tex_2ds;
- CoglBitmap *dst_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- int width, height;
-
- g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
-
- width = _cogl_bitmap_get_width (bmp);
- height = _cogl_bitmap_get_height (bmp);
-
- /* Create new texture and fill with loaded data */
- tex_2ds = g_new0 (CoglTexture2DSliced, 1);
-
- if (flags & COGL_TEXTURE_NO_SLICING)
- tex_2ds->max_waste = -1;
- else
- tex_2ds->max_waste = COGL_TEXTURE_MAX_WASTE;
-
- /* FIXME: If upload fails we should set some kind of
- * error flag but still return texture handle if the
- * user decides to destroy another texture and upload
- * this one instead (reloading from file is not needed
- * in that case). As a rule then, everytime a valid
- * CoglHandle is returned, it should also be destroyed
- * with cogl_handle_unref at some point! */
-
- dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
- if (dst_bmp == COGL_INVALID_HANDLE)
- {
- _cogl_texture_2d_sliced_free (tex_2ds);
- return COGL_INVALID_HANDLE;
- }
-
- if (!_cogl_texture_2d_sliced_init_base (tex_2ds,
- width, height,
- internal_format,
- flags))
- goto error;
-
- if (!_cogl_texture_2d_sliced_upload_to_gl (tex_2ds,
- dst_bmp))
- goto error;
-
- cogl_object_unref (dst_bmp);
-
- return _cogl_texture_2d_sliced_handle_new (tex_2ds);
-
- error:
- cogl_object_unref (dst_bmp);
- _cogl_texture_2d_sliced_free (tex_2ds);
- return COGL_INVALID_HANDLE;
-}
-
-CoglHandle
-_cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle,
- GLenum gl_target,
- GLuint width,
- GLuint height,
- GLuint x_pot_waste,
- GLuint y_pot_waste,
- CoglPixelFormat format)
-{
- /* NOTE: width, height and internal format are not queriable
- * in GLES, hence such a function prototype.
- */
-
- GLint gl_width = 0;
- GLint gl_height = 0;
- CoglTexture2DSliced *tex_2ds;
- CoglTexture *tex;
- CoglSpan x_span;
- CoglSpan y_span;
- CoglHandle tex_2d;
-
- /* This should only be called when the texture target is 2D. If a
- rectangle texture is used then _cogl_texture_new_from_foreign
- will create a cogl_texture_rectangle instead */
- g_assert (gl_target == GL_TEXTURE_2D);
-
- gl_width = width + x_pot_waste;
- gl_height = height + y_pot_waste;
-
- /* Validate pot waste */
- if (x_pot_waste < 0 || x_pot_waste >= width ||
- y_pot_waste < 0 || y_pot_waste >= height)
- return COGL_INVALID_HANDLE;
-
- tex_2d = _cogl_texture_2d_new_from_foreign (gl_target,
- gl_width,
- gl_height,
- format);
-
- if (!tex_2d)
- return COGL_INVALID_HANDLE;
-
- /* The texture 2d backend may use a different pixel format if it
- queries the actual texture so we'll refetch the format it
- actually used */
- format = cogl_texture_get_format (tex_2d);
-
- /* Create new texture */
- tex_2ds = g_new0 (CoglTexture2DSliced, 1);
-
- tex = COGL_TEXTURE (tex_2ds);
- tex->vtable = &cogl_texture_2d_sliced_vtable;
-
- tex_2ds->width = gl_width - x_pot_waste;
- tex_2ds->height = gl_height - y_pot_waste;
- tex_2ds->max_waste = 0;
-
- /* Create slice arrays */
- tex_2ds->slice_x_spans =
- g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan), 1);
-
- tex_2ds->slice_y_spans =
- g_array_sized_new (FALSE, FALSE,
- sizeof (CoglSpan), 1);
-
- tex_2ds->slice_textures =
- g_array_sized_new (FALSE, FALSE,
- sizeof (CoglHandle), 1);
-
- /* Store info for a single slice */
- x_span.start = 0;
- x_span.size = gl_width;
- x_span.waste = x_pot_waste;
- g_array_append_val (tex_2ds->slice_x_spans, x_span);
-
- y_span.start = 0;
- y_span.size = gl_height;
- y_span.waste = y_pot_waste;
- g_array_append_val (tex_2ds->slice_y_spans, y_span);
-
- g_array_append_val (tex_2ds->slice_textures, tex_2d);
-
- return _cogl_texture_2d_sliced_handle_new (tex_2ds);
-}
-
-static gboolean
-_cogl_texture_2d_sliced_is_foreign (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return FALSE;
-
- /* Pass the call on to the first slice */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
- return _cogl_texture_is_foreign (slice_tex);
-}
-
-static int
-_cogl_texture_2d_sliced_get_max_waste (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
-
- return tex_2ds->max_waste;
-}
-
-static gboolean
-_cogl_texture_2d_sliced_is_sliced (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
-
- if (tex_2ds->slice_textures == NULL)
- return FALSE;
-
- if (tex_2ds->slice_textures->len <= 1)
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_texture_2d_sliced_can_hardware_repeat (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
- CoglSpan *x_span;
- CoglSpan *y_span;
-
- /* If there's more than one texture then we can't hardware repeat */
- if (tex_2ds->slice_textures->len != 1)
- return FALSE;
-
- /* If there's any waste then we can't hardware repeat */
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0);
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0);
- if (x_span->waste > 0 || y_span->waste > 0)
- return FALSE;
-
- /* Otherwise pass the query on to the single slice texture */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
- return _cogl_texture_can_hardware_repeat (slice_tex);
-}
-
-static void
-_cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglSpan *x_span;
- CoglSpan *y_span;
- CoglHandle slice_tex;
-
- g_assert (!_cogl_texture_2d_sliced_is_sliced (tex));
-
- /* Don't include the waste in the texture coordinates */
- x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0);
- y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0);
-
- *s *= tex_2ds->width / (float)x_span->size;
- *t *= tex_2ds->height / (float)y_span->size;
-
- /* Let the child texture further transform the coords */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
- _cogl_texture_transform_coords_to_gl (slice_tex, s, t);
-}
-
-static CoglTransformResult
-_cogl_texture_2d_sliced_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- gboolean need_repeat = FALSE;
- int i;
-
- /* This is a bit lazy - in the case where the quad lies entirely
- * within a single slice we could avoid the fallback. But that
- * could likely lead to visual inconsistency if the fallback involves
- * dropping layers, so this might be the right thing to do anyways.
- */
- if (_cogl_texture_2d_sliced_is_sliced (tex))
- return COGL_TRANSFORM_SOFTWARE_REPEAT;
-
- for (i = 0; i < 4; i++)
- if (coords[i] < 0.0f || coords[i] > 1.0f)
- need_repeat = TRUE;
-
- if (need_repeat && !_cogl_texture_2d_sliced_can_hardware_repeat (tex))
- return COGL_TRANSFORM_SOFTWARE_REPEAT;
-
- _cogl_texture_2d_sliced_transform_coords_to_gl (tex, coords + 0, coords + 1);
- _cogl_texture_2d_sliced_transform_coords_to_gl (tex, coords + 2, coords + 3);
-
- return (need_repeat
- ? COGL_TRANSFORM_HARDWARE_REPEAT : COGL_TRANSFORM_NO_REPEAT);
-}
-
-static gboolean
-_cogl_texture_2d_sliced_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
-
- if (tex_2ds->slice_textures == NULL)
- return FALSE;
-
- if (tex_2ds->slice_textures->len < 1)
- return FALSE;
-
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
-
- return cogl_texture_get_gl_texture (slice_tex, out_gl_handle, out_gl_target);
-}
-
-static void
-_cogl_texture_2d_sliced_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
- int i;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
-
- /* Apply new filters to every slice. The slice texture itself should
- cache the value and avoid resubmitting the same filter value to
- GL */
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, i);
- _cogl_texture_set_filters (slice_tex, min_filter, mag_filter);
- }
-}
-
-static void
-_cogl_texture_2d_sliced_pre_paint (CoglTexture *tex,
- CoglTexturePrePaintFlags flags)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- int i;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
-
- /* Pass the pre-paint on to every slice */
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglHandle, i);
- _cogl_texture_pre_paint (slice_tex, flags);
- }
-}
-
-static void
-_cogl_texture_2d_sliced_ensure_non_quad_rendering (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- int i;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return;
-
- /* Pass the call on to every slice */
- for (i = 0; i < tex_2ds->slice_textures->len; i++)
- {
- CoglHandle slice_tex = g_array_index (tex_2ds->slice_textures,
- CoglHandle, i);
- _cogl_texture_ensure_non_quad_rendering (slice_tex);
- }
-}
-
-static gboolean
-_cogl_texture_2d_sliced_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- GLenum gl_format;
- GLenum gl_type;
-
- _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- /* Send data to GL */
- _cogl_texture_2d_sliced_upload_subregion_to_gl (tex_2ds,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp,
- gl_format,
- gl_type);
-
- return TRUE;
-}
-
-static CoglPixelFormat
-_cogl_texture_2d_sliced_get_format (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return 0;
-
- /* Pass the call on to the first slice */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
- return cogl_texture_get_format (slice_tex);
-}
-
-static GLenum
-_cogl_texture_2d_sliced_get_gl_format (CoglTexture *tex)
-{
- CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (tex);
- CoglHandle slice_tex;
-
- /* Make sure slices were created */
- if (tex_2ds->slice_textures == NULL)
- return 0;
-
- /* Pass the call on to the first slice */
- slice_tex = g_array_index (tex_2ds->slice_textures, CoglHandle, 0);
- return _cogl_texture_get_gl_format (slice_tex);
-}
-
-static int
-_cogl_texture_2d_sliced_get_width (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D_SLICED (tex)->width;
-}
-
-static int
-_cogl_texture_2d_sliced_get_height (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D_SLICED (tex)->height;
-}
-
-static const CoglTextureVtable
-cogl_texture_2d_sliced_vtable =
- {
- _cogl_texture_2d_sliced_set_region,
- NULL, /* get_data */
- _cogl_texture_2d_sliced_foreach_sub_texture_in_region,
- _cogl_texture_2d_sliced_get_max_waste,
- _cogl_texture_2d_sliced_is_sliced,
- _cogl_texture_2d_sliced_can_hardware_repeat,
- _cogl_texture_2d_sliced_transform_coords_to_gl,
- _cogl_texture_2d_sliced_transform_quad_coords_to_gl,
- _cogl_texture_2d_sliced_get_gl_texture,
- _cogl_texture_2d_sliced_set_filters,
- _cogl_texture_2d_sliced_pre_paint,
- _cogl_texture_2d_sliced_ensure_non_quad_rendering,
- _cogl_texture_2d_sliced_set_wrap_mode_parameters,
- _cogl_texture_2d_sliced_get_format,
- _cogl_texture_2d_sliced_get_gl_format,
- _cogl_texture_2d_sliced_get_width,
- _cogl_texture_2d_sliced_get_height,
- _cogl_texture_2d_sliced_is_foreign
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-framebuffer-private.h"
-
-#include <string.h>
-#include <math.h>
-
-static void _cogl_texture_2d_free (CoglTexture2D *tex_2d);
-
-COGL_TEXTURE_INTERNAL_DEFINE (Texture2D, texture_2d);
-
-static const CoglTextureVtable cogl_texture_2d_vtable;
-
-typedef struct _CoglTexture2DManualRepeatData
-{
- CoglTexture2D *tex_2d;
- CoglTextureSliceCallback callback;
- void *user_data;
-} CoglTexture2DManualRepeatData;
-
-static void
-_cogl_texture_2d_wrap_coords (float t_1, float t_2,
- float *out_t_1, float *out_t_2)
-{
- float int_part;
-
- /* Wrap t_1 and t_2 to the range [0,1] */
-
- modff (t_1 < t_2 ? t_1 : t_2, &int_part);
- t_1 -= int_part;
- t_2 -= int_part;
- if (cogl_util_float_signbit (int_part))
- {
- *out_t_1 = 1.0f + t_1;
- *out_t_2 = 1.0f + t_2;
- }
- else
- {
- *out_t_1 = t_1;
- *out_t_2 = t_2;
- }
-}
-
-static void
-_cogl_texture_2d_manual_repeat_cb (const float *coords,
- void *user_data)
-{
- CoglTexture2DManualRepeatData *data = user_data;
- float slice_coords[4];
-
- _cogl_texture_2d_wrap_coords (coords[0], coords[2],
- slice_coords + 0, slice_coords + 2);
- _cogl_texture_2d_wrap_coords (coords[1], coords[3],
- slice_coords + 1, slice_coords + 3);
-
- data->callback (COGL_TEXTURE (data->tex_2d),
- slice_coords,
- coords,
- data->user_data);
-}
-
-static void
-_cogl_texture_2d_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- CoglTexture2DManualRepeatData data;
-
- data.tex_2d = tex_2d;
- data.callback = callback;
- data.user_data = user_data;
-
- /* We need to implement manual repeating because if Cogl is calling
- this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
- and hardware repeating can't be done */
- _cogl_texture_iterate_manual_repeats (_cogl_texture_2d_manual_repeat_cb,
- virtual_tx_1, virtual_ty_1,
- virtual_tx_2, virtual_ty_2,
- &data);
-}
-
-static void
-_cogl_texture_2d_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
-
- /* Only set the wrap mode if it's different from the current value
- to avoid too many GL calls. Texture 2D doesn't make use of the r
- coordinate so we can ignore its wrap mode */
- if (tex_2d->wrap_mode_s != wrap_mode_s ||
- tex_2d->wrap_mode_t != wrap_mode_t)
- {
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap_mode_s) );
- GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap_mode_t) );
-
- tex_2d->wrap_mode_s = wrap_mode_s;
- tex_2d->wrap_mode_t = wrap_mode_t;
- }
-}
-
-static void
-_cogl_texture_2d_free (CoglTexture2D *tex_2d)
-{
- if (!tex_2d->is_foreign)
- _cogl_delete_gl_texture (tex_2d->gl_texture);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (tex_2d));
-}
-
-static gboolean
-_cogl_texture_2d_can_create (unsigned int width,
- unsigned int height,
- CoglPixelFormat internal_format)
-{
- GLenum gl_intformat;
- GLenum gl_type;
-
- /* If NPOT textures aren't supported then the size must be a power
- of two */
- if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
- (!_cogl_util_is_pot (width) ||
- !_cogl_util_is_pot (height)))
- return FALSE;
-
- _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- NULL,
- &gl_type);
-
- /* Check that the driver can create a texture with that size */
- if (!_cogl_texture_driver_size_supported (GL_TEXTURE_2D,
- gl_intformat,
- gl_type,
- width,
- height))
- return FALSE;
-
- return TRUE;
-}
-
-static CoglTexture2D *
-_cogl_texture_2d_create_base (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture2D *tex_2d = g_new (CoglTexture2D, 1);
- CoglTexture *tex = COGL_TEXTURE (tex_2d);
-
- _cogl_texture_init (tex, &cogl_texture_2d_vtable);
-
- tex_2d->width = width;
- tex_2d->height = height;
- tex_2d->mipmaps_dirty = TRUE;
- tex_2d->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
-
- /* We default to GL_LINEAR for both filters */
- tex_2d->min_filter = GL_LINEAR;
- tex_2d->mag_filter = GL_LINEAR;
-
- /* Wrap mode not yet set */
- tex_2d->wrap_mode_s = GL_FALSE;
- tex_2d->wrap_mode_t = GL_FALSE;
-
- tex_2d->is_foreign = FALSE;
-
- tex_2d->format = internal_format;
-
- return tex_2d;
-}
-
-CoglHandle
-_cogl_texture_2d_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture2D *tex_2d;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
- /* Since no data, we need some internal format */
- if (internal_format == COGL_PIXEL_FORMAT_ANY)
- internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
-
- if (!_cogl_texture_2d_can_create (width, height, internal_format))
- return COGL_INVALID_HANDLE;
-
- internal_format = _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- tex_2d = _cogl_texture_2d_create_base (width, height, flags, internal_format);
-
- _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( glTexImage2D (GL_TEXTURE_2D, 0, gl_intformat,
- width, height, 0, gl_format, gl_type, NULL) );
-
- return _cogl_texture_2d_handle_new (tex_2d);
-}
-
-CoglHandle
-_cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture2D *tex_2d;
- CoglBitmap *dst_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- guint8 *data;
-
- g_return_val_if_fail (bmp != NULL, COGL_INVALID_HANDLE);
-
- internal_format =
- _cogl_texture_determine_internal_format (_cogl_bitmap_get_format (bmp),
- internal_format);
-
- if (!_cogl_texture_2d_can_create (_cogl_bitmap_get_width (bmp),
- _cogl_bitmap_get_height (bmp),
- internal_format))
- return COGL_INVALID_HANDLE;
-
- if ((dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type)) == NULL)
- return COGL_INVALID_HANDLE;
-
- tex_2d = _cogl_texture_2d_create_base (_cogl_bitmap_get_width (bmp),
- _cogl_bitmap_get_height (bmp),
- flags,
- internal_format);
-
- /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
- supported we can fallback to using GL_GENERATE_MIPMAP */
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
- (data = _cogl_bitmap_map (dst_bmp,
- COGL_BUFFER_ACCESS_READ, 0)))
- {
- tex_2d->first_pixel.gl_format = gl_format;
- tex_2d->first_pixel.gl_type = gl_type;
- memcpy (tex_2d->first_pixel.data, data,
- _cogl_get_format_bpp (_cogl_bitmap_get_format (dst_bmp)));
-
- _cogl_bitmap_unmap (dst_bmp);
- }
-
- _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture);
- _cogl_texture_driver_upload_to_gl (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- FALSE,
- dst_bmp,
- gl_intformat,
- gl_format,
- gl_type);
-
- tex_2d->gl_format = gl_intformat;
-
- cogl_object_unref (dst_bmp);
-
- return _cogl_texture_2d_handle_new (tex_2d);
-}
-
-CoglHandle
-_cogl_texture_2d_new_from_foreign (GLuint gl_handle,
- GLuint width,
- GLuint height,
- CoglPixelFormat format)
-{
- /* NOTE: width, height and internal format are not queriable
- * in GLES, hence such a function prototype.
- */
-
- GLenum gl_error = 0;
- GLint gl_compressed = GL_FALSE;
- GLenum gl_int_format = 0;
- CoglTexture2D *tex_2d;
-
- if (!_cogl_texture_driver_allows_foreign_gl_target (GL_TEXTURE_2D))
- return COGL_INVALID_HANDLE;
-
- /* Make sure it is a valid GL texture object */
- if (!glIsTexture (gl_handle))
- return COGL_INVALID_HANDLE;
-
- /* Make sure binding succeeds */
- while ((gl_error = glGetError ()) != GL_NO_ERROR)
- ;
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, gl_handle, TRUE);
- if (glGetError () != GL_NO_ERROR)
- return COGL_INVALID_HANDLE;
-
- /* Obtain texture parameters
- (only level 0 we are interested in) */
-
-#if HAVE_COGL_GL
-
- GE( glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
- GL_TEXTURE_COMPRESSED,
- &gl_compressed) );
-
- {
- GLint val;
-
- GE( glGetTexLevelParameteriv (GL_TEXTURE_2D, 0,
- GL_TEXTURE_INTERNAL_FORMAT,
- &val) );
-
- gl_int_format = val;
- }
-
- /* If we can query GL for the actual pixel format then we'll ignore
- the passed in format and use that. */
- if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format))
- return COGL_INVALID_HANDLE;
-
-#else
-
- /* Otherwise we'll assume we can derive the GL format from the
- passed in format */
- _cogl_pixel_format_to_gl (format,
- &gl_int_format,
- NULL,
- NULL);
-
-#endif
-
- /* Note: We always trust the given width and height without querying
- * the texture object because the user may be creating a Cogl
- * texture for a texture_from_pixmap object where glTexImage2D may
- * not have been called and the texture_from_pixmap spec doesn't
- * clarify that it is reliable to query back the size from OpenGL.
- */
-
- /* Validate width and height */
- if (width <= 0 || height <= 0)
- return COGL_INVALID_HANDLE;
-
- /* Compressed texture images not supported */
- if (gl_compressed == GL_TRUE)
- return COGL_INVALID_HANDLE;
-
- /* Note: previously this code would query the texture object for
- whether it has GL_GENERATE_MIPMAP enabled to determine whether to
- auto-generate the mipmap. This doesn't make much sense any more
- since Cogl switch to using glGenerateMipmap. Ideally I think
- cogl_texture_new_from_foreign should take a flags parameter so
- that the application can decide whether it wants
- auto-mipmapping. To be compatible with existing code, Cogl now
- disables its own auto-mipmapping but leaves the value of
- GL_GENERATE_MIPMAP alone so that it would still work but without
- the dirtiness tracking that Cogl would do. */
-
- /* Create new texture */
- tex_2d = _cogl_texture_2d_create_base (width, height,
- COGL_TEXTURE_NO_AUTO_MIPMAP,
- format);
-
- /* Setup bitmap info */
- tex_2d->is_foreign = TRUE;
- tex_2d->mipmaps_dirty = TRUE;
-
- tex_2d->format = format;
-
- tex_2d->gl_texture = gl_handle;
- tex_2d->gl_format = gl_int_format;
-
- /* Unknown filter */
- tex_2d->min_filter = GL_FALSE;
- tex_2d->mag_filter = GL_FALSE;
-
- return _cogl_texture_2d_handle_new (tex_2d);
-}
-
-void
-_cogl_texture_2d_externally_modified (CoglHandle handle)
-{
- if (!_cogl_is_texture_2d (handle))
- return;
-
- COGL_TEXTURE_2D (handle)->mipmaps_dirty = TRUE;
-}
-
-void
-_cogl_texture_2d_copy_from_framebuffer (CoglHandle handle,
- int dst_x,
- int dst_y,
- int src_x,
- int src_y,
- int width,
- int height)
-{
- CoglTexture2D *tex_2d;
-
- g_return_if_fail (_cogl_is_texture_2d (handle));
-
- tex_2d = COGL_TEXTURE_2D (handle);
-
- /* Make sure the current framebuffers are bound. We explicitly avoid
- flushing the clip state so we can bind our own empty state */
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- _cogl_get_read_framebuffer (),
- 0);
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
-
- glCopyTexSubImage2D (GL_TEXTURE_2D,
- 0, /* level */
- dst_x, dst_y,
- src_x, src_y,
- width, height);
-
- tex_2d->mipmaps_dirty = TRUE;
-}
-
-static int
-_cogl_texture_2d_get_max_waste (CoglTexture *tex)
-{
- return -1;
-}
-
-static gboolean
-_cogl_texture_2d_is_sliced (CoglTexture *tex)
-{
- return FALSE;
-}
-
-static gboolean
-_cogl_texture_2d_can_hardware_repeat (CoglTexture *tex)
-{
- return TRUE;
-}
-
-static void
-_cogl_texture_2d_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- /* The texture coordinates map directly so we don't need to do
- anything */
-}
-
-static CoglTransformResult
-_cogl_texture_2d_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- /* The texture coordinates map directly so we don't need to do
- anything other than check for repeats */
-
- gboolean need_repeat = FALSE;
- int i;
-
- for (i = 0; i < 4; i++)
- if (coords[i] < 0.0f || coords[i] > 1.0f)
- need_repeat = TRUE;
-
- return (need_repeat ? COGL_TRANSFORM_HARDWARE_REPEAT
- : COGL_TRANSFORM_NO_REPEAT);
-}
-
-static gboolean
-_cogl_texture_2d_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
-
- if (out_gl_handle)
- *out_gl_handle = tex_2d->gl_texture;
-
- if (out_gl_target)
- *out_gl_target = GL_TEXTURE_2D;
-
- return TRUE;
-}
-
-static void
-_cogl_texture_2d_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
-
- if (min_filter == tex_2d->min_filter
- && mag_filter == tex_2d->mag_filter)
- return;
-
- /* Store new values */
- tex_2d->min_filter = min_filter;
- tex_2d->mag_filter = mag_filter;
-
- /* Apply new filters to the texture */
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter) );
- GE( glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter) );
-}
-
-static void
-_cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Only update if the mipmaps are dirty */
- if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
- tex_2d->auto_mipmap && tex_2d->mipmaps_dirty)
- {
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
-
- /* glGenerateMipmap is defined in the FBO extension. If it's not
- available we'll fallback to temporarily enabling
- GL_GENERATE_MIPMAP and reuploading the first pixel */
- if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
- _cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_2D);
-#ifndef HAVE_COGL_GLES2
- else
- {
- GE( glTexParameteri (GL_TEXTURE_2D,
- GL_GENERATE_MIPMAP,
- GL_TRUE) );
- GE( glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, 1, 1,
- tex_2d->first_pixel.gl_format,
- tex_2d->first_pixel.gl_type,
- tex_2d->first_pixel.data) );
- GE( glTexParameteri (GL_TEXTURE_2D,
- GL_GENERATE_MIPMAP,
- GL_FALSE) );
- }
-#endif
-
- tex_2d->mipmaps_dirty = FALSE;
- }
-}
-
-static void
-_cogl_texture_2d_ensure_non_quad_rendering (CoglTexture *tex)
-{
- /* Nothing needs to be done */
-}
-
-static gboolean
-_cogl_texture_2d_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- GLenum gl_format;
- GLenum gl_type;
- guint8 *data;
-
- _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- /* If this touches the first pixel then we'll update our copy */
- if (dst_x == 0 && dst_y == 0 &&
- !cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
- (data = _cogl_bitmap_map (bmp, COGL_BUFFER_ACCESS_READ, 0)))
- {
- CoglPixelFormat bpp =
- _cogl_get_format_bpp (_cogl_bitmap_get_format (bmp));
- tex_2d->first_pixel.gl_format = gl_format;
- tex_2d->first_pixel.gl_type = gl_type;
- memcpy (tex_2d->first_pixel.data,
- data + _cogl_bitmap_get_rowstride (bmp) * src_y + bpp * src_x,
- bpp);
-
- _cogl_bitmap_unmap (bmp);
- }
-
- /* Send data to GL */
- _cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- FALSE,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp,
- gl_format,
- gl_type);
-
- tex_2d->mipmaps_dirty = TRUE;
-
- return TRUE;
-}
-
-static gboolean
-_cogl_texture_2d_get_data (CoglTexture *tex,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data)
-{
- CoglTexture2D *tex_2d = COGL_TEXTURE_2D (tex);
- int bpp;
- GLenum gl_format;
- GLenum gl_type;
-
- bpp = _cogl_get_format_bpp (format);
-
- _cogl_pixel_format_to_gl (format,
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_2D,
- tex_2d->gl_texture,
- tex_2d->is_foreign);
- return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_2D,
- gl_format,
- gl_type,
- data);
-}
-
-static CoglPixelFormat
-_cogl_texture_2d_get_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D (tex)->format;
-}
-
-static GLenum
-_cogl_texture_2d_get_gl_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D (tex)->gl_format;
-}
-
-static int
-_cogl_texture_2d_get_width (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D (tex)->width;
-}
-
-static int
-_cogl_texture_2d_get_height (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D (tex)->height;
-}
-
-static gboolean
-_cogl_texture_2d_is_foreign (CoglTexture *tex)
-{
- return COGL_TEXTURE_2D (tex)->is_foreign;
-}
-
-static const CoglTextureVtable
-cogl_texture_2d_vtable =
- {
- _cogl_texture_2d_set_region,
- _cogl_texture_2d_get_data,
- _cogl_texture_2d_foreach_sub_texture_in_region,
- _cogl_texture_2d_get_max_waste,
- _cogl_texture_2d_is_sliced,
- _cogl_texture_2d_can_hardware_repeat,
- _cogl_texture_2d_transform_coords_to_gl,
- _cogl_texture_2d_transform_quad_coords_to_gl,
- _cogl_texture_2d_get_gl_texture,
- _cogl_texture_2d_set_filters,
- _cogl_texture_2d_pre_paint,
- _cogl_texture_2d_ensure_non_quad_rendering,
- _cogl_texture_2d_set_wrap_mode_parameters,
- _cogl_texture_2d_get_format,
- _cogl_texture_2d_get_gl_format,
- _cogl_texture_2d_get_width,
- _cogl_texture_2d_get_height,
- _cogl_texture_2d_is_foreign
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_TEXTURE_3D_PRIVATE_H
-#define __COGL_TEXTURE_3D_PRIVATE_H
-
-#include "cogl-handle.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-texture-private.h"
-
-#define COGL_TEXTURE_3D(tex) ((CoglTexture3D *) tex)
-
-typedef struct _CoglTexture3D CoglTexture3D;
-
-struct _CoglTexture3D
-{
- CoglTexture _parent;
-
- /* The internal format of the GL texture represented as a
- CoglPixelFormat */
- CoglPixelFormat format;
- /* The internal format of the GL texture represented as a GL enum */
- GLenum gl_format;
- /* The texture object number */
- GLuint gl_texture;
- int width;
- int height;
- int depth;
- GLenum min_filter;
- GLenum mag_filter;
- GLint wrap_mode_s;
- GLint wrap_mode_t;
- GLint wrap_mode_p;
- gboolean auto_mipmap;
- gboolean mipmaps_dirty;
-
- CoglTexturePixel first_pixel;
-};
-
-GQuark
-_cogl_handle_texture_3d_get_type (void);
-
-/*
- * cogl_texture_3d_new_from_bitmap:
- * @bmp_handle: A #CoglHandle to a bitmap.
- * @height: height of the texture in pixels.
- * @depth: depth of the texture in pixels.
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @internal_format: the #CoglPixelFormat that will be used for storing
- * the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a
- * premultiplied format similar to the format of the source data will
- * be used. The default blending equations of Cogl expect premultiplied
- * color data; the main use of passing a non-premultiplied format here
- * is if you have non-premultiplied source data and are going to adjust
- * the blend mode (see cogl_pipeline_set_blend()) or use the data for
- * something other than straight blending.
- * @error: A GError return location.
- *
- * Creates a new 3D texture and initializes it with the images in
- * @bmp_handle. The images are assumed to be packed together after one
- * another in the increasing y axis. The height of individual image is
- * given as @height and the number of images is given in @depth. The
- * actual height of the bitmap can be larger than @height × @depth. In
- * this case it assumes there is padding between the images.
- *
- * Return value: the newly created texture or %COGL_INVALID_HANDLE if
- * there was an error.
- */
-CoglHandle
-_cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error);
-
-#endif /* __COGL_TEXTURE_3D_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-3d-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <string.h>
-#include <math.h>
-
-/* These might not be defined on GLES */
-#ifndef GL_TEXTURE_3D
-#define GL_TEXTURE_3D 0x806F
-#endif
-#ifndef GL_TEXTURE_WRAP_R
-#define GL_TEXTURE_WRAP_R 0x8072
-#endif
-
-#define glTexImage3D ctx->drv.pf_glTexImage3D
-#define glTexSubImage3D ctx->drv.pf_glTexSubImage3D
-
-static void _cogl_texture_3d_free (CoglTexture3D *tex_3d);
-
-COGL_TEXTURE_DEFINE (Texture3D, texture_3d);
-
-static const CoglTextureVtable cogl_texture_3d_vtable;
-
-typedef struct _CoglTexture3DManualRepeatData
-{
- CoglTexture3D *tex_3d;
- CoglTextureSliceCallback callback;
- void *user_data;
-} CoglTexture3DManualRepeatData;
-
-static void
-_cogl_texture_3d_wrap_coords (float t_1, float t_2,
- float *out_t_1, float *out_t_2)
-{
- float int_part;
-
- /* Wrap t_1 and t_2 to the range [0,1] */
-
- modff (t_1 < t_2 ? t_1 : t_2, &int_part);
- t_1 -= int_part;
- t_2 -= int_part;
- if (cogl_util_float_signbit (int_part))
- {
- *out_t_1 = 1.0f + t_1;
- *out_t_2 = 1.0f + t_2;
- }
- else
- {
- *out_t_1 = t_1;
- *out_t_2 = t_2;
- }
-}
-
-static void
-_cogl_texture_3d_manual_repeat_cb (const float *coords,
- void *user_data)
-{
- CoglTexture3DManualRepeatData *data = user_data;
- float slice_coords[4];
-
- _cogl_texture_3d_wrap_coords (coords[0], coords[2],
- slice_coords + 0, slice_coords + 2);
- _cogl_texture_3d_wrap_coords (coords[1], coords[3],
- slice_coords + 1, slice_coords + 3);
-
- data->callback (COGL_TEXTURE (data->tex_3d),
- slice_coords,
- coords,
- data->user_data);
-}
-
-static void
-_cogl_texture_3d_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
- CoglTexture3DManualRepeatData data;
-
- data.tex_3d = tex_3d;
- data.callback = callback;
- data.user_data = user_data;
-
- /* We need to implement manual repeating because if Cogl is calling
- this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
- and hardware repeating can't be done */
- _cogl_texture_iterate_manual_repeats (_cogl_texture_3d_manual_repeat_cb,
- virtual_tx_1, virtual_ty_1,
- virtual_tx_2, virtual_ty_2,
- &data);
-}
-
-static void
-_cogl_texture_3d_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
-
- /* Only set the wrap mode if it's different from the current value
- to avoid too many GL calls. */
- if (tex_3d->wrap_mode_s != wrap_mode_s ||
- tex_3d->wrap_mode_t != wrap_mode_t ||
- tex_3d->wrap_mode_p != wrap_mode_p)
- {
- _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE);
- GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, wrap_mode_s) );
- GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, wrap_mode_t) );
- GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, wrap_mode_p) );
-
- tex_3d->wrap_mode_s = wrap_mode_s;
- tex_3d->wrap_mode_t = wrap_mode_t;
- tex_3d->wrap_mode_p = wrap_mode_p;
- }
-}
-
-static void
-_cogl_texture_3d_free (CoglTexture3D *tex_3d)
-{
- _cogl_delete_gl_texture (tex_3d->gl_texture);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (tex_3d));
-}
-
-static CoglTexture3D *
-_cogl_texture_3d_create_base (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTexture3D *tex_3d = g_new (CoglTexture3D, 1);
- CoglTexture *tex = COGL_TEXTURE (tex_3d);
-
- _cogl_texture_init (tex, &cogl_texture_3d_vtable);
-
- tex_3d->width = width;
- tex_3d->height = height;
- tex_3d->depth = depth;
- tex_3d->mipmaps_dirty = TRUE;
- tex_3d->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
-
- /* We default to GL_LINEAR for both filters */
- tex_3d->min_filter = GL_LINEAR;
- tex_3d->mag_filter = GL_LINEAR;
-
- /* Wrap mode not yet set */
- tex_3d->wrap_mode_s = GL_FALSE;
- tex_3d->wrap_mode_t = GL_FALSE;
- tex_3d->wrap_mode_p = GL_FALSE;
-
- tex_3d->format = internal_format;
-
- return tex_3d;
-}
-
-static gboolean
-_cogl_texture_3d_can_create (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error)
-{
- GLenum gl_intformat;
- GLenum gl_type;
-
- /* This should only happen on GLES */
- if (!cogl_features_available (COGL_FEATURE_TEXTURE_3D))
- {
- g_set_error (error,
- COGL_ERROR,
- COGL_ERROR_UNSUPPORTED,
- "3D textures are not supported by the GPU");
- return FALSE;
- }
-
- /* If NPOT textures aren't supported then the size must be a power
- of two */
- if (!cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
- (!_cogl_util_is_pot (width) ||
- !_cogl_util_is_pot (height) ||
- !_cogl_util_is_pot (depth)))
- {
- g_set_error (error,
- COGL_ERROR,
- COGL_ERROR_UNSUPPORTED,
- "A non-power-of-two size was requested but this is not "
- "supported by the GPU");
- return FALSE;
- }
-
- _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- NULL,
- &gl_type);
-
- /* Check that the driver can create a texture with that size */
- if (!_cogl_texture_driver_size_supported_3d (GL_TEXTURE_3D,
- gl_intformat,
- gl_type,
- width,
- height,
- depth))
- {
- g_set_error (error,
- COGL_ERROR,
- COGL_ERROR_UNSUPPORTED,
- "The requested dimensions are not supported by the GPU");
- return FALSE;
- }
-
- return TRUE;
-}
-
-CoglHandle
-cogl_texture_3d_new_with_size (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error)
-{
- CoglTexture3D *tex_3d;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- /* Since no data, we need some internal format */
- if (internal_format == COGL_PIXEL_FORMAT_ANY)
- internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
-
- if (!_cogl_texture_3d_can_create (width, height, depth,
- flags, internal_format,
- error))
- return COGL_INVALID_HANDLE;
-
- internal_format = _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- tex_3d = _cogl_texture_3d_create_base (width, height, depth,
- flags, internal_format);
-
- _cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
- _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE);
- GE( glTexImage3D (GL_TEXTURE_3D, 0, gl_intformat,
- width, height, depth, 0, gl_format, gl_type, NULL) );
-
- return _cogl_texture_3d_handle_new (tex_3d);
-}
-
-CoglHandle
-_cogl_texture_3d_new_from_bitmap (CoglBitmap *bmp,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error)
-{
- CoglTexture3D *tex_3d;
- CoglBitmap *dst_bmp;
- CoglPixelFormat bmp_format;
- unsigned int bmp_width;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- guint8 *data;
-
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- bmp_width = _cogl_bitmap_get_width (bmp);
- bmp_format = _cogl_bitmap_get_format (bmp);
-
- internal_format = _cogl_texture_determine_internal_format (bmp_format,
- internal_format);
-
- if (!_cogl_texture_3d_can_create (bmp_width, height, depth,
- flags, internal_format,
- error))
- return COGL_INVALID_HANDLE;
-
- dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- if (dst_bmp == NULL)
- {
- g_set_error (error, COGL_BITMAP_ERROR, COGL_BITMAP_ERROR_FAILED,
- "Bitmap conversion failed");
- return COGL_INVALID_HANDLE;
- }
-
- tex_3d = _cogl_texture_3d_create_base (bmp_width, height, depth,
- flags, internal_format);
-
- /* Keep a copy of the first pixel so that if glGenerateMipmap isn't
- supported we can fallback to using GL_GENERATE_MIPMAP */
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN) &&
- (data = _cogl_bitmap_map (dst_bmp,
- COGL_BUFFER_ACCESS_READ, 0)))
- {
- tex_3d->first_pixel.gl_format = gl_format;
- tex_3d->first_pixel.gl_type = gl_type;
- memcpy (tex_3d->first_pixel.data, data,
- _cogl_get_format_bpp (_cogl_bitmap_get_format (dst_bmp)));
-
- _cogl_bitmap_unmap (dst_bmp);
- }
-
- _cogl_texture_driver_gen (GL_TEXTURE_3D, 1, &tex_3d->gl_texture);
-
- _cogl_texture_driver_upload_to_gl_3d (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE, /* is_foreign */
- height,
- depth,
- dst_bmp,
- gl_intformat,
- gl_format,
- gl_type);
-
- tex_3d->gl_format = gl_intformat;
-
- cogl_object_unref (dst_bmp);
-
- return _cogl_texture_3d_handle_new (tex_3d);
-}
-
-CoglHandle
-cogl_texture_3d_new_from_data (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- unsigned int image_stride,
- const guint8 *data,
- GError **error)
-{
- CoglBitmap *bitmap;
- CoglHandle ret;
-
- /* These are considered a programmer errors so we won't set a
- GError. It would be nice if this was a g_return_if_fail but the
- rest of Cogl isn't using that */
- if (format == COGL_PIXEL_FORMAT_ANY)
- return COGL_INVALID_HANDLE;
-
- if (data == NULL)
- return COGL_INVALID_HANDLE;
-
- /* Rowstride from width if not given */
- if (rowstride == 0)
- rowstride = width * _cogl_get_format_bpp (format);
- /* Image stride from height and rowstride if not given */
- if (image_stride == 0)
- image_stride = height * rowstride;
-
- if (image_stride < rowstride * height)
- return COGL_INVALID_HANDLE;
-
- /* GL doesn't support uploading when the image_stride isn't a
- multiple of the rowstride. If this happens we'll just pack the
- image into a new bitmap. The documentation for this function
- recommends avoiding this situation. */
- if (image_stride % rowstride != 0)
- {
- int z, y;
- int bmp_rowstride = _cogl_get_format_bpp (format) * width;
- guint8 *bmp_data = g_malloc (bmp_rowstride * height * depth);
-
- bitmap = _cogl_bitmap_new_from_data (bmp_data,
- format,
- width,
- depth * height,
- bmp_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL /* destroy_fn_data */);
-
- /* Copy all of the images in */
- for (z = 0; z < depth; z++)
- for (y = 0; y < height; y++)
- memcpy (bmp_data + (z * bmp_rowstride * height +
- bmp_rowstride * y),
- data + z * image_stride + rowstride * y,
- bmp_rowstride);
- }
- else
- bitmap = _cogl_bitmap_new_from_data ((guint8 *) data,
- format,
- width,
- image_stride / rowstride * depth,
- rowstride,
- NULL, /* destroy_fn */
- NULL /* destroy_fn_data */);
-
- ret = _cogl_texture_3d_new_from_bitmap (bitmap,
- height,
- depth,
- flags,
- internal_format,
- error);
-
- cogl_object_unref (bitmap);
-
- return ret;
-}
-
-GQuark
-cogl_texture_3d_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-texture-3d-error-quark");
-}
-
-static int
-_cogl_texture_3d_get_max_waste (CoglTexture *tex)
-{
- return -1;
-}
-
-static gboolean
-_cogl_texture_3d_is_sliced (CoglTexture *tex)
-{
- return FALSE;
-}
-
-static gboolean
-_cogl_texture_3d_can_hardware_repeat (CoglTexture *tex)
-{
- return TRUE;
-}
-
-static void
-_cogl_texture_3d_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- /* The texture coordinates map directly so we don't need to do
- anything */
-}
-
-static CoglTransformResult
-_cogl_texture_3d_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- /* The texture coordinates map directly so we don't need to do
- anything other than check for repeats */
-
- gboolean need_repeat = FALSE;
- int i;
-
- for (i = 0; i < 4; i++)
- if (coords[i] < 0.0f || coords[i] > 1.0f)
- need_repeat = TRUE;
-
- return (need_repeat ? COGL_TRANSFORM_HARDWARE_REPEAT
- : COGL_TRANSFORM_NO_REPEAT);
-}
-
-static gboolean
-_cogl_texture_3d_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
-
- if (out_gl_handle)
- *out_gl_handle = tex_3d->gl_texture;
-
- if (out_gl_target)
- *out_gl_target = GL_TEXTURE_3D;
-
- return TRUE;
-}
-
-static void
-_cogl_texture_3d_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
-
- if (min_filter == tex_3d->min_filter
- && mag_filter == tex_3d->mag_filter)
- return;
-
- /* Store new values */
- tex_3d->min_filter = min_filter;
- tex_3d->mag_filter = mag_filter;
-
- /* Apply new filters to the texture */
- _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE);
- GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, mag_filter) );
- GE( glTexParameteri (GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, min_filter) );
-}
-
-static void
-_cogl_texture_3d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
-{
- CoglTexture3D *tex_3d = COGL_TEXTURE_3D (tex);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Only update if the mipmaps are dirty */
- if ((flags & COGL_TEXTURE_NEEDS_MIPMAP) &&
- tex_3d->auto_mipmap && tex_3d->mipmaps_dirty)
- {
- _cogl_bind_gl_texture_transient (GL_TEXTURE_3D,
- tex_3d->gl_texture,
- FALSE);
- /* glGenerateMipmap is defined in the FBO extension. If it's not
- available we'll fallback to temporarily enabling
- GL_GENERATE_MIPMAP and reuploading the first pixel */
- if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
- _cogl_texture_driver_gl_generate_mipmaps (GL_TEXTURE_3D);
-#ifndef HAVE_COGL_GLES2
- else
- {
- GE( glTexParameteri (GL_TEXTURE_3D,
- GL_GENERATE_MIPMAP,
- GL_TRUE) );
- GE( glTexSubImage3D (GL_TEXTURE_3D,
- 0, /* level */
- 0, /* xoffset */
- 0, /* yoffset */
- 0, /* zoffset */
- 1, /* width */
- 1, /* height */
- 1, /* depth */
- tex_3d->first_pixel.gl_format,
- tex_3d->first_pixel.gl_type,
- tex_3d->first_pixel.data) );
- GE( glTexParameteri (GL_TEXTURE_3D,
- GL_GENERATE_MIPMAP,
- GL_FALSE) );
- }
-#endif
-
- tex_3d->mipmaps_dirty = FALSE;
- }
-}
-
-static void
-_cogl_texture_3d_ensure_non_quad_rendering (CoglTexture *tex)
-{
- /* Nothing needs to be done */
-}
-
-static gboolean
-_cogl_texture_3d_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- /* This function doesn't really make sense for 3D textures because
- it can't specify which image to upload to */
- return FALSE;
-}
-
-static int
-_cogl_texture_3d_get_data (CoglTexture *tex,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data)
-{
- /* FIXME: we could probably implement this by assuming the data is
- big enough to hold all of the images and that there is no stride
- between the images. However it would be better to have an API
- that can provide an image stride and this function probably isn't
- particularly useful anyway so for now it just reports failure */
- return 0;
-}
-
-static CoglPixelFormat
-_cogl_texture_3d_get_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_3D (tex)->format;
-}
-
-static GLenum
-_cogl_texture_3d_get_gl_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_3D (tex)->gl_format;
-}
-
-static int
-_cogl_texture_3d_get_width (CoglTexture *tex)
-{
- return COGL_TEXTURE_3D (tex)->width;
-}
-
-static int
-_cogl_texture_3d_get_height (CoglTexture *tex)
-{
- return COGL_TEXTURE_3D (tex)->height;
-}
-
-static const CoglTextureVtable
-cogl_texture_3d_vtable =
- {
- _cogl_texture_3d_set_region,
- _cogl_texture_3d_get_data,
- _cogl_texture_3d_foreach_sub_texture_in_region,
- _cogl_texture_3d_get_max_waste,
- _cogl_texture_3d_is_sliced,
- _cogl_texture_3d_can_hardware_repeat,
- _cogl_texture_3d_transform_coords_to_gl,
- _cogl_texture_3d_transform_quad_coords_to_gl,
- _cogl_texture_3d_get_gl_texture,
- _cogl_texture_3d_set_filters,
- _cogl_texture_3d_pre_paint,
- _cogl_texture_3d_ensure_non_quad_rendering,
- _cogl_texture_3d_set_wrap_mode_parameters,
- _cogl_texture_3d_get_format,
- _cogl_texture_3d_get_gl_format,
- _cogl_texture_3d_get_width,
- _cogl_texture_3d_get_height,
- NULL /* is_foreign */
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_TEXTURE_3D_H
-#define __COGL_TEXTURE_3D_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-texture-3d
- * @short_description: Fuctions for creating and manipulating 3D textures
- *
- * These functions allow 3D textures to be used. 3D textures can be
- * thought of as layers of 2D images arranged into a cuboid
- * shape. When choosing a texel from the texture, Cogl will take into
- * account the 'r' texture coordinate to select one of the images.
- */
-
-/* All of the cogl-texture-3d API is currently experimental so we
- * suffix the actual symbols with _EXP so if somone is monitoring for
- * ABI changes it will hopefully be clearer to them what's going on if
- * any of the symbols dissapear at a later date.
- */
-#define cogl_texture_3d_new_with_size cogl_texture_3d_new_with_size_EXP
-#define cogl_texture_3d_new_from_data cogl_texture_3d_new_from_data_EXP
-#define cogl_is_texture_3d cogl_is_texture_3d_EXP
-
-/**
- * cogl_texture_3d_new_with_size:
- * @width: width of the texture in pixels.
- * @height: height of the texture in pixels.
- * @depth: depth of the texture in pixels.
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @internal_format: the #CoglPixelFormat to use for the GPU
- * storage of the texture.
- * @error: A GError return location.
- *
- * Creates a new Cogl 3D texture with the specified dimensions and
- * pixel format.
- *
- * Note that this function will throw a #GError if
- * %COGL_FEATURE_TEXTURE_3D is not advertised. It can also fail if the
- * requested dimensions are not supported by the GPU.
- *
- * Return value: a new handle to a CoglTexture3D object or
- * %COGL_INVALID_HANDLE on failure.
- * Since: 1.4
- * Stability: Unstable
- */
-CoglHandle
-cogl_texture_3d_new_with_size (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error);
-
-/**
- * cogl_texture_3d_new_from_data:
- * @width: width of the texture in pixels.
- * @height: height of the texture in pixels.
- * @depth: depth of the texture in pixels.
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @format: the #CoglPixelFormat the buffer is stored in in RAM
- * @internal_format: the #CoglPixelFormat that will be used for storing
- * the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a
- * premultiplied format similar to the format of the source data will
- * be used. The default blending equations of Cogl expect premultiplied
- * color data; the main use of passing a non-premultiplied format here
- * is if you have non-premultiplied source data and are going to adjust
- * the blend mode (see cogl_material_set_blend()) or use the data for
- * something other than straight blending.
- * @rowstride: the memory offset in bytes between the starts of
- * scanlines in @data or 0 to infer it from the width and format
- * @image_stride: the number of bytes from one image to the next. This
- * can be used to add padding between the images in a similar way
- * that the rowstride can be used to add padding between
- * rows. Alternatively 0 can be passed to infer the @image_stride
- * from the @height.
- * @data: pointer the memory region where the source buffer resides
- * @error: A GError return location.
- *
- * Creates a new 3D texture and initializes it with @data. The data is
- * assumed to be packed array of @depth images. There can be padding
- * between the images using @image_stride.
- *
- * Note that this function will throw a #GError if
- * %COGL_FEATURE_TEXTURE_3D is not advertised. It can also fail if the
- * requested dimensions are not supported by the GPU.
- *
- * Return value: the newly created texture or %COGL_INVALID_HANDLE if
- * there was an error.
- * Since: 1.4
- * Stability: Unstable
- */
-CoglHandle
-cogl_texture_3d_new_from_data (unsigned int width,
- unsigned int height,
- unsigned int depth,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- unsigned int image_stride,
- const guint8 *data,
- GError **error);
-
-/**
- * cogl_is_texture_3d:
- * @handle: a #CoglHandle
- *
- * Checks whether @handle is a #CoglHandle for a 3D texture.
- *
- * Return value: %TRUE if the passed handle represents a 3D texture
- * and %FALSE otherwise
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_is_texture_3d (CoglHandle handle);
-
-G_END_DECLS
-
-#endif /* __COGL_TEXTURE_3D_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_DRIVER_H
-#define __COGL_TEXTURE_DRIVER_H
-
-/*
- * A very small wrapper around glGenTextures() that ensures we default to
- * non-mipmap filters when creating textures. This is to save some memory as
- * the driver will not allocate room for the mipmap tree.
- */
-void
-_cogl_texture_driver_gen (GLenum gl_target,
- GLsizei n,
- GLuint *textures);
-
-/*
- * This sets up the glPixelStore state for an upload to a destination with
- * the same size, and with no offset.
- */
-/* NB: GLES can't upload a sub region of pixel data from a larger source
- * buffer which is why this interface is limited. The GL driver has a more
- * flexible version of this function that is uses internally */
-void
-_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
- int pixels_bpp);
-
-/*
- * This uploads a sub-region from source_bmp to a single GL texture handle (i.e
- * a single CoglTexture slice)
- *
- * It also updates the array of tex->first_pixels[slice_index] if
- * dst_{x,y} == 0
- *
- * The driver abstraction is in place because GLES doesn't support the pixel
- * store options required to source from a subregion, so for GLES we have
- * to manually create a transient source bitmap.
- *
- * XXX: sorry for the ridiculous number of arguments :-(
- */
-void
-_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height,
- CoglBitmap *source_bmp,
- GLuint source_gl_format,
- GLuint source_gl_type);
-
-/*
- * Replaces the contents of the GL texture with the entire bitmap. On
- * GL this just directly calls glTexImage2D, but under GLES it needs
- * to copy the bitmap if the rowstride is not a multiple of a possible
- * alignment value because there is no GL_UNPACK_ROW_LENGTH
- */
-void
-_cogl_texture_driver_upload_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type);
-
-/*
- * Replaces the contents of the GL texture with the entire bitmap. The
- * width of the texture is inferred from the bitmap. The height and
- * depth of the texture is given directly. The 'image_height' (which
- * is the number of rows between images) is inferred by dividing the
- * height of the bitmap by the depth.
- */
-void
-_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- GLint height,
- GLint depth,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type);
-
-/*
- * This sets up the glPixelStore state for an download to a destination with
- * the same size, and with no offset.
- */
-/* NB: GLES can't download pixel data into a sub region of a larger destination
- * buffer, the GL driver has a more flexible version of this function that it
- * uses internally. */
-void
-_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
- int pixels_bpp);
-
-/*
- * This driver abstraction is in place because GLES doesn't have a sane way to
- * download data from a texture so you litterally render the texture to the
- * backbuffer, and retrive the data using glReadPixels :-(
- */
-gboolean
-_cogl_texture_driver_download_from_gl (CoglTexture *tex,
- CoglBitmap *target_bmp,
- GLuint target_gl_format,
- GLuint target_gl_type);
-
-/*
- * This driver abstraction is needed because GLES doesn't support glGetTexImage
- * (). On GLES this currently just returns FALSE which will lead to a generic
- * fallback path being used that simply renders the texture and reads it back
- * from the framebuffer. (See _cogl_texture_draw_and_read () )
- */
-gboolean
-_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
- GLenum dest_gl_format,
- GLenum dest_gl_type,
- guint8 *dest);
-
-/*
- * It may depend on the driver as to what texture sizes are supported...
- */
-gboolean
-_cogl_texture_driver_size_supported (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height);
-
-gboolean
-_cogl_texture_driver_size_supported_3d (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height,
- int depth);
-
-/*
- * This driver abstraction is needed because GLES doesn't support setting
- * a texture border color.
- */
-void
-_cogl_texture_driver_try_setting_gl_border_color (
- GLuint gl_target,
- const GLfloat *transparent_color);
-
-/*
- * XXX: this should live in cogl/{gl,gles}/cogl.c
- */
-gboolean
-_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
- CoglPixelFormat *out_format);
-
-/*
- * XXX: this should live in cogl/{gl,gles}/cogl.c
- */
-CoglPixelFormat
-_cogl_pixel_format_to_gl (CoglPixelFormat format,
- GLenum *out_glintformat,
- GLenum *out_glformat,
- GLenum *out_gltype);
-
-/*
- * It may depend on the driver as to what texture targets may be used when
- * creating a foreign texture. E.g. OpenGL supports ARB_texture_rectangle
- * but GLES doesn't
- */
-gboolean
-_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target);
-
-/*
- * glGenerateMipmap semantics may need to be emulated for some drivers. E.g. by
- * enabling auto mipmap generation an re-loading a number of known texels.
- */
-void
-_cogl_texture_driver_gl_generate_mipmaps (GLenum texture_target);
-
-/*
- * The driver may impose constraints on what formats can be used to store
- * texture data read from textures. For example GLES currently only supports
- * RGBA_8888, and so we need to manually convert the data if the final
- * destination has another format.
- */
-CoglPixelFormat
-_cogl_texture_driver_find_best_gl_get_data_format (
- CoglPixelFormat format,
- GLenum *closest_gl_format,
- GLenum *closest_gl_type);
-
-#endif /* __COGL_TEXTURE_DRIVER_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_PRIVATE_H
-#define __COGL_TEXTURE_PRIVATE_H
-
-#include "cogl-bitmap-private.h"
-#include "cogl-handle.h"
-#include "cogl-pipeline-private.h"
-
-#define COGL_TEXTURE(tex) ((CoglTexture *)(tex))
-
-typedef struct _CoglTexture CoglTexture;
-typedef struct _CoglTextureVtable CoglTextureVtable;
-
-typedef void (*CoglTextureSliceCallback) (CoglHandle handle,
- const float *slice_coords,
- const float *virtual_coords,
- void *user_data);
-
-typedef void (* CoglTextureManualRepeatCallback) (const float *coords,
- void *user_data);
-
-/* Encodes three possibiloities result of transforming a quad */
-typedef enum {
- /* quad doesn't cross the boundaries of a texture */
- COGL_TRANSFORM_NO_REPEAT,
- /* quad crosses boundaries, hardware wrap mode can handle */
- COGL_TRANSFORM_HARDWARE_REPEAT,
- /* quad crosses boundaries, needs software fallback;
- * for a sliced texture, this might not actually involve
- * repeating, just a quad crossing multiple slices */
- COGL_TRANSFORM_SOFTWARE_REPEAT,
-} CoglTransformResult;
-
-/* Flags given to the pre_paint method */
-typedef enum {
- /* The texture is going to be used with filters that require
- mipmapping. This gives the texture the opportunity to
- automatically update the mipmap tree */
- COGL_TEXTURE_NEEDS_MIPMAP = 1
-} CoglTexturePrePaintFlags;
-
-struct _CoglTextureVtable
-{
- /* Virtual functions that must be implemented for a texture
- backend */
-
- /* This should update the specified sub region of the texture with a
- sub region of the given bitmap. The bitmap will have first been
- converted to a suitable format for uploading if neccessary. */
- gboolean (* set_region) (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bitmap);
-
- /* This should copy the image data of the texture into @data. The
- requested format will have been first passed through
- _cogl_texture_driver_find_best_gl_get_data_format so it should
- always be a format that is valid for GL (ie, no conversion should
- be necessary). */
- gboolean (* get_data) (CoglTexture *tex,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data);
-
- void (* foreach_sub_texture_in_region) (CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data);
-
- int (* get_max_waste) (CoglTexture *tex);
-
- gboolean (* is_sliced) (CoglTexture *tex);
-
- gboolean (* can_hardware_repeat) (CoglTexture *tex);
-
- void (* transform_coords_to_gl) (CoglTexture *tex,
- float *s,
- float *t);
- CoglTransformResult (* transform_quad_coords_to_gl) (CoglTexture *tex,
- float *coords);
-
- gboolean (* get_gl_texture) (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target);
-
- void (* set_filters) (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter);
-
- void (* pre_paint) (CoglTexture *tex, CoglTexturePrePaintFlags flags);
- void (* ensure_non_quad_rendering) (CoglTexture *tex);
-
- void (* set_wrap_mode_parameters) (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p);
-
- CoglPixelFormat (* get_format) (CoglTexture *tex);
- GLenum (* get_gl_format) (CoglTexture *tex);
- int (* get_width) (CoglTexture *tex);
- int (* get_height) (CoglTexture *tex);
-
- gboolean (* is_foreign) (CoglTexture *tex);
-};
-
-struct _CoglTexture
-{
- CoglHandleObject _parent;
- GList *framebuffers;
- const CoglTextureVtable *vtable;
-};
-
-typedef enum _CoglTextureChangeFlags
-{
- /* Whenever the internals of a texture are changed such that the
- * underlying GL textures that represent the CoglTexture change then
- * we notify cogl-material.c via
- * _cogl_pipeline_texture_pre_change_notify
- */
- COGL_TEXTURE_CHANGE_GL_TEXTURES
-
-} CoglTextureChangeFlags;
-
-typedef struct _CoglTexturePixel CoglTexturePixel;
-
-/* This is used by the texture backends to store the first pixel of
- each GL texture. This is only used when glGenerateMipmap is not
- available so that we can temporarily set GL_GENERATE_MIPMAP and
- reupload a pixel */
-struct _CoglTexturePixel
-{
- /* We need to store the format of the pixel because we store the
- data in the source format which might end up being different for
- each slice if a subregion is updated with a different format */
- GLenum gl_format;
- GLenum gl_type;
- guint8 data[4];
-};
-
-void
-_cogl_texture_init (CoglTexture *texture,
- const CoglTextureVtable *vtable);
-
-void
-_cogl_texture_free (CoglTexture *texture);
-
-/* This is used to register a type to the list of handle types that
- will be considered a texture in cogl_is_texture() */
-void
-_cogl_texture_register_texture_type (GQuark type);
-
-#define COGL_TEXTURE_DEFINE(TypeName, type_name) \
- COGL_HANDLE_DEFINE_WITH_CODE \
- (TypeName, type_name, \
- _cogl_texture_register_texture_type (_cogl_handle_ \
- ## type_name ## _get_type ()))
-
-#define COGL_TEXTURE_INTERNAL_DEFINE(TypeName, type_name) \
- COGL_HANDLE_INTERNAL_DEFINE_WITH_CODE \
- (TypeName, type_name, \
- _cogl_texture_register_texture_type (_cogl_handle_ \
- ## type_name ## _get_type ()))
-
-void
-_cogl_texture_foreach_sub_texture_in_region (CoglHandle handle,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data);
-
-gboolean
-_cogl_texture_can_hardware_repeat (CoglHandle handle);
-
-void
-_cogl_texture_transform_coords_to_gl (CoglHandle handle,
- float *s,
- float *t);
-CoglTransformResult
-_cogl_texture_transform_quad_coords_to_gl (CoglHandle handle,
- float *coords);
-
-GLenum
-_cogl_texture_get_gl_format (CoglHandle handle);
-
-void
-_cogl_texture_set_wrap_mode_parameters (CoglHandle handle,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p);
-
-
-void
-_cogl_texture_set_filters (CoglHandle handle,
- GLenum min_filter,
- GLenum mag_filter);
-
-void
-_cogl_texture_pre_paint (CoglHandle handle, CoglTexturePrePaintFlags flags);
-
-void
-_cogl_texture_ensure_non_quad_rendering (CoglHandle handle);
-
-/* Utility function to determine which pixel format to use when
- dst_format is COGL_PIXEL_FORMAT_ANY. If dst_format is not ANY then
- it will just be returned directly */
-CoglPixelFormat
-_cogl_texture_determine_internal_format (CoglPixelFormat src_format,
- CoglPixelFormat dst_format);
-
-/* Utility function to help uploading a bitmap. If the bitmap needs
- premult conversion then it will be copied and *copied_bitmap will
- be set to TRUE. Otherwise dst_bmp will be set to a shallow copy of
- src_bmp. The GLenums needed for uploading are returned */
-
-CoglBitmap *
-_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
- CoglPixelFormat dst_format,
- CoglPixelFormat *dst_format_out,
- GLenum *out_glintformat,
- GLenum *out_glformat,
- GLenum *out_gltype);
-
-void
-_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
-
-void
-_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
-
-/* Utility function for implementing manual repeating. Even texture
- backends that always support hardware repeating need this because
- when foreach_sub_texture_in_region is invoked Cogl will set the
- wrap mode to GL_CLAMP_TO_EDGE so hardware repeating can't be
- done */
-void
-_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
- float tx_1, float ty_1,
- float tx_2, float ty_2,
- void *user_data);
-
-/* Utility function to use as a fallback for getting the data of any
- texture via the framebuffer */
-
-gboolean
-_cogl_texture_draw_and_read (CoglHandle handle,
- CoglBitmap *target_bmp,
- GLuint target_gl_format,
- GLuint target_gl_type);
-
-gboolean
-_cogl_texture_is_foreign (CoglHandle handle);
-
-gboolean
-_cogl_texture_set_region_from_bitmap (CoglHandle handle,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp);
-
-void
-_cogl_texture_associate_framebuffer (CoglHandle handle,
- CoglFramebuffer *framebuffer);
-
-const GList *
-_cogl_texture_get_associated_framebuffers (CoglHandle handle);
-
-void
-_cogl_texture_flush_journal_rendering (CoglHandle handle);
-
-#endif /* __COGL_TEXTURE_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_RECTANGLE_H
-#define __COGL_TEXTURE_RECTANGLE_H
-
-#include "cogl-handle.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-texture-private.h"
-
-#define COGL_TEXTURE_RECTANGLE(tex) ((CoglTextureRectangle *) tex)
-
-typedef struct _CoglTextureRectangle CoglTextureRectangle;
-
-struct _CoglTextureRectangle
-{
- CoglTexture _parent;
-
- /* The internal format of the GL texture represented as a
- CoglPixelFormat */
- CoglPixelFormat format;
- /* The internal format of the GL texture represented as a GL enum */
- GLenum gl_format;
- /* The texture object number */
- GLuint gl_texture;
- int width;
- int height;
- GLenum min_filter;
- GLenum mag_filter;
- GLint wrap_mode_s;
- GLint wrap_mode_t;
- gboolean is_foreign;
-};
-
-GQuark
-_cogl_handle_texture_rectangle_get_type (void);
-
-CoglHandle
-_cogl_texture_rectangle_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-CoglHandle
-_cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
- GLuint width,
- GLuint height,
- CoglPixelFormat format);
-
-#endif /* __COGL_TEXTURE_RECTANGLE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-rectangle-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <string.h>
-#include <math.h>
-
-/* These aren't defined under GLES */
-#ifndef GL_TEXTURE_RECTANGLE_ARB
-#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
-#endif
-#ifndef GL_CLAMP
-#define GL_CLAMP 0x2900
-#endif
-#ifndef GL_CLAMP_TO_BORDER
-#define GL_CLAMP_TO_BORDER 0x812D
-#endif
-
-static void _cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect);
-
-COGL_TEXTURE_INTERNAL_DEFINE (TextureRectangle, texture_rectangle);
-
-static const CoglTextureVtable cogl_texture_rectangle_vtable;
-
-typedef struct _CoglTextureRectangleManualRepeatData
-{
- CoglTextureRectangle *tex_rect;
- CoglTextureSliceCallback callback;
- void *user_data;
-} CoglTextureRectangleManualRepeatData;
-
-static void
-_cogl_texture_rectangle_wrap_coords (float t_1, float t_2,
- float *out_t_1, float *out_t_2)
-{
- float int_part;
-
- /* Wrap t_1 and t_2 to the range [0,1] */
-
- modff (t_1 < t_2 ? t_1 : t_2, &int_part);
- t_1 -= int_part;
- t_2 -= int_part;
- if (cogl_util_float_signbit (int_part))
- {
- *out_t_1 = 1.0f + t_1;
- *out_t_2 = 1.0f + t_2;
- }
- else
- {
- *out_t_1 = t_1;
- *out_t_2 = t_2;
- }
-}
-
-static void
-_cogl_texture_rectangle_manual_repeat_cb (const float *coords,
- void *user_data)
-{
- CoglTextureRectangleManualRepeatData *data = user_data;
- float slice_coords[4];
-
- _cogl_texture_rectangle_wrap_coords (coords[0], coords[2],
- slice_coords + 0, slice_coords + 2);
- _cogl_texture_rectangle_wrap_coords (coords[1], coords[3],
- slice_coords + 1, slice_coords + 3);
-
- slice_coords[0] *= data->tex_rect->width;
- slice_coords[1] *= data->tex_rect->height;
- slice_coords[2] *= data->tex_rect->width;
- slice_coords[3] *= data->tex_rect->height;
-
- data->callback (COGL_TEXTURE (data->tex_rect),
- slice_coords,
- coords,
- data->user_data);
-}
-
-static void
-_cogl_texture_rectangle_foreach_sub_texture_in_region (
- CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
- CoglTextureRectangleManualRepeatData data;
-
- data.tex_rect = tex_rect;
- data.callback = callback;
- data.user_data = user_data;
-
- /* We need to implement manual repeating because if Cogl is calling
- this function then it will set the wrap mode to GL_CLAMP_TO_EDGE
- and hardware repeating can't be done */
- _cogl_texture_iterate_manual_repeats
- (_cogl_texture_rectangle_manual_repeat_cb,
- virtual_tx_1, virtual_ty_1, virtual_tx_2, virtual_ty_2,
- &data);
-}
-
-static gboolean
-can_use_wrap_mode (GLenum wrap_mode)
-{
- return (wrap_mode == GL_CLAMP ||
- wrap_mode == GL_CLAMP_TO_EDGE ||
- wrap_mode == GL_CLAMP_TO_BORDER);
-}
-
-static void
-_cogl_texture_rectangle_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
-
- /* Only set the wrap mode if it's different from the current value
- to avoid too many GL calls. Texture rectangle doesn't make use of
- the r coordinate so we can ignore its wrap mode */
- if (tex_rect->wrap_mode_s != wrap_mode_s ||
- tex_rect->wrap_mode_t != wrap_mode_t)
- {
- g_assert (can_use_wrap_mode (wrap_mode_s));
- g_assert (can_use_wrap_mode (wrap_mode_t));
-
- GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- tex_rect->is_foreign) );
- GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_WRAP_S, wrap_mode_s) );
- GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
- GL_TEXTURE_WRAP_T, wrap_mode_t) );
-
- tex_rect->wrap_mode_s = wrap_mode_s;
- tex_rect->wrap_mode_t = wrap_mode_t;
- }
-}
-
-static void
-_cogl_texture_rectangle_free (CoglTextureRectangle *tex_rect)
-{
- if (!tex_rect->is_foreign)
- _cogl_delete_gl_texture (tex_rect->gl_texture);
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (tex_rect));
-}
-
-static gboolean
-_cogl_texture_rectangle_can_create (unsigned int width,
- unsigned int height,
- CoglPixelFormat internal_format)
-{
- GLenum gl_intformat;
- GLenum gl_type;
-
- if (!cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
- return FALSE;
-
- _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- NULL,
- &gl_type);
-
- /* Check that the driver can create a texture with that size */
- if (!_cogl_texture_driver_size_supported (GL_TEXTURE_RECTANGLE_ARB,
- gl_intformat,
- gl_type,
- width,
- height))
- return FALSE;
-
- return TRUE;
-}
-
-static CoglTextureRectangle *
-_cogl_texture_rectangle_create_base (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTextureRectangle *tex_rect = g_new (CoglTextureRectangle, 1);
- CoglTexture *tex = COGL_TEXTURE (tex_rect);
-
- _cogl_texture_init (tex, &cogl_texture_rectangle_vtable);
-
- tex_rect->width = width;
- tex_rect->height = height;
-
- /* We default to GL_LINEAR for both filters */
- tex_rect->min_filter = GL_LINEAR;
- tex_rect->mag_filter = GL_LINEAR;
-
- /* Wrap mode not yet set */
- tex_rect->wrap_mode_s = GL_FALSE;
- tex_rect->wrap_mode_t = GL_FALSE;
-
- tex_rect->format = internal_format;
-
- return tex_rect;
-}
-
-CoglHandle
-_cogl_texture_rectangle_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTextureRectangle *tex_rect;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
- /* Since no data, we need some internal format */
- if (internal_format == COGL_PIXEL_FORMAT_ANY)
- internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
-
- if (!_cogl_texture_rectangle_can_create (width, height, internal_format))
- return COGL_INVALID_HANDLE;
-
- internal_format = _cogl_pixel_format_to_gl (internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- tex_rect = _cogl_texture_rectangle_create_base (width, height, flags,
- internal_format);
-
- _cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
- GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- tex_rect->is_foreign) );
- GE( glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, gl_intformat,
- width, height, 0, gl_format, gl_type, NULL) );
-
- return _cogl_texture_rectangle_handle_new (tex_rect);
-}
-
-CoglHandle
-_cogl_texture_rectangle_new_from_bitmap (CoglBitmap *bmp,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglTextureRectangle *tex_rect;
- CoglBitmap *dst_bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
-
- g_return_val_if_fail (cogl_is_bitmap (bmp), COGL_INVALID_HANDLE);
-
- internal_format =
- _cogl_texture_determine_internal_format (_cogl_bitmap_get_format (bmp),
- internal_format);
-
- if (!_cogl_texture_rectangle_can_create (_cogl_bitmap_get_width (bmp),
- _cogl_bitmap_get_height (bmp),
- internal_format))
- return COGL_INVALID_HANDLE;
-
- dst_bmp = _cogl_texture_prepare_for_upload (bmp,
- internal_format,
- &internal_format,
- &gl_intformat,
- &gl_format,
- &gl_type);
-
- if (dst_bmp == NULL)
- return COGL_INVALID_HANDLE;
-
- tex_rect = _cogl_texture_rectangle_create_base (_cogl_bitmap_get_width (bmp),
- _cogl_bitmap_get_height (bmp),
- flags,
- internal_format);
-
- _cogl_texture_driver_gen (GL_TEXTURE_RECTANGLE_ARB, 1, &tex_rect->gl_texture);
- _cogl_texture_driver_upload_to_gl (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- FALSE,
- dst_bmp,
- gl_intformat,
- gl_format,
- gl_type);
-
- tex_rect->gl_format = gl_intformat;
-
- cogl_object_unref (dst_bmp);
-
- return _cogl_texture_rectangle_handle_new (tex_rect);
-}
-
-CoglHandle
-_cogl_texture_rectangle_new_from_foreign (GLuint gl_handle,
- GLuint width,
- GLuint height,
- CoglPixelFormat format)
-{
- /* NOTE: width, height and internal format are not queriable
- * in GLES, hence such a function prototype.
- */
-
- GLenum gl_error = 0;
- GLint gl_compressed = GL_FALSE;
- GLenum gl_int_format = 0;
- CoglTextureRectangle *tex_rect;
-
- if (!_cogl_texture_driver_allows_foreign_gl_target (GL_TEXTURE_RECTANGLE_ARB))
- return COGL_INVALID_HANDLE;
-
- /* Make sure it is a valid GL texture object */
- if (!glIsTexture (gl_handle))
- return COGL_INVALID_HANDLE;
-
- /* Make sure binding succeeds */
- while ((gl_error = glGetError ()) != GL_NO_ERROR)
- ;
-
- _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, gl_handle, TRUE);
- if (glGetError () != GL_NO_ERROR)
- return COGL_INVALID_HANDLE;
-
- /* Obtain texture parameters */
-
-#if HAVE_COGL_GL
-
- GE( glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
- GL_TEXTURE_COMPRESSED,
- &gl_compressed) );
-
- {
- GLint val;
-
- GE( glGetTexLevelParameteriv (GL_TEXTURE_RECTANGLE_ARB, 0,
- GL_TEXTURE_INTERNAL_FORMAT,
- &val) );
-
- gl_int_format = val;
- }
-
- /* If we can query GL for the actual pixel format then we'll ignore
- the passed in format and use that. */
- if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format))
- return COGL_INVALID_HANDLE;
-
-#else
-
- /* Otherwise we'll assume we can derive the GL format from the
- passed in format */
- _cogl_pixel_format_to_gl (format,
- &gl_int_format,
- NULL,
- NULL);
-
-#endif
-
- /* Note: We always trust the given width and height without querying
- * the texture object because the user may be creating a Cogl
- * texture for a texture_from_pixmap object where glTexImage2D may
- * not have been called and the texture_from_pixmap spec doesn't
- * clarify that it is reliable to query back the size from OpenGL.
- */
-
- /* Validate width and height */
- if (width <= 0 || height <= 0)
- return COGL_INVALID_HANDLE;
-
- /* Compressed texture images not supported */
- if (gl_compressed == GL_TRUE)
- return COGL_INVALID_HANDLE;
-
- /* Create new texture */
- tex_rect = _cogl_texture_rectangle_create_base (width, height,
- COGL_TEXTURE_NO_AUTO_MIPMAP,
- format);
-
- /* Setup bitmap info */
- tex_rect->is_foreign = TRUE;
-
- tex_rect->format = format;
-
- tex_rect->gl_texture = gl_handle;
- tex_rect->gl_format = gl_int_format;
-
- /* Unknown filter */
- tex_rect->min_filter = GL_FALSE;
- tex_rect->mag_filter = GL_FALSE;
-
- return _cogl_texture_rectangle_handle_new (tex_rect);
-}
-
-static int
-_cogl_texture_rectangle_get_max_waste (CoglTexture *tex)
-{
- return -1;
-}
-
-static gboolean
-_cogl_texture_rectangle_is_sliced (CoglTexture *tex)
-{
- return FALSE;
-}
-
-static gboolean
-_cogl_texture_rectangle_can_hardware_repeat (CoglTexture *tex)
-{
- return FALSE;
-}
-
-static void
-_cogl_texture_rectangle_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
-
- *s *= tex_rect->width;
- *t *= tex_rect->height;
-}
-
-static CoglTransformResult
-_cogl_texture_rectangle_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
- gboolean need_repeat = FALSE;
- int i;
-
- for (i = 0; i < 4; i++)
- {
- if (coords[i] < 0.0f || coords[i] > 1.0f)
- need_repeat = TRUE;
- coords[i] *= (i & 1) ? tex_rect->height : tex_rect->width;
- }
-
- return (need_repeat ? COGL_TRANSFORM_SOFTWARE_REPEAT
- : COGL_TRANSFORM_NO_REPEAT);
-}
-
-static gboolean
-_cogl_texture_rectangle_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
-
- if (out_gl_handle)
- *out_gl_handle = tex_rect->gl_texture;
-
- if (out_gl_target)
- *out_gl_target = GL_TEXTURE_RECTANGLE_ARB;
-
- return TRUE;
-}
-
-static void
-_cogl_texture_rectangle_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
-
- if (min_filter == tex_rect->min_filter
- && mag_filter == tex_rect->mag_filter)
- return;
-
- /* Rectangle textures don't support mipmapping */
- g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);
-
- /* Store new values */
- tex_rect->min_filter = min_filter;
- tex_rect->mag_filter = mag_filter;
-
- /* Apply new filters to the texture */
- GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- tex_rect->is_foreign) );
- GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
- mag_filter) );
- GE( glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
- min_filter) );
-}
-
-static void
-_cogl_texture_rectangle_pre_paint (CoglTexture *tex,
- CoglTexturePrePaintFlags flags)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* Rectangle textures don't support mipmaps */
- g_assert ((flags & COGL_TEXTURE_NEEDS_MIPMAP) == 0);
-}
-
-static void
-_cogl_texture_rectangle_ensure_non_quad_rendering (CoglTexture *tex)
-{
- /* Nothing needs to be done */
-}
-
-static gboolean
-_cogl_texture_rectangle_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
- GLenum gl_format;
- GLenum gl_type;
-
- _cogl_pixel_format_to_gl (_cogl_bitmap_get_format (bmp),
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- /* Send data to GL */
- _cogl_texture_driver_upload_subregion_to_gl (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- FALSE,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp,
- gl_format,
- gl_type);
-
- return TRUE;
-}
-
-static gboolean
-_cogl_texture_rectangle_get_data (CoglTexture *tex,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data)
-{
- CoglTextureRectangle *tex_rect = COGL_TEXTURE_RECTANGLE (tex);
- int bpp;
- GLenum gl_format;
- GLenum gl_type;
-
- bpp = _cogl_get_format_bpp (format);
-
- _cogl_pixel_format_to_gl (format,
- NULL, /* internal format */
- &gl_format,
- &gl_type);
-
- _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
-
- GE( _cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB,
- tex_rect->gl_texture,
- tex_rect->is_foreign) );
- return _cogl_texture_driver_gl_get_tex_image (GL_TEXTURE_RECTANGLE_ARB,
- gl_format,
- gl_type,
- data);
-}
-
-static CoglPixelFormat
-_cogl_texture_rectangle_get_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_RECTANGLE (tex)->format;
-}
-
-static GLenum
-_cogl_texture_rectangle_get_gl_format (CoglTexture *tex)
-{
- return COGL_TEXTURE_RECTANGLE (tex)->gl_format;
-}
-
-static int
-_cogl_texture_rectangle_get_width (CoglTexture *tex)
-{
- return COGL_TEXTURE_RECTANGLE (tex)->width;
-}
-
-static int
-_cogl_texture_rectangle_get_height (CoglTexture *tex)
-{
- return COGL_TEXTURE_RECTANGLE (tex)->height;
-}
-
-static gboolean
-_cogl_texture_rectangle_is_foreign (CoglTexture *tex)
-{
- return COGL_TEXTURE_RECTANGLE (tex)->is_foreign;
-}
-
-static const CoglTextureVtable
-cogl_texture_rectangle_vtable =
- {
- _cogl_texture_rectangle_set_region,
- _cogl_texture_rectangle_get_data,
- _cogl_texture_rectangle_foreach_sub_texture_in_region,
- _cogl_texture_rectangle_get_max_waste,
- _cogl_texture_rectangle_is_sliced,
- _cogl_texture_rectangle_can_hardware_repeat,
- _cogl_texture_rectangle_transform_coords_to_gl,
- _cogl_texture_rectangle_transform_quad_coords_to_gl,
- _cogl_texture_rectangle_get_gl_texture,
- _cogl_texture_rectangle_set_filters,
- _cogl_texture_rectangle_pre_paint,
- _cogl_texture_rectangle_ensure_non_quad_rendering,
- _cogl_texture_rectangle_set_wrap_mode_parameters,
- _cogl_texture_rectangle_get_format,
- _cogl_texture_rectangle_get_gl_format,
- _cogl_texture_rectangle_get_width,
- _cogl_texture_rectangle_get_height,
- _cogl_texture_rectangle_is_foreign
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Matthew Allum <mallum@openedhand.com>
- * Neil Roberts <neil@linux.intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-bitmap.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-buffer-private.h"
-#include "cogl-pixel-array-private.h"
-#include "cogl-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-texture-2d-sliced-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-rectangle-private.h"
-#include "cogl-sub-texture-private.h"
-#include "cogl-atlas-texture-private.h"
-#include "cogl-pipeline.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-object-private.h"
-#include "cogl-primitives.h"
-#include "cogl-framebuffer-private.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-/* XXX:
- * The CoglHandle macros don't support any form of inheritance, so for
- * now we implement the CoglHandle support for the CoglTexture
- * abstract class manually.
- */
-
-void
-_cogl_texture_register_texture_type (GQuark type)
-{
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- ctxt->texture_types = g_slist_prepend (ctxt->texture_types,
- GINT_TO_POINTER (type));
-}
-
-gboolean
-cogl_is_texture (CoglHandle handle)
-{
- CoglHandleObject *obj = (CoglHandleObject *)handle;
- GSList *l;
-
- _COGL_GET_CONTEXT (ctxt, FALSE);
-
- if (handle == COGL_INVALID_HANDLE)
- return FALSE;
-
- for (l = ctxt->texture_types; l; l = l->next)
- if (GPOINTER_TO_INT (l->data) == obj->klass->type)
- return TRUE;
-
- return FALSE;
-}
-
-CoglHandle
-cogl_texture_ref (CoglHandle handle)
-{
- if (!cogl_is_texture (handle))
- return COGL_INVALID_HANDLE;
-
- _COGL_HANDLE_DEBUG_REF (CoglTexture, handle);
-
- cogl_handle_ref (handle);
-
- return handle;
-}
-
-void
-cogl_texture_unref (CoglHandle handle)
-{
- if (!cogl_is_texture (handle))
- {
- g_warning (G_STRINGIFY (cogl_texture_unref)
- ": Ignoring unref of Cogl handle "
- "due to type mismatch");
- return;
- }
-
- _COGL_HANDLE_DEBUG_UNREF (CoglTexture, handle);
-
- cogl_handle_unref (handle);
-}
-
-void
-_cogl_texture_init (CoglTexture *texture,
- const CoglTextureVtable *vtable)
-{
- texture->vtable = vtable;
- texture->framebuffers = NULL;
-}
-
-void
-_cogl_texture_free (CoglTexture *texture)
-{
- g_free (texture);
-}
-
-static gboolean
-_cogl_texture_needs_premult_conversion (CoglPixelFormat src_format,
- CoglPixelFormat dst_format)
-{
- return ((src_format & dst_format & COGL_A_BIT) &&
- src_format != COGL_PIXEL_FORMAT_A_8 &&
- dst_format != COGL_PIXEL_FORMAT_A_8 &&
- (src_format & COGL_PREMULT_BIT) !=
- (dst_format & COGL_PREMULT_BIT));
-}
-
-CoglPixelFormat
-_cogl_texture_determine_internal_format (CoglPixelFormat src_format,
- CoglPixelFormat dst_format)
-{
- /* If the application hasn't specified a specific format then we'll
- * pick the most appropriate. By default Cogl will use a
- * premultiplied internal format. Later we will add control over
- * this. */
- if (dst_format == COGL_PIXEL_FORMAT_ANY)
- {
- if ((src_format & COGL_A_BIT) &&
- src_format != COGL_PIXEL_FORMAT_A_8)
- return src_format | COGL_PREMULT_BIT;
- else
- return src_format;
- }
- else
- return dst_format;
-}
-
-CoglBitmap *
-_cogl_texture_prepare_for_upload (CoglBitmap *src_bmp,
- CoglPixelFormat dst_format,
- CoglPixelFormat *dst_format_out,
- GLenum *out_glintformat,
- GLenum *out_glformat,
- GLenum *out_gltype)
-{
- CoglPixelFormat src_format = _cogl_bitmap_get_format (src_bmp);
- CoglBitmap *dst_bmp;
-
- dst_format = _cogl_texture_determine_internal_format (src_format,
- dst_format);
-
- /* OpenGL supports specifying a different format for the internal
- format when uploading texture data. We should use this to convert
- formats because it is likely to be faster and support more types
- than the Cogl bitmap code. However under GLES the internal format
- must be the same as the bitmap format and it only supports a
- limited number of formats so we must convert using the Cogl
- bitmap code instead */
-
-#ifdef HAVE_COGL_GL
-
- /* If the source format does not have the same premult flag as the
- dst format then we need to copy and convert it */
- if (_cogl_texture_needs_premult_conversion (src_format,
- dst_format))
- {
- dst_bmp = _cogl_bitmap_copy (src_bmp);
-
- if (!_cogl_bitmap_convert_premult_status (dst_bmp,
- src_format ^
- COGL_PREMULT_BIT))
- {
- cogl_object_unref (dst_bmp);
- return NULL;
- }
- }
- else
- dst_bmp = cogl_object_ref (src_bmp);
-
- /* Use the source format from the src bitmap type and the internal
- format from the dst format type so that GL can do the
- conversion */
- _cogl_pixel_format_to_gl (src_format,
- NULL, /* internal format */
- out_glformat,
- out_gltype);
- _cogl_pixel_format_to_gl (dst_format,
- out_glintformat,
- NULL,
- NULL);
-
-#else /* HAVE_COGL_GL */
- {
- CoglPixelFormat closest_format;
-
- closest_format = _cogl_pixel_format_to_gl (dst_format,
- out_glintformat,
- out_glformat,
- out_gltype);
-
- if (closest_format != src_format)
- dst_bmp = _cogl_bitmap_convert_format_and_premult (src_bmp,
- closest_format);
- else
- dst_bmp = cogl_object_ref (src_bmp);
- }
-#endif /* HAVE_COGL_GL */
-
- if (dst_format_out)
- *dst_format_out = dst_format;
-
- return dst_bmp;
-}
-
-void
-_cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride)
-{
- if (!(pixels_rowstride & 0x7))
- GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 8) );
- else if (!(pixels_rowstride & 0x3))
- GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 4) );
- else if (!(pixels_rowstride & 0x1))
- GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 2) );
- else
- GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) );
-}
-
-void
-_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride)
-{
- if (!(pixels_rowstride & 0x7))
- GE( glPixelStorei (GL_PACK_ALIGNMENT, 8) );
- else if (!(pixels_rowstride & 0x3))
- GE( glPixelStorei (GL_PACK_ALIGNMENT, 4) );
- else if (!(pixels_rowstride & 0x1))
- GE( glPixelStorei (GL_PACK_ALIGNMENT, 2) );
- else
- GE( glPixelStorei (GL_PACK_ALIGNMENT, 1) );
-}
-
-/* FIXME: wrap modes should be set on pipelines not textures */
-void
-_cogl_texture_set_wrap_mode_parameters (CoglHandle handle,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
-
- tex->vtable->set_wrap_mode_parameters (tex,
- wrap_mode_s,
- wrap_mode_t,
- wrap_mode_p);
-}
-
-/* This is like CoglSpanIter except it deals with floats and it
- effectively assumes there is only one span from 0.0 to 1.0 */
-typedef struct _CoglTextureIter
-{
- float pos, end, next_pos;
- gboolean flipped;
- float t_1, t_2;
-} CoglTextureIter;
-
-static void
-_cogl_texture_iter_update (CoglTextureIter *iter)
-{
- float t_2;
- float frac_part;
-
- frac_part = modff (iter->pos, &iter->next_pos);
-
- /* modff rounds the int part towards zero so we need to add one if
- we're meant to be heading away from zero */
- if (iter->pos >= 0.0f || frac_part == 0.0f)
- iter->next_pos += 1.0f;
-
- if (iter->next_pos > iter->end)
- t_2 = iter->end;
- else
- t_2 = iter->next_pos;
-
- if (iter->flipped)
- {
- iter->t_1 = t_2;
- iter->t_2 = iter->pos;
- }
- else
- {
- iter->t_1 = iter->pos;
- iter->t_2 = t_2;
- }
-}
-
-static void
-_cogl_texture_iter_begin (CoglTextureIter *iter,
- float t_1, float t_2)
-{
- if (t_1 <= t_2)
- {
- iter->pos = t_1;
- iter->end = t_2;
- iter->flipped = FALSE;
- }
- else
- {
- iter->pos = t_2;
- iter->end = t_1;
- iter->flipped = TRUE;
- }
-
- _cogl_texture_iter_update (iter);
-}
-
-static void
-_cogl_texture_iter_next (CoglTextureIter *iter)
-{
- iter->pos = iter->next_pos;
- _cogl_texture_iter_update (iter);
-}
-
-static gboolean
-_cogl_texture_iter_end (CoglTextureIter *iter)
-{
- return iter->pos >= iter->end;
-}
-
-/* This invokes the callback with enough quads to cover the manually
- repeated range specified by the virtual texture coordinates without
- emitting coordinates outside the range [0,1] */
-void
-_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
- float tx_1, float ty_1,
- float tx_2, float ty_2,
- void *user_data)
-{
- CoglTextureIter x_iter, y_iter;
-
- for (_cogl_texture_iter_begin (&y_iter, ty_1, ty_2);
- !_cogl_texture_iter_end (&y_iter);
- _cogl_texture_iter_next (&y_iter))
- for (_cogl_texture_iter_begin (&x_iter, tx_1, tx_2);
- !_cogl_texture_iter_end (&x_iter);
- _cogl_texture_iter_next (&x_iter))
- {
- float coords[4] = { x_iter.t_1, y_iter.t_1, x_iter.t_2, y_iter.t_2 };
- callback (coords, user_data);
- }
-}
-
-CoglHandle
-cogl_texture_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglHandle tex;
-
- /* First try creating a fast-path non-sliced texture */
- tex = _cogl_texture_2d_new_with_size (width, height, flags, internal_format);
-
- /* If it fails resort to sliced textures */
- if (tex == COGL_INVALID_HANDLE)
- tex = _cogl_texture_2d_sliced_new_with_size (width,
- height,
- flags,
- internal_format);
-
- return tex;
-}
-
-CoglHandle
-cogl_texture_new_from_data (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- const guint8 *data)
-{
- CoglBitmap *bmp;
- CoglHandle tex;
-
- if (format == COGL_PIXEL_FORMAT_ANY)
- return COGL_INVALID_HANDLE;
-
- if (data == NULL)
- return COGL_INVALID_HANDLE;
-
- /* Rowstride from width if not given */
- if (rowstride == 0)
- rowstride = width * _cogl_get_format_bpp (format);
-
- /* Wrap the data into a bitmap */
- bmp = _cogl_bitmap_new_from_data ((guint8 *) data,
- format,
- width,
- height,
- rowstride,
- NULL, NULL);
-
- tex = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
-
- cogl_object_unref (bmp);
-
- return tex;
-}
-
-CoglHandle
-cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format)
-{
- CoglHandle tex;
-
- /* First try putting the texture in the atlas */
- if ((tex = _cogl_atlas_texture_new_from_bitmap (bmp_handle,
- flags,
- internal_format)))
- return tex;
-
- /* If that doesn't work try a fast path 2D texture */
- if ((tex = _cogl_texture_2d_new_from_bitmap (bmp_handle,
- flags,
- internal_format)))
- return tex;
-
- /* Otherwise create a sliced texture */
- return _cogl_texture_2d_sliced_new_from_bitmap (bmp_handle,
- flags,
- internal_format);
-}
-
-CoglHandle
-cogl_texture_new_from_file (const char *filename,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error)
-{
- CoglBitmap *bmp;
- CoglHandle handle = COGL_INVALID_HANDLE;
- CoglPixelFormat src_format;
-
- g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
-
- bmp = cogl_bitmap_new_from_file (filename, error);
- if (bmp == NULL)
- return COGL_INVALID_HANDLE;
-
- src_format = _cogl_bitmap_get_format (bmp);
-
- /* We know that the bitmap data is solely owned by this function so
- we can do the premult conversion in place. This avoids having to
- copy the bitmap which will otherwise happen in
- _cogl_texture_prepare_for_upload */
- internal_format =
- _cogl_texture_determine_internal_format (src_format, internal_format);
- if (!_cogl_texture_needs_premult_conversion (src_format, internal_format) ||
- _cogl_bitmap_convert_premult_status (bmp, src_format ^ COGL_PREMULT_BIT))
- handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
-
- cogl_object_unref (bmp);
-
- return handle;
-}
-
-CoglHandle
-cogl_texture_new_from_foreign (GLuint gl_handle,
- GLenum gl_target,
- GLuint width,
- GLuint height,
- GLuint x_pot_waste,
- GLuint y_pot_waste,
- CoglPixelFormat format)
-{
-#if HAVE_COGL_GL
- if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
- {
- if (x_pot_waste != 0 || y_pot_waste != 0)
- {
- /* It shouldn't be necessary to have waste in this case since
- * the texture isn't limited to power of two sizes. */
- g_warning ("You can't create a foreign GL_TEXTURE_RECTANGLE cogl "
- "texture with waste\n");
- return COGL_INVALID_HANDLE;
- }
-
- return _cogl_texture_rectangle_new_from_foreign (gl_handle,
- width,
- height,
- format);
- }
-#endif
-
- if (x_pot_waste != 0 || y_pot_waste != 0)
- return _cogl_texture_2d_sliced_new_from_foreign (gl_handle,
- gl_target,
- width,
- height,
- x_pot_waste,
- y_pot_waste,
- format);
- else
- return _cogl_texture_2d_new_from_foreign (gl_handle,
- width,
- height,
- format);
-}
-
-gboolean
-_cogl_texture_is_foreign (CoglHandle handle)
-{
- CoglTexture *tex;
-
- g_return_val_if_fail (cogl_is_texture (handle), FALSE);
-
- tex = COGL_TEXTURE (handle);
-
- if (tex->vtable->is_foreign)
- return tex->vtable->is_foreign (tex);
- else
- return FALSE;
-}
-
-CoglHandle
-cogl_texture_new_from_sub_texture (CoglHandle full_texture,
- int sub_x,
- int sub_y,
- int sub_width,
- int sub_height)
-{
- return _cogl_sub_texture_new (full_texture, sub_x, sub_y,
- sub_width, sub_height);
-}
-
-CoglHandle
-cogl_texture_new_from_buffer_EXP (CoglHandle buffer,
- unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- const unsigned int offset)
-{
- CoglHandle texture;
- CoglBuffer *cogl_buffer;
- CoglPixelArray *pixel_array;
- CoglBitmap *bmp;
-
- g_return_val_if_fail (cogl_is_buffer (buffer), COGL_INVALID_HANDLE);
-
- if (format == COGL_PIXEL_FORMAT_ANY)
- return COGL_INVALID_HANDLE;
-
- cogl_buffer = COGL_BUFFER (buffer);
- pixel_array = COGL_PIXEL_ARRAY (buffer);
-
- /* Rowstride from CoglBuffer or even width * bpp if not given */
- if (rowstride == 0)
- rowstride = pixel_array->stride;
- if (rowstride == 0)
- rowstride = width * _cogl_get_format_bpp (format);
-
- /* use the CoglBuffer height and width as last resort */
- if (width == 0)
- width = pixel_array->width;
- if (height == 0)
- height = pixel_array->height;
- if (width == 0 || height == 0)
- {
- /* no width or height specified, neither at creation time (because the
- * array was created by cogl_pixel_array_new()) nor when calling this
- * function */
- return COGL_INVALID_HANDLE;
- }
-
- /* Wrap the buffer into a bitmap */
- bmp = _cogl_bitmap_new_from_buffer (cogl_buffer,
- format,
- width, height,
- rowstride,
- offset);
-
- texture = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
-
- cogl_object_unref (bmp);
-
- return texture;
-}
-
-unsigned int
-cogl_texture_get_width (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_width (tex);
-}
-
-unsigned int
-cogl_texture_get_height (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_height (tex);
-}
-
-CoglPixelFormat
-cogl_texture_get_format (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return COGL_PIXEL_FORMAT_ANY;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_format (tex);
-}
-
-unsigned int
-cogl_texture_get_rowstride (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- /* FIXME: This function should go away. It previously just returned
- the rowstride that was used to upload the data as far as I can
- tell. This is not helpful */
-
- tex = COGL_TEXTURE (handle);
-
- /* Just guess at a suitable rowstride */
- return (_cogl_get_format_bpp (cogl_texture_get_format (tex))
- * cogl_texture_get_width (tex));
-}
-
-int
-cogl_texture_get_max_waste (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_max_waste (tex);
-}
-
-gboolean
-cogl_texture_is_sliced (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return FALSE;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->is_sliced (tex);
-}
-
-/* Some CoglTextures, notably sliced textures or atlas textures when repeating
- * is used, will need to divide the coordinate space into multiple GL textures
- * (or rather; in the case of atlases duplicate a single texture in multiple
- * positions to handle repeating)
- *
- * This function helps you implement primitives using such textures by
- * invoking a callback once for each sub texture that intersects a given
- * region specified in texture coordinates.
- */
-void
-_cogl_texture_foreach_sub_texture_in_region (CoglHandle handle,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
-
- tex->vtable->foreach_sub_texture_in_region (tex,
- virtual_tx_1,
- virtual_ty_1,
- virtual_tx_2,
- virtual_ty_2,
- callback,
- user_data);
-}
-
-/* If this returns FALSE, that implies _foreach_sub_texture_in_region
- * will be needed to iterate over multiple sub textures for regions whos
- * texture coordinates extend out of the range [0,1]
- */
-gboolean
-_cogl_texture_can_hardware_repeat (CoglHandle handle)
-{
- CoglTexture *tex = (CoglTexture *)handle;
-
- return tex->vtable->can_hardware_repeat (tex);
-}
-
-/* NB: You can't use this with textures comprised of multiple sub textures (use
- * cogl_texture_is_sliced() to check) since coordinate transformation for such
- * textures will be different for each slice. */
-void
-_cogl_texture_transform_coords_to_gl (CoglHandle handle,
- float *s,
- float *t)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
-
- tex->vtable->transform_coords_to_gl (tex, s, t);
-}
-
-CoglTransformResult
-_cogl_texture_transform_quad_coords_to_gl (CoglHandle handle,
- float *coords)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
-
- return tex->vtable->transform_quad_coords_to_gl (tex, coords);
-}
-
-GLenum
-_cogl_texture_get_gl_format (CoglHandle handle)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_gl_format (tex);
-}
-
-gboolean
-cogl_texture_get_gl_texture (CoglHandle handle,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return FALSE;
-
- tex = COGL_TEXTURE (handle);
-
- return tex->vtable->get_gl_texture (tex, out_gl_handle, out_gl_target);
-}
-
-void
-_cogl_texture_set_filters (CoglHandle handle,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return;
-
- tex = COGL_TEXTURE (handle);
-
- tex->vtable->set_filters (tex, min_filter, mag_filter);
-}
-
-void
-_cogl_texture_pre_paint (CoglHandle handle, CoglTexturePrePaintFlags flags)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return;
-
- tex = COGL_TEXTURE (handle);
-
- tex->vtable->pre_paint (tex, flags);
-}
-
-void
-_cogl_texture_ensure_non_quad_rendering (CoglHandle handle)
-{
- CoglTexture *tex;
-
- if (!cogl_is_texture (handle))
- return;
-
- tex = COGL_TEXTURE (handle);
-
- tex->vtable->ensure_non_quad_rendering (tex);
-}
-
-gboolean
-_cogl_texture_set_region_from_bitmap (CoglHandle handle,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
- GLenum closest_gl_format;
- GLenum closest_gl_type;
- gboolean ret;
-
- /* Shortcut out early if the image is empty */
- if (dst_width == 0 || dst_height == 0)
- return TRUE;
-
- /* Prepare the bitmap so that it will do the premultiplication
- conversion */
- bmp = _cogl_texture_prepare_for_upload (bmp,
- cogl_texture_get_format (handle),
- NULL,
- NULL,
- &closest_gl_format,
- &closest_gl_type);
-
- ret = tex->vtable->set_region (handle,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- bmp);
-
- cogl_object_unref (bmp);
-
- return ret;
-}
-
-gboolean
-cogl_texture_set_region (CoglHandle handle,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- int width,
- int height,
- CoglPixelFormat format,
- unsigned int rowstride,
- const guint8 *data)
-{
- CoglBitmap *source_bmp;
- gboolean ret;
-
- /* Check for valid format */
- if (format == COGL_PIXEL_FORMAT_ANY)
- return FALSE;
-
- /* Rowstride from width if none specified */
- if (rowstride == 0)
- rowstride = _cogl_get_format_bpp (format) * width;
-
- /* Init source bitmap */
- source_bmp = _cogl_bitmap_new_from_data ((guint8 *) data,
- format,
- width,
- height,
- rowstride,
- NULL, /* destroy_fn */
- NULL); /* destroy_fn_data */
-
- ret = _cogl_texture_set_region_from_bitmap (handle,
- src_x, src_y,
- dst_x, dst_y,
- dst_width, dst_height,
- source_bmp);
-
- cogl_object_unref (source_bmp);
-
- return ret;
-}
-
-/* Reads back the contents of a texture by rendering it to the framebuffer
- * and reading back the resulting pixels.
- *
- * It will perform multiple renders if the texture is larger than the
- * current glViewport.
- *
- * It assumes the projection and modelview have already been setup so
- * that rendering to 0,0 with the same width and height of the viewport
- * will exactly cover the viewport.
- *
- * NB: Normally this approach isn't normally used since we can just use
- * glGetTexImage, but may be used as a fallback in some circumstances.
- */
-static void
-do_texture_draw_and_read (CoglHandle handle,
- CoglBitmap *target_bmp,
- float *viewport)
-{
- int bpp;
- float rx1, ry1;
- float rx2, ry2;
- float tx1, ty1;
- float tx2, ty2;
- int bw, bh;
- CoglBitmap *rect_bmp;
- unsigned int tex_width, tex_height;
-
- bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
-
- tex_width = cogl_texture_get_width (handle);
- tex_height = cogl_texture_get_height (handle);
-
- ry2 = 0;
- ty2 = 0;
-
- /* Walk Y axis until whole bitmap height consumed */
- for (bh = tex_height; bh > 0; bh -= viewport[3])
- {
- /* Rectangle Y coords */
- ry1 = ry2;
- ry2 += (bh < viewport[3]) ? bh : viewport[3];
-
- /* Normalized texture Y coords */
- ty1 = ty2;
- ty2 = (ry2 / (float) tex_height);
-
- rx2 = 0;
- tx2 = 0;
-
- /* Walk X axis until whole bitmap width consumed */
- for (bw = tex_width; bw > 0; bw-=viewport[2])
- {
- int width;
- int height;
- int rowstride;
- guint8 *data;
-
- /* Rectangle X coords */
- rx1 = rx2;
- rx2 += (bw < viewport[2]) ? bw : viewport[2];
-
- width = rx2 - rx1;
- height = ry2 - ry1;
- rowstride = width * bpp;
-
- /* Normalized texture X coords */
- tx1 = tx2;
- tx2 = (rx2 / (float) tex_width);
-
- /* Draw a portion of texture */
- cogl_rectangle_with_texture_coords (0, 0,
- rx2 - rx1,
- ry2 - ry1,
- tx1, ty1,
- tx2, ty2);
-
- data = g_malloc (height * rowstride);
-
- /* Read into a temporary bitmap */
- rect_bmp =
- _cogl_bitmap_new_from_data (data,
- COGL_PIXEL_FORMAT_RGBA_8888,
- width,
- height,
- rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- cogl_read_pixels (viewport[0], viewport[1],
- width,
- height,
- COGL_READ_PIXELS_COLOR_BUFFER,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- data);
-
- /* Copy to target bitmap */
- _cogl_bitmap_copy_subregion (rect_bmp,
- target_bmp,
- 0,0,
- rx1,ry1,
- width,
- height);
-
- /* Free temp bitmap */
- cogl_object_unref (rect_bmp);
- }
- }
-}
-
-/* Reads back the contents of a texture by rendering it to the framebuffer
- * and reading back the resulting pixels.
- *
- * NB: Normally this approach isn't normally used since we can just use
- * glGetTexImage, but may be used as a fallback in some circumstances.
- */
-gboolean
-_cogl_texture_draw_and_read (CoglHandle handle,
- CoglBitmap *target_bmp,
- GLuint target_gl_format,
- GLuint target_gl_type)
-{
- int bpp;
- CoglFramebuffer *framebuffer;
- float viewport[4];
- CoglBitmap *alpha_bmp;
- CoglMatrixStack *projection_stack;
- CoglMatrixStack *modelview_stack;
- int target_width = _cogl_bitmap_get_width (target_bmp);
- int target_height = _cogl_bitmap_get_height (target_bmp);
- int target_rowstride = _cogl_bitmap_get_rowstride (target_bmp);
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
-
- framebuffer = cogl_get_draw_framebuffer ();
- /* Viewport needs to have some size and be inside the window for this */
- _cogl_framebuffer_get_viewport4fv (framebuffer, viewport);
- if (viewport[0] < 0 || viewport[1] < 0 ||
- viewport[2] <= 0 || viewport[3] <= 0)
- return FALSE;
-
- /* Setup orthographic projection into current viewport (0,0 in top-left
- * corner to draw the texture upside-down so we match the way cogl_read_pixels
- * works)
- */
-
- projection_stack = _cogl_framebuffer_get_projection_stack (framebuffer);
- _cogl_matrix_stack_push (projection_stack);
- _cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_ortho (projection_stack,
- 0, viewport[2],
- viewport[3], 0,
- 0,
- 100);
-
- modelview_stack = _cogl_framebuffer_get_modelview_stack (framebuffer);
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_load_identity (modelview_stack);
-
- /* Direct copy operation */
-
- if (ctx->texture_download_pipeline == COGL_INVALID_HANDLE)
- {
- ctx->texture_download_pipeline = cogl_pipeline_new ();
- cogl_pipeline_set_blend (ctx->texture_download_pipeline,
- "RGBA = ADD (SRC_COLOR, 0)",
- NULL);
- }
-
- cogl_push_source (ctx->texture_download_pipeline);
-
- cogl_pipeline_set_layer_texture (ctx->texture_download_pipeline, 0, handle);
-
- cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline,
- 0, /* layer */
- "RGBA = REPLACE (TEXTURE)",
- NULL);
-
- cogl_pipeline_set_layer_filters (ctx->texture_download_pipeline, 0,
- COGL_PIPELINE_FILTER_NEAREST,
- COGL_PIPELINE_FILTER_NEAREST);
-
- do_texture_draw_and_read (handle, target_bmp, viewport);
-
- /* Check whether texture has alpha and framebuffer not */
- /* FIXME: For some reason even if ALPHA_BITS is 8, the framebuffer
- still doesn't seem to have an alpha buffer. This might be just
- a PowerVR issue.
- GLint r_bits, g_bits, b_bits, a_bits;
- GE( glGetIntegerv (GL_ALPHA_BITS, &a_bits) );
- GE( glGetIntegerv (GL_RED_BITS, &r_bits) );
- GE( glGetIntegerv (GL_GREEN_BITS, &g_bits) );
- GE( glGetIntegerv (GL_BLUE_BITS, &b_bits) );
- printf ("R bits: %d\n", r_bits);
- printf ("G bits: %d\n", g_bits);
- printf ("B bits: %d\n", b_bits);
- printf ("A bits: %d\n", a_bits); */
- if ((cogl_texture_get_format (handle) & COGL_A_BIT)/* && a_bits == 0*/)
- {
- guint8 *srcdata;
- guint8 *dstdata;
- guint8 *srcpixel;
- guint8 *dstpixel;
- int x,y;
- int alpha_rowstride = bpp * target_width;
-
- if ((dstdata = _cogl_bitmap_map (target_bmp,
- COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD)) == NULL)
- return FALSE;
-
- srcdata = g_malloc (alpha_rowstride * target_height);
-
- /* Create temp bitmap for alpha values */
- alpha_bmp = _cogl_bitmap_new_from_data (srcdata,
- COGL_PIXEL_FORMAT_RGBA_8888,
- target_width, target_height,
- alpha_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- /* Draw alpha values into RGB channels */
- cogl_pipeline_set_layer_combine (ctx->texture_download_pipeline,
- 0, /* layer */
- "RGBA = REPLACE (TEXTURE[A])",
- NULL);
-
- do_texture_draw_and_read (handle, alpha_bmp, viewport);
-
- /* Copy temp R to target A */
-
- for (y=0; y<target_height; ++y)
- {
- for (x=0; x<target_width; ++x)
- {
- srcpixel = srcdata + x*bpp;
- dstpixel = dstdata + x*bpp;
- dstpixel[3] = srcpixel[0];
- }
- srcdata += alpha_rowstride;
- dstdata += target_rowstride;
- }
-
- _cogl_bitmap_unmap (target_bmp);
-
- cogl_object_unref (alpha_bmp);
- }
-
- /* Restore old state */
- _cogl_matrix_stack_pop (modelview_stack);
- _cogl_matrix_stack_pop (projection_stack);
-
- /* restore the original pipeline */
- cogl_pop_source ();
-
- return TRUE;
-}
-
-static gboolean
-get_texture_bits_via_offscreen (CoglHandle texture_handle,
- int x,
- int y,
- int width,
- int height,
- guint8 *dst_bits,
- unsigned int dst_rowstride,
- CoglPixelFormat dst_format)
-{
- CoglFramebuffer *framebuffer;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
- return FALSE;
-
- framebuffer = _cogl_offscreen_new_to_texture_full
- (texture_handle,
- COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL,
- 0);
-
- if (framebuffer == NULL)
- return FALSE;
-
- cogl_push_framebuffer (framebuffer);
-
- _cogl_read_pixels_with_rowstride (x, y, width, height,
- COGL_READ_PIXELS_COLOR_BUFFER,
- dst_format, dst_bits, dst_rowstride);
-
- cogl_pop_framebuffer ();
-
- cogl_object_unref (framebuffer);
-
- return TRUE;
-}
-
-static gboolean
-get_texture_bits_via_copy (CoglHandle texture_handle,
- int x,
- int y,
- int width,
- int height,
- guint8 *dst_bits,
- unsigned int dst_rowstride,
- CoglPixelFormat dst_format)
-{
- CoglTexture *tex = COGL_TEXTURE (texture_handle);
- unsigned int full_rowstride;
- guint8 *full_bits;
- gboolean ret = TRUE;
- int bpp;
- int full_tex_width, full_tex_height;
-
- full_tex_width = cogl_texture_get_width (texture_handle);
- full_tex_height = cogl_texture_get_height (texture_handle);
-
- bpp = _cogl_get_format_bpp (dst_format);
-
- full_rowstride = bpp * full_tex_width;
- full_bits = g_malloc (full_rowstride * full_tex_height);
-
- if (tex->vtable->get_data (tex,
- dst_format,
- full_rowstride,
- full_bits))
- {
- guint8 *dst = dst_bits;
- guint8 *src = full_bits + x * bpp + y * full_rowstride;
- int i;
-
- for (i = 0; i < height; i++)
- {
- memcpy (dst, src, bpp * width);
- dst += dst_rowstride;
- src += full_rowstride;
- }
- }
- else
- ret = FALSE;
-
- g_free (full_bits);
-
- return ret;
-}
-
-typedef struct
-{
- int orig_width;
- int orig_height;
- CoglBitmap *target_bmp;
- guint8 *target_bits;
- gboolean success;
-} CoglTextureGetData;
-
-static void
-texture_get_cb (CoglHandle texture_handle,
- const float *subtexture_coords,
- const float *virtual_coords,
- void *user_data)
-{
- CoglTexture *tex = COGL_TEXTURE (texture_handle);
- CoglTextureGetData *tg_data = user_data;
- CoglPixelFormat format = _cogl_bitmap_get_format (tg_data->target_bmp);
- int bpp = _cogl_get_format_bpp (format);
- unsigned int rowstride = _cogl_bitmap_get_rowstride (tg_data->target_bmp);
- int subtexture_width = cogl_texture_get_width (texture_handle);
- int subtexture_height = cogl_texture_get_height (texture_handle);
-
- int x_in_subtexture = (int) (0.5 + subtexture_width * subtexture_coords[0]);
- int y_in_subtexture = (int) (0.5 + subtexture_height * subtexture_coords[1]);
- int width = ((int) (0.5 + subtexture_width * subtexture_coords[2])
- - x_in_subtexture);
- int height = ((int) (0.5 + subtexture_height * subtexture_coords[3])
- - y_in_subtexture);
- int x_in_bitmap = (int) (0.5 + tg_data->orig_width * virtual_coords[0]);
- int y_in_bitmap = (int) (0.5 + tg_data->orig_height * virtual_coords[1]);
-
- guint8 *dst_bits;
-
- if (!tg_data->success)
- return;
-
- dst_bits = tg_data->target_bits + x_in_bitmap * bpp + y_in_bitmap * rowstride;
-
- /* If we can read everything as a single slice, then go ahead and do that
- * to avoid allocating an FBO. We'll leave it up to the GL implementation to
- * do glGetTexImage as efficiently as possible. (GLES doesn't have that,
- * so we'll fall through) */
- if (x_in_subtexture == 0 && y_in_subtexture == 0 &&
- width == subtexture_width && height == subtexture_height)
- {
- if (tex->vtable->get_data (tex,
- format,
- rowstride,
- dst_bits))
- return;
- }
-
- /* Next best option is a FBO and glReadPixels */
- if (get_texture_bits_via_offscreen (texture_handle,
- x_in_subtexture, y_in_subtexture,
- width, height,
- dst_bits,
- rowstride,
- format))
- return;
-
- /* Getting ugly: read the entire texture, copy out the part we want */
- if (get_texture_bits_via_copy (texture_handle,
- x_in_subtexture, y_in_subtexture,
- width, height,
- dst_bits,
- rowstride,
- format))
- return;
-
- /* No luck, the caller will fall back to the draw-to-backbuffer and
- * read implementation */
- tg_data->success = FALSE;
-}
-
-int
-cogl_texture_get_data (CoglHandle handle,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data)
-{
- CoglTexture *tex;
- int bpp;
- int byte_size;
- CoglPixelFormat closest_format;
- int closest_bpp;
- GLenum closest_gl_format;
- GLenum closest_gl_type;
- CoglBitmap *target_bmp;
- CoglBitmap *new_bmp;
- guint8 *src;
- guint8 *dst;
- int y;
- int tex_width;
- int tex_height;
-
- CoglTextureGetData tg_data;
-
- if (!cogl_is_texture (handle))
- return 0;
-
- tex = COGL_TEXTURE (handle);
-
- /* Default to internal format if none specified */
- if (format == COGL_PIXEL_FORMAT_ANY)
- format = cogl_texture_get_format (handle);
-
- tex_width = cogl_texture_get_width (handle);
- tex_height = cogl_texture_get_height (handle);
-
- /* Rowstride from texture width if none specified */
- bpp = _cogl_get_format_bpp (format);
- if (rowstride == 0)
- rowstride = tex_width * bpp;
-
- /* Return byte size if only that requested */
- byte_size = tex_height * rowstride;
- if (data == NULL)
- return byte_size;
-
- closest_format =
- _cogl_texture_driver_find_best_gl_get_data_format (format,
- &closest_gl_format,
- &closest_gl_type);
- closest_bpp = _cogl_get_format_bpp (closest_format);
-
- /* Is the requested format supported? */
- if (closest_format == format)
- /* Target user data directly */
- target_bmp = _cogl_bitmap_new_from_data (data,
- format,
- tex_width,
- tex_height,
- rowstride,
- NULL, NULL);
- else
- {
- int target_rowstride = tex_width * closest_bpp;
- guint8 *target_data = g_malloc (tex_height * target_rowstride);
- target_bmp = _cogl_bitmap_new_from_data (target_data,
- closest_format,
- tex_width,
- tex_height,
- target_rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
- }
-
- tg_data.orig_width = tex_width;
- tg_data.orig_height = tex_height;
- tg_data.target_bmp = target_bmp;
- tg_data.target_bits = _cogl_bitmap_map (target_bmp, COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
- if (tg_data.target_bits == NULL)
- {
- cogl_object_unref (target_bmp);
- return 0;
- }
- tg_data.success = TRUE;
-
- /* Iterating through the subtextures allows piecing together
- * the data for a sliced texture, and allows us to do the
- * read-from-framebuffer logic here in a simple fashion rather than
- * passing offsets down through the code. */
- _cogl_texture_foreach_sub_texture_in_region (handle,
- 0, 0, 1, 1,
- texture_get_cb,
- &tg_data);
-
- _cogl_bitmap_unmap (target_bmp);
-
- /* XXX: In some cases _cogl_texture_2d_download_from_gl may fail
- * to read back the texture data; such as for GLES which doesn't
- * support glGetTexImage, so here we fallback to drawing the
- * texture and reading the pixels from the framebuffer. */
- if (!tg_data.success)
- _cogl_texture_draw_and_read (tex, target_bmp,
- closest_gl_format,
- closest_gl_type);
-
- /* Was intermediate used? */
- if (closest_format != format)
- {
- guint8 *new_bmp_data;
- int new_bmp_rowstride;
-
- /* Convert to requested format */
- new_bmp = _cogl_bitmap_convert_format_and_premult (target_bmp,
- format);
-
- /* Free intermediate data and return if failed */
- cogl_object_unref (target_bmp);
-
- if (new_bmp == NULL)
- return 0;
-
- new_bmp_rowstride = _cogl_bitmap_get_rowstride (new_bmp);
- new_bmp_data = _cogl_bitmap_map (new_bmp, COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
-
- if (new_bmp_data == NULL)
- {
- cogl_object_unref (new_bmp);
- return 0;
- }
-
- /* Copy to user buffer */
- for (y = 0; y < tex_height; ++y)
- {
- src = new_bmp_data + y * new_bmp_rowstride;
- dst = data + y * rowstride;
- memcpy (dst, src, tex_width * bpp);
- }
-
- _cogl_bitmap_unmap (new_bmp);
-
- /* Free converted data */
- cogl_object_unref (new_bmp);
- }
-
- return byte_size;
-}
-
-static void
-_cogl_texture_framebuffer_destroy_cb (void *user_data,
- void *instance)
-{
- CoglTexture *tex = user_data;
- CoglFramebuffer *framebuffer = instance;
-
- tex->framebuffers = g_list_remove (tex->framebuffers, framebuffer);
-}
-
-void
-_cogl_texture_associate_framebuffer (CoglHandle handle,
- CoglFramebuffer *framebuffer)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
- static CoglUserDataKey framebuffer_destroy_notify_key;
-
- /* Note: we don't take a reference on the framebuffer here because
- * that would introduce a circular reference. */
- tex->framebuffers = g_list_prepend (tex->framebuffers, framebuffer);
-
- /* Since we haven't taken a reference on the framebuffer we setup
- * some private data so we will be notified if it is destroyed... */
- _cogl_object_set_user_data (COGL_OBJECT (framebuffer),
- &framebuffer_destroy_notify_key,
- tex,
- _cogl_texture_framebuffer_destroy_cb);
-}
-
-const GList *
-_cogl_texture_get_associated_framebuffers (CoglHandle handle)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
- return tex->framebuffers;
-}
-
-void
-_cogl_texture_flush_journal_rendering (CoglHandle handle)
-{
- CoglTexture *tex = COGL_TEXTURE (handle);
- GList *l;
-
- /* It could be that a referenced texture is part of a framebuffer
- * which has an associated journal that must be flushed before it
- * can be sampled from by the current primitive... */
- for (l = tex->framebuffers; l; l = l->next)
- _cogl_framebuffer_flush_journal (l->data);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_TEXTURE_H__
-#define __COGL_TEXTURE_H__
-
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-defines.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-texture
- * @short_description: Fuctions for creating and manipulating textures
- *
- * COGL allows creating and manipulating GL textures using a uniform
- * API that tries to hide all the various complexities of creating,
- * loading and manipulating textures.
- */
-
-#define COGL_TEXTURE_MAX_WASTE 127
-
-/**
- * cogl_texture_new_with_size:
- * @width: width of texture in pixels.
- * @height: height of texture in pixels.
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @internal_format: the #CoglPixelFormat to use for the GPU storage of the
- * texture.
- *
- * Creates a new COGL texture with the specified dimensions and pixel format.
- *
- * Return value: a #CoglHandle to the newly created texture or
- * %COGL_INVALID_HANDLE on failure
- *
- * Since: 0.8
- */
-CoglHandle
-cogl_texture_new_with_size (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-/**
- * cogl_texture_new_from_file:
- * @filename: the file to load
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @internal_format: the #CoglPixelFormat to use for the GPU storage of the
- * texture. If %COGL_PIXEL_FORMAT_ANY is given then a premultiplied
- * format similar to the format of the source data will be used. The
- * default blending equations of Cogl expect premultiplied color data;
- * the main use of passing a non-premultiplied format here is if you
- * have non-premultiplied source data and are going to adjust the blend
- * mode (see cogl_material_set_blend()) or use the data for something
- * other than straight blending.
- * @error: return location for a #GError or %NULL
- *
- * Creates a COGL texture from an image file.
- *
- * Return value: a #CoglHandle to the newly created texture or
- * %COGL_INVALID_HANDLE on failure
- *
- * Since: 0.8
- */
-CoglHandle
-cogl_texture_new_from_file (const char *filename,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format,
- GError **error);
-
-/**
- * cogl_texture_new_from_data:
- * @width: width of texture in pixels
- * @height: height of texture in pixels
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @format: the #CoglPixelFormat the buffer is stored in in RAM
- * @internal_format: the #CoglPixelFormat that will be used for storing
- * the buffer on the GPU. If COGL_PIXEL_FORMAT_ANY is given then a
- * premultiplied format similar to the format of the source data will
- * be used. The default blending equations of Cogl expect premultiplied
- * color data; the main use of passing a non-premultiplied format here
- * is if you have non-premultiplied source data and are going to adjust
- * the blend mode (see cogl_material_set_blend()) or use the data for
- * something other than straight blending.
- * @rowstride: the memory offset in bytes between the starts of
- * scanlines in @data
- * @data: pointer the memory region where the source buffer resides
- *
- * Creates a new COGL texture based on data residing in memory.
- *
- * Return value: a #CoglHandle to the newly created texture or
- * %COGL_INVALID_HANDLE on failure
- *
- * Since: 0.8
- */
-CoglHandle
-cogl_texture_new_from_data (unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- const guint8 *data);
-
-/**
- * cogl_texture_new_from_foreign:
- * @gl_handle: opengl handle of foreign texture.
- * @gl_target: opengl target type of foreign texture
- * @width: width of foreign texture
- * @height: height of foreign texture.
- * @x_pot_waste: horizontal waste on the right hand edge of the texture.
- * @y_pot_waste: vertical waste on the bottom edge of the texture.
- * @format: format of the foreign texture.
- *
- * Creates a COGL texture based on an existing OpenGL texture; the
- * width, height and format are passed along since it is not always
- * possible to query these from OpenGL.
- *
- * The waste arguments allow you to create a Cogl texture that maps to
- * a region smaller than the real OpenGL texture. For instance if your
- * hardware only supports power-of-two textures you may load a
- * non-power-of-two image into a larger power-of-two texture and use
- * the waste arguments to tell Cogl which region should be mapped to
- * the texture coordinate range [0:1].
- *
- * Return value: a #CoglHandle to the newly created texture or
- * %COGL_INVALID_HANDLE on failure
- *
- * Since: 0.8
- */
-CoglHandle
-cogl_texture_new_from_foreign (GLuint gl_handle,
- GLenum gl_target,
- GLuint width,
- GLuint height,
- GLuint x_pot_waste,
- GLuint y_pot_waste,
- CoglPixelFormat format);
-
-/**
- * cogl_texture_new_from_bitmap:
- * @bmp_handle: A CoglBitmap handle
- * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
- * @internal_format: the #CoglPixelFormat to use for the GPU storage of the
- * texture
- *
- * Creates a COGL texture from a CoglBitmap.
- *
- * Return value: a #CoglHandle to the newly created texture or
- * %COGL_INVALID_HANDLE on failure
- *
- * Since: 1.0
- */
-CoglHandle
-cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
- CoglTextureFlags flags,
- CoglPixelFormat internal_format);
-
-/**
- * cogl_is_texture:
- * @handle: A CoglHandle
- *
- * Gets whether the given handle references an existing texture object.
- *
- * Return value: %TRUE if the handle references a texture, and
- * %FALSE otherwise
- */
-gboolean
-cogl_is_texture (CoglHandle handle);
-
-/**
- * cogl_texture_get_width:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries the width of a cogl texture.
- *
- * Return value: the width of the GPU side texture in pixels
- */
-unsigned int
-cogl_texture_get_width (CoglHandle handle);
-
-/**
- * cogl_texture_get_height:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries the height of a cogl texture.
- *
- * Return value: the height of the GPU side texture in pixels
- */
-unsigned int
-cogl_texture_get_height (CoglHandle handle);
-
-/**
- * cogl_texture_get_format:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries the #CoglPixelFormat of a cogl texture.
- *
- * Return value: the #CoglPixelFormat of the GPU side texture
- */
-CoglPixelFormat
-cogl_texture_get_format (CoglHandle handle);
-
-
-/**
- * cogl_texture_get_rowstride:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries the rowstride of a cogl texture.
- *
- * Return value: the offset in bytes between each consequetive row of pixels
- */
-unsigned int
-cogl_texture_get_rowstride (CoglHandle handle);
-
-/**
- * cogl_texture_get_max_waste:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries the maximum wasted (unused) pixels in one dimension of a GPU side
- * texture.
- *
- * Return value: the maximum waste
- */
-int
-cogl_texture_get_max_waste (CoglHandle handle);
-
-/**
- * cogl_texture_is_sliced:
- * @handle: a #CoglHandle for a texture.
- *
- * Queries if a texture is sliced (stored as multiple GPU side tecture
- * objects).
- *
- * Return value: %TRUE if the texture is sliced, %FALSE if the texture
- * is stored as a single GPU texture
- */
-gboolean
-cogl_texture_is_sliced (CoglHandle handle);
-
-/**
- * cogl_texture_get_gl_texture:
- * @handle: a #CoglHandle for a texture.
- * @out_gl_handle: (out) (allow-none): pointer to return location for the
- * textures GL handle, or %NULL.
- * @out_gl_target: (out) (allow-none): pointer to return location for the
- * GL target type, or %NULL.
- *
- * Queries the GL handles for a GPU side texture through its #CoglHandle.
- *
- * If the texture is spliced the data for the first sub texture will be
- * queried.
- *
- * Return value: %TRUE if the handle was successfully retrieved, %FALSE
- * if the handle was invalid
- */
-gboolean
-cogl_texture_get_gl_texture (CoglHandle handle,
- GLuint *out_gl_handle,
- GLenum *out_gl_target);
-
-/**
- * cogl_texture_get_data:
- * @handle: a #CoglHandle for a texture.
- * @format: the #CoglPixelFormat to store the texture as.
- * @rowstride: the rowstride of @data or retrieved from texture if none is
- * specified.
- * @data: memory location to write contents of buffer, or %NULL if we're
- * only querying the data size through the return value.
- *
- * Copies the pixel data from a cogl texture to system memory.
- *
- * Return value: the size of the texture data in bytes, or 0 if the texture
- * is not valid
- */
-int
-cogl_texture_get_data (CoglHandle handle,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data);
-
-/**
- * cogl_texture_set_region:
- * @handle: a #CoglHandle.
- * @src_x: upper left coordinate to use from source data.
- * @src_y: upper left coordinate to use from source data.
- * @dst_x: upper left destination horizontal coordinate.
- * @dst_y: upper left destination vertical coordinate.
- * @dst_width: width of destination region to write.
- * @dst_height: height of destination region to write.
- * @width: width of source data buffer.
- * @height: height of source data buffer.
- * @format: the #CoglPixelFormat used in the source buffer.
- * @rowstride: rowstride of source buffer (computed from width if none
- * specified)
- * @data: the actual pixel data.
- *
- * Sets the pixels in a rectangular subregion of @handle from an in-memory
- * buffer containing pixel data.
- *
- * Return value: %TRUE if the subregion upload was successful, and
- * %FALSE otherwise
- */
-gboolean
-cogl_texture_set_region (CoglHandle handle,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- int width,
- int height,
- CoglPixelFormat format,
- unsigned int rowstride,
- const guint8 *data);
-
-/**
- * cogl_texture_new_from_sub_texture:
- * @full_texture: a #CoglHandle to an existing texture
- * @sub_x: X coordinate of the top-left of the subregion
- * @sub_y: Y coordinate of the top-left of the subregion
- * @sub_width: Width in pixels of the subregion
- * @sub_height: Height in pixels of the subregion
- *
- * Creates a new texture which represents a subregion of another
- * texture. The GL resources will be shared so that no new texture
- * data is actually allocated.
- *
- * Sub textures have undefined behaviour texture coordinates outside
- * of the range [0,1] are used. They also do not work with
- * CoglVertexBuffers.
- *
- * The sub texture will keep a reference to the full texture so you do
- * not need to keep one separately if you only want to use the sub
- * texture.
- *
- * Return value: a #CoglHandle to the new texture.
- *
- * Since: 1.2
- */
-CoglHandle
-cogl_texture_new_from_sub_texture (CoglHandle full_texture,
- int sub_x,
- int sub_y,
- int sub_width,
- int sub_height);
-
-#if defined (COGL_ENABLE_EXPERIMENTAL_API)
-
-/**
- * cogl_texture_new_from_buffer:
- * @buffer: the #CoglHandle of a pixel buffer
- * @width: width of texture in pixels or 0
- * @height: height of texture in pixels or 0
- * @flags: optional flags for the texture, or %COGL_TEXTURE_NONE
- * @format: the #CoglPixelFormat the buffer is stored in in RAM
- * @internal_format: the #CoglPixelFormat that will be used for storing
- * the buffer on the GPU. If %COGL_PIXEL_FORMAT_ANY is given then a
- * premultiplied format similar to the format of the source data will
- * be used. The default blending equations of Cogl expect premultiplied
- * color data; the main use of passing a non-premultiplied format here
- * is if you have non-premultiplied source data and are going to adjust
- * the blend mode (see cogl_material_set_blend()) or use the data for
- * something other than straight blending
- * @rowstride: the memory offset in bytes between the starts of
- * scanlines in @data. If 0 is given the row stride will be deduced from
- * @width and @format or the stride given by cogl_pixel_buffer_new_for_size()
- * @offset: offset in bytes in @buffer from where the texture data starts
- *
- * Creates a new texture using the buffer specified by @handle. If the buffer
- * has been created using cogl_pixel_buffer_new_for_size() it's possible to omit
- * the height and width values already specified at creation time.
- *
- * Return value: a #CoglHandle to the new texture or %COGL_INVALID_HANDLE on
- * failure
- *
- * Since: 1.2
- * Stability: Unstable
- */
-CoglHandle
-cogl_texture_new_from_buffer (CoglHandle buffer,
- unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- unsigned int offset);
-
-/* the function above is experimental, the actual symbol is suffixed by _EXP so
- * we can ensure ABI compatibility and leave the cogl_buffer namespace free for
- * future use. A bunch of defines translates the symbols documented above into
- * the real symbols */
-
-CoglHandle
-cogl_texture_new_from_buffer_EXP (CoglHandle buffer,
- unsigned int width,
- unsigned int height,
- CoglTextureFlags flags,
- CoglPixelFormat format,
- CoglPixelFormat internal_format,
- unsigned int rowstride,
- unsigned int offset);
-
-#define cogl_texture_new_from_buffer cogl_texture_new_from_buffer_EXP
-
-#endif
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_texture_ref:
- * @handle: a @CoglHandle.
- *
- * Increment the reference count for a cogl texture.
- *
- * Deprecated: 1.2: Use cogl_handle_ref() instead
- *
- * Return value: the @handle.
- */
-CoglHandle
-cogl_texture_ref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-/**
- * cogl_texture_unref:
- * @handle: a @CoglHandle.
- *
- * Decrement the reference count for a cogl texture.
- *
- * Deprecated: 1.2: Use cogl_handle_unref() instead
- */
-void
-cogl_texture_unref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-G_END_DECLS
-
-#endif /* __COGL_TEXTURE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_TYPES_H__
-#define __COGL_TYPES_H__
-
-#include <glib-object.h>
-
-#include <cogl/cogl-defines.h>
-#ifdef COGL_HAS_XLIB
-#include <X11/Xlib.h>
-#endif
-
-G_BEGIN_DECLS
-
-/* Some structures are meant to be opaque but they have public
- definitions because we want the size to be public so they can be
- allocated on the stack. This macro is used to ensure that users
- don't accidentally access private members */
-#ifdef CLUTTER_COMPILATION
-#define COGL_PRIVATE(x) x
-#else
-#define COGL_PRIVATE(x) private_member_ ## x
-#endif
-
-/**
- * CoglHandle:
- *
- * Type used for storing references to cogl objects, the CoglHandle is
- * a fully opaque type without any public data members.
- */
-typedef gpointer CoglHandle;
-
-/**
- * COGL_INVALID_HANDLE:
- *
- * A COGL handle that is not valid, used for unitialized handles as well as
- * error conditions.
- */
-#define COGL_INVALID_HANDLE NULL
-
-#define COGL_TYPE_HANDLE (cogl_handle_get_type ())
-GType
-cogl_handle_get_type (void) G_GNUC_CONST;
-
-/**
- * cogl_handle_ref:
- * @handle: a #CoglHandle
- *
- * Increases the reference count of @handle by 1
- *
- * Return value: (transfer none): the handle, with its reference count increased
- */
-CoglHandle
-cogl_handle_ref (CoglHandle handle);
-
-/**
- * cogl_handle_unref:
- * @handle: a #CoglHandle
- *
- * Drecreases the reference count of @handle by 1; if the reference
- * count reaches 0, the resources allocated by @handle will be freed
- */
-void
-cogl_handle_unref (CoglHandle handle);
-
-/**
- * cogl_object_ref: (skip)
- * @object: a #CoglObject
- *
- * Increases the reference count of @handle by 1
- *
- * Returns: the @object, with its reference count increased
- */
-void *
-cogl_object_ref (void *object);
-
-/**
- * cogl_object_unref: (skip)
- * @object: a #CoglObject
- *
- * Drecreases the reference count of @object by 1; if the reference
- * count reaches 0, the resources allocated by @object will be freed
- */
-void
-cogl_object_unref (void *object);
-
-/**
- * CoglFuncPtr:
- *
- * The type used by cogl for function pointers, note that this type
- * is used as a generic catch-all cast for function pointers and the
- * actual arguments and return type may be different.
- */
-typedef void (* CoglFuncPtr) (void);
-
-/**
- * CoglFixed:
- *
- * Fixed point number using a (16.16) notation.
- */
-typedef gint32 CoglFixed;
-
-#define COGL_TYPE_FIXED (cogl_fixed_get_type ())
-GType
-cogl_fixed_get_type (void) G_GNUC_CONST;
-
-/**
- * CoglAngle:
- *
- * Integer representation of an angle such that 1024 corresponds to
- * full circle (i.e., 2 * pi).
- *
- * Since: 1.0
- */
-typedef gint32 CoglAngle;
-
-typedef struct _CoglColor CoglColor;
-typedef struct _CoglTextureVertex CoglTextureVertex;
-
-/* Enum declarations */
-
-#define COGL_PIXEL_FORMAT_24 2
-#define COGL_PIXEL_FORMAT_32 3
-#define COGL_A_BIT (1 << 4)
-#define COGL_BGR_BIT (1 << 5)
-#define COGL_AFIRST_BIT (1 << 6)
-#define COGL_PREMULT_BIT (1 << 7)
-#define COGL_UNORDERED_MASK 0x0F
-#define COGL_UNPREMULT_MASK 0x7F
-
-/**
- * CoglPixelFormat:
- * @COGL_PIXEL_FORMAT_ANY: Any format
- * @COGL_PIXEL_FORMAT_A_8: 8 bits alpha mask
- * @COGL_PIXEL_FORMAT_RGB_565: RGB, 16 bits
- * @COGL_PIXEL_FORMAT_RGBA_4444: RGBA, 16 bits
- * @COGL_PIXEL_FORMAT_RGBA_5551: RGBA, 16 bits
- * @COGL_PIXEL_FORMAT_YUV: Not currently supported
- * @COGL_PIXEL_FORMAT_G_8: Single luminance component
- * @COGL_PIXEL_FORMAT_RGB_888: RGB, 24 bits
- * @COGL_PIXEL_FORMAT_BGR_888: BGR, 24 bits
- * @COGL_PIXEL_FORMAT_RGBA_8888: RGBA, 32 bits
- * @COGL_PIXEL_FORMAT_BGRA_8888: BGRA, 32 bits
- * @COGL_PIXEL_FORMAT_ARGB_8888: ARGB, 32 bits
- * @COGL_PIXEL_FORMAT_ABGR_8888: ABGR, 32 bits
- * @COGL_PIXEL_FORMAT_RGBA_8888_PRE: Premultiplied RGBA, 32 bits
- * @COGL_PIXEL_FORMAT_BGRA_8888_PRE: Premultiplied BGRA, 32 bits
- * @COGL_PIXEL_FORMAT_ARGB_8888_PRE: Premultiplied ARGB, 32 bits
- * @COGL_PIXEL_FORMAT_ABGR_8888_PRE: Premultiplied ABGR, 32 bits
- * @COGL_PIXEL_FORMAT_RGBA_4444_PRE: Premultiplied RGBA, 16 bits
- * @COGL_PIXEL_FORMAT_RGBA_5551_PRE: Premultiplied RGBA, 16 bits
- *
- * Pixel formats used by COGL. For the formats with a byte per
- * component, the order of the components specify the order in
- * increasing memory addresses. So for example
- * %COGL_PIXEL_FORMAT_RGB_888 would have the red component in the
- * lowest address, green in the next address and blue after that
- * regardless of the endinanness of the system.
- *
- * For the 16-bit formats the component order specifies the order
- * within a 16-bit number from most significant bit to least
- * significant. So for %COGL_PIXEL_FORMAT_RGB_565, the red component
- * would be in bits 11-15, the green component would be in 6-11 and
- * the blue component would be in 1-5. Therefore the order in memory
- * depends on the endianness of the system.
- *
- * When uploading a texture %COGL_PIXEL_FORMAT_ANY can be used as the
- * internal format. Cogl will try to pick the best format to use
- * internally and convert the texture data if necessary.
- *
- * Since: 0.8
- */
-typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
- COGL_PIXEL_FORMAT_ANY = 0,
- COGL_PIXEL_FORMAT_A_8 = 1 | COGL_A_BIT,
-
- COGL_PIXEL_FORMAT_RGB_565 = 4,
- COGL_PIXEL_FORMAT_RGBA_4444 = 5 | COGL_A_BIT,
- COGL_PIXEL_FORMAT_RGBA_5551 = 6 | COGL_A_BIT,
- COGL_PIXEL_FORMAT_YUV = 7,
- COGL_PIXEL_FORMAT_G_8 = 8,
-
- COGL_PIXEL_FORMAT_RGB_888 = COGL_PIXEL_FORMAT_24,
- COGL_PIXEL_FORMAT_BGR_888 = (COGL_PIXEL_FORMAT_24 | COGL_BGR_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT),
- COGL_PIXEL_FORMAT_BGRA_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT),
- COGL_PIXEL_FORMAT_ARGB_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_AFIRST_BIT),
- COGL_PIXEL_FORMAT_ABGR_8888 = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT),
-
- COGL_PIXEL_FORMAT_RGBA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT),
- COGL_PIXEL_FORMAT_BGRA_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT),
- COGL_PIXEL_FORMAT_ARGB_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_AFIRST_BIT),
- COGL_PIXEL_FORMAT_ABGR_8888_PRE = (COGL_PIXEL_FORMAT_32 | COGL_A_BIT | COGL_PREMULT_BIT | COGL_BGR_BIT | COGL_AFIRST_BIT),
- COGL_PIXEL_FORMAT_RGBA_4444_PRE = (COGL_PIXEL_FORMAT_RGBA_4444 | COGL_A_BIT | COGL_PREMULT_BIT),
- COGL_PIXEL_FORMAT_RGBA_5551_PRE = (COGL_PIXEL_FORMAT_RGBA_5551 | COGL_A_BIT | COGL_PREMULT_BIT)
-} CoglPixelFormat;
-
-/**
- * CoglFeatureFlags:
- * @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support
- * @COGL_FEATURE_TEXTURE_NPOT: Non power of two textures are supported
- * by the hardware. This is a equivalent to the
- * %COGL_FEATURE_TEXTURE_NPOT_BASIC, %COGL_FEATURE_TEXTURE_NPOT_MIPMAP
- * and %COGL_FEATURE_TEXTURE_NPOT_REPEAT features combined.
- * @COGL_FEATURE_TEXTURE_YUV: ycbcr conversion support
- * @COGL_FEATURE_TEXTURE_READ_PIXELS: glReadPixels() support
- * @COGL_FEATURE_SHADERS_GLSL: GLSL support
- * @COGL_FEATURE_SHADERS_ARBFP: ARBFP support
- * @COGL_FEATURE_OFFSCREEN: FBO support
- * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs
- * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs
- * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available
- * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support
- * @COGL_FEATURE_VBOS: VBO support
- * @COGL_FEATURE_PBOS: PBO support
- * @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if
- * %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
- * cogl_vertex_buffer_indices_new().
- * @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support
- * @COGL_FEATURE_TEXTURE_NPOT_BASIC: The hardware supports non power
- * of two textures, but you also need to check the
- * %COGL_FEATURE_TEXTURE_NPOT_MIPMAP and %COGL_FEATURE_TEXTURE_NPOT_REPEAT
- * features to know if the hardware supports npot texture mipmaps
- * or repeat modes other than
- * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE respectively.
- * @COGL_FEATURE_TEXTURE_NPOT_MIPMAP: Mipmapping is supported in
- * conjuntion with non power of two textures.
- * @COGL_FEATURE_TEXTURE_NPOT_REPEAT: Repeat modes other than
- * %COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE are supported by the
- * hardware.
- * @COGL_FEATURE_POINT_SPRITE: Whether
- * cogl_material_set_layer_point_sprite_coords_enabled() is supported.
- * @COGL_FEATURE_TEXTURE_3D: 3D texture support
- * @COGL_FEATURE_MAP_BUFFER_FOR_READ: Whether cogl_buffer_map() is
- * supported with CoglBufferAccess including read support.
- * @COGL_FEATURE_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is
- * supported with CoglBufferAccess including write support.
- *
- * Flags for the supported features.
- *
- * Since: 0.8
- */
-typedef enum
-{
- COGL_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
- COGL_FEATURE_TEXTURE_NPOT = (1 << 2),
- COGL_FEATURE_TEXTURE_YUV = (1 << 3),
- COGL_FEATURE_TEXTURE_READ_PIXELS = (1 << 4),
- COGL_FEATURE_SHADERS_GLSL = (1 << 5),
- COGL_FEATURE_OFFSCREEN = (1 << 6),
- COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7),
- COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8),
- COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9),
- COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
- COGL_FEATURE_VBOS = (1 << 11),
- COGL_FEATURE_PBOS = (1 << 12),
- COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13),
- COGL_FEATURE_DEPTH_RANGE = (1 << 14),
- COGL_FEATURE_TEXTURE_NPOT_BASIC = (1 << 15),
- COGL_FEATURE_TEXTURE_NPOT_MIPMAP = (1 << 16),
- COGL_FEATURE_TEXTURE_NPOT_REPEAT = (1 << 17),
- COGL_FEATURE_POINT_SPRITE = (1 << 18),
- COGL_FEATURE_TEXTURE_3D = (1 << 19),
- COGL_FEATURE_SHADERS_ARBFP = (1 << 20),
- COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21),
- COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22),
- COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23)
-} CoglFeatureFlags;
-
-/**
- * CoglBufferTarget:
- * @COGL_WINDOW_BUFFER: FIXME
- * @COGL_OFFSCREEN_BUFFER: FIXME
- *
- * Target flags for FBOs.
- *
- * Since: 0.8
- */
-typedef enum
-{
- COGL_WINDOW_BUFFER = (1 << 1),
- COGL_OFFSCREEN_BUFFER = (1 << 2)
-} CoglBufferTarget;
-
-/**
- * CoglColor:
- *
- * A structure for holding a color definition. The contents of
- * the CoglColor structure are private and should never by accessed
- * directly.
- *
- * Since: 1.0
- */
-struct _CoglColor
-{
- /*< private >*/
- guint8 COGL_PRIVATE (red);
- guint8 COGL_PRIVATE (green);
- guint8 COGL_PRIVATE (blue);
-
- guint8 COGL_PRIVATE (alpha);
-
- /* padding in case we want to change to floats at
- * some point */
- guint32 COGL_PRIVATE (padding0);
- guint32 COGL_PRIVATE (padding1);
- guint32 COGL_PRIVATE (padding2);
-};
-
-/**
- * CoglTextureVertex:
- * @x: Model x-coordinate
- * @y: Model y-coordinate
- * @z: Model z-coordinate
- * @tx: Texture x-coordinate
- * @ty: Texture y-coordinate
- * @color: The color to use at this vertex. This is ignored if
- * use_color is %FALSE when calling cogl_polygon()
- *
- * Used to specify vertex information when calling cogl_polygon()
- */
-struct _CoglTextureVertex
-{
- float x, y, z;
- float tx, ty;
-
- CoglColor color;
-};
-
-/**
- * CoglTextureFlags:
- * @COGL_TEXTURE_NONE: No flags specified
- * @COGL_TEXTURE_NO_AUTO_MIPMAP: Disables the automatic generation of
- * the mipmap pyramid from the base level image whenever it is
- * updated. The mipmaps are only generated when the texture is
- * rendered with a mipmap filter so it should be free to leave out
- * this flag when using other filtering modes
- * @COGL_TEXTURE_NO_SLICING: Disables the slicing of the texture
- * @COGL_TEXTURE_NO_ATLAS: Disables the insertion of the texture inside
- * the texture atlas used by Cogl
- *
- * Flags to pass to the cogl_texture_new_* family of functions.
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_TEXTURE_NONE = 0,
- COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0,
- COGL_TEXTURE_NO_SLICING = 1 << 1,
- COGL_TEXTURE_NO_ATLAS = 1 << 2
-} CoglTextureFlags;
-
-/**
- * CoglFogMode:
- * @COGL_FOG_MODE_LINEAR: Calculates the fog blend factor as:
- * |[
- * f = end - eye_distance / end - start
- * ]|
- * @COGL_FOG_MODE_EXPONENTIAL: Calculates the fog blend factor as:
- * |[
- * f = e ^ -(density * eye_distance)
- * ]|
- * @COGL_FOG_MODE_EXPONENTIAL_SQUARED: Calculates the fog blend factor as:
- * |[
- * f = e ^ -(density * eye_distance)^2
- * ]|
- *
- * The fog mode determines the equation used to calculate the fogging blend
- * factor while fogging is enabled. The simplest %COGL_FOG_MODE_LINEAR mode
- * determines f as:
- *
- * |[
- * f = end - eye_distance / end - start
- * ]|
- *
- * Where eye_distance is the distance of the current fragment in eye
- * coordinates from the origin.
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_FOG_MODE_LINEAR,
- COGL_FOG_MODE_EXPONENTIAL,
- COGL_FOG_MODE_EXPONENTIAL_SQUARED
-} CoglFogMode;
-
-/**
- * COGL_BLEND_STRING_ERROR:
- *
- * #GError domain for blend string parser errors
- *
- * Since: 1.0
- */
-#define COGL_BLEND_STRING_ERROR (cogl_blend_string_error_quark ())
-
-/**
- * CoglBlendStringError:
- * @COGL_BLEND_STRING_ERROR_PARSE_ERROR: Generic parse error
- * @COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR: Argument parse error
- * @COGL_BLEND_STRING_ERROR_INVALID_ERROR: Internal parser error
- * @COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR: Blend string not
- * supported by the GPU
- *
- * Error enumeration for the blend strings parser
- *
- * Since: 1.0
- */
-typedef enum { /*< prefix=COGL_BLEND_STRING_ERROR >*/
- COGL_BLEND_STRING_ERROR_PARSE_ERROR,
- COGL_BLEND_STRING_ERROR_ARGUMENT_PARSE_ERROR,
- COGL_BLEND_STRING_ERROR_INVALID_ERROR,
- COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR
-} CoglBlendStringError;
-
-GQuark
-cogl_blend_string_error_quark (void);
-
-#define COGL_ERROR (_cogl_error_quark ())
-
-/**
- * CoglError:
- * @COGL_ERROR_UNSUPPORTED: You tried to use a feature or
- * configuration not currently available.
- *
- * Error enumeration for Cogl
- *
- * The @COGL_ERROR_UNSUPPORTED error can be thrown for a variety of
- * reasons. For example:
- *
- * <itemizedlist>
- * <listitem><para>You've tried to use a feature that is not
- * advertised by cogl_get_features(). This could happen if you create
- * a non-sliced texture with a non-power-of-two size when
- * %COGL_FEATURE_TEXTURE_NPOT is not advertised.</para></listitem>
- * <listitem><para>The GPU can not handle the configuration you have
- * requested. An example might be if you try to use too many texture
- * layers in a single #CoglPipeline</para></listitem>
- * <listitem><para>The driver does not support some
- * configuration.</para></listiem>
- * </itemizedlist>
- *
- * Currently this is only used by Cogl API marked as experimental so
- * this enum should also be considered experimental.
- *
- * Since: 1.4
- */
-typedef enum { /*< prefix=COGL_ERROR >*/
- COGL_ERROR_UNSUPPORTED
-} CoglError;
-
-GQuark
-_cogl_error_quark (void);
-
-/**
- * CoglAttributeType:
- * @COGL_ATTRIBUTE_TYPE_BYTE: Data is the same size of a byte
- * @COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE: Data is the same size of an
- * unsigned byte
- * @COGL_ATTRIBUTE_TYPE_SHORT: Data is the same size of a short integer
- * @COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT: Data is the same size of
- * an unsigned short integer
- * @COGL_ATTRIBUTE_TYPE_FLOAT: Data is the same size of a float
- *
- * Data types for the components of a vertex attribute.
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_ATTRIBUTE_TYPE_BYTE = 0x1400,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = 0x1401,
- COGL_ATTRIBUTE_TYPE_SHORT = 0x1402,
- COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = 0x1403,
- COGL_ATTRIBUTE_TYPE_FLOAT = 0x1406
-} CoglAttributeType;
-
-/**
- * CoglIndicesType:
- * @COGL_INDICES_TYPE_UNSIGNED_BYTE: Your indices are unsigned bytes
- * @COGL_INDICES_TYPE_UNSIGNED_SHORT: Your indices are unsigned shorts
- * @COGL_INDICES_TYPE_UNSIGNED_INT: Your indices are unsigned ints
- *
- * You should aim to use the smallest data type that gives you enough
- * range, since it reduces the size of your index array and can help
- * reduce the demand on memory bandwidth.
- *
- * Note that %COGL_INDICES_TYPE_UNSIGNED_INT is only supported if the
- * %COGL_FEATURE_UNSIGNED_INT_INDICES feature is available. This
- * should always be available on OpenGL but on OpenGL ES it will only
- * be available if the GL_OES_element_index_uint extension is
- * advertized.
- */
-typedef enum {
- COGL_INDICES_TYPE_UNSIGNED_BYTE,
- COGL_INDICES_TYPE_UNSIGNED_SHORT,
- COGL_INDICES_TYPE_UNSIGNED_INT
-} CoglIndicesType;
-
-/**
- * CoglVerticesMode:
- * @COGL_VERTICES_MODE_POINTS: FIXME, equivalent to %GL_POINTS
- * @COGL_VERTICES_MODE_LINES: FIXME, equivalent to %GL_LINES
- * @COGL_VERTICES_MODE_LINE_LOOP: FIXME, equivalent to %GL_LINE_LOOP
- * @COGL_VERTICES_MODE_LINE_STRIP: FIXME, equivalent to %GL_LINE_STRIP
- * @COGL_VERTICES_MODE_TRIANGLES: FIXME, equivalent to %GL_TRIANGLES
- * @COGL_VERTICES_MODE_TRIANGLE_STRIP: FIXME, equivalent to %GL_TRIANGLE_STRIP
- * @COGL_VERTICES_MODE_TRIANGLE_FAN: FIXME, equivalent to %GL_TRIANGLE_FAN
- *
- * Different ways of interpreting vertices when drawing.
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_VERTICES_MODE_POINTS = 0x0000,
- COGL_VERTICES_MODE_LINES = 0x0001,
- COGL_VERTICES_MODE_LINE_LOOP = 0x0002,
- COGL_VERTICES_MODE_LINE_STRIP = 0x0003,
- COGL_VERTICES_MODE_TRIANGLES = 0x0004,
- COGL_VERTICES_MODE_TRIANGLE_STRIP = 0x0005,
- COGL_VERTICES_MODE_TRIANGLE_FAN = 0x0006
-} CoglVerticesMode;
-
-/* NB: The above definitions are taken from gl.h equivalents */
-
-
-/* XXX: should this be CoglMaterialDepthTestFunction?
- * It makes it very verbose but would be consistent with
- * CoglMaterialWrapMode */
-
-/**
- * CoglDepthTestFunction:
- * @COGL_DEPTH_TEST_FUNCTION_NEVER: Never passes.
- * @COGL_DEPTH_TEST_FUNCTION_LESS: Passes if the fragment's depth
- * value is less than the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_EQUAL: Passes if the fragment's depth
- * value is equal to the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_LEQUAL: Passes if the fragment's depth
- * value is less or equal to the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_GREATER: Passes if the fragment's depth
- * value is greater than the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_NOTEQUAL: Passes if the fragment's depth
- * value is not equal to the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_GEQUAL: Passes if the fragment's depth
- * value greater than or equal to the value currently in the depth buffer.
- * @COGL_DEPTH_TEST_FUNCTION_ALWAYS: Always passes.
- *
- * When using depth testing one of these functions is used to compare
- * the depth of an incoming fragment against the depth value currently
- * stored in the depth buffer. The function is changed using
- * cogl_material_set_depth_test_function().
- *
- * The test is only done when depth testing is explicitly enabled. (See
- * cogl_material_set_depth_test_enabled())
- */
-typedef enum
-{
- COGL_DEPTH_TEST_FUNCTION_NEVER = 0x0200,
- COGL_DEPTH_TEST_FUNCTION_LESS = 0x0201,
- COGL_DEPTH_TEST_FUNCTION_EQUAL = 0x0202,
- COGL_DEPTH_TEST_FUNCTION_LEQUAL = 0x0203,
- COGL_DEPTH_TEST_FUNCTION_GREATER = 0x0204,
- COGL_DEPTH_TEST_FUNCTION_NOTEQUAL = 0x0205,
- COGL_DEPTH_TEST_FUNCTION_GEQUAL = 0x0206,
- COGL_DEPTH_TEST_FUNCTION_ALWAYS = 0x0207
-} CoglDepthTestFunction;
-/* NB: The above definitions are taken from gl.h equivalents */
-
-typedef enum { /*< prefix=COGL_RENDERER_ERROR >*/
- COGL_RENDERER_ERROR_NOT_FOUND,
- COGL_RENDERER_ERROR_XLIB_DISPLAY_OPEN
-} CoglRendererError;
-
-/*
- * CoglFilterReturn:
- * @COGL_FILTER_CONTINUE: The event was not handled, continues the
- * processing
- * @COGL_FILTER_REMOVE: Remove the event, stops the processing
- *
- * Return values for the #CoglFilterFunc function.
- *
- * Stability: Unstable
- */
-typedef enum _CoglFilterReturn { /*< prefix=COGL_FILTER >*/
- COGL_FILTER_CONTINUE,
- COGL_FILTER_REMOVE
-} CoglFilterReturn;
-
-typedef enum _CoglWinsysFeature
-{
- /* Available if the window system can support multiple onscreen
- * framebuffers at the same time. */
- COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
-
- /* Available if onscreen framebuffer swaps can be automatically
- * throttled to the vblank frequency. */
- COGL_WINSYS_FEATURE_SWAP_THROTTLE,
-
- /* Available if its possible to query a counter that
- * increments at each vblank. */
- COGL_WINSYS_FEATURE_VBLANK_COUNTER,
-
- /* Available if its possible to wait until the next vertical
- * blank period */
- COGL_WINSYS_FEATURE_VBLANK_WAIT,
-
- /* Available if the window system supports mapping native
- * pixmaps to textures. */
- COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP,
-
- /* Available if the window system supports reporting an event
- * for swap buffer completions. */
- COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT,
-
- /* Available if it's possible to swap a list of sub rectangles
- * from the back buffer to the front buffer */
- COGL_WINSYS_FEATURE_SWAP_REGION,
-
- /* Available if swap_region requests can be automatically throttled
- * to the vblank frequency. */
- COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE,
-
- COGL_WINSYS_FEATURE_N_FEATURES
-} CoglWinsysFeature;
-
-/* XXX: Note these enum types are only referenced by experimental API
- * so although they aren't explicitly guarded they are implicitly
- * experimental too. */
-
-/*
- * CoglNativeFilterFunc:
- * @native_event: A pointer to the native system event
- * @data: The data that was given when the filter was added
- *
- * A callback function that can be registered with
- * cogl_renderer_add_native_filter(). The function should return
- * %COGL_FILTER_REMOVE if it wants to prevent further processing or
- * %COGL_FILTER_CONTINUE otherwise.
- *
- * The type that @native_event points to depends on the type of the
- * underlying renderer. On xlib based renderers this would point to an
- * XEvent struct and on Windows it would point to a MSG struct.
- */
-typedef CoglFilterReturn (* CoglNativeFilterFunc) (void *native_event,
- void *data);
-
-
-G_END_DECLS
-
-#endif /* __COGL_TYPES_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib-object.h>
-#include <gobject/gvaluecollector.h>
-
-#include "cogl.h"
-
-#include "cogl-fixed.h"
-#include "cogl-internal.h"
-#include "cogl-pipeline.h"
-#include "cogl-offscreen.h"
-#include "cogl-shader.h"
-#include "cogl-texture.h"
-#include "cogl-types.h"
-#include "cogl-util.h"
-
-/*
- * cogl_util_next_p2:
- * @a: Value to get the next power of two
- *
- * Calculates the next power of two greater than or equal to @a.
- *
- * Return value: @a if @a is already a power of two, otherwise returns
- * the next nearest power of two.
- */
-int
-_cogl_util_next_p2 (int a)
-{
- int rval = 1;
-
- while (rval < a)
- rval <<= 1;
-
- return rval;
-}
-
-/* gtypes */
-
-/*
- * CoglFixed
- */
-
-static GTypeInfo _info = {
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- 0,
- 0,
- NULL,
- NULL,
-};
-
-static GTypeFundamentalInfo _finfo = { 0, };
-
-static void
-cogl_value_init_fixed (GValue *value)
-{
- value->data[0].v_int = 0;
-}
-
-static void
-cogl_value_copy_fixed (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_int = src->data[0].v_int;
-}
-
-static char *
-cogl_value_collect_fixed (GValue *value,
- unsigned int n_collect_values,
- GTypeCValue *collect_values,
- unsigned int collect_flags)
-{
- value->data[0].v_int = collect_values[0].v_int;
-
- return NULL;
-}
-
-static char *
-cogl_value_lcopy_fixed (const GValue *value,
- unsigned int n_collect_values,
- GTypeCValue *collect_values,
- unsigned int collect_flags)
-{
- gint32 *fixed_p = collect_values[0].v_pointer;
-
- if (!fixed_p)
- return g_strdup_printf ("value location for '%s' passed as NULL",
- G_VALUE_TYPE_NAME (value));
-
- *fixed_p = value->data[0].v_int;
-
- return NULL;
-}
-
-static void
-cogl_value_transform_fixed_int (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_int = COGL_FIXED_TO_INT (src->data[0].v_int);
-}
-
-static void
-cogl_value_transform_fixed_double (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_double = COGL_FIXED_TO_DOUBLE (src->data[0].v_int);
-}
-
-static void
-cogl_value_transform_fixed_float (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_float = COGL_FIXED_TO_FLOAT (src->data[0].v_int);
-}
-
-static void
-cogl_value_transform_int_fixed (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_int = COGL_FIXED_FROM_INT (src->data[0].v_int);
-}
-
-static void
-cogl_value_transform_double_fixed (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_int = COGL_FIXED_FROM_DOUBLE (src->data[0].v_double);
-}
-
-static void
-cogl_value_transform_float_fixed (const GValue *src,
- GValue *dest)
-{
- dest->data[0].v_int = COGL_FIXED_FROM_FLOAT (src->data[0].v_float);
-}
-
-
-static const GTypeValueTable _cogl_fixed_value_table = {
- cogl_value_init_fixed,
- NULL,
- cogl_value_copy_fixed,
- NULL,
- "i",
- cogl_value_collect_fixed,
- "p",
- cogl_value_lcopy_fixed
-};
-
-GType
-cogl_fixed_get_type (void)
-{
- static GType _cogl_fixed_type = 0;
-
- if (G_UNLIKELY (_cogl_fixed_type == 0))
- {
- _info.value_table = & _cogl_fixed_value_table;
- _cogl_fixed_type =
- g_type_register_fundamental (g_type_fundamental_next (),
- g_intern_static_string ("CoglFixed"),
- &_info, &_finfo, 0);
-
- g_value_register_transform_func (_cogl_fixed_type, G_TYPE_INT,
- cogl_value_transform_fixed_int);
- g_value_register_transform_func (G_TYPE_INT, _cogl_fixed_type,
- cogl_value_transform_int_fixed);
-
- g_value_register_transform_func (_cogl_fixed_type, G_TYPE_FLOAT,
- cogl_value_transform_fixed_float);
- g_value_register_transform_func (G_TYPE_FLOAT, _cogl_fixed_type,
- cogl_value_transform_float_fixed);
-
- g_value_register_transform_func (_cogl_fixed_type, G_TYPE_DOUBLE,
- cogl_value_transform_fixed_double);
- g_value_register_transform_func (G_TYPE_DOUBLE, _cogl_fixed_type,
- cogl_value_transform_double_fixed);
- }
-
- return _cogl_fixed_type;
-}
-
-unsigned int
-_cogl_util_one_at_a_time_mix (unsigned int hash)
-{
- hash += ( hash << 3 );
- hash ^= ( hash >> 11 );
- hash += ( hash << 15 );
-
- return hash;
-}
-
-/* The 'ffs' function is part of C99 so it isn't always available */
-#ifndef HAVE_FFS
-
-int
-_cogl_util_ffs (int num)
-{
- int i = 1;
-
- if (num == 0)
- return 0;
-
- while ((num & 1) == 0)
- {
- num >>= 1;
- i++;
- }
-
- return i;
-}
-
-#endif /* HAVE_FFS */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_UTIL_H
-#define __COGL_UTIL_H
-
-#include <glib.h>
-#include <math.h>
-
-int
-_cogl_util_next_p2 (int a);
-
-/* The signbit macro is defined by ISO C99 so it should be available,
- however if it's not we can fallback to an evil hack */
-#ifdef signbit
-#define cogl_util_float_signbit(x) signbit(x)
-#else
-/* This trick was stolen from here:
- http://lists.boost.org/Archives/boost/2006/08/108731.php
-
- It xors the integer reinterpretations of -1.0f and 1.0f. In theory
- they should only differ by the signbit so that gives a mask for the
- sign which we can just test against the value */
-static inline gboolean
-cogl_util_float_signbit (float x)
-{
- static const union { float f; guint32 i; } negative_one = { -1.0f };
- static const union { float f; guint32 i; } positive_one = { +1.0f };
- union { float f; guint32 i; } value = { x };
-
- return !!((negative_one.i ^ positive_one.i) & value.i);
-}
-#endif
-
-/* This is a replacement for the nearbyint function which always
- rounds to the nearest integer. nearbyint is apparently a C99
- function so it might not always be available but also it seems in
- glibc it is defined as a function call so this macro could end up
- faster anyway. We can't just add 0.5f because it will break for
- negative numbers. */
-#define COGL_UTIL_NEARBYINT(x) ((int) ((x) < 0.0f ? (x) - 0.5f : (x) + 0.5f))
-
-/* Returns whether the given integer is a power of two */
-static inline gboolean
-_cogl_util_is_pot (unsigned int num)
-{
- /* Make sure there is only one bit set */
- return (num & (num - 1)) == 0;
-}
-
-/* Split Bob Jenkins' One-at-a-Time hash
- *
- * This uses the One-at-a-Time hash algorithm designed by Bob Jenkins
- * but the mixing step is split out so the function can be used in a
- * more incremental fashion.
- */
-static inline unsigned int
-_cogl_util_one_at_a_time_hash (unsigned int hash,
- void *key,
- size_t bytes)
-{
- unsigned char *p = key;
- int i;
-
- for (i = 0; i < bytes; i++)
- {
- hash += p[i];
- hash += (hash << 10);
- hash ^= (hash >> 6);
- }
-
- return hash;
-}
-
-unsigned int
-_cogl_util_one_at_a_time_mix (unsigned int hash);
-
-/* The 'ffs' function is part of C99 so it isn't always available */
-#ifdef HAVE_FFS
-#define _cogl_util_ffs ffs
-#else
-int
-_cogl_util_ffs (int num);
-#endif
-
-#endif /* __COGL_UTIL_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#include <cogl.h>
-#include <cogl-vector.h>
-
-#include <glib.h>
-#include <math.h>
-#include <string.h>
-
-void
-cogl_vector3_init (CoglVector3 *vector, float x, float y, float z)
-{
- vector->x = x;
- vector->y = y;
- vector->z = z;
-}
-
-void
-cogl_vector3_init_zero (CoglVector3 *vector)
-{
- memset (vector, 0, sizeof (CoglVector3));
-}
-
-gboolean
-cogl_vector3_equal (gconstpointer v1, gconstpointer v2)
-{
- CoglVector3 *vector0 = (CoglVector3 *)v1;
- CoglVector3 *vector1 = (CoglVector3 *)v2;
-
- g_return_val_if_fail (v1 != NULL, FALSE);
- g_return_val_if_fail (v2 != NULL, FALSE);
-
- /* There's no point picking an arbitrary epsilon that's appropriate
- * for comparing the components so we just use == that will at least
- * consider -0 and 0 to be equal. */
- return
- vector0->x == vector1->x &&
- vector0->y == vector1->y &&
- vector0->z == vector1->z;
-}
-
-gboolean
-cogl_vector3_equal_with_epsilon (const CoglVector3 *vector0,
- const CoglVector3 *vector1,
- float epsilon)
-{
- g_return_val_if_fail (vector0 != NULL, FALSE);
- g_return_val_if_fail (vector1 != NULL, FALSE);
-
- if (fabsf (vector0->x - vector1->x) < epsilon &&
- fabsf (vector0->y - vector1->y) < epsilon &&
- fabsf (vector0->z - vector1->z) < epsilon)
- return TRUE;
- else
- return FALSE;
-}
-
-CoglVector3 *
-cogl_vector3_copy (const CoglVector3 *vector)
-{
- if (vector)
- return g_slice_dup (CoglVector3, vector);
- return NULL;
-}
-
-void
-cogl_vector3_free (CoglVector3 *vector)
-{
- g_slice_free (CoglVector3, vector);
-}
-
-void
-cogl_vector3_invert (CoglVector3 *vector)
-{
- vector->x = -vector->x;
- vector->y = -vector->y;
- vector->z = -vector->z;
-}
-
-void
-cogl_vector3_add (CoglVector3 *result,
- const CoglVector3 *a,
- const CoglVector3 *b)
-{
- result->x = a->x + b->x;
- result->y = a->y + b->y;
- result->z = a->z + b->z;
-}
-
-void
-cogl_vector3_subtract (CoglVector3 *result,
- const CoglVector3 *a,
- const CoglVector3 *b)
-{
- result->x = a->x - b->x;
- result->y = a->y - b->y;
- result->z = a->z - b->z;
-}
-
-void
-cogl_vector3_multiply_scalar (CoglVector3 *vector,
- float scalar)
-{
- vector->x *= scalar;
- vector->y *= scalar;
- vector->z *= scalar;
-}
-
-void
-cogl_vector3_divide_scalar (CoglVector3 *vector,
- float scalar)
-{
- float one_over_scalar = 1.0f / scalar;
- vector->x *= one_over_scalar;
- vector->y *= one_over_scalar;
- vector->z *= one_over_scalar;
-}
-
-void
-cogl_vector3_normalize (CoglVector3 *vector)
-{
- float mag_squared =
- vector->x * vector->x +
- vector->y * vector->y +
- vector->z * vector->z;
-
- if (mag_squared > 0.0f)
- {
- float one_over_mag = 1.0f / sqrtf (mag_squared);
- vector->x *= one_over_mag;
- vector->y *= one_over_mag;
- vector->z *= one_over_mag;
- }
-}
-
-float
-cogl_vector3_magnitude (const CoglVector3 *vector)
-{
- return sqrtf (vector->x * vector->x +
- vector->y * vector->y +
- vector->z * vector->z);
-}
-
-void
-cogl_vector3_cross_product (CoglVector3 *result,
- const CoglVector3 *a,
- const CoglVector3 *b)
-{
- CoglVector3 tmp;
-
- tmp.x = a->y * b->z - a->z * b->y;
- tmp.y = a->z * b->x - a->x * b->z;
- tmp.z = a->x * b->y - a->y * b->x;
- *result = tmp;
-}
-
-float
-cogl_vector3_dot_product (const CoglVector3 *a, const CoglVector3 *b)
-{
- return a->x * b->x + a->y * b->y + a->z * b->z;
-}
-
-float
-cogl_vector3_distance (const CoglVector3 *a, const CoglVector3 *b)
-{
- float dx = b->x - a->x;
- float dy = b->y - a->y;
- float dz = b->z - a->z;
-
- return sqrtf (dx * dx + dy * dy + dz * dz);
-}
-
-#if 0
-void
-cogl_vector4_init (CoglVector4 *vector, float x, float y, float z)
-{
- vector->x = x;
- vector->y = y;
- vector->z = z;
- vector->w = w;
-}
-
-void
-cogl_vector4_init_zero (CoglVector4 *vector)
-{
- memset (vector, 0, sizeof (CoglVector4));
-}
-
-void
-cogl_vector4_init_from_vector4 (CoglVector4 *vector, CoglVector4 *src)
-{
- *vector4 = *src;
-}
-
-gboolean
-cogl_vector4_equal (gconstpointer *v0, gconstpointer *v1)
-{
- g_return_val_if_fail (v1 != NULL, FALSE);
- g_return_val_if_fail (v2 != NULL, FALSE);
-
- return memcmp (v1, v2, sizeof (float) * 4) == 0 ? TRUE : FALSE;
-}
-
-CoglVector4 *
-cogl_vector4_copy (CoglVector4 *vector)
-{
- if (vector)
- return g_slice_dup (CoglVector4, vector);
- return NULL;
-}
-
-void
-cogl_vector4_free (CoglVector4 *vector)
-{
- g_slice_free (CoglVector4, vector);
-}
-
-void
-cogl_vector4_invert (CoglVector4 *vector)
-{
- vector.x = -vector.x;
- vector.y = -vector.y;
- vector.z = -vector.z;
- vector.w = -vector.w;
-}
-
-void
-cogl_vector4_add (CoglVector4 *result,
- CoglVector4 *a,
- CoglVector4 *b)
-{
- result.x = a.x + b.x;
- result.y = a.y + b.y;
- result.z = a.z + b.z;
- result.w = a.w + b.w;
-}
-
-void
-cogl_vector4_subtract (CoglVector4 *result,
- CoglVector4 *a,
- CoglVector4 *b)
-{
- result.x = a.x - b.x;
- result.y = a.y - b.y;
- result.z = a.z - b.z;
- result.w = a.w - b.w;
-}
-
-void
-cogl_vector4_divide (CoglVector4 *vector,
- float scalar)
-{
- float one_over_scalar = 1.0f / scalar;
- result.x *= one_over_scalar;
- result.y *= one_over_scalar;
- result.z *= one_over_scalar;
- result.w *= one_over_scalar;
-}
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_VECTOR_H
-#define __COGL_VECTOR_H
-
-#include <glib.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-vector
- * @short_description: Functions for handling single precision float
- * vectors.
- *
- * This exposes a utility API that can be used for basic manipulation of 3
- * component float vectors.
- */
-
-/* All of the cogl-vector API is currently experimental so we
- * suffix the actual symbols with _EXP so if somone is monitoring for
- * ABI changes it will hopefully be clearer to them what's going on if
- * any of the symbols dissapear at a later date.
- */
-#define cogl_vector3_init cogl_vector3_init_EXP
-#define cogl_vector3_init_zero cogl_vector3_init_zero_EXP
-#define cogl_vector3_equal cogl_vector3_equal_EXP
-#define cogl_vector3_equal_with_epsilon cogl_vector3_equal_with_epsilon_EXP
-#define cogl_vector3_copy cogl_vector3_copy_EXP
-#define cogl_vector3_free cogl_vector3_free_EXP
-#define cogl_vector3_invert cogl_vector3_invert_EXP
-#define cogl_vector3_add cogl_vector3_add_EXP
-#define cogl_vector3_subtract cogl_vector3_subtract_EXP
-#define cogl_vector3_multiply_scalar cogl_vector3_multiply_scalar_EXP
-#define cogl_vector3_divide_scalar cogl_vector3_divide_scalar_EXP
-#define cogl_vector3_normalize cogl_vector3_normalize_EXP
-#define cogl_vector3_magnitude cogl_vector3_magnitude_EXP
-#define cogl_vector3_cross_product cogl_vector3_cross_product_EXP
-#define cogl_vector3_dot_product cogl_vector3_dot_product_EXP
-#define cogl_vector3_distance cogl_vector3_distance_EXP
-
-typedef struct
-{
- /* FIXME: add sse alignment constraint? */
- float x;
- float y;
- float z;
-} CoglVector3;
-
-#if 0
-typedef struct
-{
- /* FIXME: add sse alignment constraint? */
- float x;
- float y;
- float z;
- float w;
-} CoglVector4;
-#endif
-
-/**
- * cogl_vector3_init:
- * @vector: The CoglVector3 you want to initialize
- * @x: The x component
- * @y: The y component
- * @z: The z component
- *
- * Initializes a 3 component, single precision float vector which can
- * then be manipulated with the cogl_vector convenience APIs. Vectors
- * can also be used in places where a "point" is often desired.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_init (CoglVector3 *vector, float x, float y, float z);
-
-/**
- * cogl_vector3_init_zero:
- * @vector: The CoglVector3 you want to initialize
- *
- * Initializes a 3 component, single precision float vector with zero
- * for each component.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_init_zero (CoglVector3 *vector);
-
-/**
- * cogl_vector3_equal:
- * @v1: The first CoglVector3 you want to compare
- * @v2: The second CoglVector3 you want to compare
- *
- * Compares the components of two vectors and returns TRUE if they are
- * the same.
- *
- * The comparison of the components is done with the '==' operator
- * such that -0 is considered equal to 0, but otherwise there is no
- * fuzziness such as an epsilon to consider vectors that are
- * essentially identical except for some minor precision error
- * differences due to the way they have been manipulated.
- *
- * Returns: TRUE if the vectors are equal else FALSE.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_vector3_equal (gconstpointer v1, gconstpointer v2);
-
-/**
- * cogl_vector3_equal_with_epsilon:
- * @vector0: The first CoglVector3 you want to compare
- * @vector1: The second CoglVector3 you want to compare
- * @epsilon: The allowable difference between components to still be
- * considered equal
- *
- * Compares the components of two vectors using the given epsilon and
- * returns TRUE if they are the same, using an internal epsilon for
- * comparing the floats.
- *
- * Each component is compared against the epsilon value in this way:
- * |[
- * if (fabsf (vector0->x - vector1->x) < epsilon)
- * ]|
- *
- * Returns: TRUE if the vectors are equal else FALSE.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_vector3_equal_with_epsilon (const CoglVector3 *vector0,
- const CoglVector3 *vector1,
- float epsilon);
-
-/**
- * cogl_vector3_copy:
- * @vector: The CoglVector3 you want to copy
- *
- * Allocates a new #CoglVector3 structure on the heap initializing the
- * components from the given @vector and returns a pointer to the newly
- * allocated vector. You should free the memory using
- * cogl_vector3_free()
- *
- * Returns: A newly allocated #CoglVector3.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-CoglVector3 *
-cogl_vector3_copy (const CoglVector3 *vector);
-
-/**
- * cogl_vector3_free:
- * @vector: The CoglVector3 you want to free
- *
- * Frees a #CoglVector3 that was previously allocated with
- * cogl_vector_copy()
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_free (CoglVector3 *vector);
-
-/**
- * cogl_vector3_invert:
- * @vector: The CoglVector3 you want to manipulate
- *
- * Inverts/negates all the components of the given @vector.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_invert (CoglVector3 *vector);
-
-/**
- * cogl_vector3_add:
- * @result: Where you want the result written
- * @a: The first vector operand
- * @b: The second vector operand
- *
- * Adds each of the corresponding components in vectors @a and @b
- * storing the results in @result.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_add (CoglVector3 *result,
- const CoglVector3 *a,
- const CoglVector3 *b);
-
-/**
- * cogl_vector3_subtract:
- * @result: Where you want the result written
- * @a: The first vector operand
- * @b: The second vector operand
- *
- * Subtracts each of the corresponding components in vector @b from
- * @a storing the results in @result.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_subtract (CoglVector3 *result,
- const CoglVector3 *a,
- const CoglVector3 *b);
-
-/**
- * cogl_vector3_multiply_scalar:
- * @vector: The CoglVector3 you want to manipulate
- * @scalar: The scalar you want to multiply the vector components by
- *
- * Multiplies each of the @vector components by the given scalar.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_multiply_scalar (CoglVector3 *vector,
- float scalar);
-
-/**
- * cogl_vector3_divide_scalar:
- * @vector: The CoglVector3 you want to manipulate
- * @scalar: The scalar you want to divide the vector components by
- *
- * Divides each of the @vector components by the given scalar.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_divide_scalar (CoglVector3 *vector,
- float scalar);
-
-/**
- * cogl_vector3_normalize:
- * @vector: The CoglVector3 you want to manipulate
- *
- * Updates the vector so it is a "unit vector" such that the
- * @vector<!-- -->s magnitude or length is equal to 1.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_normalize (CoglVector3 *vector);
-
-/**
- * cogl_vector3_magnitude:
- * @vector: The CoglVector3 you want the magnitude for
- *
- * Calculates the scalar magnitude or length of @vector.
- *
- * Returns: The magnitude of @vector.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-float
-cogl_vector3_magnitude (const CoglVector3 *vector);
-
-/**
- * cogl_vector3_cross_product:
- * @result: Where you want the result written
- * @u: Your first CoglVector3
- * @v: Your second CoglVector3
- *
- * Calculates the cross product between the two vectors @u and @v.
- *
- * The cross product is a vector perpendicular to both @u and @v. This
- * can be useful for calculating the normal of a polygon by creating
- * two vectors in its plane using the polygons vertices and taking
- * their cross product.
- *
- * If the two vectors are parallel then the cross product is 0.
- *
- * You can use a right hand rule to determine which direction the
- * perpendicular vector will point: If you place the two vectors tail,
- * to tail and imagine grabbing the perpendicular line that extends
- * through the common tail with your right hand such that you fingers
- * rotate in the direction from @u to @v then the resulting vector
- * points along your extended thumb.
- *
- * Returns: The cross product between two vectors @u and @v.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_vector3_cross_product (CoglVector3 *result,
- const CoglVector3 *u,
- const CoglVector3 *v);
-
-/**
- * cogl_vector3_dot_product:
- * @a: Your first CoglVector3
- * @b: Your second CoglVector3
- *
- * Calculates the dot product of the two #CoglVector3<!-- -->s. This
- * can be used to determine the magnitude of one vector projected onto
- * another. (for example a surface normal)
- *
- * For example if you have a polygon with a given normal vector and
- * some other point for which you want to calculate its distance from
- * the polygon, you can create a vector between one of the polygon
- * vertices and that point and use the dot product to calculate the
- * magnitude for that vector but projected onto the normal of the
- * polygon. This way you don't just get the distance from the point to
- * the edge of the polygon you get the distance from the point to the
- * nearest part of the polygon.
- *
- * <note>If you don't use a unit length normal in the above example
- * then you would then also have to divide the result by the magnitude
- * of the normal</note>
- *
- * The dot product is calculated as:
- * |[
- * (a->x * b->x + a->y * b->y + a->z * b->z)
- * ]|
- *
- * For reference, the dot product can also be calculated from the
- * angle between two vectors as:
- * |[
- * |a||b|cos𝜃
- * ]|
- *
- * Returns: The dot product of two vectors.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-float
-cogl_vector3_dot_product (const CoglVector3 *a, const CoglVector3 *b);
-
-/**
- * cogl_vector3_distance:
- * @a: The first point
- * @b: The second point
- *
- * If you consider the two given vectors as (x,y,z) points instead
- * then this will compute the distance between those two points.
- *
- * Returns: The distance between two points given as @CoglVector3<!-- -->s
- *
- * Since: 1.4
- * Stability: Unstable
- */
-float
-cogl_vector3_distance (const CoglVector3 *a, const CoglVector3 *b);
-
-G_END_DECLS
-
-#endif /* __COGL_VECTOR_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_VERTEX_ARRAY_PRIVATE_H
-#define __COGL_VERTEX_ARRAY_PRIVATE_H
-
-#include "cogl-buffer-private.h"
-
-struct _CoglVertexArray
-{
- CoglBuffer _parent;
-};
-
-#endif /* __COGL_VERTEX_ARRAY_PRIVATE_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-object-private.h"
-#include "cogl-vertex-array.h"
-#include "cogl-vertex-array-private.h"
-
-static void _cogl_vertex_array_free (CoglVertexArray *array);
-
-COGL_BUFFER_DEFINE (VertexArray, vertex_array);
-
-CoglVertexArray *
-cogl_vertex_array_new (gsize bytes, const void *data)
-{
- CoglVertexArray *array = g_slice_new (CoglVertexArray);
- gboolean use_malloc;
-
- if (!cogl_features_available (COGL_FEATURE_VBOS))
- use_malloc = TRUE;
- else
- use_malloc = FALSE;
-
- /* parent's constructor */
- _cogl_buffer_initialize (COGL_BUFFER (array),
- bytes,
- use_malloc,
- COGL_BUFFER_BIND_TARGET_VERTEX_ARRAY,
- COGL_BUFFER_USAGE_HINT_VERTEX_ARRAY,
- COGL_BUFFER_UPDATE_HINT_STATIC);
-
- _cogl_vertex_array_object_new (array);
-
- if (data)
- cogl_buffer_set_data (COGL_BUFFER (array),
- 0,
- data,
- bytes);
- return array;
-}
-
-static void
-_cogl_vertex_array_free (CoglVertexArray *array)
-{
- /* parent's destructor */
- _cogl_buffer_fini (COGL_BUFFER (array));
-
- g_slice_free (CoglVertexArray, array);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_VERTEX_ARRAY_H__
-#define __COGL_VERTEX_ARRAY_H__
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-vertex-array
- * @short_description: Functions for creating and manipulating vertex arrays
- *
- * FIXME
- */
-
-typedef struct _CoglVertexArray CoglVertexArray;
-
-/**
- * cogl_vertex_array_new:
- * @bytes: The number of bytes to allocate for vertex attribute data.
- * @data: An optional pointer to vertex data to upload immediately.
- *
- * Declares a new #CoglVertexArray of @size bytes to contain arrays of vertex
- * attribute data. Once declared, data can be set using cogl_buffer_set_data()
- * or by mapping it into the application's address space using cogl_buffer_map().
- *
- * If @data isn't %NULL then @size bytes will be read from @data and
- * immediately copied into the new buffer.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-CoglVertexArray *
-cogl_vertex_array_new (gsize bytes,
- const void *data);
-
-/**
- * cogl_is_vertex_array:
- * @object: A #CoglObject
- *
- * Gets whether the given object references a #CoglVertexArray.
- *
- * Returns: %TRUE if the handle references a #CoglVertexArray,
- * %FALSE otherwise
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_is_vertex_array (void *object);
-
-G_END_DECLS
-
-#endif /* __COGL_VERTEX_ARRAY_H__ */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifndef __COGL_VERTEX_BUFFER_H
-#define __COGL_VERTEX_BUFFER_H
-
-#include "cogl-handle.h"
-
-#include "cogl-primitive.h"
-
-#include <glib.h>
-
-/* Note we put quite a bit into the flags here to help keep
- * the down size of the CoglVertexBufferAttrib struct below. */
-typedef enum _CoglVertexBufferAttribFlags
-{
- /* Types */
- /* NB: update the _TYPE_MASK below if these are changed */
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY = 1<<0,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY = 1<<1,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY = 1<<2,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY = 1<<3,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY = 1<<4,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID = 1<<5,
-
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMALIZED = 1<<6,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED = 1<<7,
-
- /* Usage hints */
- /* FIXME - flatten into one flag, since its used as a boolean */
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT = 1<<8,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT = 1<<9,
-
- /* GL Data types */
- /* NB: Update the _GL_TYPE_MASK below if these are changed */
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_BYTE = 1<<10,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_BYTE = 1<<11,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_SHORT = 1<<12,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_SHORT = 1<<13,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_INT = 1<<14,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_UNSIGNED_INT = 1<<15,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_FLOAT = 1<<16,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_GL_TYPE_DOUBLE = 1<<17,
-
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED = 1<<18,
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED = 1<<19
-
- /* XXX NB: If we need > 24 bits then look at changing the layout
- * of struct _CoglVertexBufferAttrib below */
-} CoglVertexBufferAttribFlags;
-
-#define COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK \
- (COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY \
- | COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY \
- | COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY \
- | COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY \
- | COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY \
- | COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
-
-typedef struct _CoglVertexBufferAttrib
-{
- /* TODO: look at breaking up the flags into seperate
- * bitfields and seperate enums */
- CoglVertexBufferAttribFlags flags:24;
- guint8 id;
- GQuark name;
- char *name_without_detail;
- union _u
- {
- const void *pointer;
- size_t vbo_offset;
- } u;
- CoglAttributeType type;
- size_t span_bytes;
- guint16 stride;
- guint8 n_components;
- guint8 texture_unit;
-
- int attribute_first;
- CoglAttribute *attribute;
-
-} CoglVertexBufferAttrib;
-
-typedef enum _CoglVertexBufferVBOFlags
-{
- COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED = 1<<0,
- COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK = 1<<1,
-
- /* FIXME - flatten into one flag, since its used as a boolean */
- COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT = 1<<3,
- COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT = 1<<4,
-
- COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED = 1<<5
-} CoglVertexBufferVBOFlags;
-
-/*
- * A CoglVertexBufferVBO represents one or more attributes in a single
- * buffer object
- */
-typedef struct _CoglVertexBufferVBO
-{
- CoglVertexBufferVBOFlags flags;
-
- CoglVertexArray *array;
- size_t array_bytes;
-
- GList *attributes;
-} CoglVertexBufferVBO;
-
-typedef struct _CoglVertexBufferIndices
-{
- CoglHandleObject _parent;
-
- CoglIndices *indices;
-} CoglVertexBufferIndices;
-
-typedef struct _CoglVertexBuffer
-{
- CoglHandleObject _parent;
-
- int n_vertices; /*!< The number of vertices in the buffer */
- GList *submitted_vbos; /* The VBOs currently submitted to the GPU */
-
- /* Note: new_attributes is normally NULL and only valid while
- * modifying a buffer. */
- GList *new_attributes; /*!< attributes pending submission */
-
- gboolean dirty_attributes;
-
- CoglPrimitive *primitive;
-
-} CoglVertexBuffer;
-
-CoglVertexBuffer *
-_cogl_vertex_buffer_pointer_from_handle (CoglHandle handle);
-
-CoglVertexBufferIndices *
-_cogl_vertex_buffer_indices_pointer_from_handle (CoglHandle handle);
-
-#endif /* __COGL_VERTEX_BUFFER_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-/* XXX: For an overview of the functionality implemented here, please
- * see cogl-vertex-buffer.h, which contains the gtk-doc section overview
- * for the Vertex Buffers API.
- */
-
-/*
- * TODO: We need to do a better job of minimizing when we call glVertexPointer
- * and pals in enable_state_for_drawing_buffer
- *
- * We should have an internal 2-tuple cache of (VBO, offset) for each of them
- * so we can avoid some GL calls. We could have cogl wrappers for the
- * gl*Pointer funcs that look like this:
- *
- * cogl_vertex_pointer (n_components, gl_type, stride, vbo, offset);
- * cogl_color_pointer (n_components, gl_type, stride, vbo, offset);
- *
- * They would also accept NULL for the VBO handle to support old style vertex
- * arrays.
- *
- * TODO:
- * Actually hook this up to the cogl shaders infrastructure. The vertex
- * buffer API has been designed to allow adding of arbitrary attributes for use
- * with shaders, but this has yet to be actually plumbed together and tested.
- * The bits we are missing:
- * - cogl_program_use doesn't currently record within ctx-> which program
- * is currently in use so a.t.m only Clutter knows the current shader.
- * - We don't query the current shader program for the generic vertex indices
- * (using glGetAttribLocation) so that we can call glEnableVertexAttribArray
- * with those indices.
- * (currently we just make up consecutive indices)
- * - some dirty flag mechanims to know when the shader program has changed
- * so we don't need to re-query it each time we draw a buffer.
- *
- * TODO
- * Expose API that lets developers get back a buffer handle for a particular
- * polygon so they may add custom attributes to them.
- * - It should be possible to query/modify attributes efficiently, in place,
- * avoiding copies. It would not be acceptable to simply require that
- * developers must query back the n_vertices of a buffer and then the
- * n_components, type and stride etc of each attribute since there
- * would be too many combinations to realistically handle.
- *
- * - In practice, some cases might be best solved with a higher level
- * EditableMesh API, (see futher below) but for many cases I think an
- * API like this might be appropriate:
- *
- * cogl_vertex_buffer_foreach_vertex (buffer_handle,
- * (AttributesBufferIteratorFunc)callback,
- * "gl_Vertex", "gl_Color", NULL);
- * static void callback (CoglVertexBufferVertex *vert)
- * {
- * GLfloat *pos = vert->attrib[0];
- * GLubyte *color = vert->attrib[1];
- * GLfloat *new_attrib = buf[vert->index];
- *
- * new_attrib = pos*color;
- * }
- *
- * TODO
- * Think about a higher level Mesh API for building/modifying attribute buffers
- * - E.g. look at Blender for inspiration here. They can build a mesh from
- * "MVert", "MFace" and "MEdge" primitives.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <glib.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-vertex-buffer-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-primitives.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-journal-private.h"
-
-#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
- (VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
-
-static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer);
-static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices);
-static CoglUserDataKey _cogl_vertex_buffer_pipeline_priv_key;
-
-COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer);
-COGL_OBJECT_DEFINE_DEPRECATED_REF_COUNTING (vertex_buffer);
-COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices);
-
-CoglHandle
-cogl_vertex_buffer_new (unsigned int n_vertices)
-{
- CoglVertexBuffer *buffer = g_slice_alloc (sizeof (CoglVertexBuffer));
-
- buffer->n_vertices = n_vertices;
-
- buffer->submitted_vbos = NULL;
- buffer->new_attributes = NULL;
- buffer->primitive = cogl_primitive_new (COGL_VERTICES_MODE_TRIANGLES,
- n_vertices, NULL);
-
- /* return COGL_INVALID_HANDLE; */
- return _cogl_vertex_buffer_handle_new (buffer);
-}
-
-unsigned int
-cogl_vertex_buffer_get_n_vertices (CoglHandle handle)
-{
- CoglVertexBuffer *buffer;
-
- if (!cogl_is_vertex_buffer (handle))
- return 0;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
-
- return buffer->n_vertices;
-}
-
-/* There are a number of standard OpenGL attributes that we deal with
- * specially. These attributes are all namespaced with a "gl_" prefix
- * so we should catch any typos instead of silently adding a custom
- * attribute.
- */
-static CoglVertexBufferAttribFlags
-validate_gl_attribute (const char *gl_attribute,
- guint8 n_components,
- guint8 *texture_unit)
-{
- CoglVertexBufferAttribFlags type;
- char *detail_seperator = NULL;
- int name_len;
-
- detail_seperator = strstr (gl_attribute, "::");
- if (detail_seperator)
- name_len = detail_seperator - gl_attribute;
- else
- name_len = strlen (gl_attribute);
-
- if (strncmp (gl_attribute, "Vertex", name_len) == 0)
- {
- if (G_UNLIKELY (n_components == 1))
- g_critical ("glVertexPointer doesn't allow 1 component vertex "
- "positions so we currently only support \"gl_Vertex\" "
- "attributes where n_components == 2, 3 or 4");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY;
- }
- else if (strncmp (gl_attribute, "Color", name_len) == 0)
- {
- if (G_UNLIKELY (n_components != 3 && n_components != 4))
- g_critical ("glColorPointer expects 3 or 4 component colors so we "
- "currently only support \"gl_Color\" attributes where "
- "n_components == 3 or 4");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY;
- }
- else if (strncmp (gl_attribute,
- "MultiTexCoord",
- strlen ("MultiTexCoord")) == 0)
- {
- unsigned int unit;
-
- if (sscanf (gl_attribute, "MultiTexCoord%u", &unit) != 1)
- {
- g_warning ("gl_MultiTexCoord attributes should include a\n"
- "texture unit number, E.g. gl_MultiTexCoord0\n");
- unit = 0;
- }
- /* FIXME: validate any '::' delimiter for this case */
- *texture_unit = unit;
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY;
- }
- else if (strncmp (gl_attribute, "Normal", name_len) == 0)
- {
- if (G_UNLIKELY (n_components != 3))
- g_critical ("glNormalPointer expects 3 component normals so we "
- "currently only support \"gl_Normal\" attributes where "
- "n_components == 3");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY;
- }
- else
- {
- g_warning ("Unknown gl_* attribute name gl_%s\n", gl_attribute);
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID;
- }
-
- return type;
-}
-
-/* There are a number of standard OpenGL attributes that we deal with
- * specially. These attributes are all namespaced with a "gl_" prefix
- * so we should catch any typos instead of silently adding a custom
- * attribute.
- */
-static CoglVertexBufferAttribFlags
-validate_cogl_attribute (const char *cogl_attribute,
- guint8 n_components,
- guint8 *texture_unit)
-{
- CoglVertexBufferAttribFlags type;
- char *detail_seperator = NULL;
- int name_len;
-
- detail_seperator = strstr (cogl_attribute, "::");
- if (detail_seperator)
- name_len = detail_seperator - cogl_attribute;
- else
- name_len = strlen (cogl_attribute);
-
- if (strncmp (cogl_attribute, "position_in", name_len) == 0)
- {
- if (G_UNLIKELY (n_components == 1))
- g_critical ("glVertexPointer doesn't allow 1 component vertex "
- "positions so we currently only support "
- "\"cogl_position_in\" attributes where "
- "n_components == 2, 3 or 4");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY;
- }
- else if (strncmp (cogl_attribute, "color_in", name_len) == 0)
- {
- if (G_UNLIKELY (n_components != 3 && n_components != 4))
- g_critical ("glColorPointer expects 3 or 4 component colors so we "
- "currently only support \"cogl_color_in\" attributes "
- "where n_components == 3 or 4");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY;
- }
- else if (strncmp (cogl_attribute,
- "cogl_tex_coord",
- strlen ("cogl_tex_coord")) == 0)
- {
- unsigned int unit;
-
- if (strcmp (cogl_attribute, "cogl_tex_coord_in") == 0)
- unit = 0;
- else if (sscanf (cogl_attribute, "cogl_tex_coord%u_in", &unit) != 1)
- {
- g_warning ("texture coordinate attributes should either be "
- "referenced as \"cogl_tex_coord_in\" or with a"
- "texture unit number like \"cogl_tex_coord1_in\"");
- unit = 0;
- }
- /* FIXME: validate any '::' delimiter for this case */
- *texture_unit = unit;
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY;
- }
- else if (strncmp (cogl_attribute, "normal_in", name_len) == 0)
- {
- if (G_UNLIKELY (n_components != 3))
- g_critical ("glNormalPointer expects 3 component normals so we "
- "currently only support \"cogl_normal_in\" attributes "
- "where n_components == 3");
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY;
- }
- else
- {
- g_warning ("Unknown cogl_* attribute name cogl_%s\n", cogl_attribute);
- type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID;
- }
-
- return type;
-}
-
-/* This validates that a custom attribute name is a valid GLSL variable name
- *
- * NB: attribute names may have a detail component delimited using '::' E.g.
- * custom_attrib::foo or custom_attrib::bar
- *
- * maybe I should hang a compiled regex somewhere to handle this
- */
-static gboolean
-validate_custom_attribute_name (const char *attribute_name)
-{
- char *detail_seperator = NULL;
- int name_len;
- int i;
-
- detail_seperator = strstr (attribute_name, "::");
- if (detail_seperator)
- name_len = detail_seperator - attribute_name;
- else
- name_len = strlen (attribute_name);
-
- if (name_len == 0
- || !g_ascii_isalpha (attribute_name[0])
- || attribute_name[0] != '_')
- return FALSE;
-
- for (i = 1; i < name_len; i++)
- if (!g_ascii_isalnum (attribute_name[i]) || attribute_name[i] != '_')
- return FALSE;
-
- return TRUE;
-}
-
-/* Iterates the CoglVertexBufferVBOs of a buffer and creates a flat list
- * of all the submitted attributes
- *
- * Note: The CoglVertexBufferAttrib structs are deep copied, except the
- * internal CoglAttribute pointer is set to NULL.
- */
-static GList *
-copy_submitted_attributes_list (CoglVertexBuffer *buffer)
-{
- GList *tmp;
- GList *submitted_attributes = NULL;
-
- for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferVBO *cogl_vbo = tmp->data;
- GList *tmp2;
-
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *attribute = tmp2->data;
- CoglVertexBufferAttrib *copy =
- g_slice_alloc (sizeof (CoglVertexBufferAttrib));
- *copy = *attribute;
- copy->name_without_detail =
- g_strdup (attribute->name_without_detail);
- copy->attribute = NULL;
- submitted_attributes = g_list_prepend (submitted_attributes, copy);
- }
- }
- return submitted_attributes;
-}
-
-static size_t
-sizeof_attribute_type (CoglAttributeType type)
-{
- switch (type)
- {
- case COGL_ATTRIBUTE_TYPE_BYTE:
- return 1;
- case COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE:
- return 1;
- case COGL_ATTRIBUTE_TYPE_SHORT:
- return 2;
- case COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT:
- return 2;
- case COGL_ATTRIBUTE_TYPE_FLOAT:
- return 4;
- }
- g_return_val_if_reached (0);
-}
-
-static size_t
-strideof (CoglAttributeType type, int n_components)
-{
- return sizeof_attribute_type (type) * n_components;
-}
-
-static char *
-canonize_attribute_name (const char *attribute_name)
-{
- char *detail_seperator = NULL;
- int name_len;
-
- if (strncmp (attribute_name, "gl_", 3) != 0)
- return g_strdup (attribute_name);
-
- /* skip past the "gl_" */
- attribute_name += 3;
-
- detail_seperator = strstr (attribute_name, "::");
- if (detail_seperator)
- name_len = detail_seperator - attribute_name;
- else
- {
- name_len = strlen (attribute_name);
- detail_seperator = "";
- }
-
- if (strncmp (attribute_name, "Vertex", name_len) == 0)
- return g_strconcat ("cogl_position_in", detail_seperator, NULL);
- else if (strncmp (attribute_name, "Color", name_len) == 0)
- return g_strconcat ("cogl_color_in", detail_seperator, NULL);
- else if (strncmp (attribute_name,
- "MultiTexCoord",
- strlen ("MultiTexCoord")) == 0)
- {
- unsigned int unit;
-
- if (sscanf (attribute_name, "MultiTexCoord%u", &unit) != 1)
- {
- g_warning ("gl_MultiTexCoord attributes should include a\n"
- "texture unit number, E.g. gl_MultiTexCoord0\n");
- unit = 0;
- }
- return g_strdup_printf ("cogl_tex_coord%u_in%s",
- unit, detail_seperator);
- }
- else if (strncmp (attribute_name, "Normal", name_len) == 0)
- return g_strconcat ("cogl_normal_in", detail_seperator, NULL);
- else
- {
- g_warning ("Unknown gl_* attribute name gl_%s\n", attribute_name);
- return g_strdup (attribute_name);
- }
-}
-
-void
-cogl_vertex_buffer_add (CoglHandle handle,
- const char *attribute_name,
- guint8 n_components,
- CoglAttributeType type,
- gboolean normalized,
- guint16 stride,
- const void *pointer)
-{
- CoglVertexBuffer *buffer;
- char *cogl_attribute_name;
- GQuark name_quark;
- gboolean modifying_an_attrib = FALSE;
- CoglVertexBufferAttrib *attribute;
- CoglVertexBufferAttribFlags flags = 0;
- guint8 texture_unit = 0;
- GList *tmp;
- char *detail;
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
- buffer->dirty_attributes = TRUE;
-
- cogl_attribute_name = canonize_attribute_name (attribute_name);
- name_quark = g_quark_from_string (cogl_attribute_name);
-
- /* The submit function works by diffing between submitted_attributes
- * and new_attributes to minimize the upload bandwidth + cost of
- * allocating new VBOs, so if there isn't already a list of new_attributes
- * we create one: */
- if (!buffer->new_attributes)
- buffer->new_attributes = copy_submitted_attributes_list (buffer);
-
- /* Note: we first look for an existing attribute that we are modifying
- * so we may skip needing to validate the name */
- for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *submitted_attribute = tmp->data;
- if (submitted_attribute->name == name_quark)
- {
- modifying_an_attrib = TRUE;
-
- attribute = submitted_attribute;
-
- /* since we will skip validate_gl/cogl_attribute in this case, we
- * need to pluck out the attribute type before overwriting the
- * flags: */
- flags |=
- attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK;
- break;
- }
- }
-
- if (!modifying_an_attrib)
- {
- /* Validate the attribute name, is suitable as a variable name */
- if (strncmp (attribute_name, "gl_", 3) == 0)
- {
- /* Note: we pass the original attribute name here so that
- * any warning messages correspond to the users original
- * attribute name... */
- flags |= validate_gl_attribute (attribute_name + 3,
- n_components,
- &texture_unit);
- if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
- return;
- }
- else if (strncmp (attribute_name, "cogl_", 5) == 0)
- {
- flags |= validate_cogl_attribute (attribute_name + 5,
- n_components,
- &texture_unit);
- if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
- return;
- }
- else
- {
- flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY;
- if (validate_custom_attribute_name (attribute_name))
- return;
- }
-
- attribute = g_slice_alloc0 (sizeof (CoglVertexBufferAttrib));
- }
-
- attribute->name = name_quark;
- detail = strstr (cogl_attribute_name, "::");
- if (detail)
- attribute->name_without_detail = g_strndup (cogl_attribute_name,
- detail - cogl_attribute_name);
- else
- attribute->name_without_detail = g_strdup (cogl_attribute_name);
- attribute->type = type;
- attribute->n_components = n_components;
- if (stride == 0)
- stride = strideof (type, n_components);
- attribute->stride = stride;
- attribute->u.pointer = pointer;
- attribute->texture_unit = texture_unit;
- attribute->attribute = NULL;
-
- flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
-
- /* Note: We currently just assume, if an attribute is *ever* updated
- * then it should be taged as frequently changing. */
- if (modifying_an_attrib)
- flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT;
- else
- flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT;
-
- if (normalized)
- flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMALIZED;
- attribute->flags = flags;
-
- attribute->span_bytes = buffer->n_vertices * attribute->stride;
-
- if (!modifying_an_attrib)
- buffer->new_attributes =
- g_list_prepend (buffer->new_attributes, attribute);
-
- g_free (cogl_attribute_name);
-}
-
-static void
-_cogl_vertex_buffer_attrib_free (CoglVertexBufferAttrib *attribute)
-{
- if (attribute->attribute)
- cogl_object_unref (attribute->attribute);
- g_free (attribute->name_without_detail);
- g_slice_free (CoglVertexBufferAttrib, attribute);
-}
-
-void
-cogl_vertex_buffer_delete (CoglHandle handle,
- const char *attribute_name)
-{
- CoglVertexBuffer *buffer;
- char *cogl_attribute_name = canonize_attribute_name (attribute_name);
- GQuark name = g_quark_from_string (cogl_attribute_name);
- GList *tmp;
-
- g_free (cogl_attribute_name);
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
- buffer->dirty_attributes = TRUE;
-
- /* The submit function works by diffing between submitted_attributes
- * and new_attributes to minimize the upload bandwidth + cost of
- * allocating new VBOs, so if there isn't already a list of new_attributes
- * we create one: */
- if (!buffer->new_attributes)
- buffer->new_attributes = copy_submitted_attributes_list (buffer);
-
- for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *submitted_attribute = tmp->data;
- if (submitted_attribute->name == name)
- {
- buffer->new_attributes =
- g_list_delete_link (buffer->new_attributes, tmp);
- _cogl_vertex_buffer_attrib_free (submitted_attribute);
- return;
- }
- }
-
- g_warning ("Failed to find an attribute named %s to delete\n",
- attribute_name);
-}
-
-static void
-set_attribute_enable (CoglHandle handle,
- const char *attribute_name,
- gboolean state)
-{
- CoglVertexBuffer *buffer;
- char *cogl_attribute_name = canonize_attribute_name (attribute_name);
- GQuark name_quark = g_quark_from_string (cogl_attribute_name);
- GList *tmp;
-
- g_free (cogl_attribute_name);
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
- buffer->dirty_attributes = TRUE;
-
- /* NB: If a buffer is currently being edited, then there can be two seperate
- * lists of attributes; those that are currently submitted and a new list yet
- * to be submitted, we need to modify both. */
-
- for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- if (attribute->name == name_quark)
- {
- if (state)
- attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
- else
- attribute->flags &= ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
- break;
- }
- }
-
- for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferVBO *cogl_vbo = tmp->data;
- GList *tmp2;
-
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *attribute = tmp2->data;
- if (attribute->name == name_quark)
- {
- if (state)
- attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
- else
- attribute->flags &= ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
- return;
- }
- }
- }
-
- g_warning ("Failed to %s attribute named %s/%s\n",
- state == TRUE ? "enable" : "disable",
- attribute_name, cogl_attribute_name);
-}
-
-void
-cogl_vertex_buffer_enable (CoglHandle handle,
- const char *attribute_name)
-{
- set_attribute_enable (handle, attribute_name, TRUE);
-}
-
-void
-cogl_vertex_buffer_disable (CoglHandle handle,
- const char *attribute_name)
-{
- set_attribute_enable (handle, attribute_name, FALSE);
-}
-
-/* Given an attribute that we know has already been submitted before, this
- * function looks for the existing VBO that contains it.
- *
- * Note: It will free redundant attribute struct once the corresponding
- * VBO has been found.
- */
-static void
-filter_already_submitted_attribute (CoglVertexBufferAttrib *attribute,
- GList **reuse_vbos,
- GList **submitted_vbos)
-{
- GList *tmp;
-
- /* First check the cogl_vbos we already know are being reused since we
- * are more likley to get a match here */
- for (tmp = *reuse_vbos; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferVBO *cogl_vbo = tmp->data;
- GList *tmp2;
-
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *vbo_attribute = tmp2->data;
-
- if (vbo_attribute->name == attribute->name)
- {
- vbo_attribute->flags &=
- ~COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED;
- /* Note: we don't free the redundant attribute here, since it
- * will be freed after all filtering in
- * cogl_vertex_buffer_submit */
- return;
- }
- }
- }
-
- for (tmp = *submitted_vbos; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferVBO *cogl_vbo = tmp->data;
- CoglVertexBufferAttrib *reuse_attribute = NULL;
- GList *tmp2;
-
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *vbo_attribute = tmp2->data;
- if (vbo_attribute->name == attribute->name)
- {
- reuse_attribute = vbo_attribute;
- /* Note: we don't free the redundant attribute here, since it
- * will be freed after all filtering in
- * cogl_vertex_buffer_submit */
-
- *submitted_vbos = g_list_remove_link (*submitted_vbos, tmp);
- tmp->next = *reuse_vbos;
- *reuse_vbos = tmp;
- break;
- }
- }
-
- if (!reuse_attribute)
- continue;
-
- /* Mark all but the matched attribute as UNUSED, so that when we
- * finish filtering all our attributes any attrributes still
- * marked as UNUSED can be removed from their cogl_vbo */
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *vbo_attribute = tmp2->data;
- if (vbo_attribute != reuse_attribute)
- vbo_attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED;
- }
-
- return;
- }
-
- g_critical ("Failed to find the cogl vbo that corresponds to an\n"
- "attribute that had apparently already been submitted!");
-}
-
-/* When we first mark a CoglVertexBufferVBO to be reused, we mark the
- * attributes as unsed, so that when filtering of attributes into VBOs is done
- * we can then prune the now unsed attributes. */
-static void
-remove_unused_attributes (CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
- GList *next;
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- next = tmp->next;
-
- if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_UNUSED)
- {
- cogl_vbo->attributes =
- g_list_delete_link (cogl_vbo->attributes, tmp);
- g_slice_free (CoglVertexBufferAttrib, attribute);
- }
- }
-}
-
-/* Give a newly added, strided, attribute, this function looks for a
- * CoglVertexBufferVBO that the attribute is interleved with. If it can't
- * find one then a new CoglVertexBufferVBO is allocated and added to the
- * list of new_strided_vbos.
- */
-static void
-filter_strided_attribute (CoglVertexBufferAttrib *attribute,
- GList **new_vbos)
-{
- GList *tmp;
- CoglVertexBufferVBO *new_cogl_vbo;
-
- for (tmp = *new_vbos; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferVBO *cogl_vbo = tmp->data;
- GList *tmp2;
-
- if (!(cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED))
- continue;
-
- for (tmp2 = cogl_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *vbo_attribute = tmp2->data;
- const char *attribute_start = attribute->u.pointer;
- const char *vbo_attribute_start = vbo_attribute->u.pointer;
-
- /* NB: All attributes have buffer->n_vertices values which
- * simplifies determining which attributes are interleved
- * since we assume they will start no farther than +- a
- * stride away from each other:
- */
- if (attribute_start <= (vbo_attribute_start - vbo_attribute->stride)
- || attribute_start
- >= (vbo_attribute_start + vbo_attribute->stride))
- continue; /* Not interleved */
-
- cogl_vbo->attributes =
- g_list_prepend (cogl_vbo->attributes, attribute);
-
- if (attribute->flags &
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT)
- {
- cogl_vbo->flags &=
- ~COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT;
- cogl_vbo->flags |=
- COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT;
- }
- return;
- }
- }
- new_cogl_vbo = g_slice_alloc (sizeof (CoglVertexBufferVBO));
- new_cogl_vbo->attributes = NULL;
- new_cogl_vbo->attributes =
- g_list_prepend (new_cogl_vbo->attributes, attribute);
- /* Any one of the interleved attributes will have the same span_bytes */
- new_cogl_vbo->array = NULL;
- new_cogl_vbo->array_bytes = attribute->span_bytes;
- new_cogl_vbo->flags = COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED;
-
- if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INFREQUENT_RESUBMIT)
- new_cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT;
- else
- new_cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT;
-
- *new_vbos = g_list_prepend (*new_vbos, new_cogl_vbo);
- return;
-}
-
-/* This iterates through the list of submitted VBOs looking for one that
- * contains attribute. If found the list *link* is removed and returned */
-static GList *
-unlink_submitted_vbo_containing_attribute (GList **submitted_vbos,
- CoglVertexBufferAttrib *attribute)
-{
- GList *tmp;
- GList *next = NULL;
-
- for (tmp = *submitted_vbos; tmp != NULL; tmp = next)
- {
- CoglVertexBufferVBO *submitted_vbo = tmp->data;
- GList *tmp2;
-
- next = tmp->next;
-
- for (tmp2 = submitted_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *submitted_attribute = tmp2->data;
-
- if (submitted_attribute->name == attribute->name)
- {
- *submitted_vbos = g_list_remove_link (*submitted_vbos, tmp);
- return tmp;
- }
- }
- }
-
- return NULL;
-}
-
-/* Unlinks all the submitted VBOs that conflict with the new cogl_vbo and
- * returns them as a list. */
-static GList *
-get_submitted_vbo_conflicts (GList **submitted_vbos,
- CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
- GList *conflicts = NULL;
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- {
- GList *link =
- unlink_submitted_vbo_containing_attribute (submitted_vbos,
- tmp->data);
- if (link)
- {
- /* prepend the link to the list of conflicts: */
- link->next = conflicts;
- conflicts = link;
- }
- }
- return conflicts;
-}
-
-/* Any attributes in cogl_vbo gets removed from conflict_vbo */
-static void
-disassociate_conflicting_attributes (CoglVertexBufferVBO *conflict_vbo,
- CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
-
- /* NB: The attributes list in conflict_vbo will be shrinking so
- * we iterate those in the inner loop. */
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- GList *tmp2;
- for (tmp2 = conflict_vbo->attributes; tmp2 != NULL; tmp2 = tmp2->next)
- {
- CoglVertexBufferAttrib *conflict_attribute = tmp2->data;
-
- if (conflict_attribute->name == attribute->name)
- {
- _cogl_vertex_buffer_attrib_free (conflict_attribute);
- conflict_vbo->attributes =
- g_list_delete_link (conflict_vbo->attributes, tmp2);
- break;
- }
- }
- }
-}
-
-static void
-cogl_vertex_buffer_vbo_free (CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- _cogl_vertex_buffer_attrib_free (tmp->data);
- g_list_free (cogl_vbo->attributes);
-
- if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED)
- cogl_object_unref (cogl_vbo->array);
-
- g_slice_free (CoglVertexBufferVBO, cogl_vbo);
-}
-
-/* This figures out the lowest attribute client pointer. (This pointer is used
- * to upload all the interleved attributes).
- *
- * In the process it also replaces the client pointer with the attributes
- * offset, and marks the attribute as submitted.
- */
-static const void *
-prep_strided_vbo_for_upload (CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
- const char *lowest_pointer = NULL;
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- const char *client_pointer = attribute->u.pointer;
-
- if (!lowest_pointer || client_pointer < lowest_pointer)
- lowest_pointer = client_pointer;
- }
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- const char *client_pointer = attribute->u.pointer;
- attribute->u.vbo_offset = client_pointer - lowest_pointer;
- attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED;
- }
-
- return lowest_pointer;
-}
-
-static gboolean
-upload_multipack_vbo_via_map_buffer (CoglVertexBufferVBO *cogl_vbo)
-{
- GList *tmp;
- unsigned int offset = 0;
- guint8 *buf;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- buf = cogl_buffer_map (COGL_BUFFER (cogl_vbo->array),
- COGL_BUFFER_ACCESS_WRITE,
- COGL_BUFFER_MAP_HINT_DISCARD);
- if (!buf)
- return FALSE;
-
- for (tmp = cogl_vbo->attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
- gsize attribute_size = attribute->span_bytes;
- gsize type_size = sizeof_attribute_type (attribute->type);
-
- PAD_FOR_ALIGNMENT (offset, type_size);
-
- memcpy (buf + offset, attribute->u.pointer, attribute_size);
-
- attribute->u.vbo_offset = offset;
- attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED;
- offset += attribute_size;
- }
-
- cogl_buffer_unmap (COGL_BUFFER (cogl_vbo->array));
-
- return TRUE;
-}
-
-static void
-upload_multipack_vbo_via_buffer_sub_data (CoglVertexBufferVBO *cogl_vbo)
-{
- GList *l;
- unsigned int offset = 0;
-
- for (l = cogl_vbo->attributes; l != NULL; l = l->next)
- {
- CoglVertexBufferAttrib *attribute = l->data;
- gsize attribute_size = attribute->span_bytes;
- gsize type_size = sizeof_attribute_type (attribute->type);
-
- PAD_FOR_ALIGNMENT (offset, type_size);
-
- cogl_buffer_set_data (COGL_BUFFER (cogl_vbo->array),
- offset,
- attribute->u.pointer,
- attribute_size);
-
- attribute->u.vbo_offset = offset;
- attribute->flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED;
- offset += attribute_size;
- }
-}
-
-static void
-upload_attributes (CoglVertexBufferVBO *cogl_vbo)
-{
- CoglBufferUpdateHint usage;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT)
- usage = COGL_BUFFER_UPDATE_HINT_DYNAMIC;
- else
- usage = COGL_BUFFER_UPDATE_HINT_STATIC;
- cogl_buffer_set_update_hint (COGL_BUFFER (cogl_vbo->array), usage);
-
- if (cogl_vbo->flags & COGL_VERTEX_BUFFER_VBO_FLAG_STRIDED)
- {
- const void *pointer = prep_strided_vbo_for_upload (cogl_vbo);
- cogl_buffer_set_data (COGL_BUFFER (cogl_vbo->array),
- 0, /* offset */
- pointer,
- cogl_vbo->array_bytes);
- }
- else /* MULTIPACK */
- {
- /* I think it might depend on the specific driver/HW whether its better
- * to use glMapBuffer here or glBufferSubData here. There is even a good
- * thread about this topic here:
- * http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg35004.html
- * For now I have gone with glMapBuffer, but the jury is still out.
- */
-
- if (!upload_multipack_vbo_via_map_buffer (cogl_vbo))
- upload_multipack_vbo_via_buffer_sub_data (cogl_vbo);
- }
-
- cogl_vbo->flags |= COGL_VERTEX_BUFFER_VBO_FLAG_SUBMITTED;
-}
-
-/* Note: although there ends up being quite a few inner loops involved with
- * resolving buffers, the number of attributes will be low so I don't expect
- * them to cause a problem. */
-static void
-cogl_vertex_buffer_vbo_resolve (CoglVertexBuffer *buffer,
- CoglVertexBufferVBO *new_cogl_vbo,
- GList **final_vbos)
-{
- GList *conflicts;
- GList *tmp;
- GList *next;
- gboolean found_target_vbo = FALSE;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- conflicts =
- get_submitted_vbo_conflicts (&buffer->submitted_vbos, new_cogl_vbo);
-
- for (tmp = conflicts; tmp != NULL; tmp = next)
- {
- CoglVertexBufferVBO *conflict_vbo = tmp->data;
-
- next = tmp->next;
-
- disassociate_conflicting_attributes (conflict_vbo, new_cogl_vbo);
-
- if (!conflict_vbo->attributes)
- {
- /* See if we can re-use this now empty VBO: */
-
- if (!found_target_vbo
- && conflict_vbo->array_bytes == new_cogl_vbo->array_bytes)
- {
- found_target_vbo = TRUE;
- new_cogl_vbo->array = cogl_object_ref (conflict_vbo->array);
- cogl_vertex_buffer_vbo_free (conflict_vbo);
-
- upload_attributes (new_cogl_vbo);
-
- *final_vbos = g_list_prepend (*final_vbos, new_cogl_vbo);
- }
- else
- cogl_vertex_buffer_vbo_free (conflict_vbo);
- }
- else
- {
- /* Relink the VBO back into buffer->submitted_vbos since it may
- * be involved in other conflicts later */
- tmp->next = buffer->submitted_vbos;
- tmp->prev = NULL;
- buffer->submitted_vbos = tmp;
- }
- }
-
- if (!found_target_vbo)
- {
- new_cogl_vbo->array = cogl_vertex_array_new (new_cogl_vbo->array_bytes,
- NULL);
-
- upload_attributes (new_cogl_vbo);
- *final_vbos = g_list_prepend (*final_vbos, new_cogl_vbo);
- }
-}
-
-static void
-update_primitive_attributes (CoglVertexBuffer *buffer)
-{
- GList *l;
- int n_attributes = 0;
- CoglAttribute **attributes;
- int i;
-
- if (!buffer->dirty_attributes)
- return;
-
- buffer->dirty_attributes = FALSE;
-
- for (l = buffer->submitted_vbos; l; l = l->next)
- {
- CoglVertexBufferVBO *cogl_vbo = l->data;
- GList *l2;
-
- for (l2 = cogl_vbo->attributes; l2; l2 = l2->next, n_attributes++)
- ;
- }
-
- g_return_if_fail (n_attributes > 0);
-
- attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes + 1);
-
- i = 0;
- for (l = buffer->submitted_vbos; l; l = l->next)
- {
- CoglVertexBufferVBO *cogl_vbo = l->data;
- GList *l2;
-
- for (l2 = cogl_vbo->attributes; l2; l2 = l2->next)
- {
- CoglVertexBufferAttrib *attribute = l2->data;
- if (G_LIKELY (attribute->flags &
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED))
- {
- if (G_UNLIKELY (!attribute->attribute))
- {
- attribute->attribute =
- cogl_attribute_new (cogl_vbo->array,
- attribute->name_without_detail,
- attribute->stride,
- attribute->u.vbo_offset,
- attribute->n_components,
- attribute->type);
- }
-
- attributes[i++] = attribute->attribute;
- }
- }
- }
-
- attributes[i] = NULL;
-
- cogl_primitive_set_attributes (buffer->primitive, attributes);
-}
-
-static void
-cogl_vertex_buffer_submit_real (CoglVertexBuffer *buffer)
-{
- GList *tmp;
- CoglVertexBufferVBO *new_multipack_vbo;
- GList *new_multipack_vbo_link;
- GList *new_vbos = NULL;
- GList *reuse_vbos = NULL;
- GList *final_vbos = NULL;
-
- if (!buffer->new_attributes)
- goto done;
-
- /* The objective now is to copy the attribute data supplied by the client
- * into buffer objects, but it's important to minimize the number of
- * redundant data uploads.
- *
- * We obviously aim to group together the attributes that are interleved so
- * that they can be delivered in one go to the driver.
- * All BOs for interleved data are created as STATIC_DRAW_ARB.
- *
- * Non interleved attributes tagged as INFREQUENT_RESUBMIT will be grouped
- * together back to back in a single BO created as STATIC_DRAW_ARB
- *
- * Non interleved attributes tagged as FREQUENT_RESUBMIT will be copied into
- * individual buffer objects, and the BO itself created DYNAMIC_DRAW_ARB
- *
- * If we are modifying a previously submitted CoglVertexBuffer then we are
- * carefull not to needlesly delete OpenGL buffer objects and replace with
- * new ones, instead we upload new data to the existing buffers.
- */
-
- /* NB: We must forget attribute->pointer after submitting since the user
- * is free to re-use that memory for other purposes now. */
-
- /* Pseudo code:
- *
- * Broadly speaking we start with a list of unsorted attributes, and filter
- * those into 'new' and 're-use' CoglVertexBufferVBO (CBO) lists. We then
- * take the list of new CBO structs and compare with the CBOs that have
- * already been submitted to the GPU (but ignoring those we already know will
- * be re-used) to determine what other CBOs can be re-used, due to being
- * superseded, and what new GL VBOs need to be created.
- *
- * We have two kinds of CBOs:
- * - Multi Pack CBOs
- * These contain multiple attributes tightly packed back to back)
- * - Strided CBOs
- * These typically contain multiple interleved sets of attributes,
- * though they can contain just one attribute with a stride
- *
- * First create a new-CBOs entry "new-multipack-CBO"
- * Tag "new-multipack-CBO" as MULTIPACK + INFREQUENT_RESUBMIT
- * For each unsorted attrib:
- * if already marked as submitted:
- * iterate reuse-CBOs:
- * if we find one that contains this attribute:
- * free redundant unsorted attrib struct
- * remove the UNUSED flag from the attrib found in the reuse-CBO
- * continue to next unsorted attrib
- * iterate submitted VBOs:
- * if we find one that contains this attribute:
- * free redundant unsorted attrib struct
- * unlink the vbo and move it to the list of reuse-CBOs
- * mark all attributes except the one just matched as UNUSED
- * assert (found)
- * continue to next unsorted attrib
- * if strided:
- * iterate the new, strided, CBOs, to see if the attribute is
- * interleved with one of them, if found:
- * add to the matched CBO
- * else if not found:
- * create a new-CBOs entry tagged STRIDED + INFREQUENT_RESUBMIT
- * else if unstrided && tagged with FREQUENT_RESUBMIT:
- * create a new-CBOs entry tagged MULTIPACK + FREQUENT_RESUBMIT
- * else
- * add to the new-multipack-CBO
- * free list of unsorted-attribs
- *
- * Next compare the new list of CBOs with the submitted set and try to
- * minimize the memory bandwidth required to upload the attributes and the
- * overhead of creating new GL-BOs.
- *
- * We deal with four sets of CBOs:
- * - The "new" CBOs
- * (as determined above during filtering)
- * - The "re-use" CBOs
- * (as determined above during filtering)
- * - The "submitted" CBOs
- * (I.e. ones currently submitted to the GPU)
- * - The "final" CBOs
- * (The result of resolving the differences between the above sets)
- *
- * The re-use CBOs are dealt with first, and we simply delete any remaining
- * attributes in these that are still marked as UNUSED, and move them
- * to the list of final CBOs.
- *
- * Next we iterate through the "new" CBOs, searching for conflicts
- * with the "submitted" CBOs and commit our decision to the "final" CBOs
- *
- * When searching for submitted entries we always unlink items from the
- * submitted list once we make matches (before we make descisions
- * based on the matches). If the CBO node is superseded it is freed,
- * if it is modified but may be needed for more descisions later it is
- * relinked back into the submitted list and if it's identical to a new
- * CBO it will be linked into the final list.
- *
- * At the end the list of submitted CBOs represents the attributes that were
- * deleted from the buffer.
- *
- * Iterate re-use-CBOs:
- * Iterate attribs for each:
- * if attrib UNUSED:
- * remove the attrib from the CBO + free
- * |Note: we could potentially mark this as a re-useable gap
- * |if needs be later.
- * add re-use CBO to the final-CBOs
- * Iterate new-CBOs:
- * List submitted CBOs conflicting with the this CBO (Unlinked items)
- * found-target-BO=FALSE
- * Iterate conflicting CBOs:
- * Disassociate conflicting attribs from conflicting CBO struct
- * If no attribs remain:
- * If found-target-BO!=TRUE
- * _AND_ If the total size of the conflicting CBO is compatible:
- * |Note: We don't currently consider re-using oversized buffers
- * found-target-BO=TRUE
- * upload replacement data
- * free submitted CBO struct
- * add new CBO struct to final-CBOs
- * else:
- * delete conflict GL-BO
- * delete conflict CBO struct
- * else:
- * relink CBO back into submitted-CBOs
- *
- * if found-target-BO == FALSE:
- * create a new GL-BO
- * upload data
- * add new CBO struct to final-BOs
- *
- * Iterate through the remaining "submitted" CBOs:
- * delete the submitted GL-BO
- * free the submitted CBO struct
- */
-
- new_multipack_vbo = g_slice_alloc (sizeof (CoglVertexBufferVBO));
- new_multipack_vbo->array = NULL;
- new_multipack_vbo->array_bytes = 0;
- new_multipack_vbo->flags =
- COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK
- | COGL_VERTEX_BUFFER_VBO_FLAG_INFREQUENT_RESUBMIT;
- new_multipack_vbo->attributes = NULL;
- new_vbos = g_list_prepend (new_vbos, new_multipack_vbo);
- /* We save the link pointer here, just so we can do a fast removal later if
- * no attributes get added to this vbo. */
- new_multipack_vbo_link = new_vbos;
-
- /* Start with a list of unsorted attributes, and filter those into
- * potential new Cogl BO structs
- */
- for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
- {
- CoglVertexBufferAttrib *attribute = tmp->data;
-
- if (attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_SUBMITTED)
- {
- /* If the attribute is already marked as submitted, then we need
- * to find the existing VBO that contains it so we dont delete it.
- *
- * NB: this also frees the attribute struct since it's implicitly
- * redundant in this case.
- */
- filter_already_submitted_attribute (attribute,
- &reuse_vbos,
- &buffer->submitted_vbos);
- }
- else if (attribute->stride)
- {
- /* look for a CoglVertexBufferVBO that the attribute is
- * interleved with. If one can't be found then a new
- * CoglVertexBufferVBO is allocated and added to the list of
- * new_vbos: */
- filter_strided_attribute (attribute, &new_vbos);
- }
- else if (attribute->flags &
- COGL_VERTEX_BUFFER_ATTRIB_FLAG_FREQUENT_RESUBMIT)
- {
- CoglVertexBufferVBO *cogl_vbo =
- g_slice_alloc (sizeof (CoglVertexBufferVBO));
-
- /* attributes we expect will be frequently resubmitted are placed
- * in their own VBO so that updates don't impact other attributes
- */
-
- cogl_vbo->flags =
- COGL_VERTEX_BUFFER_VBO_FLAG_MULTIPACK
- | COGL_VERTEX_BUFFER_VBO_FLAG_FREQUENT_RESUBMIT;
- cogl_vbo->attributes = NULL;
- cogl_vbo->attributes = g_list_prepend (cogl_vbo->attributes,
- attribute);
- cogl_vbo->array = NULL;
- cogl_vbo->array_bytes = attribute->span_bytes;
- new_vbos = g_list_prepend (new_vbos, cogl_vbo);
- }
- else
- {
- gsize type_size = sizeof_attribute_type (attribute->flags);
-
- /* Infrequently updated attributes just get packed back to back
- * in a single VBO: */
- new_multipack_vbo->attributes =
- g_list_prepend (new_multipack_vbo->attributes,
- attribute);
-
- /* Note: we have to ensure that each run of attributes is
- * naturally aligned according to its data type, which may
- * require some padding bytes: */
-
- /* XXX: We also have to be sure that the attributes aren't
- * reorderd before being uploaded because the alignment padding
- * is based on the adjacent attribute.
- */
-
- PAD_FOR_ALIGNMENT (new_multipack_vbo->array_bytes, type_size);
-
- new_multipack_vbo->array_bytes += attribute->span_bytes;
- }
- }
-
- /* At this point all buffer->new_attributes have been filtered into
- * CoglVertexBufferVBOs... */
- g_list_free (buffer->new_attributes);
- buffer->new_attributes = NULL;
-
- /* If the multipack vbo wasn't needed: */
- if (new_multipack_vbo->attributes == NULL)
- {
- new_vbos = g_list_delete_link (new_vbos, new_multipack_vbo_link);
- g_slice_free (CoglVertexBufferVBO, new_multipack_vbo);
- }
-
- for (tmp = reuse_vbos; tmp != NULL; tmp = tmp->next)
- remove_unused_attributes (tmp->data);
- final_vbos = g_list_concat (final_vbos, reuse_vbos);
-
- for (tmp = new_vbos; tmp != NULL; tmp = tmp->next)
- cogl_vertex_buffer_vbo_resolve (buffer, tmp->data, &final_vbos);
-
- /* Anything left corresponds to deleted attributes: */
- for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
- cogl_vertex_buffer_vbo_free (tmp->data);
- g_list_free (buffer->submitted_vbos);
- g_list_free (new_vbos);
-
- buffer->submitted_vbos = final_vbos;
-
-done:
- update_primitive_attributes (buffer);
-}
-
-void
-cogl_vertex_buffer_submit (CoglHandle handle)
-{
- CoglVertexBuffer *buffer;
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
-
- cogl_vertex_buffer_submit_real (buffer);
-}
-
-typedef struct
-{
- /* We have a ref-count on this private structure because we need to
- refer to it both from the private data on a pipeline and any weak
- pipelines that we create from it. If we didn't have the ref count
- then we would depend on the order of destruction of a
- CoglPipeline and the weak materials to avoid a crash */
- unsigned int ref_count;
-
- CoglPipeline *real_source;
-} VertexBufferMaterialPrivate;
-
-static void
-unref_pipeline_priv (VertexBufferMaterialPrivate *priv)
-{
- if (--priv->ref_count < 1)
- g_slice_free (VertexBufferMaterialPrivate, priv);
-}
-
-static void
-weak_override_source_destroyed_cb (CoglPipeline *pipeline,
- void *user_data)
-{
- VertexBufferMaterialPrivate *pipeline_priv = user_data;
- pipeline_priv->real_source = NULL;
- /* A reference was added when we copied the weak material so we need
- to unref it here */
- unref_pipeline_priv (pipeline_priv);
-}
-
-static gboolean
-validate_layer_cb (CoglPipeline *pipeline,
- int layer_index,
- void *user_data)
-{
- VertexBufferMaterialPrivate *pipeline_priv = user_data;
- CoglPipeline *source = pipeline_priv->real_source;
-
- if (!cogl_pipeline_get_layer_point_sprite_coords_enabled (source,
- layer_index))
- {
- CoglPipelineWrapMode wrap_s;
- CoglPipelineWrapMode wrap_t;
- CoglPipelineWrapMode wrap_p;
- gboolean need_override_source = FALSE;
-
- /* By default COGL_PIPELINE_WRAP_MODE_AUTOMATIC becomes
- * GL_CLAMP_TO_EDGE but we want GL_REPEAT to maintain
- * compatibility with older versions of Cogl so we'll override
- * it. We don't want to do this for point sprites because in
- * that case the whole texture is drawn so you would usually
- * want clamp-to-edge.
- */
- wrap_s = cogl_pipeline_get_layer_wrap_mode_s (source, layer_index);
- if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- need_override_source = TRUE;
- wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT;
- }
- wrap_t = cogl_pipeline_get_layer_wrap_mode_t (source, layer_index);
- if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- need_override_source = TRUE;
- wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT;
- }
- wrap_p = cogl_pipeline_get_layer_wrap_mode_p (source, layer_index);
- if (wrap_p == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
- {
- need_override_source = TRUE;
- wrap_p = COGL_PIPELINE_WRAP_MODE_REPEAT;
- }
-
- if (need_override_source)
- {
- if (pipeline_priv->real_source == pipeline)
- {
- pipeline_priv->ref_count++;
- pipeline_priv->real_source = source =
- _cogl_pipeline_weak_copy (pipeline,
- weak_override_source_destroyed_cb,
- pipeline_priv);
- }
-
- cogl_pipeline_set_layer_wrap_mode_s (source, layer_index, wrap_s);
- cogl_pipeline_set_layer_wrap_mode_t (source, layer_index, wrap_t);
- cogl_pipeline_set_layer_wrap_mode_p (source, layer_index, wrap_p);
- }
- }
-
- return TRUE;
-}
-
-static void
-destroy_pipeline_priv_cb (void *user_data)
-{
- unref_pipeline_priv (user_data);
-}
-
-static void
-update_primitive_and_draw (CoglVertexBuffer *buffer,
- CoglVerticesMode mode,
- int first,
- int count,
- CoglVertexBufferIndices *buffer_indices)
-{
- VertexBufferMaterialPrivate *pipeline_priv;
- CoglPipeline *users_source;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_primitive_set_mode (buffer->primitive, mode);
- cogl_primitive_set_first_vertex (buffer->primitive, first);
- cogl_primitive_set_n_vertices (buffer->primitive, count);
-
- if (buffer_indices)
- cogl_primitive_set_indices (buffer->primitive, buffer_indices->indices);
- else
- cogl_primitive_set_indices (buffer->primitive, NULL);
-
- cogl_vertex_buffer_submit_real (buffer);
-
- users_source = cogl_get_source ();
- pipeline_priv =
- cogl_object_get_user_data (COGL_OBJECT (users_source),
- &_cogl_vertex_buffer_pipeline_priv_key);
- if (G_UNLIKELY (!pipeline_priv))
- {
- pipeline_priv = g_slice_new0 (VertexBufferMaterialPrivate);
- pipeline_priv->ref_count = 1;
- cogl_object_set_user_data (COGL_OBJECT (users_source),
- &_cogl_vertex_buffer_pipeline_priv_key,
- pipeline_priv,
- destroy_pipeline_priv_cb);
- }
-
- if (G_UNLIKELY (!pipeline_priv->real_source))
- {
- pipeline_priv->real_source = users_source;
- cogl_pipeline_foreach_layer (pipeline_priv->real_source,
- validate_layer_cb,
- pipeline_priv);
- }
-
- cogl_push_source (pipeline_priv->real_source);
-
- cogl_primitive_draw (buffer->primitive);
-
- cogl_pop_source ();
-}
-
-void
-cogl_vertex_buffer_draw (CoglHandle handle,
- CoglVerticesMode mode,
- int first,
- int count)
-{
- CoglVertexBuffer *buffer;
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
-
- update_primitive_and_draw (buffer, mode, first, count, NULL);
-}
-
-static CoglHandle
-_cogl_vertex_buffer_indices_new_real (CoglIndices *indices)
-{
- CoglVertexBufferIndices *buffer_indices =
- g_slice_alloc (sizeof (CoglVertexBufferIndices));
- buffer_indices->indices = indices;
-
- return _cogl_vertex_buffer_indices_handle_new (buffer_indices);
-}
-
-CoglHandle
-cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
- const void *indices_array,
- int indices_len)
-{
- CoglIndices *indices =
- cogl_indices_new (indices_type, indices_array, indices_len);
- return _cogl_vertex_buffer_indices_new_real (indices);
-}
-
-CoglIndicesType
-cogl_vertex_buffer_indices_get_type (CoglHandle indices_handle)
-{
- CoglVertexBufferIndices *buffer_indices = NULL;
-
- if (!cogl_is_vertex_buffer_indices (indices_handle))
- return COGL_INDICES_TYPE_UNSIGNED_SHORT;
-
- buffer_indices =
- _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
-
- return cogl_indices_get_type (buffer_indices->indices);
-}
-
-void
-_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices)
-{
- cogl_object_unref (buffer_indices->indices);
- g_slice_free (CoglVertexBufferIndices, buffer_indices);
-}
-
-void
-cogl_vertex_buffer_draw_elements (CoglHandle handle,
- CoglVerticesMode mode,
- CoglHandle indices_handle,
- int min_index,
- int max_index,
- int indices_offset,
- int count)
-{
- CoglVertexBuffer *buffer;
- CoglVertexBufferIndices *buffer_indices;
-
- if (!cogl_is_vertex_buffer (handle))
- return;
-
- buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
-
- if (!cogl_is_vertex_buffer_indices (indices_handle))
- return;
-
- buffer_indices =
- _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
-
- update_primitive_and_draw (buffer, mode, indices_offset, count,
- buffer_indices);
-}
-
-static void
-_cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
-{
- GList *tmp;
-
- for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
- cogl_vertex_buffer_vbo_free (tmp->data);
- g_list_free (buffer->submitted_vbos);
-
- for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
- _cogl_vertex_buffer_attrib_free (tmp->data);
- g_list_free (buffer->new_attributes);
-
- if (buffer->primitive)
- cogl_object_unref (buffer->primitive);
-
- g_slice_free (CoglVertexBuffer, buffer);
-}
-
-CoglHandle
-cogl_vertex_buffer_indices_get_for_quads (unsigned int n_indices)
-{
- _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
-
- if (n_indices <= 256 / 4 * 6)
- {
- if (ctx->quad_buffer_indices_byte == COGL_INVALID_HANDLE)
- {
- /* NB: cogl_get_quad_indices takes n_quads not n_indices... */
- CoglIndices *indices = cogl_get_rectangle_indices (256 / 4);
- cogl_object_ref (indices);
- ctx->quad_buffer_indices_byte =
- _cogl_vertex_buffer_indices_new_real (indices);
- }
-
- return ctx->quad_buffer_indices_byte;
- }
- else
- {
- if (ctx->quad_buffer_indices &&
- ctx->quad_buffer_indices_len < n_indices)
- {
- cogl_handle_unref (ctx->quad_buffer_indices);
- ctx->quad_buffer_indices = COGL_INVALID_HANDLE;
- }
-
- if (ctx->quad_buffer_indices == COGL_INVALID_HANDLE)
- {
- /* NB: cogl_get_quad_indices takes n_quads not n_indices... */
- CoglIndices *indices = cogl_get_rectangle_indices (n_indices / 6);
- cogl_object_ref (indices);
- ctx->quad_buffer_indices =
- _cogl_vertex_buffer_indices_new_real (indices);
- }
-
- ctx->quad_buffer_indices_len = n_indices;
-
- return ctx->quad_buffer_indices;
- }
-
- g_return_val_if_reached (NULL);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_VERTEX_BUFFER_H__
-#define __COGL_VERTEX_BUFFER_H__
-
-#include <glib.h>
-#include <cogl/cogl-defines.h>
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-vertex-buffer
- * @short_description: An API for submitting extensible arrays of vertex
- * attributes to be mapped into the GPU for fast drawing.
- *
- * For example to describe a textured triangle, you could create a new cogl
- * vertex buffer with 3 vertices, and then you might add 2 attributes for each
- * vertex:
- * <orderedlist>
- * <listitem>
- * a "gl_Position" describing the (x,y,z) position for each vertex.
- * </listitem>
- * <listitem>
- * a "gl_MultiTexCoord0" describing the (tx,ty) texture coordinates for each
- * vertex.
- * </listitem>
- * </orderedlist>
- *
- * The Vertex Buffer API is designed to be a fairly raw mechanism for
- * developers to be able to submit geometry to Cogl in a format that can be
- * directly consumed by an OpenGL driver and mapped into your GPU for fast
- * re-use. It is designed to avoid repeated validation of the attributes by the
- * driver; to minimize transport costs (e.g. considering indirect GLX
- * use-cases) and to potentially avoid repeated format conversions when
- * attributes are supplied in a format that is not natively supported by the
- * GPU.
- *
- * Although this API does allow you to modify attributes after they have been
- * submitted to the GPU you should be aware that modification is not that
- * cheap, since it implies validating the new data and potentially the
- * OpenGL driver will need to reformat it for the GPU.
- *
- * If at all possible think of tricks that let you re-use static attributes,
- * and if you do need to repeatedly update attributes (e.g. for some kind of
- * morphing geometry) then only update and re-submit the specific attributes
- * that have changed.
- */
-
-/**
- * cogl_vertex_buffer_new:
- * @n_vertices: The number of vertices that your attributes will correspond to.
- *
- * Creates a new vertex buffer that you can use to add attributes.
- *
- * Return value: a new #CoglHandle
- */
-CoglHandle
-cogl_vertex_buffer_new (unsigned int n_vertices);
-
-/**
- * cogl_vertex_buffer_get_n_vertices:
- * @handle: A vertex buffer handle
- *
- * Retrieves the number of vertices that @handle represents
- *
- * Return value: the number of vertices
- */
-unsigned int
-cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
-
-/**
- * cogl_vertex_buffer_add:
- * @handle: A vertex buffer handle
- * @attribute_name: The name of your attribute. It should be a valid GLSL
- * variable name and standard attribute types must use one of following
- * built-in names: (Note: they correspond to the built-in names of GLSL)
- * <itemizedlist>
- * <listitem>"gl_Color"</listitem>
- * <listitem>"gl_Normal"</listitem>
- * <listitem>"gl_MultiTexCoord0, gl_MultiTexCoord1, ..."</listitem>
- * <listitem>"gl_Vertex"</listitem>
- * </itemizedlist>
- * To support adding multiple variations of the same attribute the name
- * can have a detail component, E.g. "gl_Color::active" or
- * "gl_Color::inactive"
- * @n_components: The number of components per attribute and must be 1, 2,
- * 3 or 4
- * @type: a #CoglAttributeType specifying the data type of each component.
- * @normalized: If %TRUE, this specifies that values stored in an integer
- * format should be mapped into the range [-1.0, 1.0] or [0.0, 1.0]
- * for unsigned values. If %FALSE they are converted to floats
- * directly.
- * @stride: This specifies the number of bytes from the start of one attribute
- * value to the start of the next value (for the same attribute). So, for
- * example, with a position interleved with color like this:
- * XYRGBAXYRGBAXYRGBA, then if each letter represents a byte, the
- * stride for both attributes is 6. The special value 0 means the
- * values are stored sequentially in memory.
- * @pointer: This addresses the first attribute in the vertex array. This
- * must remain valid until you either call cogl_vertex_buffer_submit() or
- * issue a draw call.
- *
- * Adds an attribute to a buffer, or replaces a previously added
- * attribute with the same name.
- *
- * You either can use one of the built-in names such as "gl_Vertex", or
- * "gl_MultiTexCoord0" to add standard attributes, like positions, colors
- * and normals, or you can add custom attributes for use in shaders.
- *
- * The number of vertices declared when calling cogl_vertex_buffer_new()
- * determines how many attribute values will be read from the supplied
- * @pointer.
- *
- * The data for your attribute isn't copied anywhere until you call
- * cogl_vertex_buffer_submit(), or issue a draw call which automatically
- * submits pending attribute changes. so the supplied pointer must remain
- * valid until then. If you are updating an existing attribute (done by
- * re-adding it) then you still need to re-call cogl_vertex_buffer_submit()
- * to commit the changes to the GPU. Be carefull to minimize the number
- * of calls to cogl_vertex_buffer_submit(), though.
- *
- * <note>If you are interleving attributes it is assumed that each interleaved
- * attribute starts no farther than +- stride bytes from the other attributes
- * it is interleved with. I.e. this is ok:
- * <programlisting>
- * |-0-0-0-0-0-0-0-0-0-0|
- * </programlisting>
- * This is not ok:
- * <programlisting>
- * |- - - - -0-0-0-0-0-0 0 0 0 0|
- * </programlisting>
- * (Though you can have multiple groups of interleved attributes)</note>
- */
-void
-cogl_vertex_buffer_add (CoglHandle handle,
- const char *attribute_name,
- guint8 n_components,
- CoglAttributeType type,
- gboolean normalized,
- guint16 stride,
- const void *pointer);
-
-/**
- * cogl_vertex_buffer_delete:
- * @handle: A vertex buffer handle
- * @attribute_name: The name of a previously added attribute
- *
- * Deletes an attribute from a buffer. You will need to call
- * cogl_vertex_buffer_submit() or issue a draw call to commit this
- * change to the GPU.
- */
-void
-cogl_vertex_buffer_delete (CoglHandle handle,
- const char *attribute_name);
-
-/**
- * cogl_vertex_buffer_submit:
- * @handle: A vertex buffer handle
- *
- * Submits all the user added attributes to the GPU; once submitted, the
- * attributes can be used for drawing.
- *
- * You should aim to minimize calls to this function since it implies
- * validating your data; it potentially incurs a transport cost (especially if
- * you are using GLX indirect rendering) and potentially a format conversion
- * cost if the GPU doesn't natively support any of the given attribute formats.
- */
-void
-cogl_vertex_buffer_submit (CoglHandle handle);
-
-/**
- * cogl_vertex_buffer_disable:
- * @handle: A vertex buffer handle
- * @attribute_name: The name of the attribute you want to disable
- *
- * Disables a previosuly added attribute.
- *
- * Since it can be costly to add and remove new attributes to buffers; to make
- * individual buffers more reuseable it is possible to enable and disable
- * attributes before using a buffer for drawing.
- *
- * You don't need to call cogl_vertex_buffer_submit() after using this
- * function.
- */
-void
-cogl_vertex_buffer_disable (CoglHandle handle,
- const char *attribute_name);
-
-/**
- * cogl_vertex_buffer_enable:
- * @handle: A vertex buffer handle
- * @attribute_name: The name of the attribute you want to enable
- *
- * Enables a previosuly disabled attribute.
- *
- * Since it can be costly to add and remove new attributes to buffers; to make
- * individual buffers more reuseable it is possible to enable and disable
- * attributes before using a buffer for drawing.
- *
- * You don't need to call cogl_vertex_buffer_submit() after using this function
- */
-void
-cogl_vertex_buffer_enable (CoglHandle handle,
- const char *attribute_name);
-
-/**
- * cogl_vertex_buffer_draw:
- * @handle: A vertex buffer handle
- * @mode: A #CoglVerticesMode specifying how the vertices should be
- * interpreted.
- * @first: Specifies the index of the first vertex you want to draw with
- * @count: Specifies the number of vertices you want to draw.
- *
- * Allows you to draw geometry using all or a subset of the
- * vertices in a vertex buffer.
- *
- * Any un-submitted attribute changes are automatically submitted before
- * drawing.
- */
-void
-cogl_vertex_buffer_draw (CoglHandle handle,
- CoglVerticesMode mode,
- int first,
- int count);
-
-/**
- * cogl_vertex_buffer_indices_new:
- * @indices_type: a #CoglIndicesType specifying the data type used for
- * the indices.
- * @indices_array: (array length=indices_len): Specifies the address of
- * your array of indices
- * @indices_len: The number of indices in indices_array
- *
- * Depending on how much geometry you are submitting it can be worthwhile
- * optimizing the number of redundant vertices you submit. Using an index
- * array allows you to reference vertices multiple times, for example
- * during triangle strips.
- *
- * Return value: A CoglHandle for the indices which you can pass to
- * cogl_vertex_buffer_draw_elements().
- */
-CoglHandle
-cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
- const void *indices_array,
- int indices_len);
-
-/**
- * cogl_vertex_buffer_indices_get_type:
- * @indices: An indices handle
- *
- * Queries back the data type used for the given indices
- *
- * Returns: The CoglIndicesType used
- */
-CoglIndicesType
-cogl_vertex_buffer_indices_get_type (CoglHandle indices);
-
-/**
- * cogl_vertex_buffer_draw_elements:
- * @handle: A vertex buffer handle
- * @mode: A #CoglVerticesMode specifying how the vertices should be
- * interpreted.
- * @indices: A CoglHandle for a set of indices allocated via
- * cogl_vertex_buffer_indices_new ()
- * @min_index: Specifies the minimum vertex index contained in indices
- * @max_index: Specifies the maximum vertex index contained in indices
- * @indices_offset: An offset into named indices. The offset marks the first
- * index to use for drawing.
- * @count: Specifies the number of vertices you want to draw.
- *
- * This function lets you use an array of indices to specify the vertices
- * within your vertex buffer that you want to draw. The indices themselves
- * are created by calling cogl_vertex_buffer_indices_new ()
- *
- * Any un-submitted attribute changes are automatically submitted before
- * drawing.
- */
-void
-cogl_vertex_buffer_draw_elements (CoglHandle handle,
- CoglVerticesMode mode,
- CoglHandle indices,
- int min_index,
- int max_index,
- int indices_offset,
- int count);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_vertex_buffer_ref:
- * @handle: a @CoglHandle.
- *
- * Increment the reference count for a vertex buffer
- *
- * Return value: the @handle.
- *
- * Deprecated: 1.2: Use cogl_handle_ref() instead
- */
-CoglHandle
-cogl_vertex_buffer_ref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-/**
- * cogl_vertex_buffer_unref:
- * @handle: a @CoglHandle.
- *
- * Decrement the reference count for a vertex buffer
- *
- * Deprecated: 1.2: Use cogl_handle_unref() instead
- */
-void
-cogl_vertex_buffer_unref (CoglHandle handle) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_vertex_buffer_indices_get_for_quads:
- * @n_indices: the number of indices in the vertex buffer.
- *
- * Creates a vertex buffer containing the indices needed to draw pairs
- * of triangles from a list of vertices grouped as quads. There will
- * be at least @n_indices entries in the buffer (but there may be
- * more).
- *
- * The indices will follow this pattern:
- *
- * 0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7 ... etc
- *
- * For example, if you submit vertices for a quad like like that shown
- * in <xref linkend="quad-indices-order"/> then you can request 6
- * indices to render two triangles like those shown in <xref
- * linkend="quad-indices-triangles"/>.
- *
- * <figure id="quad-indices-order">
- * <title>Example of vertices submitted to form a quad</title>
- * <graphic fileref="quad-indices-order.png" format="PNG"/>
- * </figure>
- *
- * <figure id="quad-indices-triangles">
- * <title>Illustration of the triangle indices that will be generated</title>
- * <graphic fileref="quad-indices-triangles.png" format="PNG"/>
- * </figure>
- *
- * Returns: A %CoglHandle containing the indices. The handled is
- * owned by Cogl and should not be modified or unref'd.
- */
-CoglHandle
-cogl_vertex_buffer_indices_get_for_quads (unsigned int n_indices);
-
-/**
- * cogl_is_vertex_buffer:
- * @handle: a #CoglHandle for a vertex buffer object
- *
- * Checks whether @handle is a Vertex Buffer Object
- *
- * Return value: %TRUE if the handle is a VBO, and %FALSE
- * otherwise
- *
- * Since: 1.0
- */
-gboolean
-cogl_is_vertex_buffer (CoglHandle handle);
-
-/**
- * cogl_is_vertex_buffer_indices:
- * @handle: a #CoglHandle
- *
- * Checks whether @handle is a handle to the indices for a vertex
- * buffer object
- *
- * Return value: %TRUE if the handle is indices, and %FALSE
- * otherwise
- *
- * Since: 1.4
- */
-gboolean
-cogl_is_vertex_buffer_indices (CoglHandle handle);
-
-G_END_DECLS
-
-#endif /* __COGL_VERTEX_BUFFER_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_XLIB_PRIVATE_H
-#define __COGL_XLIB_PRIVATE_H
-
-#include "cogl/cogl.h"
-
-#include <X11/Xlib.h>
-
-typedef struct _CoglXlibTrapState CoglXlibTrapState;
-
-struct _CoglXlibTrapState
-{
- /* These values are intended to be internal to
- * _cogl_xlib_{un,}trap_errors but they need to be in the header so
- * that the struct can be allocated on the stack */
- int (* old_error_handler) (Display *, XErrorEvent *);
- int trapped_error_code;
- CoglXlibTrapState *old_state;
-};
-
-void
-_cogl_xlib_query_damage_extension (void);
-
-int
-_cogl_xlib_get_damage_base (void);
-
-void
-_cogl_xlib_trap_errors (CoglXlibTrapState *state);
-
-int
-_cogl_xlib_untrap_errors (CoglXlibTrapState *state);
-
-/*
- * _cogl_xlib_add_filter:
- *
- * Adds a callback function that will receive all X11 events. The
- * function can stop further processing of the event by return
- * %COGL_XLIB_FILTER_REMOVE.
- */
-void
-_cogl_xlib_add_filter (CoglNativeFilterFunc func,
- void *data);
-
-/*
- * _cogl_xlib_remove_filter:
- *
- * Removes a callback that was previously added with
- * _cogl_xlib_add_filter().
- */
-void
-_cogl_xlib_remove_filter (CoglNativeFilterFunc func,
- void *data);
-
-#endif /* __COGL_XLIB_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <cogl.h>
-#include <cogl-internal.h>
-#include <cogl-handle.h>
-#include <cogl-context-private.h>
-#include <cogl-framebuffer-private.h>
-#include <cogl-display-private.h>
-#include <cogl-renderer-private.h>
-#include <cogl-renderer-xlib-private.h>
-
-#include <X11/Xlib.h>
-#include <X11/extensions/Xdamage.h>
-
-#include "cogl-xlib.h"
-
-/* FIXME: when we remove the last X11 based Clutter backend then we
- * will get rid of these functions and instead rely on the equivalent
- * _cogl_renderer_xlib API
- */
-
-/* This can't be in the Cogl context because it can be set before
- context is created */
-static Display *_cogl_xlib_display = NULL;
-
-Display *
-cogl_xlib_get_display (void)
-{
- _COGL_GET_CONTEXT (ctx, NULL);
-
- if (!ctx->stub_winsys)
- return cogl_renderer_xlib_get_display (ctx->display->renderer);
-
- /* _cogl_xlib_set_display should be called before this function */
- g_assert (_cogl_xlib_display != NULL);
-
- return _cogl_xlib_display;
-}
-
-void
-cogl_xlib_set_display (Display *display)
-{
- /* This can only be called once before the Cogl context is created */
- g_assert (_cogl_xlib_display == NULL);
-
- _cogl_xlib_display = display;
-}
-
-/* These three functions are wrappers around the equivalent renderer
- functions. They can be removed once all xlib-based backends in
- Clutter know about the renderer */
-CoglFilterReturn
-cogl_xlib_handle_event (XEvent *xevent)
-{
- _COGL_GET_CONTEXT (ctx, COGL_FILTER_CONTINUE);
-
- /* Pass the event on to the renderer */
- return cogl_renderer_handle_native_event (ctx->display->renderer, xevent);
-}
-
-void
-_cogl_xlib_add_filter (CoglNativeFilterFunc func,
- void *data)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_renderer_add_native_filter (ctx->display->renderer, func, data);
-}
-
-void
-_cogl_xlib_remove_filter (CoglNativeFilterFunc func,
- void *data)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_renderer_remove_native_filter (ctx->display->renderer, func, data);
-}
-
-static int
-error_handler (Display *xdpy,
- XErrorEvent *error)
-{
- _COGL_GET_CONTEXT (ctxt, 0);
-
- g_assert (ctxt->trap_state);
-
- ctxt->trap_state->trapped_error_code = error->error_code;
-
- return 0;
-}
-
-void
-_cogl_xlib_trap_errors (CoglXlibTrapState *state)
-{
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- if (!ctxt->stub_winsys)
- {
- _cogl_renderer_xlib_trap_errors (ctxt->display->renderer, state);
- return;
- }
-
- state->trapped_error_code = 0;
- state->old_error_handler = XSetErrorHandler (error_handler);
-
- state->old_state = ctxt->trap_state;
- ctxt->trap_state = state;
-}
-
-int
-_cogl_xlib_untrap_errors (CoglXlibTrapState *state)
-{
- _COGL_GET_CONTEXT (ctxt, 0);
-
- if (!ctxt->stub_winsys)
- {
- return _cogl_renderer_xlib_untrap_errors (ctxt->display->renderer, state);
- }
-
- g_assert (state == ctxt->trap_state);
-
- XSetErrorHandler (state->old_error_handler);
-
- ctxt->trap_state = state->old_state;
-
- return state->trapped_error_code;
-}
-
-void
-_cogl_xlib_query_damage_extension (void)
-{
- int damage_error;
-
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- /* Check whether damage events are supported on this display */
- if (!XDamageQueryExtension (cogl_xlib_get_display (),
- &ctxt->damage_base,
- &damage_error))
- ctxt->damage_base = -1;
-}
-
-int
-_cogl_xlib_get_damage_base (void)
-{
- _COGL_GET_CONTEXT (ctxt, -1);
-
- if (!ctxt->stub_winsys)
- {
- CoglRendererX11 *x11_renderer = ctxt->display->renderer->winsys;
- return x11_renderer->damage_base;
- }
- else
- return ctxt->damage_base;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL_XLIB_H__
-#define __COGL_XLIB_H__
-
-#include <cogl/cogl-types.h>
-
-#include <X11/Xlib.h>
-
-G_BEGIN_DECLS
-
-/*
- * cogl_xlib_get_display:
- *
- * Return value: the Xlib display that will be used by the Xlib winsys
- * backend. The display needs to be set with _cogl_xlib_set_display()
- * before this function is called.
- *
- * Stability: Unstable
- */
-#define cogl_xlib_get_display cogl_xlib_get_display_EXP
-Display *
-cogl_xlib_get_display (void);
-
-/*
- * cogl_xlib_set_display:
- *
- * Sets the Xlib display that Cogl will use for the Xlib winsys
- * backend. This function should eventually go away when Cogl gains a
- * more complete winsys abstraction.
- *
- * Stability: Unstable
- */
-#define cogl_xlib_set_display cogl_xlib_set_display_EXP
-void
-cogl_xlib_set_display (Display *display);
-
-/*
- * cogl_xlib_handle_event:
- * @xevent: pointer to XEvent structure
- *
- * This function processes a single X event; it can be used to hook
- * into external X event retrieval (for example that done by Clutter
- * or GDK).
- *
- * Return value: #CoglXlibFilterReturn. %COGL_XLIB_FILTER_REMOVE
- * indicates that Cogl has internally handled the event and the
- * caller should do no further processing. %COGL_XLIB_FILTER_CONTINUE
- * indicates that Cogl is either not interested in the event,
- * or has used the event to update internal state without taking
- * any exclusive action.
- *
- * Stability: Unstable
- */
-#define cogl_xlib_handle_event cogl_xlib_handle_event_EXP
-CoglFilterReturn
-cogl_xlib_handle_event (XEvent *xevent);
-
-#endif /* __COGL_XLIB_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-#include <string.h>
-#include <math.h>
-#include <stdlib.h>
-#include <gmodule.h>
-
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-context-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-winsys-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-matrix-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-attribute-private.h"
-#include "cogl-framebuffer-private.h"
-
-#ifdef HAVE_COGL_GL
-#define glClientActiveTexture ctx->drv.pf_glClientActiveTexture
-#endif
-
-#ifdef COGL_GL_DEBUG
-/* GL error to string conversion */
-static const struct {
- GLuint error_code;
- const char *error_string;
-} gl_errors[] = {
- { GL_NO_ERROR, "No error" },
- { GL_INVALID_ENUM, "Invalid enumeration value" },
- { GL_INVALID_VALUE, "Invalid value" },
- { GL_INVALID_OPERATION, "Invalid operation" },
-#ifdef HAVE_COGL_GL
- { GL_STACK_OVERFLOW, "Stack overflow" },
- { GL_STACK_UNDERFLOW, "Stack underflow" },
-#endif
- { GL_OUT_OF_MEMORY, "Out of memory" },
-
-#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
- { GL_INVALID_FRAMEBUFFER_OPERATION_EXT, "Invalid framebuffer operation" }
-#endif
-};
-
-static const unsigned int n_gl_errors = G_N_ELEMENTS (gl_errors);
-
-const char *
-cogl_gl_error_to_string (GLenum error_code)
-{
- int i;
-
- for (i = 0; i < n_gl_errors; i++)
- {
- if (gl_errors[i].error_code == error_code)
- return gl_errors[i].error_string;
- }
-
- return "Unknown GL error";
-}
-#endif /* COGL_GL_DEBUG */
-
-CoglFuncPtr
-cogl_get_proc_address (const char* name)
-{
- void *address;
- static GModule *module = NULL;
-#ifdef COGL_HAS_FULL_WINSYS
- const CoglWinsysVtable *winsys;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- winsys = _cogl_context_get_winsys (ctx);
-
- address = winsys->get_proc_address (name);
-#else
- address = _cogl_winsys_get_proc_address (name);
-#endif
- if (address)
- return address;
-
- /* this should find the right function if the program is linked against a
- * library providing it */
- if (G_UNLIKELY (module == NULL))
- module = g_module_open (NULL, 0);
-
- if (module)
- {
- gpointer symbol;
-
- if (g_module_symbol (module, name, &symbol))
- return symbol;
- }
-
- return NULL;
-}
-
-gboolean
-_cogl_check_extension (const char *name, const gchar *ext)
-{
- char *end;
- int name_len, n;
-
- if (name == NULL || ext == NULL)
- return FALSE;
-
- end = (char*)(ext + strlen(ext));
-
- name_len = strlen(name);
-
- while (ext < end)
- {
- n = strcspn(ext, " ");
-
- if ((name_len == n) && (!strncmp(name, ext, n)))
- return TRUE;
- ext += (n + 1);
- }
-
- return FALSE;
-}
-
-/* XXX: This has been deprecated as public API */
-gboolean
-cogl_check_extension (const char *name, const char *ext)
-{
- return _cogl_check_extension (name, ext);
-}
-
-/* XXX: it's expected that we'll deprecated this with
- * cogl_framebuffer_clear at some point. */
-void
-cogl_clear (const CoglColor *color, unsigned long buffers)
-{
- _cogl_framebuffer_clear (cogl_get_draw_framebuffer (), buffers, color);
-}
-
-static gboolean
-toggle_flag (CoglContext *ctx,
- unsigned long new_flags,
- unsigned long flag,
- GLenum gl_flag)
-{
- /* Toggles and caches a single enable flag on or off
- * by comparing to current state
- */
- if (new_flags & flag)
- {
- if (!(ctx->enable_flags & flag))
- {
- GE( glEnable (gl_flag) );
- ctx->enable_flags |= flag;
- return TRUE;
- }
- }
- else if (ctx->enable_flags & flag)
- {
- GE( glDisable (gl_flag) );
- ctx->enable_flags &= ~flag;
- }
-
- return FALSE;
-}
-
-#ifdef HAVE_COGL_GLES2
-
-/* Under GLES2 there are no builtin client flags so toggle_client_flag
- should never be reached */
-
-#define toggle_client_flag(ctx, new_flags, flag, gl_flag) \
- g_assert (((new_flags) & (flag)) == 0)
-
-#else /* HAVE_COGL_GLES2 */
-
-static gboolean
-toggle_client_flag (CoglContext *ctx,
- unsigned long new_flags,
- unsigned long flag,
- GLenum gl_flag)
-{
- /* Toggles and caches a single client-side enable flag
- * on or off by comparing to current state
- */
- if (new_flags & flag)
- {
- if (!(ctx->enable_flags & flag))
- {
- GE( glEnableClientState (gl_flag) );
- ctx->enable_flags |= flag;
- return TRUE;
- }
- }
- else if (ctx->enable_flags & flag)
- {
- GE( glDisableClientState (gl_flag) );
- ctx->enable_flags &= ~flag;
- }
-
- return FALSE;
-}
-
-#endif /* HAVE_COGL_GLES2 */
-
-void
-_cogl_enable (unsigned long flags)
-{
- /* This function essentially caches glEnable state() in the
- * hope of lessening number GL traffic.
- */
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- toggle_flag (ctx, flags,
- COGL_ENABLE_BACKFACE_CULLING,
- GL_CULL_FACE);
-
- toggle_client_flag (ctx, flags,
- COGL_ENABLE_VERTEX_ARRAY,
- GL_VERTEX_ARRAY);
-
- toggle_client_flag (ctx, flags,
- COGL_ENABLE_COLOR_ARRAY,
- GL_COLOR_ARRAY);
-}
-
-unsigned long
-_cogl_get_enable (void)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- return ctx->enable_flags;
-}
-
-/* XXX: This API has been deprecated */
-void
-cogl_set_depth_test_enabled (gboolean setting)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->legacy_depth_test_enabled == setting)
- return;
-
- ctx->legacy_depth_test_enabled = setting;
- if (ctx->legacy_depth_test_enabled)
- ctx->legacy_state_set++;
- else
- ctx->legacy_state_set--;
-}
-
-/* XXX: This API has been deprecated */
-gboolean
-cogl_get_depth_test_enabled (void)
-{
- _COGL_GET_CONTEXT (ctx, FALSE);
- return ctx->legacy_depth_test_enabled;
-}
-
-void
-cogl_set_backface_culling_enabled (gboolean setting)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->enable_backface_culling == setting)
- return;
-
- /* Currently the journal can't track changes to backface culling state... */
- _cogl_framebuffer_flush_journal (cogl_get_draw_framebuffer ());
-
- ctx->enable_backface_culling = setting;
-}
-
-gboolean
-cogl_get_backface_culling_enabled (void)
-{
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- return ctx->enable_backface_culling;
-}
-
-void
-_cogl_flush_face_winding (void)
-{
- CoglFrontWinding winding;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* The front face winding doesn't matter if we aren't performing any
- * backface culling... */
- if (!ctx->enable_backface_culling)
- return;
-
- /* NB: We use a clockwise face winding order when drawing offscreen because
- * all offscreen rendering is done upside down resulting in reversed winding
- * for all triangles.
- */
- if (cogl_is_offscreen (cogl_get_draw_framebuffer ()))
- winding = COGL_FRONT_WINDING_CLOCKWISE;
- else
- winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;
-
- if (winding != ctx->flushed_front_winding)
- {
-
- if (winding == COGL_FRONT_WINDING_CLOCKWISE)
- GE (glFrontFace (GL_CW));
- else
- GE (glFrontFace (GL_CCW));
- ctx->flushed_front_winding = winding;
- }
-}
-
-void
-cogl_set_source_color (const CoglColor *color)
-{
- CoglPipeline *pipeline;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (cogl_color_get_alpha_byte (color) == 0xff)
- {
- cogl_pipeline_set_color (ctx->opaque_color_pipeline, color);
- pipeline = ctx->opaque_color_pipeline;
- }
- else
- {
- CoglColor premultiplied = *color;
- cogl_color_premultiply (&premultiplied);
- cogl_pipeline_set_color (ctx->blended_color_pipeline, &premultiplied);
- pipeline = ctx->blended_color_pipeline;
- }
-
- cogl_set_source (pipeline);
-}
-
-void
-cogl_set_viewport (int x,
- int y,
- int width,
- int height)
-{
- CoglFramebuffer *framebuffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
-
- _cogl_framebuffer_set_viewport (framebuffer,
- x,
- y,
- width,
- height);
-}
-
-/* XXX: This should be deprecated, and we should expose a way to also
- * specify an x and y viewport offset */
-void
-cogl_viewport (unsigned int width,
- unsigned int height)
-{
- cogl_set_viewport (0, 0, width, height);
-}
-
-CoglFeatureFlags
-cogl_get_features (void)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- return ctx->feature_flags;
-}
-
-gboolean
-cogl_features_available (CoglFeatureFlags features)
-{
- _COGL_GET_CONTEXT (ctx, 0);
-
- return (ctx->feature_flags & features) == features;
-}
-
-/* XXX: This function should either be replaced with one returning
- * integers, or removed/deprecated and make the
- * _cogl_framebuffer_get_viewport* functions public.
- */
-void
-cogl_get_viewport (float viewport[4])
-{
- CoglFramebuffer *framebuffer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- framebuffer = cogl_get_draw_framebuffer ();
- _cogl_framebuffer_get_viewport4fv (framebuffer, viewport);
-}
-
-void
-cogl_get_bitmasks (int *red,
- int *green,
- int *blue,
- int *alpha)
-{
- CoglFramebuffer *framebuffer;
-
- framebuffer = cogl_get_draw_framebuffer ();
-
- if (red)
- *red = _cogl_framebuffer_get_red_bits (framebuffer);
-
- if (green)
- *green = _cogl_framebuffer_get_green_bits (framebuffer);
-
- if (blue)
- *blue = _cogl_framebuffer_get_blue_bits (framebuffer);
-
- if (alpha)
- *alpha = _cogl_framebuffer_get_alpha_bits (framebuffer);
-}
-
-void
-cogl_set_fog (const CoglColor *fog_color,
- CoglFogMode mode,
- float density,
- float z_near,
- float z_far)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->legacy_fog_state.enabled == FALSE)
- ctx->legacy_state_set++;
-
- ctx->legacy_fog_state.enabled = TRUE;
- ctx->legacy_fog_state.color = *fog_color;
- ctx->legacy_fog_state.mode = mode;
- ctx->legacy_fog_state.density = density;
- ctx->legacy_fog_state.z_near = z_near;
- ctx->legacy_fog_state.z_far = z_far;
-}
-
-void
-cogl_disable_fog (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->legacy_fog_state.enabled == TRUE)
- ctx->legacy_state_set--;
-
- ctx->legacy_fog_state.enabled = FALSE;
-}
-
-void
-cogl_flush (void)
-{
- GList *l;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- for (l = ctx->framebuffers; l; l = l->next)
- _cogl_framebuffer_flush_journal (l->data);
-}
-
-void
-_cogl_read_pixels_with_rowstride (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels,
- int rowstride)
-{
- CoglFramebuffer *framebuffer = _cogl_get_read_framebuffer ();
- int framebuffer_height;
- int bpp;
- CoglBitmap *bmp;
- GLenum gl_intformat;
- GLenum gl_format;
- GLenum gl_type;
- CoglPixelFormat bmp_format;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (source == COGL_READ_PIXELS_COLOR_BUFFER);
-
- if (width == 1 && height == 1 && !framebuffer->clear_clip_dirty)
- {
- /* If everything drawn so far for this frame is still in the
- * Journal then if all of the rectangles only have a flat
- * opaque color we have a fast-path for reading a single pixel
- * that avoids the relatively high cost of flushing primitives
- * to be drawn on the GPU (considering how simple the geometry
- * is in this case) and then blocking on the long GPU pipelines
- * for the result.
- */
- if (_cogl_framebuffer_try_fast_read_pixel (framebuffer,
- x, y, source, format,
- pixels))
- return;
- }
-
- /* make sure any batched primitives get emitted to the GL driver
- * before issuing our read pixels...
- *
- * XXX: Note we currently use cogl_flush to ensure *all* journals
- * are flushed here and not _cogl_journal_flush because we don't
- * track the dependencies between framebuffers so we don't know if
- * the current framebuffer depends on the contents of other
- * framebuffers which could also have associated journal entries.
- */
- cogl_flush ();
-
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- framebuffer,
- 0);
-
- framebuffer_height = cogl_framebuffer_get_height (framebuffer);
-
- /* The y co-ordinate should be given in OpenGL's coordinate system
- * so 0 is the bottom row
- *
- * NB: all offscreen rendering is done upside down so no conversion
- * is necissary in this case.
- */
- if (!cogl_is_offscreen (framebuffer))
- y = framebuffer_height - y - height;
-
- /* Initialise the CoglBitmap */
- bpp = _cogl_get_format_bpp (format);
- bmp_format = format;
-
- if ((format & COGL_A_BIT))
- {
- /* We match the premultiplied state of the target buffer to the
- * premultiplied state of the framebuffer so that it will get
- * converted to the right format below */
-
- if ((framebuffer->format & COGL_PREMULT_BIT))
- bmp_format |= COGL_PREMULT_BIT;
- else
- bmp_format &= ~COGL_PREMULT_BIT;
- }
-
- bmp = _cogl_bitmap_new_from_data (pixels,
- bmp_format, width, height, rowstride,
- NULL, NULL);
-
- _cogl_pixel_format_to_gl (format, &gl_intformat, &gl_format, &gl_type);
-
- /* Under GLES only GL_RGBA with GL_UNSIGNED_BYTE as well as an
- implementation specific format under
- GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES and
- GL_IMPLEMENTATION_COLOR_READ_TYPE_OES is supported. We could try
- to be more clever and check if the requested type matches that
- but we would need some reliable functions to convert from GL
- types to Cogl types. For now, lets just always read in
- GL_RGBA/GL_UNSIGNED_BYTE and convert if necessary. We also need
- to use this intermediate buffer if the rowstride has padding
- because GLES does not support setting GL_ROW_LENGTH */
-#ifndef COGL_HAS_GL
- if (gl_format != GL_RGBA || gl_type != GL_UNSIGNED_BYTE ||
- rowstride != 4 * width)
- {
- CoglBitmap *tmp_bmp, *dst_bmp;
- guint8 *tmp_data = g_malloc (width * height * 4);
-
- tmp_bmp = _cogl_bitmap_new_from_data (tmp_data,
- COGL_PIXEL_FORMAT_RGBA_8888 |
- (bmp_format & COGL_PREMULT_BIT),
- width, height, 4 * width,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- _cogl_texture_driver_prep_gl_for_pixels_download (4 * width, 4);
-
- GE( glReadPixels (x, y, width, height,
- GL_RGBA, GL_UNSIGNED_BYTE,
- tmp_data) );
-
- /* CoglBitmap doesn't currently have a way to convert without
- allocating its own buffer so we have to copy the data
- again */
- if ((dst_bmp = _cogl_bitmap_convert_format_and_premult (tmp_bmp,
- format)))
- {
- _cogl_bitmap_copy_subregion (dst_bmp,
- bmp,
- 0, 0,
- 0, 0,
- width, height);
- cogl_object_unref (dst_bmp);
- }
- else
- {
- /* FIXME: there's no way to report an error here so we'll
- just have to leave the data initialised */
- }
-
- cogl_object_unref (tmp_bmp);
- }
- else
-#endif
- {
- _cogl_texture_driver_prep_gl_for_pixels_download (rowstride, bpp);
-
- GE( glReadPixels (x, y, width, height, gl_format, gl_type, pixels) );
-
- /* Convert to the premult format specified by the caller
- in-place. This will do nothing if the premult status is already
- correct. */
- _cogl_bitmap_convert_premult_status (bmp, format);
- }
-
- /* NB: All offscreen rendering is done upside down so there is no need
- * to flip in this case... */
- if (!cogl_is_offscreen (framebuffer))
- {
- guint8 *temprow = g_alloca (rowstride * sizeof (guint8));
-
- /* TODO: consider using the GL_MESA_pack_invert extension in the future
- * to avoid this flip... */
-
- /* vertically flip the buffer in-place */
- for (y = 0; y < height / 2; y++)
- {
- if (y != height - y - 1) /* skip center row */
- {
- memcpy (temprow,
- pixels + y * rowstride, rowstride);
- memcpy (pixels + y * rowstride,
- pixels + (height - y - 1) * rowstride, rowstride);
- memcpy (pixels + (height - y - 1) * rowstride,
- temprow,
- rowstride);
- }
- }
- }
-
- cogl_object_unref (bmp);
-}
-
-void
-cogl_read_pixels (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels)
-{
- _cogl_read_pixels_with_rowstride (x, y, width, height,
- source, format, pixels,
- /* rowstride */
- _cogl_get_format_bpp (format) * width);
-}
-
-void
-cogl_begin_gl (void)
-{
- unsigned long enable_flags = 0;
- CoglPipeline *pipeline;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (ctx->in_begin_gl_block)
- {
- static gboolean shown = FALSE;
- if (!shown)
- g_warning ("You should not nest cogl_begin_gl/cogl_end_gl blocks");
- shown = TRUE;
- return;
- }
- ctx->in_begin_gl_block = TRUE;
-
- /* Flush all batched primitives */
- cogl_flush ();
-
- /* Flush framebuffer state, including clip state, modelview and
- * projection matrix state
- *
- * NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. */
- _cogl_framebuffer_flush_state (cogl_get_draw_framebuffer (),
- _cogl_get_read_framebuffer (),
- 0);
-
- /* Setup the state for the current pipeline */
-
- /* We considered flushing a specific, minimal pipeline here to try and
- * simplify the GL state, but decided to avoid special cases and second
- * guessing what would be actually helpful.
- *
- * A user should instead call cogl_set_source_color4ub() before
- * cogl_begin_gl() to simplify the state flushed.
- *
- * XXX: note defining n_tex_coord_attribs using
- * cogl_pipeline_get_n_layers is a hack, but the problem is that
- * n_tex_coord_attribs is usually defined when drawing a primitive
- * which isn't happening here.
- *
- * Maybe it would be more useful if this code did flush the
- * opaque_color_pipeline and then call into cogl-pipeline-opengl.c to then
- * restore all state for the material's backend back to default OpenGL
- * values.
- */
- pipeline = cogl_get_source ();
- _cogl_pipeline_flush_gl_state (pipeline,
- FALSE,
- cogl_pipeline_get_n_layers (pipeline));
-
- if (ctx->enable_backface_culling)
- enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
-
- _cogl_enable (enable_flags);
- _cogl_flush_face_winding ();
-
- /* Disable any cached vertex arrays */
- _cogl_attribute_disable_cached_arrays ();
-}
-
-void
-cogl_end_gl (void)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!ctx->in_begin_gl_block)
- {
- static gboolean shown = FALSE;
- if (!shown)
- g_warning ("cogl_end_gl is being called before cogl_begin_gl");
- shown = TRUE;
- return;
- }
- ctx->in_begin_gl_block = FALSE;
-}
-
-void
-cogl_push_matrix (void)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_push (modelview_stack);
-}
-
-void
-cogl_pop_matrix (void)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_pop (modelview_stack);
-}
-
-void
-cogl_scale (float x, float y, float z)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_scale (modelview_stack, x, y, z);
-}
-
-void
-cogl_translate (float x, float y, float z)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_translate (modelview_stack, x, y, z);
-}
-
-void
-cogl_rotate (float angle, float x, float y, float z)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_rotate (modelview_stack, angle, x, y, z);
-}
-
-void
-cogl_transform (const CoglMatrix *matrix)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_multiply (modelview_stack, matrix);
-}
-
-void
-cogl_perspective (float fov_y,
- float aspect,
- float z_near,
- float z_far)
-{
- float ymax = z_near * tanf (fov_y * G_PI / 360.0);
-
- cogl_frustum (-ymax * aspect, /* left */
- ymax * aspect, /* right */
- -ymax, /* bottom */
- ymax, /* top */
- z_near,
- z_far);
-}
-
-void
-cogl_frustum (float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (cogl_get_draw_framebuffer ());
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_matrix_stack_load_identity (projection_stack);
-
- _cogl_matrix_stack_frustum (projection_stack,
- left,
- right,
- bottom,
- top,
- z_near,
- z_far);
-}
-
-void
-cogl_ortho (float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far)
-{
- CoglMatrix ortho;
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (cogl_get_draw_framebuffer ());
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- cogl_matrix_init_identity (&ortho);
- cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
- _cogl_matrix_stack_set (projection_stack, &ortho);
-}
-
-void
-cogl_get_modelview_matrix (CoglMatrix *matrix)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_get (modelview_stack, matrix);
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_set_modelview_matrix (CoglMatrix *matrix)
-{
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_set (modelview_stack, matrix);
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_get_projection_matrix (CoglMatrix *matrix)
-{
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_get (projection_stack, matrix);
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-void
-cogl_set_projection_matrix (CoglMatrix *matrix)
-{
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (cogl_get_draw_framebuffer ());
- _cogl_matrix_stack_set (projection_stack, matrix);
-
- /* FIXME: Update the inverse projection matrix!! Presumably use
- * of clip planes must currently be broken if this API is used. */
- _COGL_MATRIX_DEBUG_PRINT (matrix);
-}
-
-CoglClipState *
-_cogl_get_clip_state (void)
-{
- CoglFramebuffer *framebuffer;
-
- framebuffer = cogl_get_draw_framebuffer ();
- return _cogl_framebuffer_get_clip_state (framebuffer);
-}
-
-GQuark
-_cogl_driver_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-driver-error-quark");
-}
-
-typedef struct _CoglSourceState
-{
- CoglPipeline *pipeline;
- int push_count;
-} CoglSourceState;
-
-static void
-_push_source_real (CoglPipeline *pipeline)
-{
- CoglSourceState *top = g_slice_new (CoglSourceState);
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- top->pipeline = cogl_object_ref (pipeline);
- top->push_count = 1;
-
- ctx->source_stack = g_list_prepend (ctx->source_stack, top);
-}
-
-/* FIXME: This should take a context pointer for Cogl 2.0 Technically
- * we could make it so we can retrieve a context reference from the
- * pipeline, but this would not by symmetric with cogl_pop_source. */
-void
-cogl_push_source (void *material_or_pipeline)
-{
- CoglSourceState *top;
- CoglPipeline *pipeline = COGL_PIPELINE (material_or_pipeline);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
-
- if (ctx->source_stack)
- {
- top = ctx->source_stack->data;
- if (top->pipeline == pipeline)
- {
- top->push_count++;
- return;
- }
- else
- _push_source_real (pipeline);
- }
- else
- _push_source_real (pipeline);
-}
-
-/* FIXME: This needs to take a context pointer for Cogl 2.0 */
-void
-cogl_pop_source (void)
-{
- CoglSourceState *top;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (ctx->source_stack);
-
- top = ctx->source_stack->data;
- top->push_count--;
- if (top->push_count == 0)
- {
- cogl_object_unref (top->pipeline);
- g_slice_free (CoglSourceState, top);
- ctx->source_stack = g_list_delete_link (ctx->source_stack,
- ctx->source_stack);
- }
-}
-
-/* FIXME: This needs to take a context pointer for Cogl 2.0 */
-void *
-cogl_get_source (void)
-{
- CoglSourceState *top;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_return_val_if_fail (ctx->source_stack, NULL);
-
- top = ctx->source_stack->data;
- return top->pipeline;
-}
-
-void
-cogl_set_source (void *material_or_pipeline)
-{
- CoglSourceState *top;
- CoglPipeline *pipeline = COGL_PIPELINE (material_or_pipeline);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (cogl_is_pipeline (pipeline));
- g_return_if_fail (ctx->source_stack);
-
- top = ctx->source_stack->data;
- if (top->pipeline == pipeline)
- return;
-
- if (top->push_count == 1)
- {
- /* NB: top->pipeline may be only thing keeping pipeline
- * alive currently so ref pipeline first... */
- cogl_object_ref (pipeline);
- cogl_object_unref (top->pipeline);
- top->pipeline = pipeline;
- }
- else
- {
- top->push_count--;
- cogl_push_source (pipeline);
- }
-}
-
-void
-cogl_set_source_texture (CoglHandle texture_handle)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_return_if_fail (texture_handle != NULL);
-
- cogl_pipeline_set_layer_texture (ctx->texture_pipeline, 0, texture_handle);
- cogl_set_source (ctx->texture_pipeline);
-}
-
-void
-cogl_set_source_color4ub (guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha)
-{
- CoglColor c = { 0, };
-
- cogl_color_init_from_4ub (&c, red, green, blue, alpha);
- cogl_set_source_color (&c);
-}
-
-void
-cogl_set_source_color4f (float red,
- float green,
- float blue,
- float alpha)
-{
- CoglColor c = { 0, };
-
- cogl_color_init_from_4f (&c, red, green, blue, alpha);
- cogl_set_source_color (&c);
-}
-
-/* Scale from OpenGL normalized device coordinates (ranging from -1 to 1)
- * to Cogl window/framebuffer coordinates (ranging from 0 to buffer-size) with
- * (0,0) being top left. */
-#define VIEWPORT_TRANSFORM_X(x, vp_origin_x, vp_width) \
- ( ( ((x) + 1.0) * ((vp_width) / 2.0) ) + (vp_origin_x) )
-/* Note: for Y we first flip all coordinates around the X axis while in
- * normalized device coodinates */
-#define VIEWPORT_TRANSFORM_Y(y, vp_origin_y, vp_height) \
- ( ( ((-(y)) + 1.0) * ((vp_height) / 2.0) ) + (vp_origin_y) )
-
-/* Transform a homogeneous vertex position from model space to Cogl
- * window coordinates (with 0,0 being top left) */
-void
-_cogl_transform_point (const CoglMatrix *matrix_mv,
- const CoglMatrix *matrix_p,
- const float *viewport,
- float *x,
- float *y)
-{
- float z = 0;
- float w = 1;
-
- /* Apply the modelview matrix transform */
- cogl_matrix_transform_point (matrix_mv, x, y, &z, &w);
-
- /* Apply the projection matrix transform */
- cogl_matrix_transform_point (matrix_p, x, y, &z, &w);
-
- /* Perform perspective division */
- *x /= w;
- *y /= w;
-
- /* Apply viewport transform */
- *x = VIEWPORT_TRANSFORM_X (*x, viewport[0], viewport[2]);
- *y = VIEWPORT_TRANSFORM_Y (*y, viewport[1], viewport[3]);
-}
-
-#undef VIEWPORT_TRANSFORM_X
-#undef VIEWPORT_TRANSFORM_Y
-
-GQuark
-_cogl_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-error-quark");
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
-
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_H__
-#define __COGL_H__
-
-#include <glib.h>
-
-#define __COGL_H_INSIDE__
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
-#ifndef COGL_ENABLE_EXPERIMENTAL_API
-#define COGL_ENABLE_EXPERIMENTAL_API
-#endif
-#endif
-
-/* We currently keep gtype integration delimited in case we eventually
- * want to split it out into a separate utility library when Cogl
- * becomes a standalone project. (like cairo-gobject.so)
- */
-#define _COGL_SUPPORTS_GTYPE_INTEGRATION
-
-#include <cogl/cogl-defines.h>
-
-#include <cogl/cogl-object.h>
-#include <cogl/cogl-bitmap.h>
-#include <cogl/cogl-color.h>
-#include <cogl/cogl-fixed.h>
-#include <cogl/cogl-material-compat.h>
-#include <cogl/cogl-matrix.h>
-#include <cogl/cogl-offscreen.h>
-#include <cogl/cogl-primitives.h>
-#ifdef COGL_ENABLE_EXPERIMENTAL_2_0_API
-#include <cogl/cogl2-path.h>
-#include <cogl/cogl2-clip-state.h>
-#else
-#include <cogl/cogl-path.h>
-#include <cogl/cogl-clip-state.h>
-#endif
-#include <cogl/cogl-shader.h>
-#include <cogl/cogl-texture.h>
-#include <cogl/cogl-types.h>
-#include <cogl/cogl-vertex-buffer.h>
-
-#include <cogl/cogl-enum-types.h>
-
-#include <cogl/cogl-deprecated.h>
-
-typedef struct _CoglFramebuffer CoglFramebuffer;
-
-#if defined (COGL_ENABLE_EXPERIMENTAL_API)
-#include <cogl/cogl-swap-chain.h>
-#include <cogl/cogl-renderer.h>
-#include <cogl/cogl-display.h>
-#include <cogl/cogl-context.h>
-#include <cogl/cogl-buffer.h>
-#include <cogl/cogl-pixel-array.h>
-#include <cogl/cogl-vector.h>
-#include <cogl/cogl-texture-3d.h>
-#include <cogl/cogl-index-array.h>
-#include <cogl/cogl-vertex-array.h>
-#include <cogl/cogl-indices.h>
-#include <cogl/cogl-attribute.h>
-#include <cogl/cogl-primitive.h>
-#include <cogl/cogl-pipeline.h>
-#include <cogl/cogl-framebuffer.h>
-#ifdef COGL_HAS_XLIB
-#include <cogl/cogl-xlib.h>
-#endif
-/* XXX: This will definitly go away once all the Clutter winsys
- * code has been migrated down into Cogl! */
-#include <cogl/cogl-clutter.h>
-#endif
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl
- * @short_description: General purpose API
- *
- * General utility functions for COGL.
- */
-
-/**
- * cogl_get_option_group:
- *
- * Retrieves the #GOptionGroup used by COGL to parse the command
- * line options. Clutter uses this to handle the COGL command line
- * options during its initialization process.
- *
- * Return value: a #GOptionGroup
- *
- * Since: 1.0
- */
-GOptionGroup *
-cogl_get_option_group (void);
-
-/* Misc */
-/**
- * cogl_get_features:
- *
- * Returns all of the features supported by COGL.
- *
- * Return value: A logical OR of all the supported COGL features.
- *
- * Since: 0.8
- */
-CoglFeatureFlags
-cogl_get_features (void);
-
-/**
- * cogl_features_available:
- * @features: A bitmask of features to check for
- *
- * Checks whether the given COGL features are available. Multiple
- * features can be checked for by or-ing them together with the '|'
- * operator. %TRUE is only returned if all of the requested features
- * are available.
- *
- * Return value: %TRUE if the features are available, %FALSE otherwise.
- */
-gboolean
-cogl_features_available (CoglFeatureFlags features);
-
-/**
- * cogl_get_proc_address:
- * @name: the name of the function.
- *
- * Gets a pointer to a given GL or GL ES extension function. This acts
- * as a wrapper around glXGetProcAddress() or whatever is the
- * appropriate function for the current backend.
- *
- * Return value: a pointer to the requested function or %NULL if the
- * function is not available.
- */
-CoglFuncPtr
-cogl_get_proc_address (const char *name);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_check_extension:
- * @name: extension to check for
- * @ext: list of extensions
- *
- * Check whether @name occurs in list of extensions in @ext.
- *
- * Return value: %TRUE if the extension occurs in the list, %FALSE otherwise.
- *
- * Deprecated: 1.2: OpenGL is an implementation detail for Cogl and so it's
- * not appropriate to expose OpenGL extensions through the Cogl API. This
- * function can be replaced by the following equivalent code:
- * |[
- * gboolean retval = (strstr (ext, name) != NULL) ? TRUE : FALSE;
- * ]|
- */
-gboolean
-cogl_check_extension (const char *name,
- const char *ext) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_get_bitmasks:
- * @red: (out): Return location for the number of red bits or %NULL
- * @green: (out): Return location for the number of green bits or %NULL
- * @blue: (out): Return location for the number of blue bits or %NULL
- * @alpha: (out): Return location for the number of alpha bits or %NULL
- *
- * Gets the number of bitplanes used for each of the color components
- * in the color buffer. Pass %NULL for any of the arguments if the
- * value is not required.
- */
-void
-cogl_get_bitmasks (int *red,
- int *green,
- int *blue,
- int *alpha);
-
-/*
- * _cogl_framebuffer_get_red_bits:
- * @framebuffer: a handle for a framebuffer
- *
- * Retrieves the number of red bits of @framebuffer
- *
- * Return value: the number of bits
- *
- * Since: 1.4
- */
-int
-_cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer);
-
-/*
- * _cogl_framebuffer_get_green_bits:
- * @framebuffer: a handle for a framebuffer
- *
- * Retrieves the number of green bits of @framebuffer
- *
- * Return value: the number of bits
- *
- * Since: 1.4
- */
-int
-_cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer);
-
-/*
- * _cogl_framebuffer_get_blue_bits:
- * @framebuffer: a handle for a framebuffer
- *
- * Retrieves the number of blue bits of @framebuffer
- *
- * Return value: the number of bits
- *
- * Since: 1.4
- */
-int
-_cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer);
-
-/*
- * _cogl_framebuffer_get_alpha_bits:
- * @framebuffer: a handle for a framebuffer
- *
- * Retrieves the number of alpha bits of @framebuffer
- *
- * Return value: the number of bits
- *
- * Since: 1.4
- */
-int
-_cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer);
-
-/**
- * cogl_perspective:
- * @fovy: Vertical of view angle in degrees.
- * @aspect: Aspect ratio of diesplay
- * @z_near: Nearest visible point
- * @z_far: Furthest visible point along the z-axis
- *
- * Replaces the current projection matrix with a perspective matrix
- * based on the provided values.
- */
-void
-cogl_perspective (float fovy,
- float aspect,
- float z_near,
- float z_far);
-
-/**
- * cogl_frustum:
- * @left: Left clipping plane
- * @right: Right clipping plane
- * @bottom: Bottom clipping plane
- * @top: Top clipping plane
- * @z_near: Nearest visible point
- * @z_far: Furthest visible point along the z-axis
- *
- * Replaces the current projection matrix with a perspective matrix
- * for the given viewing frustum.
- *
- * Since: 0.8.2
- */
-void
-cogl_frustum (float left,
- float right,
- float bottom,
- float top,
- float z_near,
- float z_far);
-
-/**
- * cogl_ortho:
- * @left: The coordinate for the left clipping plane
- * @right: The coordinate for the right clipping plane
- * @bottom: The coordinate for the bottom clipping plane
- * @top: The coordinate for the top clipping plane
- * @near: The <emphasis>distance</emphasis> to the near clipping
- * plane (negative if the plane is behind the viewer)
- * @far: The <emphasis>distance</emphasis> for the far clipping
- * plane (negative if the plane is behind the viewer)
- *
- * Replaces the current projection matrix with an orthographic projection
- * matrix. See <xref linkend="cogl-ortho-matrix"/> to see how the matrix is
- * calculated.
- *
- * <figure id="cogl-ortho-matrix">
- * <title></title>
- * <graphic fileref="cogl_ortho.png" format="PNG"/>
- * </figure>
- *
- * <note>This function copies the arguments from OpenGL's glOrtho() even
- * though they are unnecessarily confusing due to the z near and z far
- * arguments actually being a "distance" from the origin, where
- * negative values are behind the viewer, instead of coordinates for
- * the z clipping planes which would have been consistent with the
- * left, right bottom and top arguments.</note>
- *
- * Since: 1.0
- */
-void
-cogl_ortho (float left,
- float right,
- float bottom,
- float top,
- float near,
- float far);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_viewport:
- * @width: Width of the viewport
- * @height: Height of the viewport
- *
- * Replace the current viewport with the given values.
- *
- * Since: 0.8.2
- *
- * Deprecated: 1.2: Use cogl_set_viewport() instead
- */
-void
-cogl_viewport (unsigned int width,
- unsigned int height) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_set_viewport:
- * @x: X offset of the viewport
- * @y: Y offset of the viewport
- * @width: Width of the viewport
- * @height: Height of the viewport
- *
- * Replaces the current viewport with the given values.
- *
- * Since: 1.2
- */
-void
-cogl_set_viewport (int x,
- int y,
- int width,
- int height);
-
-/**
- * cogl_push_matrix:
- *
- * Stores the current model-view matrix on the matrix stack. The matrix
- * can later be restored with cogl_pop_matrix().
- */
-void
-cogl_push_matrix (void);
-
-/**
- * cogl_pop_matrix:
- *
- * Restores the current model-view matrix from the matrix stack.
- */
-void
-cogl_pop_matrix (void);
-
-/**
- * cogl_scale:
- * @x: Amount to scale along the x-axis
- * @y: Amount to scale along the y-axis
- * @z: Amount to scale along the z-axis
- *
- * Multiplies the current model-view matrix by one that scales the x,
- * y and z axes by the given values.
- */
-void
-cogl_scale (float x,
- float y,
- float z);
-
-/**
- * cogl_translate:
- * @x: Distance to translate along the x-axis
- * @y: Distance to translate along the y-axis
- * @z: Distance to translate along the z-axis
- *
- * Multiplies the current model-view matrix by one that translates the
- * model along all three axes according to the given values.
- */
-void
-cogl_translate (float x,
- float y,
- float z);
-
-/**
- * cogl_rotate:
- * @angle: Angle in degrees to rotate.
- * @x: X-component of vertex to rotate around.
- * @y: Y-component of vertex to rotate around.
- * @z: Z-component of vertex to rotate around.
- *
- * Multiplies the current model-view matrix by one that rotates the
- * model around the vertex specified by @x, @y and @z. The rotation
- * follows the right-hand thumb rule so for example rotating by 10
- * degrees about the vertex (0, 0, 1) causes a small counter-clockwise
- * rotation.
- */
-void
-cogl_rotate (float angle,
- float x,
- float y,
- float z);
-
-/**
- * cogl_transform:
- * @matrix: the matrix to multiply with the current model-view
- *
- * Multiplies the current model-view matrix by the given matrix.
- *
- * Since: 1.4
- */
-void
-cogl_transform (const CoglMatrix *matrix);
-
-/**
- * cogl_get_modelview_matrix:
- * @matrix: (out): return location for the model-view matrix
- *
- * Stores the current model-view matrix in @matrix.
- */
-void
-cogl_get_modelview_matrix (CoglMatrix *matrix);
-
-/**
- * cogl_set_modelview_matrix:
- * @matrix: the new model-view matrix
- *
- * Loads @matrix as the new model-view matrix.
- */
-void
-cogl_set_modelview_matrix (CoglMatrix *matrix);
-
-/**
- * cogl_get_projection_matrix:
- * @matrix: (out): return location for the projection matrix
- *
- * Stores the current projection matrix in @matrix.
- */
-void
-cogl_get_projection_matrix (CoglMatrix *matrix);
-
-/**
- * cogl_set_projection_matrix:
- * @matrix: the new projection matrix
- *
- * Loads matrix as the new projection matrix.
- */
-void
-cogl_set_projection_matrix (CoglMatrix *matrix);
-
-/**
- * cogl_get_viewport:
- * @v: (out) (array fixed-size=4): pointer to a 4 element array
- * of #float<!-- -->s to receive the viewport dimensions.
- *
- * Stores the current viewport in @v. @v[0] and @v[1] get the x and y
- * position of the viewport and @v[2] and @v[3] get the width and
- * height.
- */
-void
-cogl_get_viewport (float v[4]);
-
-/**
- * cogl_set_depth_test_enabled:
- * @setting: %TRUE to enable depth testing or %FALSE to disable.
- *
- * Sets whether depth testing is enabled. If it is disabled then the
- * order that actors are layered on the screen depends solely on the
- * order specified using clutter_actor_raise() and
- * clutter_actor_lower(), otherwise it will also take into account the
- * actor's depth. Depth testing is disabled by default.
- *
- * Deprecated: 1.4: Use cogl_material_set_depth_test_enabled()
- * instead.
- */
-void
-cogl_set_depth_test_enabled (gboolean setting);
-
-/**
- * cogl_get_depth_test_enabled:
- *
- * Queries if depth testing has been enabled via cogl_set_depth_test_enable()
- *
- * Return value: %TRUE if depth testing is enabled, and %FALSE otherwise
- *
- * Deprecated: 1.4: Use cogl_material_get_depth_test_enabled()
- * instead.
- */
-gboolean
-cogl_get_depth_test_enabled (void);
-
-/**
- * cogl_set_backface_culling_enabled:
- * @setting: %TRUE to enable backface culling or %FALSE to disable.
- *
- * Sets whether textures positioned so that their backface is showing
- * should be hidden. This can be used to efficiently draw two-sided
- * textures or fully closed cubes without enabling depth testing. This
- * only affects calls to the cogl_rectangle* family of functions and
- * cogl_vertex_buffer_draw*. Backface culling is disabled by default.
- */
-void
-cogl_set_backface_culling_enabled (gboolean setting);
-
-/**
- * cogl_get_backface_culling_enabled:
- *
- * Queries if backface culling has been enabled via
- * cogl_set_backface_culling_enabled()
- *
- * Return value: %TRUE if backface culling is enabled, and %FALSE otherwise
- */
-gboolean
-cogl_get_backface_culling_enabled (void);
-
-/**
- * cogl_set_fog:
- * @fog_color: The color of the fog
- * @mode: A #CoglFogMode that determines the equation used to calculate the
- * fogging blend factor.
- * @density: Used by %COGL_FOG_MODE_EXPONENTIAL and by
- * %COGL_FOG_MODE_EXPONENTIAL_SQUARED equations.
- * @z_near: Position along Z axis where no fogging should be applied
- * @z_far: Position along Z axis where full fogging should be applied
- *
- * Enables fogging. Fogging causes vertices that are further away from the eye
- * to be rendered with a different color. The color is determined according to
- * the chosen fog mode; at it's simplest the color is linearly interpolated so
- * that vertices at @z_near are drawn fully with their original color and
- * vertices at @z_far are drawn fully with @fog_color. Fogging will remain
- * enabled until you call cogl_disable_fog().
- *
- * <note>The fogging functions only work correctly when primitives use
- * unmultiplied alpha colors. By default Cogl will premultiply textures
- * and cogl_set_source_color() will premultiply colors, so unless you
- * explicitly load your textures requesting an unmultiplied internal format
- * and use cogl_material_set_color() you can only use fogging with fully
- * opaque primitives. This might improve in the future when we can depend
- * on fragment shaders.</note>
- */
-void
-cogl_set_fog (const CoglColor *fog_color,
- CoglFogMode mode,
- float density,
- float z_near,
- float z_far);
-
-/**
- * cogl_disable_fog:
- *
- * This function disables fogging, so primitives drawn afterwards will not be
- * blended with any previously set fog color.
- */
-void
-cogl_disable_fog (void);
-
-/**
- * CoglBufferBit:
- * @COGL_BUFFER_BIT_COLOR: Selects the primary color buffer
- * @COGL_BUFFER_BIT_DEPTH: Selects the depth buffer
- * @COGL_BUFFER_BIT_STENCIL: Selects the stencil buffer
- *
- * Types of auxiliary buffers
- *
- * Since: 1.0
- */
-typedef enum {
- COGL_BUFFER_BIT_COLOR = 1L<<0,
- COGL_BUFFER_BIT_DEPTH = 1L<<1,
- COGL_BUFFER_BIT_STENCIL = 1L<<2
-} CoglBufferBit;
-
-/**
- * cogl_clear:
- * @color: Background color to clear to
- * @buffers: A mask of #CoglBufferBit<!-- -->'s identifying which auxiliary
- * buffers to clear
- *
- * Clears all the auxiliary buffers identified in the @buffers mask, and if
- * that includes the color buffer then the specified @color is used.
- */
-void
-cogl_clear (const CoglColor *color,
- unsigned long buffers);
-
-/**
- * cogl_set_source:
- * @material: A #CoglMaterial
- *
- * This function changes the material at the top of the source stack.
- * The material at the top of this stack defines the GPU state used to
- * process subsequent primitives, such as rectangles drawn with
- * cogl_rectangle() or vertices drawn using cogl_vertex_buffer_draw().
- *
- * Since: 1.0
- */
-void
-cogl_set_source (void *material);
-
-/**
- * cogl_get_source:
- *
- * Returns the current source material as previously set using
- * cogl_set_source().
- *
- * <note>You should typically consider the returned material immutable
- * and not try to change any of its properties unless you own a
- * reference to that material. At times you may be able to get a
- * reference to an internally managed materials and the result of
- * modifying such materials is undefined.</note>
- *
- * Return value: The current source material.
- *
- * Since: 1.6
- */
-void *
-cogl_get_source (void);
-
-/**
- * cogl_push_source:
- * @material: A #CoglMaterial
- *
- * Pushes the given @material to the top of the source stack. The
- * material at the top of this stack defines the GPU state used to
- * process later primitives as defined by cogl_set_source().
- *
- * Since: 1.6
- */
-void
-cogl_push_source (void *material);
-
-/**
- * cogl_pop_source:
- *
- * Removes the material at the top of the source stack. The material
- * at the top of this stack defines the GPU state used to process
- * later primitives as defined by cogl_set_source().
- *
- * Since: 1.6
- */
-void
-cogl_pop_source (void);
-
-/**
- * cogl_set_source_color:
- * @color: a #CoglColor
- *
- * This is a convenience function for creating a solid fill source material
- * from the given color. This color will be used for any subsequent drawing
- * operation.
- *
- * The color will be premultiplied by Cogl, so the color should be
- * non-premultiplied. For example: use (1.0, 0.0, 0.0, 0.5) for
- * semi-transparent red.
- *
- * See also cogl_set_source_color4ub() and cogl_set_source_color4f()
- * if you already have the color components.
- *
- * Since: 1.0
- */
-void
-cogl_set_source_color (const CoglColor *color);
-
-/**
- * cogl_set_source_color4ub:
- * @red: value of the red channel, between 0 and 255
- * @green: value of the green channel, between 0 and 255
- * @blue: value of the blue channel, between 0 and 255
- * @alpha: value of the alpha channel, between 0 and 255
- *
- * This is a convenience function for creating a solid fill source material
- * from the given color using unsigned bytes for each component. This
- * color will be used for any subsequent drawing operation.
- *
- * The value for each component is an unsigned byte in the range
- * between 0 and 255.
- *
- * Since: 1.0
- */
-void
-cogl_set_source_color4ub (guint8 red,
- guint8 green,
- guint8 blue,
- guint8 alpha);
-
-/**
- * cogl_set_source_color4f:
- * @red: value of the red channel, between 0 and %1.0
- * @green: value of the green channel, between 0 and %1.0
- * @blue: value of the blue channel, between 0 and %1.0
- * @alpha: value of the alpha channel, between 0 and %1.0
- *
- * This is a convenience function for creating a solid fill source material
- * from the given color using normalized values for each component. This color
- * will be used for any subsequent drawing operation.
- *
- * The value for each component is a fixed point number in the range
- * between 0 and %1.0. If the values passed in are outside that
- * range, they will be clamped.
- *
- * Since: 1.0
- */
-void
-cogl_set_source_color4f (float red,
- float green,
- float blue,
- float alpha);
-
-/**
- * cogl_set_source_texture:
- * @texture_handle: The Cogl texture you want as your source
- *
- * This is a convenience function for creating a material with the first
- * layer set to #texture_handle and setting that material as the source with
- * cogl_set_source.
- *
- * Note: There is no interaction between calls to cogl_set_source_color
- * and cogl_set_source_texture. If you need to blend a texture with a color then
- * you can create a simple material like this:
- * <programlisting>
- * material = cogl_material_new ();
- * cogl_material_set_color4ub (material, 0xff, 0x00, 0x00, 0x80);
- * cogl_material_set_layer (material, 0, tex_handle);
- * cogl_set_source (material);
- * </programlisting>
- *
- * Since: 1.0
- */
-void
-cogl_set_source_texture (CoglHandle texture_handle);
-
-/**
- * SECTION:cogl-clipping
- * @short_description: Fuctions for manipulating a stack of clipping regions
- *
- * To support clipping your geometry to rectangles or paths Cogl exposes a
- * stack based API whereby each clip region you push onto the stack is
- * intersected with the previous region.
- */
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_clip_push_window_rect:
- * @x_offset: left edge of the clip rectangle in window coordinates
- * @y_offset: top edge of the clip rectangle in window coordinates
- * @width: width of the clip rectangle
- * @height: height of the clip rectangle
- *
- * Specifies a rectangular clipping area for all subsequent drawing
- * operations. Any drawing commands that extend outside the rectangle
- * will be clipped so that only the portion inside the rectangle will
- * be displayed. The rectangle dimensions are not transformed by the
- * current model-view matrix.
- *
- * The rectangle is intersected with the current clip region. To undo
- * the effect of this function, call cogl_clip_pop().
- *
- * Deprecated: 1.2: Use cogl_clip_push_window_rectangle() instead
- */
-void
-cogl_clip_push_window_rect (float x_offset,
- float y_offset,
- float width,
- float height) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_clip_push_window_rectangle:
- * @x_offset: left edge of the clip rectangle in window coordinates
- * @y_offset: top edge of the clip rectangle in window coordinates
- * @width: width of the clip rectangle
- * @height: height of the clip rectangle
- *
- * Specifies a rectangular clipping area for all subsequent drawing
- * operations. Any drawing commands that extend outside the rectangle
- * will be clipped so that only the portion inside the rectangle will
- * be displayed. The rectangle dimensions are not transformed by the
- * current model-view matrix.
- *
- * The rectangle is intersected with the current clip region. To undo
- * the effect of this function, call cogl_clip_pop().
- *
- * Since: 1.2
- */
-void
-cogl_clip_push_window_rectangle (int x_offset,
- int y_offset,
- int width,
- int height);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_clip_push:
- * @x_offset: left edge of the clip rectangle
- * @y_offset: top edge of the clip rectangle
- * @width: width of the clip rectangle
- * @height: height of the clip rectangle
- *
- * Specifies a rectangular clipping area for all subsequent drawing
- * operations. Any drawing commands that extend outside the rectangle
- * will be clipped so that only the portion inside the rectangle will
- * be displayed. The rectangle dimensions are transformed by the
- * current model-view matrix.
- *
- * The rectangle is intersected with the current clip region. To undo
- * the effect of this function, call cogl_clip_pop().
- *
- * Deprecated: 1.2: The x, y, width, height arguments are inconsistent
- * with other API that specify rectangles in model space, and when used
- * with a coordinate space that puts the origin at the center and y+
- * extending up, it's awkward to use. Please use cogl_clip_push_rectangle()
- * instead
- */
-void
-cogl_clip_push (float x_offset,
- float y_offset,
- float width,
- float height) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_clip_push_rectangle:
- * @x0: x coordinate for top left corner of the clip rectangle
- * @y0: y coordinate for top left corner of the clip rectangle
- * @x1: x coordinate for bottom right corner of the clip rectangle
- * @y1: y coordinate for bottom right corner of the clip rectangle
- *
- * Specifies a rectangular clipping area for all subsequent drawing
- * operations. Any drawing commands that extend outside the rectangle
- * will be clipped so that only the portion inside the rectangle will
- * be displayed. The rectangle dimensions are transformed by the
- * current model-view matrix.
- *
- * The rectangle is intersected with the current clip region. To undo
- * the effect of this function, call cogl_clip_pop().
- *
- * Since: 1.2
- */
-void
-cogl_clip_push_rectangle (float x0,
- float y0,
- float x1,
- float y1);
-
-/**
- * cogl_clip_push_from_path_preserve:
- *
- * Sets a new clipping area using the current path. The current path
- * is then cleared. The clipping area is intersected with the previous
- * clipping area. To restore the previous clipping area, call
- * cogl_clip_pop().
- *
- * Since: 1.0
- */
-void
-cogl_clip_push_from_path_preserve (void);
-
-/**
- * cogl_clip_pop:
- *
- * Reverts the clipping region to the state before the last call to
- * cogl_clip_push().
- */
-void
-cogl_clip_pop (void);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_clip_ensure:
- *
- * Ensures that the current clipping region has been set in GL. This
- * will automatically be called before any Cogl primitives but it
- * maybe be neccessary to call if you are using raw GL calls with
- * clipping.
- *
- * Deprecated: 1.2: Calling this function has no effect
- *
- * Since: 1.0
- */
-void
-cogl_clip_ensure (void) G_GNUC_DEPRECATED;
-
-/**
- * cogl_clip_stack_save:
- *
- * Save the entire state of the clipping stack and then clear all
- * clipping. The previous state can be returned to with
- * cogl_clip_stack_restore(). Each call to cogl_clip_push() after this
- * must be matched by a call to cogl_clip_pop() before calling
- * cogl_clip_stack_restore().
- *
- * Deprecated: 1.2: This was originally added to allow us to save the
- * clip stack when switching to an offscreen framebuffer, but it's
- * not necessary anymore given that framebuffers now own separate
- * clip stacks which will be automatically switched between when a
- * new buffer is set. Calling this function has no effect
- *
- * Since: 0.8.2
- */
-void
-cogl_clip_stack_save (void) G_GNUC_DEPRECATED;
-
-/**
- * cogl_clip_stack_restore:
- *
- * Restore the state of the clipping stack that was previously saved
- * by cogl_clip_stack_save().
- *
- * Deprecated: 1.2: This was originally added to allow us to restore
- * the clip stack when switching back from an offscreen framebuffer,
- * but it's not necessary anymore given that framebuffers now own
- * separate clip stacks which will be automatically switched between
- * when a new buffer is set. Calling this function has no effect
- *
- * Since: 0.8.2
- */
-void
-cogl_clip_stack_restore (void) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * cogl_set_framebuffer:
- * @buffer: A #CoglFramebuffer object, either onscreen or offscreen.
- *
- * This redirects all subsequent drawing to the specified framebuffer. This can
- * either be an offscreen buffer created with cogl_offscreen_new_to_texture ()
- * or in the future it may be an onscreen framebuffers too.
- *
- * Since: 1.2
- */
-void
-cogl_set_framebuffer (CoglFramebuffer *buffer);
-
-/**
- * cogl_push_framebuffer:
- * @buffer: A #CoglFramebuffer object, either onscreen or offscreen.
- *
- * Redirects all subsequent drawing to the specified framebuffer. This can
- * either be an offscreen buffer created with cogl_offscreen_new_to_texture ()
- * or in the future it may be an onscreen framebuffer too.
- *
- * You should understand that a framebuffer owns the following state:
- * <itemizedlist>
- * <listitem><simpara>The projection matrix</simpara></listitem>
- * <listitem><simpara>The modelview matrix stack</simpara></listitem>
- * <listitem><simpara>The viewport</simpara></listitem>
- * <listitem><simpara>The clip stack</simpara></listitem>
- * </itemizedlist>
- * So these items will automatically be saved and restored when you
- * push and pop between different framebuffers.
- *
- * Also remember a newly allocated framebuffer will have an identity matrix for
- * the projection and modelview matrices which gives you a coordinate space
- * like OpenGL with (-1, -1) corresponding to the top left of the viewport,
- * (1, 1) corresponding to the bottom right and +z coming out towards the
- * viewer.
- *
- * If you want to set up a coordinate space like Clutter does with (0, 0)
- * corresponding to the top left and (framebuffer_width, framebuffer_height)
- * corresponding to the bottom right you can do so like this:
- *
- * |[
- * static void
- * setup_viewport (unsigned int width,
- * unsigned int height,
- * float fovy,
- * float aspect,
- * float z_near,
- * float z_far)
- * {
- * float z_camera;
- * CoglMatrix projection_matrix;
- * CoglMatrix mv_matrix;
- *
- * cogl_set_viewport (0, 0, width, height);
- * cogl_perspective (fovy, aspect, z_near, z_far);
- *
- * cogl_get_projection_matrix (&projection_matrix);
- * z_camera = 0.5 * projection_matrix.xx;
- *
- * cogl_matrix_init_identity (&mv_matrix);
- * cogl_matrix_translate (&mv_matrix, -0.5f, -0.5f, -z_camera);
- * cogl_matrix_scale (&mv_matrix, 1.0f / width, -1.0f / height, 1.0f / width);
- * cogl_matrix_translate (&mv_matrix, 0.0f, -1.0 * height, 0.0f);
- * cogl_set_modelview_matrix (&mv_matrix);
- * }
- *
- * static void
- * my_init_framebuffer (ClutterStage *stage,
- * CoglFramebuffer *framebuffer,
- * unsigned int framebuffer_width,
- * unsigned int framebuffer_height)
- * {
- * ClutterPerspective perspective;
- *
- * clutter_stage_get_perspective (stage, &perspective);
- *
- * cogl_push_framebuffer (framebuffer);
- * setup_viewport (framebuffer_width,
- * framebuffer_height,
- * perspective.fovy,
- * perspective.aspect,
- * perspective.z_near,
- * perspective.z_far);
- * }
- * ]|
- *
- * The previous framebuffer can be restored by calling cogl_pop_framebuffer()
- *
- * Since: 1.2
- */
-void
-cogl_push_framebuffer (CoglFramebuffer *buffer);
-
-/**
- * cogl_pop_framebuffer:
- *
- * Restores the framebuffer that was previously at the top of the stack.
- * All subsequent drawing will be redirected to this framebuffer.
- *
- * Since: 1.2
- */
-void
-cogl_pop_framebuffer (void);
-
-#ifndef COGL_DISABLE_DEPRECATED
-
-/**
- * cogl_set_draw_buffer:
- * @target: A #CoglBufferTarget that specifies what kind of framebuffer you
- * are setting as the render target.
- * @offscreen: If you are setting a framebuffer of type COGL_OFFSCREEN_BUFFER
- * then this is a CoglHandle for the offscreen buffer.
- *
- * Redirects all subsequent drawing to the specified framebuffer. This
- * can either be an offscreen buffer created with
- * cogl_offscreen_new_to_texture () or you can revert to your original
- * on screen window buffer.
- *
- * Deprecated: 1.2: The target argument was redundant since we could look at
- * the type of CoglHandle given instead.
- */
-void
-cogl_set_draw_buffer (CoglBufferTarget target,
- CoglHandle offscreen) G_GNUC_DEPRECATED;
-
-/**
- * cogl_push_draw_buffer:
- *
- * Save cogl_set_draw_buffer() state.
- *
- * Deprecated: 1.2: The draw buffer API was replaced with a framebuffer API
- */
-void
-cogl_push_draw_buffer (void) G_GNUC_DEPRECATED;
-
-/**
- * cogl_pop_draw_buffer:
- *
- * Restore cogl_set_draw_buffer() state.
- *
- * Deprecated: 1.2: The draw buffer API was replaced with a framebuffer API
- */
-void
-cogl_pop_draw_buffer (void) G_GNUC_DEPRECATED;
-
-#endif /* COGL_DISABLE_DEPRECATED */
-
-/**
- * CoglReadPixelsFlags:
- * @COGL_READ_PIXELS_COLOR_BUFFER: Read from the color buffer
- *
- * Flags for cogl_read_pixels()
- *
- * Since: 1.0
- */
-typedef enum { /*< prefix=COGL_READ_PIXELS >*/
- COGL_READ_PIXELS_COLOR_BUFFER = 1L << 0
-} CoglReadPixelsFlags;
-
-/**
- * cogl_read_pixels:
- * @x: The window x position to start reading from
- * @y: The window y position to start reading from
- * @width: The width of the rectangle you want to read
- * @height: The height of the rectangle you want to read
- * @source: Identifies which auxillary buffer you want to read
- * (only COGL_READ_PIXELS_COLOR_BUFFER supported currently)
- * @format: The pixel format you want the result in
- * (only COGL_PIXEL_FORMAT_RGBA_8888 supported currently)
- * @pixels: The location to write the pixel data.
- *
- * This reads a rectangle of pixels from the current framebuffer where
- * position (0, 0) is the top left. The pixel at (x, y) is the first
- * read, and the data is returned with a rowstride of (width * 4).
- *
- * Currently Cogl assumes that the framebuffer is in a premultiplied
- * format so if @format is non-premultiplied it will convert it. To
- * read the pixel values without any conversion you should either
- * specify a format that doesn't use an alpha channel or use one of
- * the formats ending in PRE.
- */
-void
-cogl_read_pixels (int x,
- int y,
- int width,
- int height,
- CoglReadPixelsFlags source,
- CoglPixelFormat format,
- guint8 *pixels);
-
-/**
- * cogl_flush:
- *
- * This function should only need to be called in exceptional circumstances.
- *
- * As an optimization Cogl drawing functions may batch up primitives
- * internally, so if you are trying to use raw GL outside of Cogl you stand a
- * better chance of being successful if you ask Cogl to flush any batched
- * geometry before making your state changes.
- *
- * It only ensure that the underlying driver is issued all the commands
- * necessary to draw the batched primitives. It provides no guarantees about
- * when the driver will complete the rendering.
- *
- * This provides no guarantees about the GL state upon returning and to avoid
- * confusing Cogl you should aim to restore any changes you make before
- * resuming use of Cogl.
- *
- * If you are making state changes with the intention of affecting Cogl drawing
- * primitives you are 100% on your own since you stand a good chance of
- * conflicting with Cogl internals. For example clutter-gst which currently
- * uses direct GL calls to bind ARBfp programs will very likely break when Cogl
- * starts to use ARBfb programs itself for the material API.
- *
- * Since: 1.0
- */
-void
-cogl_flush (void);
-
-/**
- * cogl_begin_gl:
- *
- * We do not advise nor reliably support the interleaving of raw GL drawing and
- * Cogl drawing functions, but if you insist, cogl_begin_gl() and cogl_end_gl()
- * provide a simple mechanism that may at least give you a fighting chance of
- * succeeding.
- *
- * Note: this doesn't help you modify the behaviour of Cogl drawing functions
- * through the modification of GL state; that will never be reliably supported,
- * but if you are trying to do something like:
- *
- * |[
- * {
- * - setup some OpenGL state.
- * - draw using OpenGL (e.g. glDrawArrays() )
- * - reset modified OpenGL state.
- * - continue using Cogl to draw
- * }
- * ]|
- *
- * You should surround blocks of drawing using raw GL with cogl_begin_gl()
- * and cogl_end_gl():
- *
- * |[
- * {
- * cogl_begin_gl ();
- * - setup some OpenGL state.
- * - draw using OpenGL (e.g. glDrawArrays() )
- * - reset modified OpenGL state.
- * cogl_end_gl ();
- * - continue using Cogl to draw
- * }
- * ]|
- *
- * Don't ever try and do:
- *
- * |[
- * {
- * - setup some OpenGL state.
- * - use Cogl to draw
- * - reset modified OpenGL state.
- * }
- * ]|
- *
- * When the internals of Cogl evolves, this is very liable to break.
- *
- * This function will flush all batched primitives, and subsequently flush
- * all internal Cogl state to OpenGL as if it were going to draw something
- * itself.
- *
- * The result is that the OpenGL modelview matrix will be setup; the state
- * corresponding to the current source material will be set up and other world
- * state such as backface culling, depth and fogging enabledness will be sent
- * to OpenGL.
- *
- * <note>No special material state is flushed, so if you want Cogl to setup a
- * simplified material state it is your responsibility to set a simple source
- * material before calling cogl_begin_gl(). E.g. by calling
- * cogl_set_source_color4ub().</note>
- *
- * <note>It is your responsibility to restore any OpenGL state that you modify
- * to how it was after calling cogl_begin_gl() if you don't do this then the
- * result of further Cogl calls is undefined.</note>
- *
- * <note>You can not nest begin/end blocks.</note>
- *
- * Again we would like to stress, we do not advise the use of this API and if
- * possible we would prefer to improve Cogl than have developers require raw
- * OpenGL.
- *
- * Since: 1.0
- */
-void
-cogl_begin_gl (void);
-
-/**
- * cogl_end_gl:
- *
- * This is the counterpart to cogl_begin_gl() used to delimit blocks of drawing
- * code using raw OpenGL. Please refer to cogl_begin_gl() for full details.
- *
- * Since: 1.0
- */
-void
-cogl_end_gl (void);
-
-G_END_DECLS
-
-#undef __COGL_H_INSIDE__
-
-#endif /* __COGL_H__ */
+++ /dev/null
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-apiversion=@COGL_API_VERSION@
-requires=@COGL_PKG_REQUIRES@
-
-Name: Cogl
-Description: An object oriented GL/GLES Abstraction/Utility Layer
-Version: @COGL_VERSION@
-Libs: -L${libdir} -lcogl
-Cflags: -I${includedir}/cogl -DCOGL_ENABLE_EXPERIMENTAL_2_0_API
-Requires: ${requires}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-clip-state-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-journal-private.h"
-
-void
-cogl2_clip_push_from_path (CoglPath *path)
-{
- CoglFramebuffer *framebuffer;
- CoglClipState *clip_state;
- CoglMatrix modelview_matrix;
-
- framebuffer = cogl_get_draw_framebuffer ();
- clip_state = _cogl_framebuffer_get_clip_state (framebuffer);
-
- cogl_get_modelview_matrix (&modelview_matrix);
-
- clip_state->stacks->data =
- _cogl_clip_stack_push_from_path (clip_state->stacks->data,
- path,
- &modelview_matrix);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL2_CLIP_STATE_H
-#define __COGL2_CLIP_STATE_H
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-#define cogl_clip_push_from_path cogl2_clip_push_from_path
-/**
- * cogl_clip_push_from_path:
- * @path: The path to clip with.
- *
- * Sets a new clipping area using @path. The clipping area is intersected
- * with the previous clipping area. To restore the previous clipping area,
- * call cogl_clip_pop().
- *
- * Since: 1.8
- * Stability: Unstable
- */
-void
-cogl_clip_push_from_path (CoglPath *path);
-
-G_END_DECLS
-
-#endif /* __COGL2_CLIP_STATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- * Authors:
- * Ivan Leben <ivan@openedhand.com>
- * Øyvind Kolås <pippin@linux.intel.com>
- * Neil Roberts <neil@linux.intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-object.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-journal-private.h"
-#include "cogl-pipeline-private.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-framebuffer-private.h"
-#include "cogl-path-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-primitives-private.h"
-#include "cogl-private.h"
-#include "cogl-attribute-private.h"
-#include "tesselator/tesselator.h"
-
-#include <string.h>
-#include <math.h>
-
-#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
-
-static void _cogl_path_free (CoglPath *path);
-
-static void _cogl_path_build_fill_vbo (CoglPath *path);
-static void _cogl_path_build_stroke_vbo (CoglPath *path);
-
-COGL_OBJECT_DEFINE (Path, path);
-
-static void
-_cogl_path_data_clear_vbos (CoglPathData *data)
-{
- int i;
-
- if (data->fill_vbo)
- {
- cogl_object_unref (data->fill_vbo);
- cogl_object_unref (data->fill_vbo_indices);
-
- for (i = 0; i < COGL_PATH_N_ATTRIBUTES; i++)
- cogl_object_unref (data->fill_vbo_attributes[i]);
-
- data->fill_vbo = NULL;
- }
-
- if (data->stroke_vbo)
- {
- cogl_object_unref (data->stroke_vbo);
-
- for (i = 0; i < data->stroke_vbo_n_attributes; i++)
- cogl_object_unref (data->stroke_vbo_attributes[i]);
-
- g_free (data->stroke_vbo_attributes);
-
- data->stroke_vbo = NULL;
- }
-}
-
-static void
-_cogl_path_data_unref (CoglPathData *data)
-{
- if (--data->ref_count <= 0)
- {
- _cogl_path_data_clear_vbos (data);
-
- g_array_free (data->path_nodes, TRUE);
-
- g_slice_free (CoglPathData, data);
- }
-}
-
-static void
-_cogl_path_modify (CoglPath *path)
-{
- /* This needs to be called whenever the path is about to be modified
- to implement copy-on-write semantics */
-
- /* If there is more than one path using the data then we need to
- copy the data instead */
- if (path->data->ref_count != 1)
- {
- CoglPathData *old_data = path->data;
-
- path->data = g_slice_dup (CoglPathData, old_data);
- path->data->path_nodes = g_array_new (FALSE, FALSE,
- sizeof (CoglPathNode));
- g_array_append_vals (path->data->path_nodes,
- old_data->path_nodes->data,
- old_data->path_nodes->len);
-
- path->data->fill_vbo = COGL_INVALID_HANDLE;
- path->data->ref_count = 1;
-
- _cogl_path_data_unref (old_data);
- }
- /* The path is altered so the vbo will now be invalid */
- else if (path->data->fill_vbo)
- _cogl_path_data_clear_vbos (path->data);
-}
-
-void
-cogl2_path_set_fill_rule (CoglPath *path,
- CoglPathFillRule fill_rule)
-{
- g_return_if_fail (cogl_is_path (path));
-
- if (path->data->fill_rule != fill_rule)
- {
- _cogl_path_modify (path);
-
- path->data->fill_rule = fill_rule;
- }
-}
-
-CoglPathFillRule
-cogl2_path_get_fill_rule (CoglPath *path)
-{
- g_return_val_if_fail (cogl_is_path (path), COGL_PATH_FILL_RULE_NON_ZERO);
-
- return path->data->fill_rule;
-}
-
-static void
-_cogl_path_add_node (CoglPath *path,
- gboolean new_sub_path,
- float x,
- float y)
-{
- CoglPathNode new_node;
- CoglPathData *data;
-
- _cogl_path_modify (path);
-
- data = path->data;
-
- new_node.x = x;
- new_node.y = y;
- new_node.path_size = 0;
-
- if (new_sub_path || data->path_nodes->len == 0)
- data->last_path = data->path_nodes->len;
-
- g_array_append_val (data->path_nodes, new_node);
-
- g_array_index (data->path_nodes, CoglPathNode, data->last_path).path_size++;
-
- if (data->path_nodes->len == 1)
- {
- data->path_nodes_min.x = data->path_nodes_max.x = x;
- data->path_nodes_min.y = data->path_nodes_max.y = y;
- }
- else
- {
- if (x < data->path_nodes_min.x)
- data->path_nodes_min.x = x;
- if (x > data->path_nodes_max.x)
- data->path_nodes_max.x = x;
- if (y < data->path_nodes_min.y)
- data->path_nodes_min.y = y;
- if (y > data->path_nodes_max.y)
- data->path_nodes_max.y = y;
- }
-
- /* Once the path nodes have been modified then we'll assume it's no
- longer a rectangle. cogl2_path_rectangle will set this back to
- TRUE if this has been called from there */
- data->is_rectangle = FALSE;
-}
-
-static void
-_cogl_path_stroke_nodes (CoglPath *path)
-{
- CoglPathData *data = path->data;
- CoglPipeline *copy = NULL;
- CoglPipeline *source;
- unsigned int path_start;
- int path_num = 0;
- CoglPathNode *node;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (G_UNLIKELY (ctx->legacy_state_set))
- {
- CoglPipeline *users_source = cogl_get_source ();
- copy = cogl_pipeline_copy (users_source);
- _cogl_pipeline_apply_legacy_state (copy);
- source = copy;
- }
- else
- source = cogl_get_source ();
-
- if (cogl_pipeline_get_n_layers (source) != 0)
- {
- /* If we haven't already created a derivative pipeline... */
- if (!copy)
- copy = cogl_pipeline_copy (source);
- _cogl_pipeline_prune_to_n_layers (copy, 0);
- source = copy;
- }
-
- _cogl_path_build_stroke_vbo (path);
-
- cogl_push_source (source);
-
- for (path_start = 0;
- path_start < data->path_nodes->len;
- path_start += node->path_size)
- {
- node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
- cogl_draw_attributes (COGL_VERTICES_MODE_LINE_STRIP,
- 0, node->path_size,
- data->stroke_vbo_attributes[path_num],
- NULL);
-
- path_num++;
- }
-
- cogl_pop_source ();
-
- if (copy)
- cogl_object_unref (copy);
-}
-
-void
-_cogl_path_get_bounds (CoglPath *path,
- float *min_x,
- float *min_y,
- float *max_x,
- float *max_y)
-{
- CoglPathData *data = path->data;
-
- if (data->path_nodes->len == 0)
- {
- *min_x = 0.0f;
- *min_y = 0.0f;
- *max_x = 0.0f;
- *max_y = 0.0f;
- }
- else
- {
- *min_x = data->path_nodes_min.x;
- *min_y = data->path_nodes_min.y;
- *max_x = data->path_nodes_max.x;
- *max_y = data->path_nodes_max.y;
- }
-}
-
-static void
-_cogl_path_fill_nodes_with_stencil_buffer (CoglPath *path)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- g_assert (ctx->current_clip_stack_valid);
-
- _cogl_add_path_to_stencil_buffer (path,
- ctx->current_clip_stack_uses_stencil,
- FALSE);
-
- _cogl_rectangle_immediate (path->data->path_nodes_min.x,
- path->data->path_nodes_min.y,
- path->data->path_nodes_max.x,
- path->data->path_nodes_max.y);
-
- /* The stencil buffer now contains garbage so the clip area needs to
- * be rebuilt.
- *
- * NB: We only ever try and update the clip state during
- * _cogl_journal_init (when we flush the framebuffer state) which is
- * only called when the journal first gets something logged in it; so
- * we call cogl_flush() to emtpy the journal.
- */
- _cogl_clip_stack_dirty ();
-}
-
-static void
-_cogl_path_fill_nodes (CoglPath *path)
-{
- const GList *l;
-
- /* If any of the layers of the current pipeline contain sliced
- textures or textures with waste then it won't work to draw the
- path directly. Instead we can use draw the texture as a quad
- clipped to the stencil buffer. */
- for (l = _cogl_pipeline_get_layers (cogl_get_source ()); l; l = l->next)
- {
- CoglHandle layer = l->data;
- CoglHandle texture = _cogl_pipeline_layer_get_texture (layer);
-
- if (texture != COGL_INVALID_HANDLE &&
- (cogl_texture_is_sliced (texture) ||
- !_cogl_texture_can_hardware_repeat (texture)))
- {
- if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
- _cogl_path_fill_nodes_with_stencil_buffer (path);
- else
- {
- static gboolean seen_warning = FALSE;
-
- if (!seen_warning)
- {
- g_warning ("Paths can not be filled using materials with "
- "sliced textures unless there is a stencil "
- "buffer");
- seen_warning = TRUE;
- }
- }
-
- return;
- }
- }
-
- _cogl_path_build_fill_vbo (path);
-
- _cogl_draw_indexed_attributes_array
- (COGL_VERTICES_MODE_TRIANGLES,
- 0, /* first_vertex */
- path->data->fill_vbo_n_indices,
- path->data->fill_vbo_indices,
- path->data->fill_vbo_attributes,
- COGL_DRAW_SKIP_JOURNAL_FLUSH |
- COGL_DRAW_SKIP_PIPELINE_VALIDATION |
- COGL_DRAW_SKIP_FRAMEBUFFER_FLUSH);
-}
-
-void
-_cogl_add_path_to_stencil_buffer (CoglPath *path,
- gboolean merge,
- gboolean need_clear)
-{
- CoglPathData *data = path->data;
- CoglFramebuffer *framebuffer = cogl_get_draw_framebuffer ();
- CoglMatrixStack *modelview_stack =
- _cogl_framebuffer_get_modelview_stack (framebuffer);
- CoglMatrixStack *projection_stack =
- _cogl_framebuffer_get_projection_stack (framebuffer);
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- /* This can be called from the clip stack code which doesn't flush
- the matrix stacks between calls so we need to ensure they're
- flushed now */
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- /* Just setup a simple pipeline that doesn't use texturing... */
- cogl_push_source (ctx->stencil_pipeline);
-
- _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE, 0);
-
- GE( glEnable (GL_STENCIL_TEST) );
-
- GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
- GE( glDepthMask (FALSE) );
-
- if (merge)
- {
- GE (glStencilMask (2));
- GE (glStencilFunc (GL_LEQUAL, 0x2, 0x6));
- }
- else
- {
- /* If we're not using the stencil buffer for clipping then we
- don't need to clear the whole stencil buffer, just the area
- that will be drawn */
- if (need_clear)
- /* If this is being called from the clip stack code then it
- will have set up a scissor for the minimum bounding box of
- all of the clips. That box will likely mean that this
- _cogl_clear won't need to clear the entire
- buffer. _cogl_clear4f is used instead of cogl_clear because
- it won't try to flush the journal */
- _cogl_clear4f (COGL_BUFFER_BIT_STENCIL, 0, 0, 0, 0);
- else
- {
- /* Just clear the bounding box */
- GE( glStencilMask (~(GLuint) 0) );
- GE( glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
- _cogl_rectangle_immediate (data->path_nodes_min.x,
- data->path_nodes_min.y,
- data->path_nodes_max.x,
- data->path_nodes_max.y);
- }
- GE (glStencilMask (1));
- GE (glStencilFunc (GL_LEQUAL, 0x1, 0x3));
- }
-
- GE (glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT));
-
- if (path->data->path_nodes->len >= 3)
- _cogl_path_fill_nodes (path);
-
- if (merge)
- {
- /* Now we have the new stencil buffer in bit 1 and the old
- stencil buffer in bit 0 so we need to intersect them */
- GE (glStencilMask (3));
- GE (glStencilFunc (GL_NEVER, 0x2, 0x3));
- GE (glStencilOp (GL_DECR, GL_DECR, GL_DECR));
- /* Decrement all of the bits twice so that only pixels where the
- value is 3 will remain */
-
- _cogl_matrix_stack_push (projection_stack);
- _cogl_matrix_stack_load_identity (projection_stack);
- _cogl_matrix_stack_flush_to_gl (projection_stack,
- COGL_MATRIX_PROJECTION);
-
- _cogl_matrix_stack_push (modelview_stack);
- _cogl_matrix_stack_load_identity (modelview_stack);
- _cogl_matrix_stack_flush_to_gl (modelview_stack,
- COGL_MATRIX_MODELVIEW);
-
- _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
- _cogl_rectangle_immediate (-1.0, -1.0, 1.0, 1.0);
-
- _cogl_matrix_stack_pop (modelview_stack);
- _cogl_matrix_stack_pop (projection_stack);
- }
-
- GE (glStencilMask (~(GLuint) 0));
- GE (glDepthMask (TRUE));
- GE (glColorMask (TRUE, TRUE, TRUE, TRUE));
-
- GE (glStencilFunc (GL_EQUAL, 0x1, 0x1));
- GE (glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP));
-
- /* restore the original pipeline */
- cogl_pop_source ();
-}
-
-void
-cogl2_path_fill (CoglPath *path)
-{
- CoglFramebuffer *framebuffer;
-
- g_return_if_fail (cogl_is_path (path));
-
- if (path->data->path_nodes->len == 0)
- return;
-
- /* If the path is a simple rectangle then we can divert to using
- cogl_rectangle which should be faster because it can go through
- the journal instead of uploading the geometry just for two
- triangles */
- if (path->data->is_rectangle)
- {
- float x_1, y_1, x_2, y_2;
-
- _cogl_path_get_bounds (path, &x_1, &y_1, &x_2, &y_2);
- cogl_rectangle (x_1, y_1, x_2, y_2);
- }
- else
- {
- framebuffer = cogl_get_draw_framebuffer ();
-
- _cogl_framebuffer_flush_journal (framebuffer);
-
- /* NB: _cogl_framebuffer_flush_state may disrupt various state (such
- * as the pipeline state) when flushing the clip stack, so should
- * always be done first when preparing to draw. */
- _cogl_framebuffer_flush_state (framebuffer,
- _cogl_get_read_framebuffer (),
- 0);
-
- _cogl_path_fill_nodes (path);
- }
-}
-
-void
-cogl2_path_stroke (CoglPath *path)
-{
- g_return_if_fail (cogl_is_path (path));
-
- if (path->data->path_nodes->len == 0)
- return;
-
- _cogl_path_stroke_nodes (path);
-}
-
-void
-cogl2_path_move_to (CoglPath *path,
- float x,
- float y)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- _cogl_path_add_node (path, TRUE, x, y);
-
- data = path->data;
-
- data->path_start.x = x;
- data->path_start.y = y;
-
- data->path_pen = data->path_start;
-}
-
-void
-cogl2_path_rel_move_to (CoglPath *path,
- float x,
- float y)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- data = path->data;
-
- cogl2_path_move_to (path,
- data->path_pen.x + x,
- data->path_pen.y + y);
-}
-
-void
-cogl2_path_line_to (CoglPath *path,
- float x,
- float y)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- _cogl_path_add_node (path, FALSE, x, y);
-
- data = path->data;
-
- data->path_pen.x = x;
- data->path_pen.y = y;
-}
-
-void
-cogl2_path_rel_line_to (CoglPath *path,
- float x,
- float y)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- data = path->data;
-
- cogl2_path_line_to (path,
- data->path_pen.x + x,
- data->path_pen.y + y);
-}
-
-void
-cogl2_path_close (CoglPath *path)
-{
- g_return_if_fail (cogl_is_path (path));
-
- _cogl_path_add_node (path, FALSE, path->data->path_start.x,
- path->data->path_start.y);
-
- path->data->path_pen = path->data->path_start;
-}
-
-void
-cogl2_path_line (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- cogl2_path_move_to (path, x_1, y_1);
- cogl2_path_line_to (path, x_2, y_2);
-}
-
-void
-cogl2_path_polyline (CoglPath *path,
- const float *coords,
- int num_points)
-{
- int c = 0;
-
- g_return_if_fail (cogl_is_path (path));
-
- cogl2_path_move_to (path, coords[0], coords[1]);
-
- for (c = 1; c < num_points; ++c)
- cogl2_path_line_to (path, coords[2*c], coords[2*c+1]);
-}
-
-void
-cogl2_path_polygon (CoglPath *path,
- const float *coords,
- int num_points)
-{
- cogl2_path_polyline (path, coords, num_points);
- cogl2_path_close (path);
-}
-
-void
-cogl2_path_rectangle (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- gboolean is_rectangle;
-
- /* If the path was previously empty and the rectangle isn't mirrored
- then we'll record that this is a simple rectangle path so that we
- can optimise it */
- is_rectangle = (path->data->path_nodes->len == 0 &&
- x_2 >= x_1 &&
- y_2 >= y_1);
-
- cogl2_path_move_to (path, x_1, y_1);
- cogl2_path_line_to (path, x_2, y_1);
- cogl2_path_line_to (path, x_2, y_2);
- cogl2_path_line_to (path, x_1, y_2);
- cogl2_path_close (path);
-
- path->data->is_rectangle = is_rectangle;
-}
-
-gboolean
-_cogl_path_is_rectangle (CoglPath *path)
-{
- return path->data->is_rectangle;
-}
-
-static void
-_cogl_path_arc (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2,
- float angle_step,
- unsigned int move_first)
-{
- float a = 0x0;
- float cosa = 0x0;
- float sina = 0x0;
- float px = 0x0;
- float py = 0x0;
-
- /* Fix invalid angles */
-
- if (angle_1 == angle_2 || angle_step == 0x0)
- return;
-
- if (angle_step < 0x0)
- angle_step = -angle_step;
-
- /* Walk the arc by given step */
-
- a = angle_1;
- while (a != angle_2)
- {
- cosa = cosf (a * (G_PI/180.0));
- sina = sinf (a * (G_PI/180.0));
-
- px = center_x + (cosa * radius_x);
- py = center_y + (sina * radius_y);
-
- if (a == angle_1 && move_first)
- cogl2_path_move_to (path, px, py);
- else
- cogl2_path_line_to (path, px, py);
-
- if (G_LIKELY (angle_2 > angle_1))
- {
- a += angle_step;
- if (a > angle_2)
- a = angle_2;
- }
- else
- {
- a -= angle_step;
- if (a < angle_2)
- a = angle_2;
- }
- }
-
- /* Make sure the final point is drawn */
-
- cosa = cosf (angle_2 * (G_PI/180.0));
- sina = sinf (angle_2 * (G_PI/180.0));
-
- px = center_x + (cosa * radius_x);
- py = center_y + (sina * radius_y);
-
- cogl2_path_line_to (path, px, py);
-}
-
-void
-cogl2_path_arc (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2)
-{
- float angle_step = 10;
-
- g_return_if_fail (cogl_is_path (path));
-
- /* it is documented that a move to is needed to create a freestanding
- * arc
- */
- _cogl_path_arc (path,
- center_x, center_y,
- radius_x, radius_y,
- angle_1, angle_2,
- angle_step, 0 /* no move */);
-}
-
-
-static void
-_cogl_path_rel_arc (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2,
- float angle_step)
-{
- CoglPathData *data;
-
- data = path->data;
-
- _cogl_path_arc (path,
- data->path_pen.x + center_x,
- data->path_pen.y + center_y,
- radius_x, radius_y,
- angle_1, angle_2,
- angle_step, 0 /* no move */);
-}
-
-void
-cogl2_path_ellipse (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y)
-{
- float angle_step = 10;
-
- g_return_if_fail (cogl_is_path (path));
-
- /* FIXME: if shows to be slow might be optimized
- * by mirroring just a quarter of it */
-
- _cogl_path_arc (path,
- center_x, center_y,
- radius_x, radius_y,
- 0, 360,
- angle_step, 1 /* move first */);
-
- cogl2_path_close (path);
-}
-
-void
-cogl2_path_round_rectangle (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float radius,
- float arc_step)
-{
- float inner_width = x_2 - x_1 - radius * 2;
- float inner_height = y_2 - y_1 - radius * 2;
-
- g_return_if_fail (cogl_is_path (path));
-
- cogl2_path_move_to (path, x_1, y_1 + radius);
- _cogl_path_rel_arc (path,
- radius, 0,
- radius, radius,
- 180,
- 270,
- arc_step);
-
- cogl2_path_line_to (path,
- path->data->path_pen.x + inner_width,
- path->data->path_pen.y);
- _cogl_path_rel_arc (path,
- 0, radius,
- radius, radius,
- -90,
- 0,
- arc_step);
-
- cogl2_path_line_to (path,
- path->data->path_pen.x,
- path->data->path_pen.y + inner_height);
-
- _cogl_path_rel_arc (path,
- -radius, 0,
- radius, radius,
- 0,
- 90,
- arc_step);
-
- cogl2_path_line_to (path,
- path->data->path_pen.x - inner_width,
- path->data->path_pen.y);
- _cogl_path_rel_arc (path,
- 0, -radius,
- radius, radius,
- 90,
- 180,
- arc_step);
-
- cogl2_path_close (path);
-}
-
-static void
-_cogl_path_bezier3_sub (CoglPath *path,
- CoglBezCubic *cubic)
-{
- CoglBezCubic cubics[_COGL_MAX_BEZ_RECURSE_DEPTH];
- CoglBezCubic *cleft;
- CoglBezCubic *cright;
- CoglBezCubic *c;
- floatVec2 dif1;
- floatVec2 dif2;
- floatVec2 mm;
- floatVec2 c1;
- floatVec2 c2;
- floatVec2 c3;
- floatVec2 c4;
- floatVec2 c5;
- int cindex;
-
- /* Put first curve on stack */
- cubics[0] = *cubic;
- cindex = 0;
-
- while (cindex >= 0)
- {
- c = &cubics[cindex];
-
-
- /* Calculate distance of control points from their
- * counterparts on the line between end points */
- dif1.x = (c->p2.x * 3) - (c->p1.x * 2) - c->p4.x;
- dif1.y = (c->p2.y * 3) - (c->p1.y * 2) - c->p4.y;
- dif2.x = (c->p3.x * 3) - (c->p4.x * 2) - c->p1.x;
- dif2.y = (c->p3.y * 3) - (c->p4.y * 2) - c->p1.y;
-
- if (dif1.x < 0)
- dif1.x = -dif1.x;
- if (dif1.y < 0)
- dif1.y = -dif1.y;
- if (dif2.x < 0)
- dif2.x = -dif2.x;
- if (dif2.y < 0)
- dif2.y = -dif2.y;
-
-
- /* Pick the greatest of two distances */
- if (dif1.x < dif2.x) dif1.x = dif2.x;
- if (dif1.y < dif2.y) dif1.y = dif2.y;
-
- /* Cancel if the curve is flat enough */
- if (dif1.x + dif1.y <= 1.0 ||
- cindex == _COGL_MAX_BEZ_RECURSE_DEPTH-1)
- {
- /* Add subdivision point (skip last) */
- if (cindex == 0)
- return;
-
- _cogl_path_add_node (path, FALSE, c->p4.x, c->p4.y);
-
- --cindex;
-
- continue;
- }
-
- /* Left recursion goes on top of stack! */
- cright = c; cleft = &cubics[++cindex];
-
- /* Subdivide into 2 sub-curves */
- c1.x = ((c->p1.x + c->p2.x) / 2);
- c1.y = ((c->p1.y + c->p2.y) / 2);
- mm.x = ((c->p2.x + c->p3.x) / 2);
- mm.y = ((c->p2.y + c->p3.y) / 2);
- c5.x = ((c->p3.x + c->p4.x) / 2);
- c5.y = ((c->p3.y + c->p4.y) / 2);
-
- c2.x = ((c1.x + mm.x) / 2);
- c2.y = ((c1.y + mm.y) / 2);
- c4.x = ((mm.x + c5.x) / 2);
- c4.y = ((mm.y + c5.y) / 2);
-
- c3.x = ((c2.x + c4.x) / 2);
- c3.y = ((c2.y + c4.y) / 2);
-
- /* Add left recursion to stack */
- cleft->p1 = c->p1;
- cleft->p2 = c1;
- cleft->p3 = c2;
- cleft->p4 = c3;
-
- /* Add right recursion to stack */
- cright->p1 = c3;
- cright->p2 = c4;
- cright->p3 = c5;
- cright->p4 = c->p4;
- }
-}
-
-void
-cogl2_path_curve_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3)
-{
- CoglBezCubic cubic;
-
- g_return_if_fail (cogl_is_path (path));
-
- /* Prepare cubic curve */
- cubic.p1 = path->data->path_pen;
- cubic.p2.x = x_1;
- cubic.p2.y = y_1;
- cubic.p3.x = x_2;
- cubic.p3.y = y_2;
- cubic.p4.x = x_3;
- cubic.p4.y = y_3;
-
- /* Run subdivision */
- _cogl_path_bezier3_sub (path, &cubic);
-
- /* Add last point */
- _cogl_path_add_node (path, FALSE, cubic.p4.x, cubic.p4.y);
- path->data->path_pen = cubic.p4;
-}
-
-void
-cogl2_path_rel_curve_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- data = path->data;
-
- cogl2_path_curve_to (path,
- data->path_pen.x + x_1,
- data->path_pen.y + y_1,
- data->path_pen.x + x_2,
- data->path_pen.y + y_2,
- data->path_pen.x + x_3,
- data->path_pen.y + y_3);
-}
-
-CoglPath *
-cogl2_path_new (void)
-{
- CoglPath *path;
- CoglPathData *data;
-
- path = g_slice_new (CoglPath);
- data = path->data = g_slice_new (CoglPathData);
-
- data->ref_count = 1;
- data->fill_rule = COGL_PATH_FILL_RULE_EVEN_ODD;
- data->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
- data->last_path = 0;
- data->fill_vbo = COGL_INVALID_HANDLE;
- data->stroke_vbo = NULL;
- data->is_rectangle = FALSE;
-
- return _cogl_path_object_new (path);
-}
-
-CoglPath *
-cogl_path_copy (CoglPath *old_path)
-{
- CoglPath *new_path;
-
- g_return_val_if_fail (cogl_is_path (old_path), NULL);
-
- new_path = g_slice_new (CoglPath);
- new_path->data = old_path->data;
- new_path->data->ref_count++;
-
- return _cogl_path_object_new (new_path);
-}
-
-static void
-_cogl_path_free (CoglPath *path)
-{
- _cogl_path_data_unref (path->data);
- g_slice_free (CoglPath, path);
-}
-
-/* If second order beziers were needed the following code could
- * be re-enabled:
- */
-#if 0
-
-static void
-_cogl_path_bezier2_sub (CoglPath *path,
- CoglBezQuad *quad)
-{
- CoglBezQuad quads[_COGL_MAX_BEZ_RECURSE_DEPTH];
- CoglBezQuad *qleft;
- CoglBezQuad *qright;
- CoglBezQuad *q;
- floatVec2 mid;
- floatVec2 dif;
- floatVec2 c1;
- floatVec2 c2;
- floatVec2 c3;
- int qindex;
-
- /* Put first curve on stack */
- quads[0] = *quad;
- qindex = 0;
-
- /* While stack is not empty */
- while (qindex >= 0)
- {
-
- q = &quads[qindex];
-
- /* Calculate distance of control point from its
- * counterpart on the line between end points */
- mid.x = ((q->p1.x + q->p3.x) / 2);
- mid.y = ((q->p1.y + q->p3.y) / 2);
- dif.x = (q->p2.x - mid.x);
- dif.y = (q->p2.y - mid.y);
- if (dif.x < 0) dif.x = -dif.x;
- if (dif.y < 0) dif.y = -dif.y;
-
- /* Cancel if the curve is flat enough */
- if (dif.x + dif.y <= 1.0 ||
- qindex == _COGL_MAX_BEZ_RECURSE_DEPTH - 1)
- {
- /* Add subdivision point (skip last) */
- if (qindex == 0) return;
- _cogl_path_add_node (path, FALSE, q->p3.x, q->p3.y);
- --qindex; continue;
- }
-
- /* Left recursion goes on top of stack! */
- qright = q; qleft = &quads[++qindex];
-
- /* Subdivide into 2 sub-curves */
- c1.x = ((q->p1.x + q->p2.x) / 2);
- c1.y = ((q->p1.y + q->p2.y) / 2);
- c3.x = ((q->p2.x + q->p3.x) / 2);
- c3.y = ((q->p2.y + q->p3.y) / 2);
- c2.x = ((c1.x + c3.x) / 2);
- c2.y = ((c1.y + c3.y) / 2);
-
- /* Add left recursion onto stack */
- qleft->p1 = q->p1;
- qleft->p2 = c1;
- qleft->p3 = c2;
-
- /* Add right recursion onto stack */
- qright->p1 = c2;
- qright->p2 = c3;
- qright->p3 = q->p3;
- }
-}
-
-void
-cogl_path_curve2_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- CoglBezQuad quad;
-
- /* Prepare quadratic curve */
- quad.p1 = path->data->path_pen;
- quad.p2.x = x_1;
- quad.p2.y = y_1;
- quad.p3.x = x_2;
- quad.p3.y = y_2;
-
- /* Run subdivision */
- _cogl_path_bezier2_sub (&quad);
-
- /* Add last point */
- _cogl_path_add_node (FALSE, quad.p3.x, quad.p3.y);
- path->data->path_pen = quad.p3;
-}
-
-void
-cogl_rel_curve2_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2)
-{
- CoglPathData *data;
-
- g_return_if_fail (cogl_is_path (path));
-
- data = path->data;
-
- cogl_path_curve2_to (data->path_pen.x + x_1,
- data->path_pen.y + y_1,
- data->path_pen.x + x_2,
- data->path_pen.y + y_2);
-}
-
-#endif
-
-typedef struct _CoglPathTesselator CoglPathTesselator;
-typedef struct _CoglPathTesselatorVertex CoglPathTesselatorVertex;
-
-struct _CoglPathTesselator
-{
- GLUtesselator *glu_tess;
- GLenum primitive_type;
- int vertex_number;
- /* Array of CoglPathTesselatorVertex. This needs to grow when the
- combine callback is called */
- GArray *vertices;
- /* Array of integers for the indices into the vertices array. Each
- element will either be guint8, guint16 or guint32 depending on
- the number of vertices */
- GArray *indices;
- CoglIndicesType indices_type;
- /* Indices used to split fans and strips */
- int index_a, index_b;
-};
-
-struct _CoglPathTesselatorVertex
-{
- float x, y, s, t;
-};
-
-static void
-_cogl_path_tesselator_begin (GLenum type,
- CoglPathTesselator *tess)
-{
- g_assert (type == GL_TRIANGLES ||
- type == GL_TRIANGLE_FAN ||
- type == GL_TRIANGLE_STRIP);
-
- tess->primitive_type = type;
- tess->vertex_number = 0;
-}
-
-static CoglIndicesType
-_cogl_path_tesselator_get_indices_type_for_size (int n_vertices)
-{
- if (n_vertices <= 256)
- return COGL_INDICES_TYPE_UNSIGNED_BYTE;
- else if (n_vertices <= 65536)
- return COGL_INDICES_TYPE_UNSIGNED_SHORT;
- else
- return COGL_INDICES_TYPE_UNSIGNED_INT;
-}
-
-static void
-_cogl_path_tesselator_allocate_indices_array (CoglPathTesselator *tess)
-{
- switch (tess->indices_type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- tess->indices = g_array_new (FALSE, FALSE, sizeof (guint8));
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- tess->indices = g_array_new (FALSE, FALSE, sizeof (guint16));
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- tess->indices = g_array_new (FALSE, FALSE, sizeof (guint32));
- break;
- }
-}
-
-static void
-_cogl_path_tesselator_add_index (CoglPathTesselator *tess, int vertex_index)
-{
- switch (tess->indices_type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- {
- guint8 val = vertex_index;
- g_array_append_val (tess->indices, val);
- }
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- {
- guint16 val = vertex_index;
- g_array_append_val (tess->indices, val);
- }
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- {
- guint32 val = vertex_index;
- g_array_append_val (tess->indices, val);
- }
- break;
- }
-}
-
-static void
-_cogl_path_tesselator_vertex (void *vertex_data,
- CoglPathTesselator *tess)
-{
- int vertex_index;
-
- vertex_index = GPOINTER_TO_INT (vertex_data);
-
- /* This tries to convert all of the primitives into GL_TRIANGLES
- with indices to share vertices */
- switch (tess->primitive_type)
- {
- case GL_TRIANGLES:
- /* Directly use the vertex */
- _cogl_path_tesselator_add_index (tess, vertex_index);
- break;
-
- case GL_TRIANGLE_FAN:
- if (tess->vertex_number == 0)
- tess->index_a = vertex_index;
- else if (tess->vertex_number == 1)
- tess->index_b = vertex_index;
- else
- {
- /* Create a triangle with the first vertex, the previous
- vertex and this vertex */
- _cogl_path_tesselator_add_index (tess, tess->index_a);
- _cogl_path_tesselator_add_index (tess, tess->index_b);
- _cogl_path_tesselator_add_index (tess, vertex_index);
- /* Next time we will use this vertex as the previous
- vertex */
- tess->index_b = vertex_index;
- }
- break;
-
- case GL_TRIANGLE_STRIP:
- if (tess->vertex_number == 0)
- tess->index_a = vertex_index;
- else if (tess->vertex_number == 1)
- tess->index_b = vertex_index;
- else
- {
- _cogl_path_tesselator_add_index (tess, tess->index_a);
- _cogl_path_tesselator_add_index (tess, tess->index_b);
- _cogl_path_tesselator_add_index (tess, vertex_index);
- if (tess->vertex_number & 1)
- tess->index_b = vertex_index;
- else
- tess->index_a = vertex_index;
- }
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- tess->vertex_number++;
-}
-
-static void
-_cogl_path_tesselator_end (CoglPathTesselator *tess)
-{
- tess->primitive_type = GL_FALSE;
-}
-
-static void
-_cogl_path_tesselator_combine (double coords[3],
- void *vertex_data[4],
- float weight[4],
- void **out_data,
- CoglPathTesselator *tess)
-{
- CoglPathTesselatorVertex *vertex;
- CoglIndicesType new_indices_type;
- int i;
-
- /* Add a new vertex to the array */
- g_array_set_size (tess->vertices, tess->vertices->len + 1);
- vertex = &g_array_index (tess->vertices,
- CoglPathTesselatorVertex,
- tess->vertices->len - 1);
- /* The data is just the index to the vertex */
- *out_data = GINT_TO_POINTER (tess->vertices->len - 1);
- /* Set the coordinates of the new vertex */
- vertex->x = coords[0];
- vertex->y = coords[1];
- /* Generate the texture coordinates as the weighted average of the
- four incoming coordinates */
- vertex->s = 0.0f;
- vertex->t = 0.0f;
- for (i = 0; i < 4; i++)
- {
- CoglPathTesselatorVertex *old_vertex =
- &g_array_index (tess->vertices, CoglPathTesselatorVertex,
- GPOINTER_TO_INT (vertex_data[i]));
- vertex->s += old_vertex->s * weight[i];
- vertex->t += old_vertex->t * weight[i];
- }
-
- /* Check if we've reached the limit for the data type of our indices */
- new_indices_type =
- _cogl_path_tesselator_get_indices_type_for_size (tess->vertices->len);
- if (new_indices_type != tess->indices_type)
- {
- CoglIndicesType old_indices_type = new_indices_type;
- GArray *old_vertices = tess->indices;
-
- /* Copy the indices to an array of the new type */
- tess->indices_type = new_indices_type;
- _cogl_path_tesselator_allocate_indices_array (tess);
-
- switch (old_indices_type)
- {
- case COGL_INDICES_TYPE_UNSIGNED_BYTE:
- for (i = 0; i < old_vertices->len; i++)
- _cogl_path_tesselator_add_index (tess,
- g_array_index (old_vertices,
- guint8, i));
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_SHORT:
- for (i = 0; i < old_vertices->len; i++)
- _cogl_path_tesselator_add_index (tess,
- g_array_index (old_vertices,
- guint16, i));
- break;
-
- case COGL_INDICES_TYPE_UNSIGNED_INT:
- for (i = 0; i < old_vertices->len; i++)
- _cogl_path_tesselator_add_index (tess,
- g_array_index (old_vertices,
- guint32, i));
- break;
- }
-
- g_array_free (old_vertices, TRUE);
- }
-}
-
-static void
-_cogl_path_build_fill_vbo (CoglPath *path)
-{
- CoglPathTesselator tess;
- unsigned int path_start = 0;
- CoglPathData *data = path->data;
- int i;
-
- /* If we've already got a vbo then we don't need to do anything */
- if (data->fill_vbo)
- return;
-
- tess.primitive_type = FALSE;
-
- /* Generate a vertex for each point on the path */
- tess.vertices = g_array_new (FALSE, FALSE, sizeof (CoglPathTesselatorVertex));
- g_array_set_size (tess.vertices, data->path_nodes->len);
- for (i = 0; i < data->path_nodes->len; i++)
- {
- CoglPathNode *node =
- &g_array_index (data->path_nodes, CoglPathNode, i);
- CoglPathTesselatorVertex *vertex =
- &g_array_index (tess.vertices, CoglPathTesselatorVertex, i);
-
- vertex->x = node->x;
- vertex->y = node->y;
-
- /* Add texture coordinates so that a texture would be drawn to
- fit the bounding box of the path and then cropped by the
- path */
- if (data->path_nodes_min.x == data->path_nodes_max.x)
- vertex->s = 0.0f;
- else
- vertex->s = ((node->x - data->path_nodes_min.x)
- / (data->path_nodes_max.x - data->path_nodes_min.x));
- if (data->path_nodes_min.y == data->path_nodes_max.y)
- vertex->t = 0.0f;
- else
- vertex->t = ((node->y - data->path_nodes_min.y)
- / (data->path_nodes_max.y - data->path_nodes_min.y));
- }
-
- tess.indices_type =
- _cogl_path_tesselator_get_indices_type_for_size (data->path_nodes->len);
- _cogl_path_tesselator_allocate_indices_array (&tess);
-
- tess.glu_tess = gluNewTess ();
-
- if (data->fill_rule == COGL_PATH_FILL_RULE_EVEN_ODD)
- gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
- GLU_TESS_WINDING_ODD);
- else
- gluTessProperty (tess.glu_tess, GLU_TESS_WINDING_RULE,
- GLU_TESS_WINDING_NONZERO);
-
- /* All vertices are on the xy-plane */
- gluTessNormal (tess.glu_tess, 0.0, 0.0, 1.0);
-
- gluTessCallback (tess.glu_tess, GLU_TESS_BEGIN_DATA,
- _cogl_path_tesselator_begin);
- gluTessCallback (tess.glu_tess, GLU_TESS_VERTEX_DATA,
- _cogl_path_tesselator_vertex);
- gluTessCallback (tess.glu_tess, GLU_TESS_END_DATA,
- _cogl_path_tesselator_end);
- gluTessCallback (tess.glu_tess, GLU_TESS_COMBINE_DATA,
- _cogl_path_tesselator_combine);
-
- gluTessBeginPolygon (tess.glu_tess, &tess);
-
- while (path_start < data->path_nodes->len)
- {
- CoglPathNode *node =
- &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
- gluTessBeginContour (tess.glu_tess);
-
- for (i = 0; i < node->path_size; i++)
- {
- double vertex[3] = { node[i].x, node[i].y, 0.0 };
- gluTessVertex (tess.glu_tess, vertex,
- GINT_TO_POINTER (i + path_start));
- }
-
- gluTessEndContour (tess.glu_tess);
-
- path_start += node->path_size;
- }
-
- gluTessEndPolygon (tess.glu_tess);
-
- gluDeleteTess (tess.glu_tess);
-
- data->fill_vbo = cogl_vertex_array_new (sizeof (CoglPathTesselatorVertex) *
- tess.vertices->len,
- tess.vertices->data);
- g_array_free (tess.vertices, TRUE);
-
- data->fill_vbo_attributes[0] =
- cogl_attribute_new (data->fill_vbo,
- "cogl_position_in",
- sizeof (CoglPathTesselatorVertex),
- G_STRUCT_OFFSET (CoglPathTesselatorVertex, x),
- 2, /* n_components */
- COGL_ATTRIBUTE_TYPE_FLOAT);
- data->fill_vbo_attributes[1] =
- cogl_attribute_new (data->fill_vbo,
- "cogl_tex_coord0_in",
- sizeof (CoglPathTesselatorVertex),
- G_STRUCT_OFFSET (CoglPathTesselatorVertex, s),
- 2, /* n_components */
- COGL_ATTRIBUTE_TYPE_FLOAT);
- /* NULL terminator */
- data->fill_vbo_attributes[2] = NULL;
-
- data->fill_vbo_indices = cogl_indices_new (tess.indices_type,
- tess.indices->data,
- tess.indices->len);
- data->fill_vbo_n_indices = tess.indices->len;
- g_array_free (tess.indices, TRUE);
-}
-
-static void
-_cogl_path_build_stroke_vbo (CoglPath *path)
-{
- CoglPathData *data = path->data;
- unsigned int n_attributes = 0;
- unsigned int path_start;
- CoglPathNode *node;
- floatVec2 *vbo_p;
- unsigned int i;
-
- /* If we've already got a cached vbo then we don't need to do anything */
- if (data->stroke_vbo)
- return;
-
- data->stroke_vbo = cogl_vertex_array_new (data->path_nodes->len *
- sizeof (floatVec2),
- NULL);
-
- vbo_p =
- _cogl_buffer_map_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
-
- /* Copy the vertices in and count the number of sub paths. Each sub
- path will form a separate attribute so we can paint the disjoint
- line strips */
- for (path_start = 0;
- path_start < data->path_nodes->len;
- path_start += node->path_size)
- {
- node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
- for (i = 0; i < node->path_size; i++)
- {
- vbo_p[path_start + i].x = node[i].x;
- vbo_p[path_start + i].y = node[i].y;
- }
-
- n_attributes++;
- }
-
- _cogl_buffer_unmap_for_fill_or_fallback (COGL_BUFFER (data->stroke_vbo));
-
- data->stroke_vbo_attributes = g_new (CoglAttribute *, n_attributes);
-
- /* Now we can loop the sub paths again to create the attributes */
- for (i = 0, path_start = 0;
- path_start < data->path_nodes->len;
- i++, path_start += node->path_size)
- {
- node = &g_array_index (data->path_nodes, CoglPathNode, path_start);
-
- data->stroke_vbo_attributes[i] =
- cogl_attribute_new (data->stroke_vbo,
- "cogl_position_in",
- sizeof (floatVec2),
- path_start * sizeof (floatVec2),
- 2, /* n_components */
- COGL_ATTRIBUTE_TYPE_FLOAT);
- }
-
- data->stroke_vbo_n_attributes = n_attributes;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
-#error "Only <cogl/cogl.h> can be included directly."
-#endif
-
-#ifndef __COGL2_PATH_H__
-#define __COGL2_PATH_H__
-
-#include <cogl/cogl-types.h>
-
-G_BEGIN_DECLS
-
-/**
- * SECTION:cogl-paths
- * @short_description: Functions for constructing and drawing 2D paths.
- *
- * There are two levels on which drawing with cogl-paths can be used.
- * The highest level functions construct various simple primitive
- * shapes to be either filled or stroked. Using a lower-level set of
- * functions more complex and arbitrary paths can be constructed by
- * concatenating straight line, bezier curve and arc segments.
- *
- * When constructing arbitrary paths, the current pen location is
- * initialized using the move_to command. The subsequent path segments
- * implicitly use the last pen location as their first vertex and move
- * the pen location to the last vertex they produce at the end. Also
- * there are special versions of functions that allow specifying the
- * vertices of the path segments relative to the last pen location
- * rather then in the absolute coordinates.
- */
-
-typedef struct _CoglPath CoglPath;
-
-#define COGL_PATH(obj) ((CoglPath *)(obj))
-
-#define cogl_path_new cogl2_path_new
-/**
- * cogl_path_new:
- *
- * Creates a new, empty path object. The default fill rule is
- * %COGL_PATH_FILL_RULE_EVEN_ODD.
- *
- * Return value: A pointer to a newly allocated #CoglPath, which can
- * be freed using cogl_object_unref().
- *
- * Since: 2.0
- */
-CoglPath *
-cogl_path_new (void);
-
-/**
- * cogl_path_copy:
- * @path: A #CoglPath object
- *
- * Returns a new copy of the path in @path. The new path has a
- * reference count of 1 so you should unref it with
- * cogl_object_unref() if you no longer need it.
- *
- * Internally the path will share the data until one of the paths is
- * modified so copying paths should be relatively cheap.
- *
- * Return value: a copy of the path in @path.
- *
- * Since: 2.0
- */
-CoglPath *
-cogl_path_copy (CoglPath *path);
-
-/**
- * cogl_is_path:
- * @object: A #CoglObject
- *
- * Gets whether the given object references an existing path object.
- *
- * Return value: %TRUE if the object references a #CoglPath,
- * %FALSE otherwise.
- *
- * Since: 2.0
- */
-gboolean
-cogl_is_path (void *object);
-
-#define cogl_path_move_to cogl2_path_move_to
-/**
- * cogl_path_move_to:
- * @x: X coordinate of the pen location to move to.
- * @y: Y coordinate of the pen location to move to.
- *
- * Moves the pen to the given location. If there is an existing path
- * this will start a new disjoint subpath.
- *
- * Since: 2.0
- */
-void
-cogl_path_move_to (CoglPath *path,
- float x,
- float y);
-
-#define cogl_path_rel_move_to cogl2_path_rel_move_to
-/**
- * cogl_path_rel_move_to:
- * @x: X offset from the current pen location to move the pen to.
- * @y: Y offset from the current pen location to move the pen to.
- *
- * Moves the pen to the given offset relative to the current pen
- * location. If there is an existing path this will start a new
- * disjoint subpath.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_move_to (CoglPath *path,
- float x,
- float y);
-
-#define cogl_path_line_to cogl2_path_line_to
-/**
- * cogl_path_line_to:
- * @x: X coordinate of the end line vertex
- * @y: Y coordinate of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates.
- *
- * Since: 2.0
- */
-void
-cogl_path_line_to (CoglPath *path,
- float x,
- float y);
-
-#define cogl_path_rel_line_to cogl2_path_rel_line_to
-/**
- * cogl_path_rel_line_to:
- * @x: X offset from the current pen location of the end line vertex
- * @y: Y offset from the current pen location of the end line vertex
- *
- * Adds a straight line segment to the current path that ends at the
- * given coordinates relative to the current pen location.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_line_to (CoglPath *path,
- float x,
- float y);
-
-#define cogl_path_arc cogl2_path_arc
-/**
- * cogl_path_arc:
- * @center_x: X coordinate of the elliptical arc center
- * @center_y: Y coordinate of the elliptical arc center
- * @radius_x: X radius of the elliptical arc
- * @radius_y: Y radius of the elliptical arc
- * @angle_1: Angle in degrees at which the arc begin
- * @angle_2: Angle in degrees at which the arc ends
- *
- * Adds an elliptical arc segment to the current path. A straight line
- * segment will link the current pen location with the first vertex
- * of the arc. If you perform a move_to to the arcs start just before
- * drawing it you create a free standing arc.
- *
- * The angles are measured in degrees where 0° is in the direction of
- * the positive X axis and 90° is in the direction of the positive Y
- * axis. The angle of the arc begins at @angle_1 and heads towards
- * @angle_2 (so if @angle_2 is less than @angle_1 it will decrease,
- * otherwise it will increase).
- *
- * Since: 2.0
- */
-void
-cogl_path_arc (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y,
- float angle_1,
- float angle_2);
-
-#define cogl_path_curve_to cogl2_path_curve_to
-/**
- * cogl_path_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point.
- *
- * Since: 2.0
- */
-void
-cogl_path_curve_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3);
-
-#define cogl_path_rel_curve_to cogl2_path_rel_curve_to
-/**
- * cogl_path_rel_curve_to:
- * @x_1: X coordinate of the second bezier control point
- * @y_1: Y coordinate of the second bezier control point
- * @x_2: X coordinate of the third bezier control point
- * @y_2: Y coordinate of the third bezier control point
- * @x_3: X coordinate of the fourth bezier control point
- * @y_3: Y coordinate of the fourth bezier control point
- *
- * Adds a cubic bezier curve segment to the current path with the given
- * second, third and fourth control points and using current pen location
- * as the first control point. The given coordinates are relative to the
- * current pen location.
- *
- * Since: 2.0
- */
-void
-cogl_path_rel_curve_to (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float x_3,
- float y_3);
-
-#define cogl_path_close cogl2_path_close
-/**
- * cogl_path_close:
- *
- * Closes the path being constructed by adding a straight line segment
- * to it that ends at the first vertex of the path.
- *
- * Since: 2.0
- */
-void
-cogl_path_close (CoglPath *path);
-
-#define cogl_path_line cogl2_path_line
-/**
- * cogl_path_line:
- * @x_1: X coordinate of the start line vertex
- * @y_1: Y coordinate of the start line vertex
- * @x_2: X coordinate of the end line vertex
- * @y_2: Y coordinate of the end line vertex
- *
- * Constructs a straight line shape starting and ending at the given
- * coordinates. If there is an existing path this will start a new
- * disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_line (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-#define cogl_path_polyline cogl2_path_polyline
-/**
- * cogl_path_polyline:
- * @coords: (in) (array) (transfer none): A pointer to the first element of an
- * array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a series of straight line segments, starting from the
- * first given vertex coordinate. If there is an existing path this
- * will start a new disjoint sub-path. Each subsequent segment starts
- * where the previous one ended and ends at the next given vertex
- * coordinate.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices. (num_points - 1) segments will
- * be constructed.
- *
- * Since: 2.0
- */
-void
-cogl_path_polyline (CoglPath *path,
- const float *coords,
- int num_points);
-
-#define cogl_path_polygon cogl2_path_polygon
-/**
- * cogl_path_polygon:
- * @coords: (in) (array) (transfer none): A pointer to the first element of
- * an array of fixed-point values that specify the vertex coordinates.
- * @num_points: The total number of vertices.
- *
- * Constructs a polygonal shape of the given number of vertices. If
- * there is an existing path this will start a new disjoint sub-path.
- *
- * The coords array must contain 2 * num_points values. The first value
- * represents the X coordinate of the first vertex, the second value
- * represents the Y coordinate of the first vertex, continuing in the same
- * fashion for the rest of the vertices.
- *
- * Since: 2.0
- */
-void
-cogl_path_polygon (CoglPath *path,
- const float *coords,
- int num_points);
-
-#define cogl_path_rectangle cogl2_path_rectangle
-/**
- * cogl_path_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- *
- * Constructs a rectangular shape at the given coordinates. If there
- * is an existing path this will start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_rectangle (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2);
-
-#define cogl_path_ellipse cogl2_path_ellipse
-/**
- * cogl_path_ellipse:
- * @center_x: X coordinate of the ellipse center
- * @center_y: Y coordinate of the ellipse center
- * @radius_x: X radius of the ellipse
- * @radius_y: Y radius of the ellipse
- *
- * Constructs an ellipse shape. If there is an existing path this will
- * start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_ellipse (CoglPath *path,
- float center_x,
- float center_y,
- float radius_x,
- float radius_y);
-
-#define cogl_path_round_rectangle cogl2_path_round_rectangle
-/**
- * cogl_path_round_rectangle:
- * @x_1: X coordinate of the top-left corner.
- * @y_1: Y coordinate of the top-left corner.
- * @x_2: X coordinate of the bottom-right corner.
- * @y_2: Y coordinate of the bottom-right corner.
- * @radius: Radius of the corner arcs.
- * @arc_step: Angle increment resolution for subdivision of
- * the corner arcs.
- *
- * Constructs a rectangular shape with rounded corners. If there is an
- * existing path this will start a new disjoint sub-path.
- *
- * Since: 2.0
- */
-void
-cogl_path_round_rectangle (CoglPath *path,
- float x_1,
- float y_1,
- float x_2,
- float y_2,
- float radius,
- float arc_step);
-
-/**
- * CoglPathFillRule:
- * @COGL_PATH_FILL_RULE_NON_ZERO: Each time the line crosses an edge of
- * the path from left to right one is added to a counter and each time
- * it crosses from right to left the counter is decremented. If the
- * counter is non-zero then the point will be filled. See <xref
- * linkend="fill-rule-non-zero"/>.
- * @COGL_PATH_FILL_RULE_EVEN_ODD: If the line crosses an edge of the
- * path an odd number of times then the point will filled, otherwise
- * it won't. See <xref linkend="fill-rule-even-odd"/>.
- *
- * #CoglPathFillRule is used to determine how a path is filled. There
- * are two options - 'non-zero' and 'even-odd'. To work out whether any
- * point will be filled imagine drawing an infinetely long line in any
- * direction from that point. The number of times and the direction
- * that the edges of the path crosses this line determines whether the
- * line is filled as described below. Any open sub paths are treated
- * as if there was an extra line joining the first point and the last
- * point.
- *
- * The default fill rule is %COGL_PATH_FILL_RULE_EVEN_ODD. The fill
- * rule is attached to the current path so preserving a path with
- * cogl_get_path() also preserves the fill rule. Calling
- * cogl_path_new() resets the current fill rule to the default.
- *
- * <figure id="fill-rule-non-zero">
- * <title>Example of filling various paths using the non-zero rule</title>
- * <graphic fileref="fill-rule-non-zero.png" format="PNG"/>
- * </figure>
- *
- * <figure id="fill-rule-even-odd">
- * <title>Example of filling various paths using the even-odd rule</title>
- * <graphic fileref="fill-rule-even-odd.png" format="PNG"/>
- * </figure>
- *
- * Since: 1.4
- */
-typedef enum {
- COGL_PATH_FILL_RULE_NON_ZERO,
- COGL_PATH_FILL_RULE_EVEN_ODD
-} CoglPathFillRule;
-
-#define cogl_path_set_fill_rule cogl2_path_set_fill_rule
-/**
- * cogl_path_set_fill_rule:
- * @fill_rule: The new fill rule.
- *
- * Sets the fill rule of the current path to @fill_rule. This will
- * affect how the path is filled when cogl_path_fill() is later
- * called. Note that the fill rule state is attached to the path so
- * calling cogl_get_path() will preserve the fill rule and calling
- * cogl_path_new() will reset the fill rule back to the default.
- *
- * Since: 2.0
- */
-void
-cogl_path_set_fill_rule (CoglPath *path, CoglPathFillRule fill_rule);
-
-#define cogl_path_get_fill_rule cogl2_path_get_fill_rule
-/**
- * cogl_path_get_fill_rule:
- *
- * Retrieves the fill rule set using cogl_path_set_fill_rule().
- *
- * Return value: the fill rule that is used for the current path.
- *
- * Since: 2.0
- */
-CoglPathFillRule
-cogl_path_get_fill_rule (CoglPath *path);
-
-#define cogl_path_fill cogl2_path_fill
-/**
- * cogl_path_fill:
- *
- * Fills the interior of the constructed shape using the current
- * drawing color.
- *
- * The interior of the shape is determined using the fill rule of the
- * path. See %CoglPathFillRule for details.
- *
- * <note>The result of referencing sliced textures in your current
- * pipeline when filling a path are undefined. You should pass
- * the %COGL_TEXTURE_NO_SLICING flag when loading any texture you will
- * use while filling a path.</note>
- *
- * Since: 2.0
- */
-void
-cogl_path_fill (CoglPath *path);
-
-#define cogl_path_stroke cogl2_path_stroke
-/**
- * cogl_path_stroke:
- *
- * Strokes the constructed shape using the current drawing color and a
- * width of 1 pixel (regardless of the current transformation
- * matrix).
- *
- * Since: 2.0
- */
-void
-cogl_path_stroke (CoglPath *path);
-
-G_END_DECLS
-
-#endif /* __COGL2_PATH_H__ */
-
+++ /dev/null
-include $(top_srcdir)/build/autotools/Makefile.am.silent
-
-NULL =
-
-SUBDIRS = $(COGL_DRIVER)
-
-DIST_SUBDIRS = gl gles
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_CONTEXT_DRIVER_H
-#define __COGL_CONTEXT_DRIVER_H
-
-#include "cogl.h"
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-
-#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
-
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- ret (APIENTRY * pf_ ## name) args;
-
-#define COGL_FEATURE_END()
-
-typedef struct _CoglContextDriver
-{
- /* This defines a list of function pointers */
-#include "cogl-feature-functions-gl.h"
-
- GLint gl_max_program_temoraries_arb;
-} CoglContextDriver;
-
-#undef COGL_FEATURE_BEGIN
-#undef COGL_FEATURE_FUNCTION
-#undef COGL_FEATURE_END
-
-#endif /* __COGL_CONTEXT_DRIVER_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This is included multiple times with different definitions for
- these macros */
-
-COGL_FEATURE_BEGIN (offscreen, 255, 255,
- /* for some reason the ARB version of this
- extension doesn't have an ARB suffix for the
- functions */
- "ARB:\0EXT\0",
- "framebuffer_object\0",
- COGL_FEATURE_OFFSCREEN,
- 0)
-COGL_FEATURE_FUNCTION (void, glGenRenderbuffers,
- (GLsizei n,
- GLuint *renderbuffers))
-COGL_FEATURE_FUNCTION (void, glDeleteRenderbuffers,
- (GLsizei n,
- const GLuint *renderbuffers))
-COGL_FEATURE_FUNCTION (void, glBindRenderbuffer,
- (GLenum target,
- GLuint renderbuffer))
-COGL_FEATURE_FUNCTION (void, glRenderbufferStorage,
- (GLenum target,
- GLenum internalformat,
- GLsizei width,
- GLsizei height))
-COGL_FEATURE_FUNCTION (void, glGenFramebuffers,
- (GLsizei n,
- GLuint *framebuffers))
-COGL_FEATURE_FUNCTION (void, glBindFramebuffer,
- (GLenum target,
- GLuint framebuffer))
-COGL_FEATURE_FUNCTION (void, glFramebufferTexture2D,
- (GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level))
-COGL_FEATURE_FUNCTION (void, glFramebufferRenderbuffer,
- (GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer))
-COGL_FEATURE_FUNCTION (GLenum, glCheckFramebufferStatus,
- (GLenum target))
-COGL_FEATURE_FUNCTION (void, glDeleteFramebuffers,
- (GLsizei n,
- const GLuint *framebuffers))
-COGL_FEATURE_FUNCTION (void, glGenerateMipmap,
- (GLenum target))
-COGL_FEATURE_FUNCTION (void, glGetFramebufferAttachmentParameteriv,
- (GLenum target,
- GLenum attachment,
- GLenum pname,
- GLint *params))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (offscreen_blit, 255, 255,
- "EXT\0",
- "framebuffer_blit\0",
- COGL_FEATURE_OFFSCREEN_BLIT,
- 0)
-COGL_FEATURE_FUNCTION (void, glBlitFramebuffer,
- (GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1,
- GLbitfield mask,
- GLenum filter))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (offscreen_multisample, 255, 255,
- "EXT\0",
- "framebuffer_multisample\0",
- COGL_FEATURE_OFFSCREEN_MULTISAMPLE,
- 0)
-COGL_FEATURE_FUNCTION (void, glRenderbufferStorageMultisample,
- (GLenum target,
- GLsizei samples,
- GLenum internalformat,
- GLsizei width,
- GLsizei height))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (read_pixels_async, 2, 1,
- "EXT\0",
- "pixel_buffer_object\0",
- COGL_FEATURE_PBOS,
- 0)
-COGL_FEATURE_END ()
-
-/* ARB_fragment_program */
-COGL_FEATURE_BEGIN (arbfp, 255, 255,
- "ARB\0",
- "fragment_program\0",
- COGL_FEATURE_SHADERS_ARBFP,
- 0)
-COGL_FEATURE_FUNCTION (void, glGenPrograms,
- (GLsizei n,
- GLuint *programs))
-COGL_FEATURE_FUNCTION (void, glDeletePrograms,
- (GLsizei n,
- GLuint *programs))
-COGL_FEATURE_FUNCTION (void, glBindProgram,
- (GLenum target,
- GLuint program))
-COGL_FEATURE_FUNCTION (void, glProgramString,
- (GLenum target,
- GLenum format,
- GLsizei len,
- const void *program))
-COGL_FEATURE_FUNCTION (void, glProgramLocalParameter4fv,
- (GLenum target,
- GLuint index,
- GLfloat *params))
-COGL_FEATURE_END ()
-
-/* The function names in OpenGL 2.0 are different so we can't easily
- just check for GL 2.0 */
-COGL_FEATURE_BEGIN (shaders_glsl, 2, 0,
- "\0",
- "\0",
- COGL_FEATURE_SHADERS_GLSL,
- 0)
-COGL_FEATURE_FUNCTION (GLuint, glCreateProgram,
- (void))
-COGL_FEATURE_FUNCTION (GLuint, glCreateShader,
- (GLenum shaderType))
-COGL_FEATURE_FUNCTION (void, glShaderSource,
- (GLuint shader,
- GLsizei count,
- const GLchar **string,
- const GLint *length))
-COGL_FEATURE_FUNCTION (void, glCompileShader,
- (GLuint shader))
-COGL_FEATURE_FUNCTION (void, glDeleteShader,
- (GLuint shader))
-COGL_FEATURE_FUNCTION (void, glAttachShader,
- (GLuint program,
- GLuint shader))
-COGL_FEATURE_FUNCTION (void, glLinkProgram,
- (GLuint program))
-COGL_FEATURE_FUNCTION (void, glUseProgram,
- (GLuint program))
-COGL_FEATURE_FUNCTION (GLint, glGetUniformLocation,
- (GLuint program,
- const GLchar *name))
-COGL_FEATURE_FUNCTION (void, glDeleteProgram,
- (GLuint program))
-COGL_FEATURE_FUNCTION (void, glGetShaderInfoLog,
- (GLuint shader,
- GLsizei maxLength,
- GLsizei *length,
- GLchar *infoLog))
-COGL_FEATURE_FUNCTION (void, glGetShaderiv,
- (GLuint shader,
- GLenum pname,
- GLint *params))
-
-COGL_FEATURE_FUNCTION (void, glVertexAttribPointer,
- (GLuint index,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- const GLvoid *pointer))
-COGL_FEATURE_FUNCTION (void, glEnableVertexAttribArray,
- (GLuint index))
-COGL_FEATURE_FUNCTION (void, glDisableVertexAttribArray,
- (GLuint index))
-
-COGL_FEATURE_FUNCTION (void, glUniform1f,
- (GLint location,
- GLfloat v0))
-COGL_FEATURE_FUNCTION (void, glUniform2f,
- (GLint location,
- GLfloat v0,
- GLfloat v1))
-COGL_FEATURE_FUNCTION (void, glUniform3f,
- (GLint location,
- GLfloat v0,
- GLfloat v1,
- GLfloat v2))
-COGL_FEATURE_FUNCTION (void, glUniform4f,
- (GLint location,
- GLfloat v0,
- GLfloat v1,
- GLfloat v2,
- GLfloat v3))
-COGL_FEATURE_FUNCTION (void, glUniform1fv,
- (GLint location,
- GLsizei count,
- const GLfloat * value))
-COGL_FEATURE_FUNCTION (void, glUniform2fv,
- (GLint location,
- GLsizei count,
- const GLfloat * value))
-COGL_FEATURE_FUNCTION (void, glUniform3fv,
- (GLint location,
- GLsizei count,
- const GLfloat * value))
-COGL_FEATURE_FUNCTION (void, glUniform4fv,
- (GLint location,
- GLsizei count,
- const GLfloat * value))
-COGL_FEATURE_FUNCTION (void, glUniform1i,
- (GLint location,
- GLint v0))
-COGL_FEATURE_FUNCTION (void, glUniform2i,
- (GLint location,
- GLint v0,
- GLint v1))
-COGL_FEATURE_FUNCTION (void, glUniform3i,
- (GLint location,
- GLint v0,
- GLint v1,
- GLint v2))
-COGL_FEATURE_FUNCTION (void, glUniform4i,
- (GLint location,
- GLint v0,
- GLint v1,
- GLint v2,
- GLint v3))
-COGL_FEATURE_FUNCTION (void, glUniform1iv,
- (GLint location,
- GLsizei count,
- const GLint * value))
-COGL_FEATURE_FUNCTION (void, glUniform2iv,
- (GLint location,
- GLsizei count,
- const GLint * value))
-COGL_FEATURE_FUNCTION (void, glUniform3iv,
- (GLint location,
- GLsizei count,
- const GLint * value))
-COGL_FEATURE_FUNCTION (void, glUniform4iv,
- (GLint location,
- GLsizei count,
- const GLint * value))
-COGL_FEATURE_FUNCTION (void, glUniformMatrix2fv,
- (GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value))
-COGL_FEATURE_FUNCTION (void, glUniformMatrix3fv,
- (GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value))
-COGL_FEATURE_FUNCTION (void, glUniformMatrix4fv,
- (GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value))
-
-COGL_FEATURE_FUNCTION (void, glGetProgramiv,
- (GLuint program,
- GLenum pname,
- GLint *params))
-
-COGL_FEATURE_FUNCTION (void, glGetProgramInfoLog,
- (GLuint program,
- GLsizei bufSize,
- GLsizei *length,
- GLchar *infoLog))
-
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (vbos, 1, 5,
- "ARB\0",
- "vertex_buffer_object\0",
- COGL_FEATURE_VBOS |
- COGL_FEATURE_MAP_BUFFER_FOR_READ |
- COGL_FEATURE_MAP_BUFFER_FOR_WRITE,
- 0)
-COGL_FEATURE_FUNCTION (void, glGenBuffers,
- (GLuint n,
- GLuint *buffers))
-COGL_FEATURE_FUNCTION (void, glBindBuffer,
- (GLenum target,
- GLuint buffer))
-COGL_FEATURE_FUNCTION (void, glBufferData,
- (GLenum target,
- GLsizeiptr size,
- const GLvoid *data,
- GLenum usage))
-COGL_FEATURE_FUNCTION (void, glBufferSubData,
- (GLenum target,
- GLintptr offset,
- GLsizeiptr size,
- const GLvoid *data))
-COGL_FEATURE_FUNCTION (void *, glMapBuffer,
- (GLenum target,
- GLenum access))
-COGL_FEATURE_FUNCTION (GLboolean, glUnmapBuffer,
- (GLenum target))
-COGL_FEATURE_FUNCTION (void, glDeleteBuffers,
- (GLsizei n,
- const GLuint *buffers))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (texture_rectangle, 255, 255,
- "ARB\0",
- "texture_rectangle\0",
- COGL_FEATURE_TEXTURE_RECTANGLE,
- 0)
-COGL_FEATURE_END ()
-
-/* Cogl requires OpenGL 1.2 so we assume these functions are always
- available and don't bother setting any feature flags. We still have
- to fetch the function pointers though because under Windows you can
- not call any function defined after GL 1.1 directly */
-COGL_FEATURE_BEGIN (in_1_2, 1, 2,
- "\0",
- "\0",
- 0,
- 0)
-COGL_FEATURE_FUNCTION (void, glDrawRangeElements,
- (GLenum mode,
- GLuint start,
- GLuint end,
- GLsizei count,
- GLenum type,
- const GLvoid *indices))
-COGL_FEATURE_FUNCTION (void, glBlendEquation,
- (GLenum mode))
-COGL_FEATURE_FUNCTION (void, glBlendColor,
- (GLclampf red,
- GLclampf green,
- GLclampf blue,
- GLclampf alpha))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (texture_3d, 1, 2,
- "\0",
- "\0",
- COGL_FEATURE_TEXTURE_3D,
- 0)
-COGL_FEATURE_FUNCTION (void, glTexImage3D,
- (GLenum target, GLint level,
- GLint internalFormat,
- GLsizei width, GLsizei height,
- GLsizei depth, GLint border,
- GLenum format, GLenum type,
- const GLvoid *pixels))
-COGL_FEATURE_FUNCTION (void, glTexSubImage3D,
- (GLenum target, GLint level,
- GLint xoffset, GLint yoffset,
- GLint zoffset, GLsizei width,
- GLsizei height, GLsizei depth,
- GLenum format,
- GLenum type, const GLvoid *pixels))
-COGL_FEATURE_END ()
-
-/* Available in GL 1.3 or the multitexture extension. These are
- required */
-COGL_FEATURE_BEGIN (multitexture, 1, 3,
- "ARB\0",
- "multitexture\0",
- 0,
- 0)
-COGL_FEATURE_FUNCTION (void, glActiveTexture,
- (GLenum texture))
-COGL_FEATURE_FUNCTION (void, glClientActiveTexture,
- (GLenum texture))
-COGL_FEATURE_END ()
-
-/* Optional, declared in 1.4 */
-COGL_FEATURE_BEGIN (blend_func_separate, 1, 4,
- "EXT\0",
- "blend_func_separate\0",
- 0,
- 0)
-COGL_FEATURE_FUNCTION (void, glBlendFuncSeparate,
- (GLenum srcRGB,
- GLenum dstRGB,
- GLenum srcAlpha,
- GLenum dstAlpha))
-COGL_FEATURE_END ()
-
-/* Optional, declared in 2.0 */
-COGL_FEATURE_BEGIN (blend_equation_separate, 2, 0,
- "EXT\0",
- "blend_equation_separate\0",
- 0,
- 0)
-COGL_FEATURE_FUNCTION (void, glBlendEquationSeparate,
- (GLenum modeRGB,
- GLenum modeAlpha))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (point_sprites, 2, 0,
- "ARB\0",
- "point_sprite\0",
- COGL_FEATURE_POINT_SPRITE,
- 0)
-COGL_FEATURE_END ()
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl.h"
-
-#include "cogl-private.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-feature-private.h"
-
-static gboolean
-_cogl_get_gl_version (int *major_out, int *minor_out)
-{
- const char *version_string, *major_end, *minor_end;
- int major = 0, minor = 0;
-
- /* Get the OpenGL version number */
- if ((version_string = (const char *) glGetString (GL_VERSION)) == NULL)
- return FALSE;
-
- /* Extract the major number */
- for (major_end = version_string; *major_end >= '0'
- && *major_end <= '9'; major_end++)
- major = (major * 10) + *major_end - '0';
- /* If there were no digits or the major number isn't followed by a
- dot then it is invalid */
- if (major_end == version_string || *major_end != '.')
- return FALSE;
-
- /* Extract the minor number */
- for (minor_end = major_end + 1; *minor_end >= '0'
- && *minor_end <= '9'; minor_end++)
- minor = (minor * 10) + *minor_end - '0';
- /* If there were no digits or there is an unexpected character then
- it is invalid */
- if (minor_end == major_end + 1
- || (*minor_end && *minor_end != ' ' && *minor_end != '.'))
- return FALSE;
-
- *major_out = major;
- *minor_out = minor;
-
- return TRUE;
-}
-
-gboolean
-_cogl_gl_check_version (GError **error)
-{
- int major, minor;
- const char *gl_extensions;
-
- if (!_cogl_get_gl_version (&major, &minor))
- {
- g_set_error (error,
- COGL_DRIVER_ERROR,
- COGL_DRIVER_ERROR_UNKNOWN_VERSION,
- "The OpenGL version could not be determined");
- return FALSE;
- }
-
- /* GL 1.3 supports all of the required functionality in core */
- if (COGL_CHECK_GL_VERSION (major, minor, 1, 3))
- return TRUE;
-
- gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
-
- /* OpenGL 1.2 is only supported if we have the multitexturing
- extension */
- if (!_cogl_check_extension ("GL_ARB_multitexture", gl_extensions))
- {
- g_set_error (error,
- COGL_DRIVER_ERROR,
- COGL_DRIVER_ERROR_INVALID_VERSION,
- "The OpenGL driver is missing "
- "the GL_ARB_multitexture extension");
- return FALSE;
- }
-
- /* OpenGL 1.2 is required */
- if (!COGL_CHECK_GL_VERSION (major, minor, 1, 2))
- {
- g_set_error (error,
- COGL_DRIVER_ERROR,
- COGL_DRIVER_ERROR_INVALID_VERSION,
- "The OpenGL version of your driver (%i.%i) "
- "is not compatible with Cogl",
- major, minor);
- return FALSE;
- }
-
- return TRUE;
-}
-
-/* Define a set of arrays containing the functions required from GL
- for each feature */
-#define COGL_FEATURE_BEGIN(name, min_gl_major, min_gl_minor, \
- namespaces, extension_names, \
- feature_flags, feature_flags_private) \
- static const CoglFeatureFunction cogl_feature_ ## name ## _funcs[] = {
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, drv.pf_ ## name) },
-#define COGL_FEATURE_END() \
- { NULL, 0 }, \
- };
-#include "cogl-feature-functions-gl.h"
-
-/* Define an array of features */
-#undef COGL_FEATURE_BEGIN
-#define COGL_FEATURE_BEGIN(name, min_gl_major, min_gl_minor, \
- namespaces, extension_names, \
- feature_flags, feature_flags_private) \
- { min_gl_major, min_gl_minor, namespaces, \
- extension_names, feature_flags, feature_flags_private, 0, \
- cogl_feature_ ## name ## _funcs },
-#undef COGL_FEATURE_FUNCTION
-#define COGL_FEATURE_FUNCTION(ret, name, args)
-#undef COGL_FEATURE_END
-#define COGL_FEATURE_END()
-
-static const CoglFeatureData cogl_feature_data[] =
- {
-#include "cogl-feature-functions-gl.h"
- };
-
-#undef COGL_FEATURE_BEGIN
-#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
-#undef COGL_FEATURE_FUNCTION
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- context->drv.pf_ ## name = NULL;
-#undef COGL_FEATURE_END
-#define COGL_FEATURE_END()
-
-static void
-initialize_function_table (CoglContext *context)
-{
- #include "cogl-feature-functions-gl.h"
-}
-
-/* Query the GL extensions and lookup the corresponding function
- * pointers. Theoretically the list of extensions can change for
- * different GL contexts so it is the winsys backend's responsiblity
- * to know when to re-query the GL extensions. */
-void
-_cogl_gl_update_features (CoglContext *context)
-{
- CoglFeatureFlags flags = 0;
- const char *gl_extensions;
- int max_clip_planes = 0;
- int num_stencil_bits = 0;
- int gl_major = 0, gl_minor = 0;
- int i;
-
- COGL_NOTE (WINSYS,
- "Checking features\n"
- " GL_VENDOR: %s\n"
- " GL_RENDERER: %s\n"
- " GL_VERSION: %s\n"
- " GL_EXTENSIONS: %s",
- glGetString (GL_VENDOR),
- glGetString (GL_RENDERER),
- glGetString (GL_VERSION),
- glGetString (GL_EXTENSIONS));
-
- _cogl_get_gl_version (&gl_major, &gl_minor);
-
- flags = (COGL_FEATURE_TEXTURE_READ_PIXELS
- | COGL_FEATURE_UNSIGNED_INT_INDICES);
-
- gl_extensions = (const char *)glGetString (GL_EXTENSIONS);
-
- if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 2, 0) ||
- _cogl_check_extension ("GL_ARB_texture_non_power_of_two", gl_extensions))
- {
- flags |= COGL_FEATURE_TEXTURE_NPOT
- | COGL_FEATURE_TEXTURE_NPOT_BASIC
- | COGL_FEATURE_TEXTURE_NPOT_MIPMAP
- | COGL_FEATURE_TEXTURE_NPOT_REPEAT;
- }
-
-#ifdef GL_YCBCR_MESA
- if (_cogl_check_extension ("GL_MESA_ycbcr_texture", gl_extensions))
- {
- flags |= COGL_FEATURE_TEXTURE_YUV;
- }
-#endif
-
- GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
- /* We need at least three stencil bits to combine clips */
- if (num_stencil_bits > 2)
- flags |= COGL_FEATURE_STENCIL_BUFFER;
-
- GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
- if (max_clip_planes >= 4)
- flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
-
- initialize_function_table (context);
-
- for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
- if (_cogl_feature_check ("GL", cogl_feature_data + i,
- gl_major, gl_minor,
- gl_extensions,
- context))
- flags |= cogl_feature_data[i].feature_flags;
-
- /* Cache features */
- context->feature_flags |= flags;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Matthew Allum <mallum@openedhand.com>
- * Neil Roberts <neil@linux.intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-bitmap.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-primitives.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define glGenerateMipmap ctx->drv.pf_glGenerateMipmap
-#define glTexImage3D ctx->drv.pf_glTexImage3D
-
-void
-_cogl_texture_driver_gen (GLenum gl_target,
- GLsizei n,
- GLuint *textures)
-{
- unsigned int i;
-
- GE (glGenTextures (n, textures));
-
- for (i = 0; i < n; i++)
- {
- _cogl_bind_gl_texture_transient (gl_target,
- textures[i],
- FALSE);
-
- switch (gl_target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
- GE( glTexParameteri (gl_target,
- GL_TEXTURE_MIN_FILTER,
- GL_LINEAR) );
- break;
-
- case GL_TEXTURE_RECTANGLE_ARB:
- /* Texture rectangles already default to GL_LINEAR so nothing
- needs to be done */
- break;
-
- default:
- g_assert_not_reached();
- }
- }
-}
-
-/* OpenGL - unlike GLES - can upload a sub region of pixel data from a larger
- * source buffer */
-static void
-prep_gl_for_pixels_upload_full (int pixels_rowstride,
- int image_height,
- int pixels_src_x,
- int pixels_src_y,
- int pixels_bpp)
-{
- GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
-
- GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
- GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
-
- if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
- GE( glPixelStorei (GL_UNPACK_IMAGE_HEIGHT, image_height) );
-
- _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
-}
-
-void
-_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
- int pixels_bpp)
-{
- prep_gl_for_pixels_upload_full (pixels_rowstride, 0, 0, 0, pixels_bpp);
-}
-
-/* OpenGL - unlike GLES - can download pixel data into a sub region of
- * a larger destination buffer */
-static void
-prep_gl_for_pixels_download_full (int pixels_rowstride,
- int image_height,
- int pixels_src_x,
- int pixels_src_y,
- int pixels_bpp)
-{
- GE( glPixelStorei (GL_PACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
-
- GE( glPixelStorei (GL_PACK_SKIP_PIXELS, pixels_src_x) );
- GE( glPixelStorei (GL_PACK_SKIP_ROWS, pixels_src_y) );
-
- if (cogl_features_available (COGL_FEATURE_TEXTURE_3D))
- GE( glPixelStorei (GL_PACK_IMAGE_HEIGHT, image_height) );
-
- _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
-}
-
-void
-_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
- int pixels_bpp)
-{
- prep_gl_for_pixels_download_full (pixels_rowstride, 0, 0, 0, pixels_bpp);
-}
-
-void
-_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height,
- CoglBitmap *source_bmp,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- guint8 *data;
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
-
- data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- 0,
- src_x,
- src_y,
- bpp);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- GE( glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (source_bmp);
-}
-
-void
-_cogl_texture_driver_upload_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- guint8 *data;
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
-
- data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- 0, 0, 0, bpp);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- GE( glTexImage2D (gl_target, 0,
- internal_gl_format,
- _cogl_bitmap_get_width (source_bmp),
- _cogl_bitmap_get_height (source_bmp),
- 0,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (source_bmp);
-}
-
-void
-_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- GLint height,
- GLint depth,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- guint8 *data;
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- /* Setup gl alignment to match rowstride and top-left corner */
- prep_gl_for_pixels_upload_full (_cogl_bitmap_get_rowstride (source_bmp),
- (_cogl_bitmap_get_height (source_bmp) /
- depth),
- 0, 0, bpp);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- GE( glTexImage3D (gl_target,
- 0, /* level */
- internal_gl_format,
- _cogl_bitmap_get_width (source_bmp),
- height,
- depth,
- 0,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (source_bmp);
-}
-
-gboolean
-_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
- GLenum dest_gl_format,
- GLenum dest_gl_type,
- guint8 *dest)
-{
- GE (glGetTexImage (gl_target,
- 0, /* level */
- dest_gl_format,
- dest_gl_type,
- (GLvoid *)dest));
- return TRUE;
-}
-
-gboolean
-_cogl_texture_driver_size_supported_3d (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height,
- int depth)
-{
- GLenum proxy_target;
- GLint new_width = 0;
-
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (gl_target == GL_TEXTURE_3D)
- proxy_target = GL_PROXY_TEXTURE_3D;
- else
- /* Unknown target, assume it's not supported */
- return FALSE;
-
- /* Proxy texture allows for a quick check for supported size */
- GE( glTexImage3D (proxy_target, 0, GL_RGBA,
- width, height, depth, 0 /* border */,
- gl_format, gl_type, NULL) );
-
- GE( glGetTexLevelParameteriv (proxy_target, 0,
- GL_TEXTURE_WIDTH, &new_width) );
-
- return new_width != 0;
-}
-
-gboolean
-_cogl_texture_driver_size_supported (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height)
-{
- GLenum proxy_target;
- GLint new_width = 0;
-
- if (gl_target == GL_TEXTURE_2D)
- proxy_target = GL_PROXY_TEXTURE_2D;
-#if HAVE_COGL_GL
- else if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
- proxy_target = GL_PROXY_TEXTURE_RECTANGLE_ARB;
-#endif
- else
- /* Unknown target, assume it's not supported */
- return FALSE;
-
- /* Proxy texture allows for a quick check for supported size */
- GE( glTexImage2D (proxy_target, 0, GL_RGBA,
- width, height, 0 /* border */,
- gl_format, gl_type, NULL) );
-
- GE( glGetTexLevelParameteriv (proxy_target, 0,
- GL_TEXTURE_WIDTH, &new_width) );
-
- return new_width != 0;
-}
-
-void
-_cogl_texture_driver_try_setting_gl_border_color (
- GLuint gl_target,
- const GLfloat *transparent_color)
-{
- /* Use a transparent border color so that we can leave the
- color buffer alone when using texture co-ordinates
- outside of the texture */
- GE( glTexParameterfv (gl_target, GL_TEXTURE_BORDER_COLOR,
- transparent_color) );
-}
-
-gboolean
-_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
- CoglPixelFormat *out_format)
-{
- /* It doesn't really matter we convert to exact same
- format (some have no cogl match anyway) since format
- is re-matched against cogl when getting or setting
- texture image data.
- */
-
- switch (gl_int_format)
- {
- case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8:
- case GL_ALPHA12: case GL_ALPHA16:
-
- *out_format = COGL_PIXEL_FORMAT_A_8;
- return TRUE;
-
- case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8:
- case GL_LUMINANCE12: case GL_LUMINANCE16:
-
- *out_format = COGL_PIXEL_FORMAT_G_8;
- return TRUE;
-
- case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8:
- case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2:
-
- *out_format = COGL_PIXEL_FORMAT_RGB_888;
- return TRUE;
-
- case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1:
- case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16:
-
- *out_format = COGL_PIXEL_FORMAT_RGBA_8888;
- return TRUE;
- }
-
- return FALSE;
-}
-
-CoglPixelFormat
-_cogl_pixel_format_to_gl (CoglPixelFormat format,
- GLenum *out_glintformat,
- GLenum *out_glformat,
- GLenum *out_gltype)
-{
- CoglPixelFormat required_format;
- GLenum glintformat = 0;
- GLenum glformat = 0;
- GLenum gltype = 0;
-
- /* FIXME: check YUV support */
-
- required_format = format;
-
- /* Find GL equivalents */
- switch (format & COGL_UNPREMULT_MASK)
- {
- case COGL_PIXEL_FORMAT_A_8:
- glintformat = GL_ALPHA;
- glformat = GL_ALPHA;
- gltype = GL_UNSIGNED_BYTE;
- break;
- case COGL_PIXEL_FORMAT_G_8:
- glintformat = GL_LUMINANCE;
- glformat = GL_LUMINANCE;
- gltype = GL_UNSIGNED_BYTE;
- break;
-
- case COGL_PIXEL_FORMAT_RGB_888:
- glintformat = GL_RGB;
- glformat = GL_RGB;
- gltype = GL_UNSIGNED_BYTE;
- break;
- case COGL_PIXEL_FORMAT_BGR_888:
- glintformat = GL_RGB;
- glformat = GL_BGR;
- gltype = GL_UNSIGNED_BYTE;
- break;
- case COGL_PIXEL_FORMAT_RGBA_8888:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_BYTE;
- break;
- case COGL_PIXEL_FORMAT_BGRA_8888:
- glintformat = GL_RGBA;
- glformat = GL_BGRA;
- gltype = GL_UNSIGNED_BYTE;
- break;
-
- /* The following two types of channel ordering
- * have no GL equivalent unless defined using
- * system word byte ordering */
- case COGL_PIXEL_FORMAT_ARGB_8888:
- glintformat = GL_RGBA;
- glformat = GL_BGRA;
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- gltype = GL_UNSIGNED_INT_8_8_8_8;
-#else
- gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
-#endif
- break;
-
- case COGL_PIXEL_FORMAT_ABGR_8888:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- gltype = GL_UNSIGNED_INT_8_8_8_8;
-#else
- gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
-#endif
- break;
-
- /* The following three types of channel ordering
- * are always defined using system word byte
- * ordering (even according to GLES spec) */
- case COGL_PIXEL_FORMAT_RGB_565:
- glintformat = GL_RGB;
- glformat = GL_RGB;
- gltype = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case COGL_PIXEL_FORMAT_RGBA_4444:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4;
- break;
- case COGL_PIXEL_FORMAT_RGBA_5551:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_5_5_5_1;
- break;
-
- /* FIXME: check extensions for YUV support */
- default:
- break;
- }
-
- if (out_glintformat != NULL)
- *out_glintformat = glintformat;
- if (out_glformat != NULL)
- *out_glformat = glformat;
- if (out_gltype != NULL)
- *out_gltype = gltype;
-
- return required_format;
-}
-
-gboolean
-_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
-{
- /* GL_ARB_texture_rectangle textures are supported if they are
- created from foreign because some chipsets have trouble with
- GL_ARB_texture_non_power_of_two. There is no Cogl call to create
- them directly to emphasize the fact that they don't work fully
- (for example, no mipmapping and complicated shader support) */
-
- /* Allow 2-dimensional or rectangle textures only */
- if (gl_target != GL_TEXTURE_2D && gl_target != GL_TEXTURE_RECTANGLE_ARB)
- return FALSE;
-
- return TRUE;
-}
-
-void
-_cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
-{
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- GE( glGenerateMipmap (gl_target) );
-}
-
-CoglPixelFormat
-_cogl_texture_driver_find_best_gl_get_data_format (
- CoglPixelFormat format,
- GLenum *closest_gl_format,
- GLenum *closest_gl_type)
-{
- /* Find closest format that's supported by GL */
- return _cogl_pixel_format_to_gl (format,
- NULL, /* don't need */
- closest_gl_format,
- closest_gl_type);
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_CONTEXT_DRIVER_H
-#define __COGL_CONTEXT_DRIVER_H
-
-#include "cogl.h"
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-
-#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
-
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- ret (APIENTRY * pf_ ## name) args;
-
-#define COGL_FEATURE_END()
-
-typedef struct _CoglContextDriver
-{
- /* This defines a list of function pointers */
-#include "cogl-feature-functions-gles.h"
-
-} CoglContextDriver;
-
-#undef COGL_FEATURE_BEGIN
-#undef COGL_FEATURE_FUNCTION
-#undef COGL_FEATURE_END
-
-#endif /* __COGL_CONTEXT_DRIVER_H */
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This is included multiple times with different definitions for
- these macros */
-
-COGL_FEATURE_BEGIN (offscreen, 255, 255,
- "OES\0",
- "framebuffer_object\0",
- COGL_FEATURE_OFFSCREEN,
- 0)
-COGL_FEATURE_FUNCTION (void, glGenRenderbuffers,
- (GLsizei n,
- GLuint *renderbuffers))
-COGL_FEATURE_FUNCTION (void, glDeleteRenderbuffers,
- (GLsizei n,
- const GLuint *renderbuffers))
-COGL_FEATURE_FUNCTION (void, glBindRenderbuffer,
- (GLenum target,
- GLuint renderbuffer))
-COGL_FEATURE_FUNCTION (void, glRenderbufferStorage,
- (GLenum target,
- GLenum internalformat,
- GLsizei width,
- GLsizei height))
-COGL_FEATURE_FUNCTION (void, glGenFramebuffers,
- (GLsizei n,
- GLuint *framebuffers))
-COGL_FEATURE_FUNCTION (void, glBindFramebuffer,
- (GLenum target,
- GLuint framebuffer))
-COGL_FEATURE_FUNCTION (void, glFramebufferTexture2D,
- (GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level))
-COGL_FEATURE_FUNCTION (void, glFramebufferRenderbuffer,
- (GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer))
-COGL_FEATURE_FUNCTION (GLenum, glCheckFramebufferStatus,
- (GLenum target))
-COGL_FEATURE_FUNCTION (void, glDeleteFramebuffers,
- (GLsizei n,
- const GLuint *framebuffers))
-COGL_FEATURE_FUNCTION (void, glGenerateMipmap,
- (GLenum target))
-COGL_FEATURE_FUNCTION (void, glGetFramebufferAttachmentParameteriv,
- (GLenum target,
- GLenum attachment,
- GLenum pname,
- GLint *params))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (offscreen_blit, 255, 255,
- "ANGLE\0",
- "framebuffer_blit\0",
- COGL_FEATURE_OFFSCREEN_BLIT,
- 0)
-COGL_FEATURE_FUNCTION (void, glBlitFramebuffer,
- (GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1,
- GLbitfield mask,
- GLenum filter))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (element_index_uint, 255, 255,
- "OES\0",
- "element_index_uint\0",
- COGL_FEATURE_UNSIGNED_INT_INDICES,
- 0)
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (texture_npot, 255, 255,
- "OES\0IMG\0",
- "texture_npot\0",
- COGL_FEATURE_TEXTURE_NPOT |
- COGL_FEATURE_TEXTURE_NPOT_BASIC |
- COGL_FEATURE_TEXTURE_NPOT_MIPMAP |
- COGL_FEATURE_TEXTURE_NPOT_REPEAT,
- 0)
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (texture_3d, 1, 2,
- "OES\0",
- "texture_3D\0",
- COGL_FEATURE_TEXTURE_3D,
- 0)
-COGL_FEATURE_FUNCTION (void, glTexImage3D,
- (GLenum target, GLint level,
- GLint internalFormat,
- GLsizei width, GLsizei height,
- GLsizei depth, GLint border,
- GLenum format, GLenum type,
- const GLvoid *pixels))
-COGL_FEATURE_FUNCTION (void, glTexSubImage3D,
- (GLenum target, GLint level,
- GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const GLvoid* pixels))
-COGL_FEATURE_END ()
-
-COGL_FEATURE_BEGIN (map_buffer, 255, 255,
- "OES\0",
- "mapbuffer\0",
- COGL_FEATURE_MAP_BUFFER_FOR_WRITE,
- 0)
-COGL_FEATURE_FUNCTION (void *, glMapBuffer,
- (GLenum target,
- GLenum access))
-COGL_FEATURE_FUNCTION (GLboolean, glUnmapBuffer,
- (GLenum target))
-COGL_FEATURE_END ()
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-context-private.h"
-#include "cogl-feature-private.h"
-
-gboolean
-_cogl_gl_check_version (GError **error)
-{
- /* The GLES backend doesn't have any particular version requirements */
- return TRUE;
-}
-
-/* Define a set of arrays containing the functions required from GL
- for each feature */
-#define COGL_FEATURE_BEGIN(name, min_gl_major, min_gl_minor, \
- namespaces, extension_names, \
- feature_flags, feature_flags_private) \
- static const CoglFeatureFunction cogl_feature_ ## name ## _funcs[] = {
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglContext, drv.pf_ ## name) },
-#define COGL_FEATURE_END() \
- { NULL, 0 }, \
- };
-#include "cogl-feature-functions-gles.h"
-
-/* Define an array of features */
-#undef COGL_FEATURE_BEGIN
-#define COGL_FEATURE_BEGIN(name, min_gl_major, min_gl_minor, \
- namespaces, extension_names, \
- feature_flags, feature_flags_private) \
- { min_gl_major, min_gl_minor, namespaces, \
- extension_names, feature_flags, feature_flags_private, 0, \
- cogl_feature_ ## name ## _funcs },
-#undef COGL_FEATURE_FUNCTION
-#define COGL_FEATURE_FUNCTION(ret, name, args)
-#undef COGL_FEATURE_END
-#define COGL_FEATURE_END()
-
-static const CoglFeatureData cogl_feature_data[] =
- {
-#include "cogl-feature-functions-gles.h"
- };
-
-#undef COGL_FEATURE_BEGIN
-#define COGL_FEATURE_BEGIN(a, b, c, d, e, f, g)
-#undef COGL_FEATURE_FUNCTION
-#define COGL_FEATURE_FUNCTION(ret, name, args) \
- context->drv.pf_ ## name = NULL;
-#undef COGL_FEATURE_END
-#define COGL_FEATURE_END()
-
-static void
-initialize_function_table (CoglContext *context)
-{
- #include "cogl-feature-functions-gles.h"
-}
-
-/* Query the GL extensions and lookup the corresponding function
- * pointers. Theoretically the list of extensions can change for
- * different GL contexts so it is the winsys backend's responsiblity
- * to know when to re-query the GL extensions. */
-void
-_cogl_gl_update_features (CoglContext *context)
-{
- CoglFeatureFlags flags = 0;
- const char *gl_extensions;
-#ifndef HAVE_COGL_GLES2
- int max_clip_planes = 0;
-#endif
- int num_stencil_bits = 0;
- int i;
-
- COGL_NOTE (WINSYS,
- "Checking features\n"
- " GL_VENDOR: %s\n"
- " GL_RENDERER: %s\n"
- " GL_VERSION: %s\n"
- " GL_EXTENSIONS: %s",
- glGetString (GL_VENDOR),
- glGetString (GL_RENDERER),
- glGetString (GL_VERSION),
- glGetString (GL_EXTENSIONS));
-
- gl_extensions = (const char*) glGetString (GL_EXTENSIONS);
-
-
- GE( glGetIntegerv (GL_STENCIL_BITS, &num_stencil_bits) );
- /* We need at least three stencil bits to combine clips */
- if (num_stencil_bits > 2)
- flags |= COGL_FEATURE_STENCIL_BUFFER;
-
-#ifndef HAVE_COGL_GLES2
- GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
- if (max_clip_planes >= 4)
- flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
-#endif
-
-#ifdef HAVE_COGL_GLES2
- flags |= COGL_FEATURE_SHADERS_GLSL | COGL_FEATURE_OFFSCREEN;
- /* Note GLES 2 core doesn't support mipmaps for npot textures or
- * repeat modes other than CLAMP_TO_EDGE. */
- flags |= COGL_FEATURE_TEXTURE_NPOT_BASIC;
-#endif
-
- flags |= COGL_FEATURE_VBOS;
-
- /* Both GLES 1.1 and GLES 2.0 support point sprites in core */
- flags |= COGL_FEATURE_POINT_SPRITE;
-
- initialize_function_table (context);
-
- for (i = 0; i < G_N_ELEMENTS (cogl_feature_data); i++)
- if (_cogl_feature_check ("GL", cogl_feature_data + i,
- 0, 0,
- gl_extensions,
- context))
- flags |= cogl_feature_data[i].feature_flags;
-
- /* Cache features */
- context->feature_flags |= flags;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Matthew Allum <mallum@openedhand.com>
- * Neil Roberts <neil@linux.intel.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-bitmap.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-pipeline.h"
-#include "cogl-pipeline-opengl-private.h"
-#include "cogl-context-private.h"
-#include "cogl-handle.h"
-#include "cogl-primitives.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <math.h>
-
-#define glTexImage3D ctx->drv.pf_glTexImage3D
-#define glTexSubImage3D ctx->drv.pf_glTexSubImage3D
-
-#ifndef GL_TEXTURE_3D
-#define GL_TEXTURE_3D 0x806F
-#endif
-#ifndef GL_MAX_3D_TEXTURE_SIZE_OES
-#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073
-#endif
-
-void
-_cogl_texture_driver_gen (GLenum gl_target,
- GLsizei n,
- GLuint *textures)
-{
- unsigned int i;
-
- GE (glGenTextures (n, textures));
-
- for (i = 0; i < n; i++)
- {
- _cogl_bind_gl_texture_transient (gl_target, textures[i], FALSE);
-
- switch (gl_target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_3D:
- /* GL_TEXTURE_MAG_FILTER defaults to GL_LINEAR, no need to set it */
- GE( glTexParameteri (gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR) );
- break;
-
- default:
- g_assert_not_reached();
- }
- }
-}
-
-void
-_cogl_texture_driver_prep_gl_for_pixels_upload (int pixels_rowstride,
- int pixels_bpp)
-{
- _cogl_texture_prep_gl_alignment_for_pixels_upload (pixels_rowstride);
-}
-
-void
-_cogl_texture_driver_prep_gl_for_pixels_download (int pixels_rowstride,
- int pixels_bpp)
-{
- _cogl_texture_prep_gl_alignment_for_pixels_download (pixels_rowstride);
-}
-
-static CoglBitmap *
-prepare_bitmap_alignment_for_upload (CoglBitmap *src_bmp)
-{
- CoglPixelFormat format = _cogl_bitmap_get_format (src_bmp);
- int bpp = _cogl_get_format_bpp (format);
- int src_rowstride = _cogl_bitmap_get_rowstride (src_bmp);
- int width = _cogl_bitmap_get_width (src_bmp);
- int alignment = 1;
-
- if (src_rowstride == 0)
- return cogl_object_ref (src_bmp);
-
- /* Work out the alignment of the source rowstride */
- alignment = 1 << (_cogl_util_ffs (src_rowstride) - 1);
- alignment = MIN (alignment, 8);
-
- /* If the aligned data equals the rowstride then we can upload from
- the bitmap directly using GL_UNPACK_ALIGNMENT */
- if (((width * bpp + alignment - 1) & ~(alignment - 1)) == src_rowstride)
- return cogl_object_ref (src_bmp);
- /* Otherwise we need to copy the bitmap to pack the alignment
- because GLES has no GL_ROW_LENGTH */
- else
- return _cogl_bitmap_copy (src_bmp);
-}
-
-void
-_cogl_texture_driver_upload_subregion_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- int width,
- int height,
- CoglBitmap *source_bmp,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- guint8 *data;
- CoglPixelFormat source_format = _cogl_bitmap_get_format (source_bmp);
- int bpp = _cogl_get_format_bpp (source_format);
- CoglBitmap *slice_bmp;
- int rowstride;
-
- /* If we are copying a sub region of the source bitmap then we need
- to copy it because GLES does not support GL_UNPACK_ROW_LENGTH */
- if (src_x != 0 || src_y != 0 ||
- width != _cogl_bitmap_get_width (source_bmp) ||
- height != _cogl_bitmap_get_height (source_bmp))
- {
- rowstride = bpp * width;
- rowstride = (rowstride + 3) & ~3;
- slice_bmp =
- _cogl_bitmap_new_from_data (g_malloc (height * rowstride),
- source_format,
- width, height,
- rowstride,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
- _cogl_bitmap_copy_subregion (source_bmp,
- slice_bmp,
- src_x, src_y,
- 0, 0, /* dst_x/y */
- width, height);
- }
- else
- {
- slice_bmp = prepare_bitmap_alignment_for_upload (source_bmp);
- rowstride = _cogl_bitmap_get_rowstride (slice_bmp);
- }
-
- /* Setup gl alignment to match rowstride and top-left corner */
- _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
-
- data = _cogl_bitmap_bind (slice_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- GE( glTexSubImage2D (gl_target, 0,
- dst_x, dst_y,
- width, height,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (slice_bmp);
-
- cogl_object_unref (slice_bmp);
-}
-
-void
-_cogl_texture_driver_upload_to_gl (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
- int rowstride;
- int bmp_width = _cogl_bitmap_get_width (source_bmp);
- int bmp_height = _cogl_bitmap_get_height (source_bmp);
- CoglBitmap *bmp;
- guint8 *data;
-
- bmp = prepare_bitmap_alignment_for_upload (source_bmp);
- rowstride = _cogl_bitmap_get_rowstride (bmp);
-
- /* Setup gl alignment to match rowstride and top-left corner */
- _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- data = _cogl_bitmap_bind (bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- GE( glTexImage2D (gl_target, 0,
- internal_gl_format,
- bmp_width, bmp_height,
- 0,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (bmp);
-
- cogl_object_unref (bmp);
-}
-
-void
-_cogl_texture_driver_upload_to_gl_3d (GLenum gl_target,
- GLuint gl_handle,
- gboolean is_foreign,
- GLint height,
- GLint depth,
- CoglBitmap *source_bmp,
- GLint internal_gl_format,
- GLuint source_gl_format,
- GLuint source_gl_type)
-{
- int bpp = _cogl_get_format_bpp (_cogl_bitmap_get_format (source_bmp));
- int rowstride = _cogl_bitmap_get_rowstride (source_bmp);
- int bmp_width = _cogl_bitmap_get_width (source_bmp);
- int bmp_height = _cogl_bitmap_get_height (source_bmp);
- guint8 *data;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- _cogl_bind_gl_texture_transient (gl_target, gl_handle, is_foreign);
-
- /* If the rowstride or image height can't be specified with just
- GL_ALIGNMENT alone then we need to copy the bitmap because there
- is no GL_ROW_LENGTH */
- if (rowstride / bpp != bmp_width ||
- height != bmp_height / depth)
- {
- CoglBitmap *bmp;
- int image_height = bmp_height / depth;
- int i;
-
- _cogl_texture_driver_prep_gl_for_pixels_upload (bmp_width * bpp, bpp);
-
- /* Initialize the texture with empty data and then upload each
- image with a sub-region update */
-
- GE( glTexImage3D (gl_target,
- 0, /* level */
- internal_gl_format,
- bmp_width,
- height,
- depth,
- 0,
- source_gl_format,
- source_gl_type,
- NULL) );
-
- bmp = _cogl_bitmap_new_from_data (g_malloc (bpp * bmp_width * height),
- _cogl_bitmap_get_format (source_bmp),
- bmp_width,
- height,
- bpp * bmp_width,
- (CoglBitmapDestroyNotify) g_free,
- NULL);
-
- for (i = 0; i < depth; i++)
- {
- _cogl_bitmap_copy_subregion (source_bmp,
- bmp,
- 0, image_height * i,
- 0, 0,
- bmp_width,
- height);
-
- data = _cogl_bitmap_bind (bmp,
- COGL_BUFFER_ACCESS_READ, 0);
-
- GE( glTexSubImage3D (gl_target,
- 0, /* level */
- 0, /* xoffset */
- 0, /* yoffset */
- i, /* zoffset */
- bmp_width, /* width */
- height, /* height */
- 1, /* depth */
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (bmp);
- }
-
- cogl_object_unref (bmp);
- }
- else
- {
- data = _cogl_bitmap_bind (source_bmp, COGL_BUFFER_ACCESS_READ, 0);
-
- _cogl_texture_driver_prep_gl_for_pixels_upload (rowstride, bpp);
-
- GE( glTexImage3D (gl_target,
- 0, /* level */
- internal_gl_format,
- bmp_width,
- height,
- depth,
- 0,
- source_gl_format,
- source_gl_type,
- data) );
-
- _cogl_bitmap_unbind (source_bmp);
- }
-}
-
-/* NB: GLES doesn't support glGetTexImage2D, so cogl-texture will instead
- * fallback to a generic render + readpixels approach to downloading
- * texture data. (See _cogl_texture_draw_and_read() ) */
-gboolean
-_cogl_texture_driver_gl_get_tex_image (GLenum gl_target,
- GLenum dest_gl_format,
- GLenum dest_gl_type,
- guint8 *dest)
-{
- return FALSE;
-}
-
-gboolean
-_cogl_texture_driver_size_supported_3d (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height,
- int depth)
-{
- GLint max_size;
-
- /* GLES doesn't support a proxy texture target so let's at least
- check whether the size is greater than
- GL_MAX_3D_TEXTURE_SIZE_OES */
- GE( glGetIntegerv (GL_MAX_3D_TEXTURE_SIZE_OES, &max_size) );
-
- return width <= max_size && height <= max_size && depth <= max_size;
-}
-
-gboolean
-_cogl_texture_driver_size_supported (GLenum gl_target,
- GLenum gl_format,
- GLenum gl_type,
- int width,
- int height)
-{
- GLint max_size;
-
- /* GLES doesn't support a proxy texture target so let's at least
- check whether the size is greater than GL_MAX_TEXTURE_SIZE */
- GE( glGetIntegerv (GL_MAX_TEXTURE_SIZE, &max_size) );
-
- return width <= max_size && height <= max_size;
-}
-
-void
-_cogl_texture_driver_try_setting_gl_border_color (
- GLuint gl_target,
- const GLfloat *transparent_color)
-{
- /* FAIL! */
-}
-
-gboolean
-_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
- CoglPixelFormat *out_format)
-{
- return TRUE;
-}
-
-CoglPixelFormat
-_cogl_pixel_format_to_gl (CoglPixelFormat format,
- GLenum *out_glintformat,
- GLenum *out_glformat,
- GLenum *out_gltype)
-{
- CoglPixelFormat required_format;
- GLenum glintformat = 0;
- GLenum glformat = 0;
- GLenum gltype = 0;
-
- /* FIXME: check YUV support */
-
- required_format = format;
-
- /* Find GL equivalents */
- switch (format & COGL_UNPREMULT_MASK)
- {
- case COGL_PIXEL_FORMAT_A_8:
- glintformat = GL_ALPHA;
- glformat = GL_ALPHA;
- gltype = GL_UNSIGNED_BYTE;
- break;
- case COGL_PIXEL_FORMAT_G_8:
- glintformat = GL_LUMINANCE;
- glformat = GL_LUMINANCE;
- gltype = GL_UNSIGNED_BYTE;
- break;
-
- /* Just one 24-bit ordering supported */
- case COGL_PIXEL_FORMAT_RGB_888:
- case COGL_PIXEL_FORMAT_BGR_888:
- glintformat = GL_RGB;
- glformat = GL_RGB;
- gltype = GL_UNSIGNED_BYTE;
- required_format = COGL_PIXEL_FORMAT_RGB_888;
- break;
-
- /* Just one 32-bit ordering supported */
- case COGL_PIXEL_FORMAT_RGBA_8888:
- case COGL_PIXEL_FORMAT_BGRA_8888:
- case COGL_PIXEL_FORMAT_ARGB_8888:
- case COGL_PIXEL_FORMAT_ABGR_8888:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_BYTE;
- required_format = COGL_PIXEL_FORMAT_RGBA_8888;
- required_format |= (format & COGL_PREMULT_BIT);
- break;
-
- /* The following three types of channel ordering
- * are always defined using system word byte
- * ordering (even according to GLES spec) */
- case COGL_PIXEL_FORMAT_RGB_565:
- glintformat = GL_RGB;
- glformat = GL_RGB;
- gltype = GL_UNSIGNED_SHORT_5_6_5;
- break;
- case COGL_PIXEL_FORMAT_RGBA_4444:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_4_4_4_4;
- break;
- case COGL_PIXEL_FORMAT_RGBA_5551:
- glintformat = GL_RGBA;
- glformat = GL_RGBA;
- gltype = GL_UNSIGNED_SHORT_5_5_5_1;
- break;
-
- /* FIXME: check extensions for YUV support */
- default:
- break;
- }
-
- if (out_glintformat != NULL)
- *out_glintformat = glintformat;
- if (out_glformat != NULL)
- *out_glformat = glformat;
- if (out_gltype != NULL)
- *out_gltype = gltype;
-
- return required_format;
-}
-
-gboolean
-_cogl_texture_driver_allows_foreign_gl_target (GLenum gl_target)
-{
- /* Allow 2-dimensional textures only */
- if (gl_target != GL_TEXTURE_2D)
- return FALSE;
- return TRUE;
-}
-
-void
-_cogl_texture_driver_gl_generate_mipmaps (GLenum gl_target)
-{
-#ifdef HAVE_COGL_GLES2
- GE( glGenerateMipmap (gl_target) );
-#endif
-}
-
-CoglPixelFormat
-_cogl_texture_driver_find_best_gl_get_data_format (
- CoglPixelFormat format,
- GLenum *closest_gl_format,
- GLenum *closest_gl_type)
-{
- /* Find closest format that's supported by GL
- (Can't use _cogl_pixel_format_to_gl since available formats
- when reading pixels on GLES are severely limited) */
- *closest_gl_format = GL_RGBA;
- *closest_gl_type = GL_UNSIGNED_BYTE;
- return COGL_PIXEL_FORMAT_RGBA_8888;
-}
-
+++ /dev/null
-/* stbi-1.18 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
- when you control the images you're loading
-
- QUICK NOTES:
- Primarily of interest to game developers and other people who can
- avoid problematic images and only need the trivial interface
-
- JPEG baseline (no JPEG progressive, no oddball channel decimations)
- PNG 8-bit only
- BMP non-1bpp, non-RLE
- TGA (not sure what subset, if a subset)
- PSD (composited view only, no extra channels)
- HDR (radiance rgbE format)
- writes BMP,TGA (define STBI_NO_WRITE to remove code)
- decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
- supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
-
- TODO:
- stbi_info_*
-
- history:
- 1.18 fix a threading bug (local mutable static)
- 1.17 support interlaced PNG
- 1.16 major bugfix - convert_format converted one too many pixels
- 1.15 initialize some fields for thread safety
- 1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
- 1.13 threadsafe
- 1.12 const qualifiers in the API
- 1.11 Support installable IDCT, colorspace conversion routines
- 1.10 Fixes for 64-bit (don't use "unsigned long")
- optimized upsampling by Fabian "ryg" Giesen
- 1.09 Fix format-conversion for PSD code (bad global variables!)
- 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz
- 1.07 attempt to fix C++ warning/errors again
- 1.06 attempt to fix C++ warning/errors again
- 1.05 fix TGA loading to return correct *comp and use good luminance calc
- 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free
- 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR
- 1.02 support for (subset of) HDR files, float interface for preferred access to them
- 1.01 fix bug: possible bug in handling right-side up bmps... not sure
- fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all
- 1.00 interface to zlib that skips zlib header
- 0.99 correct handling of alpha in palette
- 0.98 TGA loader by lonesock; dynamically add loaders (untested)
- 0.97 jpeg errors on too large a file; also catch another malloc failure
- 0.96 fix detection of invalid v value - particleman@mollyrocket forum
- 0.95 during header scan, seek to markers in case of padding
- 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same
- 0.93 handle jpegtran output; verbose errors
- 0.92 read 4,8,16,24,32-bit BMP files of several formats
- 0.91 output 24-bit Windows 3.0 BMP files
- 0.90 fix a few more warnings; bump version number to approach 1.0
- 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd
- 0.60 fix compiling as c++
- 0.59 fix warnings: merge Dave Moore's -Wall fixes
- 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian
- 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less
- than 16 available
- 0.56 fix bug: zlib uncompressed mode len vs. nlen
- 0.55 fix bug: restart_interval not initialized to 0
- 0.54 allow NULL for 'int *comp'
- 0.53 fix bug in png 3->4; speedup png decoding
- 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
- 0.51 obey req_comp requests, 1-component jpegs return as 1-component,
- on 'test' only check type, not whether we support this variant
-*/
-
-
-#ifndef STBI_INCLUDE_STB_IMAGE_H
-#define STBI_INCLUDE_STB_IMAGE_H
-
-//// begin header file ////////////////////////////////////////////////////
-//
-// Limitations:
-// - no progressive/interlaced support (jpeg, png)
-// - 8-bit samples only (jpeg, png)
-// - not threadsafe
-// - channel subsampling of at most 2 in each dimension (jpeg)
-// - no delayed line count (jpeg) -- IJG doesn't support either
-//
-// Basic usage (see HDR discussion below):
-// int x,y,n;
-// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
-// // ... process data if not NULL ...
-// // ... x = width, y = height, n = # 8-bit components per pixel ...
-// // ... replace '0' with '1'..'4' to force that many components per pixel
-// stbi_image_free(data)
-//
-// Standard parameters:
-// int *x -- outputs image width in pixels
-// int *y -- outputs image height in pixels
-// int *comp -- outputs # of image components in image file
-// int req_comp -- if non-zero, # of image components requested in result
-//
-// The return value from an image loader is an 'unsigned char *' which points
-// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
-// with each pixel consisting of N interleaved 8-bit components; the first
-// pixel pointed to is top-left-most in the image. There is no padding between
-// image scanlines or between pixels, regardless of format. The number of
-// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
-// If req_comp is non-zero, *comp has the number of components that _would_
-// have been output otherwise. E.g. if you set req_comp to 4, you will always
-// get RGBA output, but you can check *comp to easily see if it's opaque.
-//
-// An output image with N components has the following components interleaved
-// in this order in each pixel:
-//
-// N=#comp components
-// 1 grey
-// 2 grey, alpha
-// 3 red, green, blue
-// 4 red, green, blue, alpha
-//
-// If image loading fails for any reason, the return value will be NULL,
-// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
-// can be queried for an extremely brief, end-user unfriendly explanation
-// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
-// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
-// more user-friendly ones.
-//
-// Paletted PNG and BMP images are automatically depalettized.
-//
-//
-// ===========================================================================
-//
-// HDR image support (disable by defining STBI_NO_HDR)
-//
-// stb_image now supports loading HDR images in general, and currently
-// the Radiance .HDR file format, although the support is provided
-// generically. You can still load any file through the existing interface;
-// if you attempt to load an HDR file, it will be automatically remapped to
-// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
-// both of these constants can be reconfigured through this interface:
-//
-// stbi_hdr_to_ldr_gamma(2.2f);
-// stbi_hdr_to_ldr_scale(1.0f);
-//
-// (note, do not use _inverse_ constants; stbi_image will invert them
-// appropriately).
-//
-// Additionally, there is a new, parallel interface for loading files as
-// (linear) floats to preserve the full dynamic range:
-//
-// float *data = stbi_loadf(filename, &x, &y, &n, 0);
-//
-// If you load LDR images through this interface, those images will
-// be promoted to floating point values, run through the inverse of
-// constants corresponding to the above:
-//
-// stbi_ldr_to_hdr_scale(1.0f);
-// stbi_ldr_to_hdr_gamma(2.2f);
-//
-// Finally, given a filename (or an open file or memory block--see header
-// file for details) containing image data, you can query for the "most
-// appropriate" interface to use (that is, whether the image is HDR or
-// not), using:
-//
-// stbi_is_hdr(char *filename);
-
-#ifndef STBI_NO_STDIO
-#include <stdio.h>
-#endif
-
-#define STBI_VERSION 1
-
-enum
-{
- STBI_default = 0, // only used for req_comp
-
- STBI_grey = 1,
- STBI_grey_alpha = 2,
- STBI_rgb = 3,
- STBI_rgb_alpha = 4,
-};
-
-typedef unsigned char stbi_uc;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// WRITING API
-
-#if !defined(STBI_NO_WRITE) && !defined(STBI_NO_STDIO)
-// write a BMP/TGA file given tightly packed 'comp' channels (no padding, nor bmp-stride-padding)
-// (you must include the appropriate extension in the filename).
-// returns TRUE on success, FALSE if couldn't open file, error writing file
-extern int stbi_write_bmp (char const *filename, int x, int y, int comp, void *data);
-extern int stbi_write_tga (char const *filename, int x, int y, int comp, void *data);
-#endif
-
-// PRIMARY API - works on images of any type
-
-// load image by filename, open file, or memory buffer
-#ifndef STBI_NO_STDIO
-extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-// for stbi_load_from_file, file pointer is left pointing immediately after image
-
-#ifndef STBI_NO_HDR
-#ifndef STBI_NO_STDIO
-extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-#endif
-extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-
-extern void stbi_hdr_to_ldr_gamma(float gamma);
-extern void stbi_hdr_to_ldr_scale(float scale);
-
-extern void stbi_ldr_to_hdr_gamma(float gamma);
-extern void stbi_ldr_to_hdr_scale(float scale);
-
-#endif // STBI_NO_HDR
-
-// get a VERY brief reason for failure
-// NOT THREADSAFE
-extern char *stbi_failure_reason (void);
-
-// free the loaded image -- this is just free()
-extern void stbi_image_free (void *retval_from_stbi_load);
-
-// get image dimensions & components without fully decoding
-extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
-#ifndef STBI_NO_STDIO
-extern int stbi_info (char const *filename, int *x, int *y, int *comp);
-extern int stbi_is_hdr (char const *filename);
-extern int stbi_is_hdr_from_file(FILE *f);
-#endif
-
-// ZLIB client - used by PNG, available for other purposes
-
-extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
-extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
-extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
-
-extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
-extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
-
-// TYPE-SPECIFIC ACCESS
-
-// is it a jpeg?
-extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len);
-extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-
-#ifndef STBI_NO_STDIO
-extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern int stbi_jpeg_test_file (FILE *f);
-extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-
-extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp);
-extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-
-// is it a png?
-extern int stbi_png_test_memory (stbi_uc const *buffer, int len);
-extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-
-#ifndef STBI_NO_STDIO
-extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern int stbi_png_info (char const *filename, int *x, int *y, int *comp);
-extern int stbi_png_test_file (FILE *f);
-extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-
-// is it a bmp?
-extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len);
-
-extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-#ifndef STBI_NO_STDIO
-extern int stbi_bmp_test_file (FILE *f);
-extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-#endif
-
-// is it a tga?
-extern int stbi_tga_test_memory (stbi_uc const *buffer, int len);
-
-extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-#ifndef STBI_NO_STDIO
-extern int stbi_tga_test_file (FILE *f);
-extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-#endif
-
-// is it a psd?
-extern int stbi_psd_test_memory (stbi_uc const *buffer, int len);
-
-extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-#ifndef STBI_NO_STDIO
-extern int stbi_psd_test_file (FILE *f);
-extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-#endif
-
-// is it an hdr?
-extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len);
-
-extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp);
-extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
-#ifndef STBI_NO_STDIO
-extern int stbi_hdr_test_file (FILE *f);
-extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
-#endif
-
-// define new loaders
-typedef struct
-{
- int (*test_memory)(stbi_uc const *buffer, int len);
- stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
- #ifndef STBI_NO_STDIO
- int (*test_file)(FILE *f);
- stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp);
- #endif
-} stbi_loader;
-
-// register a loader by filling out the above structure (you must defined ALL functions)
-// returns 1 if added or already added, 0 if not added (too many loaders)
-// NOT THREADSAFE
-extern int stbi_register_loader(stbi_loader *loader);
-
-// define faster low-level operations (typically SIMD support)
-#if STBI_SIMD
-typedef void (*stbi_idct_8x8)(uint8 *out, int out_stride, short data[64], unsigned short *dequantize);
-// compute an integer IDCT on "input"
-// input[x] = data[x] * dequantize[x]
-// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride'
-// CLAMP results to 0..255
-typedef void (*stbi_YCbCr_to_RGB_run)(uint8 *output, uint8 const *y, uint8 const *cb, uint8 const *cr, int count, int step);
-// compute a conversion from YCbCr to RGB
-// 'count' pixels
-// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B
-// y: Y input channel
-// cb: Cb input channel; scale/biased to be 0..255
-// cr: Cr input channel; scale/biased to be 0..255
-
-extern void stbi_install_idct(stbi_idct_8x8 func);
-extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func);
-#endif // STBI_SIMD
-
-#ifdef __cplusplus
-}
-#endif
-
-//
-//
-//// end header file /////////////////////////////////////////////////////
-#endif // STBI_INCLUDE_STB_IMAGE_H
-
-#ifndef STBI_HEADER_FILE_ONLY
-
-#ifndef STBI_NO_HDR
-#include <math.h> // ldexp
-#include <string.h> // strcmp
-#endif
-
-#ifndef STBI_NO_STDIO
-#include <stdio.h>
-#endif
-#include <stdlib.h>
-#include <memory.h>
-#include <assert.h>
-#include <stdarg.h>
-
-#ifndef _MSC_VER
- #ifdef __cplusplus
- #define __forceinline inline
- #else
- #define __forceinline
- #endif
-#endif
-
-
-// implementation:
-typedef unsigned char uint8;
-typedef unsigned short uint16;
-typedef signed short int16;
-typedef unsigned int uint32;
-typedef signed int int32;
-typedef unsigned int uint;
-
-// should produce compiler error if size is wrong
-typedef unsigned char validate_uint32[sizeof(uint32)==4];
-
-#if defined(STBI_NO_STDIO) && !defined(STBI_NO_WRITE)
-#define STBI_NO_WRITE
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Generic API that works on all image types
-//
-
-// this is not threadsafe
-static char *failure_reason;
-
-char *stbi_failure_reason(void)
-{
- return failure_reason;
-}
-
-static int e(char *str)
-{
- failure_reason = str;
- return 0;
-}
-
-#ifdef STBI_NO_FAILURE_STRINGS
- #define e(x,y) 0
-#elif defined(STBI_FAILURE_USERMSG)
- #define e(x,y) e(y)
-#else
- #define e(x,y) e(x)
-#endif
-
-#define epf(x,y) ((float *) (e(x,y)?NULL:NULL))
-#define epuc(x,y) ((unsigned char *) (e(x,y)?NULL:NULL))
-
-void stbi_image_free(void *retval_from_stbi_load)
-{
- free(retval_from_stbi_load);
-}
-
-#define MAX_LOADERS 32
-stbi_loader *loaders[MAX_LOADERS];
-static int max_loaders = 0;
-
-int stbi_register_loader(stbi_loader *loader)
-{
- int i;
- for (i=0; i < MAX_LOADERS; ++i) {
- // already present?
- if (loaders[i] == loader)
- return 1;
- // end of the list?
- if (loaders[i] == NULL) {
- loaders[i] = loader;
- max_loaders = i+1;
- return 1;
- }
- }
- // no room for it
- return 0;
-}
-
-#ifndef STBI_NO_HDR
-static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp);
-static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp);
-#endif
-
-#ifndef STBI_NO_STDIO
-unsigned char *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- FILE *f = fopen(filename, "rb");
- unsigned char *result;
- if (!f) return epuc("can't fopen", "Unable to open file");
- result = stbi_load_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return result;
-}
-
-unsigned char *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- int i;
- if (stbi_jpeg_test_file(f))
- return stbi_jpeg_load_from_file(f,x,y,comp,req_comp);
- if (stbi_png_test_file(f))
- return stbi_png_load_from_file(f,x,y,comp,req_comp);
- if (stbi_bmp_test_file(f))
- return stbi_bmp_load_from_file(f,x,y,comp,req_comp);
- if (stbi_psd_test_file(f))
- return stbi_psd_load_from_file(f,x,y,comp,req_comp);
- #ifndef STBI_NO_HDR
- if (stbi_hdr_test_file(f)) {
- float *hdr = stbi_hdr_load_from_file(f, x,y,comp,req_comp);
- return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
- }
- #endif
- for (i=0; i < max_loaders; ++i)
- if (loaders[i]->test_file(f))
- return loaders[i]->load_from_file(f,x,y,comp,req_comp);
- // test tga last because it's a crappy test!
- if (stbi_tga_test_file(f))
- return stbi_tga_load_from_file(f,x,y,comp,req_comp);
- return epuc("unknown image type", "Image not of any known type, or corrupt");
-}
-#endif
-
-unsigned char *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- int i;
- if (stbi_jpeg_test_memory(buffer,len))
- return stbi_jpeg_load_from_memory(buffer,len,x,y,comp,req_comp);
- if (stbi_png_test_memory(buffer,len))
- return stbi_png_load_from_memory(buffer,len,x,y,comp,req_comp);
- if (stbi_bmp_test_memory(buffer,len))
- return stbi_bmp_load_from_memory(buffer,len,x,y,comp,req_comp);
- if (stbi_psd_test_memory(buffer,len))
- return stbi_psd_load_from_memory(buffer,len,x,y,comp,req_comp);
- #ifndef STBI_NO_HDR
- if (stbi_hdr_test_memory(buffer, len)) {
- float *hdr = stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp);
- return hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
- }
- #endif
- for (i=0; i < max_loaders; ++i)
- if (loaders[i]->test_memory(buffer,len))
- return loaders[i]->load_from_memory(buffer,len,x,y,comp,req_comp);
- // test tga last because it's a crappy test!
- if (stbi_tga_test_memory(buffer,len))
- return stbi_tga_load_from_memory(buffer,len,x,y,comp,req_comp);
- return epuc("unknown image type", "Image not of any known type, or corrupt");
-}
-
-#ifndef STBI_NO_HDR
-
-#ifndef STBI_NO_STDIO
-float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- FILE *f = fopen(filename, "rb");
- float *result;
- if (!f) return epf("can't fopen", "Unable to open file");
- result = stbi_loadf_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return result;
-}
-
-float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- unsigned char *data;
- #ifndef STBI_NO_HDR
- if (stbi_hdr_test_file(f))
- return stbi_hdr_load_from_file(f,x,y,comp,req_comp);
- #endif
- data = stbi_load_from_file(f, x, y, comp, req_comp);
- if (data)
- return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
- return epf("unknown image type", "Image not of any known type, or corrupt");
-}
-#endif
-
-float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi_uc *data;
- #ifndef STBI_NO_HDR
- if (stbi_hdr_test_memory(buffer, len))
- return stbi_hdr_load_from_memory(buffer, len,x,y,comp,req_comp);
- #endif
- data = stbi_load_from_memory(buffer, len, x, y, comp, req_comp);
- if (data)
- return ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
- return epf("unknown image type", "Image not of any known type, or corrupt");
-}
-#endif
-
-// these is-hdr-or-not is defined independent of whether STBI_NO_HDR is
-// defined, for API simplicity; if STBI_NO_HDR is defined, it always
-// reports false!
-
-int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len)
-{
- #ifndef STBI_NO_HDR
- return stbi_hdr_test_memory(buffer, len);
- #else
- return 0;
- #endif
-}
-
-#ifndef STBI_NO_STDIO
-extern int stbi_is_hdr (char const *filename)
-{
- FILE *f = fopen(filename, "rb");
- int result=0;
- if (f) {
- result = stbi_is_hdr_from_file(f);
- fclose(f);
- }
- return result;
-}
-
-extern int stbi_is_hdr_from_file(FILE *f)
-{
- #ifndef STBI_NO_HDR
- return stbi_hdr_test_file(f);
- #else
- return 0;
- #endif
-}
-
-#endif
-
-// @TODO: get image dimensions & components without fully decoding
-#ifndef STBI_NO_STDIO
-extern int stbi_info (char const *filename, int *x, int *y, int *comp);
-extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-
-#ifndef STBI_NO_HDR
-static float h2l_gamma_i=1.0f/2.2f, h2l_scale_i=1.0f;
-static float l2h_gamma=2.2f, l2h_scale=1.0f;
-
-void stbi_hdr_to_ldr_gamma(float gamma) { h2l_gamma_i = 1/gamma; }
-void stbi_hdr_to_ldr_scale(float scale) { h2l_scale_i = 1/scale; }
-
-void stbi_ldr_to_hdr_gamma(float gamma) { l2h_gamma = gamma; }
-void stbi_ldr_to_hdr_scale(float scale) { l2h_scale = scale; }
-#endif
-
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Common code used by all image loaders
-//
-
-enum
-{
- SCAN_load=0,
- SCAN_type,
- SCAN_header,
-};
-
-typedef struct
-{
- uint32 img_x, img_y;
- int img_n, img_out_n;
-
- #ifndef STBI_NO_STDIO
- FILE *img_file;
- #endif
- uint8 *img_buffer, *img_buffer_end;
-} stbi;
-
-#ifndef STBI_NO_STDIO
-static void start_file(stbi *s, FILE *f)
-{
- s->img_file = f;
-}
-#endif
-
-static void start_mem(stbi *s, uint8 const *buffer, int len)
-{
-#ifndef STBI_NO_STDIO
- s->img_file = NULL;
-#endif
- s->img_buffer = (uint8 *) buffer;
- s->img_buffer_end = (uint8 *) buffer+len;
-}
-
-__forceinline static int get8(stbi *s)
-{
-#ifndef STBI_NO_STDIO
- if (s->img_file) {
- int c = fgetc(s->img_file);
- return c == EOF ? 0 : c;
- }
-#endif
- if (s->img_buffer < s->img_buffer_end)
- return *s->img_buffer++;
- return 0;
-}
-
-__forceinline static int at_eof(stbi *s)
-{
-#ifndef STBI_NO_STDIO
- if (s->img_file)
- return feof(s->img_file);
-#endif
- return s->img_buffer >= s->img_buffer_end;
-}
-
-__forceinline static uint8 get8u(stbi *s)
-{
- return (uint8) get8(s);
-}
-
-static void skip(stbi *s, int n)
-{
-#ifndef STBI_NO_STDIO
- if (s->img_file)
- fseek(s->img_file, n, SEEK_CUR);
- else
-#endif
- s->img_buffer += n;
-}
-
-static int get16(stbi *s)
-{
- int z = get8(s);
- return (z << 8) + get8(s);
-}
-
-static uint32 get32(stbi *s)
-{
- uint32 z = get16(s);
- return (z << 16) + get16(s);
-}
-
-static int get16le(stbi *s)
-{
- int z = get8(s);
- return z + (get8(s) << 8);
-}
-
-static uint32 get32le(stbi *s)
-{
- uint32 z = get16le(s);
- return z + (get16le(s) << 16);
-}
-
-static void getn(stbi *s, stbi_uc *buffer, int n)
-{
-#ifndef STBI_NO_STDIO
- if (s->img_file) {
- fread(buffer, 1, n, s->img_file);
- return;
- }
-#endif
- memcpy(buffer, s->img_buffer, n);
- s->img_buffer += n;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// generic converter from built-in img_n to req_comp
-// individual types do this automatically as much as possible (e.g. jpeg
-// does all cases internally since it needs to colorspace convert anyway,
-// and it never has alpha, so very few cases ). png can automatically
-// interleave an alpha=255 channel, but falls back to this for other cases
-//
-// assume data buffer is malloced, so malloc a new one and free that one
-// only failure mode is malloc failing
-
-static uint8 compute_y(int r, int g, int b)
-{
- return (uint8) (((r*77) + (g*150) + (29*b)) >> 8);
-}
-
-static unsigned char *convert_format(unsigned char *data, int img_n, int req_comp, uint x, uint y)
-{
- int i,j;
- unsigned char *good;
-
- if (req_comp == img_n) return data;
- assert(req_comp >= 1 && req_comp <= 4);
-
- good = (unsigned char *) malloc(req_comp * x * y);
- if (good == NULL) {
- free(data);
- return epuc("outofmem", "Out of memory");
- }
-
- for (j=0; j < (int) y; ++j) {
- unsigned char *src = data + j * x * img_n ;
- unsigned char *dest = good + j * x * req_comp;
-
- #define COMBO(a,b) ((a)*8+(b))
- #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
- // convert source image with img_n components to one with req_comp components;
- // avoid switch per pixel, so use switch per scanline and massive macros
- switch(COMBO(img_n, req_comp)) {
- CASE(1,2) dest[0]=src[0], dest[1]=255; break;
- CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break;
- CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break;
- CASE(2,1) dest[0]=src[0]; break;
- CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break;
- CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break;
- CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break;
- CASE(3,1) dest[0]=compute_y(src[0],src[1],src[2]); break;
- CASE(3,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = 255; break;
- CASE(4,1) dest[0]=compute_y(src[0],src[1],src[2]); break;
- CASE(4,2) dest[0]=compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break;
- CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break;
- default: assert(0);
- }
- #undef CASE
- }
-
- free(data);
- return good;
-}
-
-#ifndef STBI_NO_HDR
-static float *ldr_to_hdr(stbi_uc *data, int x, int y, int comp)
-{
- int i,k,n;
- float *output = (float *) malloc(x * y * comp * sizeof(float));
- if (output == NULL) { free(data); return epf("outofmem", "Out of memory"); }
- // compute number of non-alpha components
- if (comp & 1) n = comp; else n = comp-1;
- for (i=0; i < x*y; ++i) {
- for (k=0; k < n; ++k) {
- output[i*comp + k] = (float) pow(data[i*comp+k]/255.0f, l2h_gamma) * l2h_scale;
- }
- if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f;
- }
- free(data);
- return output;
-}
-
-#define float2int(x) ((int) (x))
-static stbi_uc *hdr_to_ldr(float *data, int x, int y, int comp)
-{
- int i,k,n;
- stbi_uc *output = (stbi_uc *) malloc(x * y * comp);
- if (output == NULL) { free(data); return epuc("outofmem", "Out of memory"); }
- // compute number of non-alpha components
- if (comp & 1) n = comp; else n = comp-1;
- for (i=0; i < x*y; ++i) {
- for (k=0; k < n; ++k) {
- float z = (float) pow(data[i*comp+k]*h2l_scale_i, h2l_gamma_i) * 255 + 0.5f;
- if (z < 0) z = 0;
- if (z > 255) z = 255;
- output[i*comp + k] = float2int(z);
- }
- if (k < comp) {
- float z = data[i*comp+k] * 255 + 0.5f;
- if (z < 0) z = 0;
- if (z > 255) z = 255;
- output[i*comp + k] = float2int(z);
- }
- }
- free(data);
- return output;
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// "baseline" JPEG/JFIF decoder (not actually fully baseline implementation)
-//
-// simple implementation
-// - channel subsampling of at most 2 in each dimension
-// - doesn't support delayed output of y-dimension
-// - simple interface (only one output format: 8-bit interleaved RGB)
-// - doesn't try to recover corrupt jpegs
-// - doesn't allow partial loading, loading multiple at once
-// - still fast on x86 (copying globals into locals doesn't help x86)
-// - allocates lots of intermediate memory (full size of all components)
-// - non-interleaved case requires this anyway
-// - allows good upsampling (see next)
-// high-quality
-// - upsampled channels are bilinearly interpolated, even across blocks
-// - quality integer IDCT derived from IJG's 'slow'
-// performance
-// - fast huffman; reasonable integer IDCT
-// - uses a lot of intermediate memory, could cache poorly
-// - load http://nothings.org/remote/anemones.jpg 3 times on 2.8Ghz P4
-// stb_jpeg: 1.34 seconds (MSVC6, default release build)
-// stb_jpeg: 1.06 seconds (MSVC6, processor = Pentium Pro)
-// IJL11.dll: 1.08 seconds (compiled by intel)
-// IJG 1998: 0.98 seconds (MSVC6, makefile provided by IJG)
-// IJG 1998: 0.95 seconds (MSVC6, makefile + proc=PPro)
-
-// huffman decoding acceleration
-#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache
-
-typedef struct
-{
- uint8 fast[1 << FAST_BITS];
- // weirdly, repacking this into AoS is a 10% speed loss, instead of a win
- uint16 code[256];
- uint8 values[256];
- uint8 size[257];
- unsigned int maxcode[18];
- int delta[17]; // old 'firstsymbol' - old 'firstcode'
-} huffman;
-
-typedef struct
-{
- #if STBI_SIMD
- unsigned short dequant2[4][64];
- #endif
- stbi s;
- huffman huff_dc[4];
- huffman huff_ac[4];
- uint8 dequant[4][64];
-
-// sizes for components, interleaved MCUs
- int img_h_max, img_v_max;
- int img_mcu_x, img_mcu_y;
- int img_mcu_w, img_mcu_h;
-
-// definition of jpeg image component
- struct
- {
- int id;
- int h,v;
- int tq;
- int hd,ha;
- int dc_pred;
-
- int x,y,w2,h2;
- uint8 *data;
- void *raw_data;
- uint8 *linebuf;
- } img_comp[4];
-
- uint32 code_buffer; // jpeg entropy-coded buffer
- int code_bits; // number of valid bits
- unsigned char marker; // marker seen while filling entropy buffer
- int nomore; // flag if we saw a marker so must stop
-
- int scan_n, order[4];
- int restart_interval, todo;
-} jpeg;
-
-static int build_huffman(huffman *h, int *count)
-{
- int i,j,k=0,code;
- // build size list for each symbol (from JPEG spec)
- for (i=0; i < 16; ++i)
- for (j=0; j < count[i]; ++j)
- h->size[k++] = (uint8) (i+1);
- h->size[k] = 0;
-
- // compute actual symbols (from jpeg spec)
- code = 0;
- k = 0;
- for(j=1; j <= 16; ++j) {
- // compute delta to add to code to compute symbol id
- h->delta[j] = k - code;
- if (h->size[k] == j) {
- while (h->size[k] == j)
- h->code[k++] = (uint16) (code++);
- if (code-1 >= (1 << j)) return e("bad code lengths","Corrupt JPEG");
- }
- // compute largest code + 1 for this size, preshifted as needed later
- h->maxcode[j] = code << (16-j);
- code <<= 1;
- }
- h->maxcode[j] = 0xffffffff;
-
- // build non-spec acceleration table; 255 is flag for not-accelerated
- memset(h->fast, 255, 1 << FAST_BITS);
- for (i=0; i < k; ++i) {
- int s = h->size[i];
- if (s <= FAST_BITS) {
- int c = h->code[i] << (FAST_BITS-s);
- int m = 1 << (FAST_BITS-s);
- for (j=0; j < m; ++j) {
- h->fast[c+j] = (uint8) i;
- }
- }
- }
- return 1;
-}
-
-static void grow_buffer_unsafe(jpeg *j)
-{
- do {
- int b = j->nomore ? 0 : get8(&j->s);
- if (b == 0xff) {
- int c = get8(&j->s);
- if (c != 0) {
- j->marker = (unsigned char) c;
- j->nomore = 1;
- return;
- }
- }
- j->code_buffer = (j->code_buffer << 8) | b;
- j->code_bits += 8;
- } while (j->code_bits <= 24);
-}
-
-// (1 << n) - 1
-static uint32 bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535};
-
-// decode a jpeg huffman value from the bitstream
-__forceinline static int decode(jpeg *j, huffman *h)
-{
- unsigned int temp;
- int c,k;
-
- if (j->code_bits < 16) grow_buffer_unsafe(j);
-
- // look at the top FAST_BITS and determine what symbol ID it is,
- // if the code is <= FAST_BITS
- c = (j->code_buffer >> (j->code_bits - FAST_BITS)) & ((1 << FAST_BITS)-1);
- k = h->fast[c];
- if (k < 255) {
- if (h->size[k] > j->code_bits)
- return -1;
- j->code_bits -= h->size[k];
- return h->values[k];
- }
-
- // naive test is to shift the code_buffer down so k bits are
- // valid, then test against maxcode. To speed this up, we've
- // preshifted maxcode left so that it has (16-k) 0s at the
- // end; in other words, regardless of the number of bits, it
- // wants to be compared against something shifted to have 16;
- // that way we don't need to shift inside the loop.
- if (j->code_bits < 16)
- temp = (j->code_buffer << (16 - j->code_bits)) & 0xffff;
- else
- temp = (j->code_buffer >> (j->code_bits - 16)) & 0xffff;
- for (k=FAST_BITS+1 ; ; ++k)
- if (temp < h->maxcode[k])
- break;
- if (k == 17) {
- // error! code not found
- j->code_bits -= 16;
- return -1;
- }
-
- if (k > j->code_bits)
- return -1;
-
- // convert the huffman code to the symbol id
- c = ((j->code_buffer >> (j->code_bits - k)) & bmask[k]) + h->delta[k];
- assert((((j->code_buffer) >> (j->code_bits - h->size[c])) & bmask[h->size[c]]) == h->code[c]);
-
- // convert the id to a symbol
- j->code_bits -= k;
- return h->values[c];
-}
-
-// combined JPEG 'receive' and JPEG 'extend', since baseline
-// always extends everything it receives.
-__forceinline static int extend_receive(jpeg *j, int n)
-{
- unsigned int m = 1 << (n-1);
- unsigned int k;
- if (j->code_bits < n) grow_buffer_unsafe(j);
- k = (j->code_buffer >> (j->code_bits - n)) & bmask[n];
- j->code_bits -= n;
- // the following test is probably a random branch that won't
- // predict well. I tried to table accelerate it but failed.
- // maybe it's compiling as a conditional move?
- if (k < m)
- return (-1 << n) + k + 1;
- else
- return k;
-}
-
-// given a value that's at position X in the zigzag stream,
-// where does it appear in the 8x8 matrix coded as row-major?
-static uint8 dezigzag[64+15] =
-{
- 0, 1, 8, 16, 9, 2, 3, 10,
- 17, 24, 32, 25, 18, 11, 4, 5,
- 12, 19, 26, 33, 40, 48, 41, 34,
- 27, 20, 13, 6, 7, 14, 21, 28,
- 35, 42, 49, 56, 57, 50, 43, 36,
- 29, 22, 15, 23, 30, 37, 44, 51,
- 58, 59, 52, 45, 38, 31, 39, 46,
- 53, 60, 61, 54, 47, 55, 62, 63,
- // let corrupt input sample past end
- 63, 63, 63, 63, 63, 63, 63, 63,
- 63, 63, 63, 63, 63, 63, 63
-};
-
-// decode one 64-entry block--
-static int decode_block(jpeg *j, short data[64], huffman *hdc, huffman *hac, int b)
-{
- int diff,dc,k;
- int t = decode(j, hdc);
- if (t < 0) return e("bad huffman code","Corrupt JPEG");
-
- // 0 all the ac values now so we can do it 32-bits at a time
- memset(data,0,64*sizeof(data[0]));
-
- diff = t ? extend_receive(j, t) : 0;
- dc = j->img_comp[b].dc_pred + diff;
- j->img_comp[b].dc_pred = dc;
- data[0] = (short) dc;
-
- // decode AC components, see JPEG spec
- k = 1;
- do {
- int r,s;
- int rs = decode(j, hac);
- if (rs < 0) return e("bad huffman code","Corrupt JPEG");
- s = rs & 15;
- r = rs >> 4;
- if (s == 0) {
- if (rs != 0xf0) break; // end block
- k += 16;
- } else {
- k += r;
- // decode into unzigzag'd location
- data[dezigzag[k++]] = (short) extend_receive(j,s);
- }
- } while (k < 64);
- return 1;
-}
-
-// take a -128..127 value and clamp it and convert to 0..255
-__forceinline static uint8 clamp(int x)
-{
- x += 128;
- // trick to use a single test to catch both cases
- if ((unsigned int) x > 255) {
- if (x < 0) return 0;
- if (x > 255) return 255;
- }
- return (uint8) x;
-}
-
-#define f2f(x) (int) (((x) * 4096 + 0.5))
-#define fsh(x) ((x) << 12)
-
-// derived from jidctint -- DCT_ISLOW
-#define IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \
- int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \
- p2 = s2; \
- p3 = s6; \
- p1 = (p2+p3) * f2f(0.5411961f); \
- t2 = p1 + p3*f2f(-1.847759065f); \
- t3 = p1 + p2*f2f( 0.765366865f); \
- p2 = s0; \
- p3 = s4; \
- t0 = fsh(p2+p3); \
- t1 = fsh(p2-p3); \
- x0 = t0+t3; \
- x3 = t0-t3; \
- x1 = t1+t2; \
- x2 = t1-t2; \
- t0 = s7; \
- t1 = s5; \
- t2 = s3; \
- t3 = s1; \
- p3 = t0+t2; \
- p4 = t1+t3; \
- p1 = t0+t3; \
- p2 = t1+t2; \
- p5 = (p3+p4)*f2f( 1.175875602f); \
- t0 = t0*f2f( 0.298631336f); \
- t1 = t1*f2f( 2.053119869f); \
- t2 = t2*f2f( 3.072711026f); \
- t3 = t3*f2f( 1.501321110f); \
- p1 = p5 + p1*f2f(-0.899976223f); \
- p2 = p5 + p2*f2f(-2.562915447f); \
- p3 = p3*f2f(-1.961570560f); \
- p4 = p4*f2f(-0.390180644f); \
- t3 += p1+p4; \
- t2 += p2+p3; \
- t1 += p2+p4; \
- t0 += p1+p3;
-
-#if !STBI_SIMD
-// .344 seconds on 3*anemones.jpg
-static void idct_block(uint8 *out, int out_stride, short data[64], uint8 *dequantize)
-{
- int i,val[64],*v=val;
- uint8 *o,*dq = dequantize;
- short *d = data;
-
- // columns
- for (i=0; i < 8; ++i,++d,++dq, ++v) {
- // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
- if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
- && d[40]==0 && d[48]==0 && d[56]==0) {
- // no shortcut 0 seconds
- // (1|2|3|4|5|6|7)==0 0 seconds
- // all separate -0.047 seconds
- // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds
- int dcterm = d[0] * dq[0] << 2;
- v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
- } else {
- IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24],
- d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56])
- // constants scaled things up by 1<<12; let's bring them back
- // down, but keep 2 extra bits of precision
- x0 += 512; x1 += 512; x2 += 512; x3 += 512;
- v[ 0] = (x0+t3) >> 10;
- v[56] = (x0-t3) >> 10;
- v[ 8] = (x1+t2) >> 10;
- v[48] = (x1-t2) >> 10;
- v[16] = (x2+t1) >> 10;
- v[40] = (x2-t1) >> 10;
- v[24] = (x3+t0) >> 10;
- v[32] = (x3-t0) >> 10;
- }
- }
-
- for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
- // no fast case since the first 1D IDCT spread components out
- IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
- // constants scaled things up by 1<<12, plus we had 1<<2 from first
- // loop, plus horizontal and vertical each scale by sqrt(8) so together
- // we've got an extra 1<<3, so 1<<17 total we need to remove.
- x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536;
- o[0] = clamp((x0+t3) >> 17);
- o[7] = clamp((x0-t3) >> 17);
- o[1] = clamp((x1+t2) >> 17);
- o[6] = clamp((x1-t2) >> 17);
- o[2] = clamp((x2+t1) >> 17);
- o[5] = clamp((x2-t1) >> 17);
- o[3] = clamp((x3+t0) >> 17);
- o[4] = clamp((x3-t0) >> 17);
- }
-}
-#else
-static void idct_block(uint8 *out, int out_stride, short data[64], unsigned short *dequantize)
-{
- int i,val[64],*v=val;
- uint8 *o;
- unsigned short *dq = dequantize;
- short *d = data;
-
- // columns
- for (i=0; i < 8; ++i,++d,++dq, ++v) {
- // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing
- if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0
- && d[40]==0 && d[48]==0 && d[56]==0) {
- // no shortcut 0 seconds
- // (1|2|3|4|5|6|7)==0 0 seconds
- // all separate -0.047 seconds
- // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds
- int dcterm = d[0] * dq[0] << 2;
- v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm;
- } else {
- IDCT_1D(d[ 0]*dq[ 0],d[ 8]*dq[ 8],d[16]*dq[16],d[24]*dq[24],
- d[32]*dq[32],d[40]*dq[40],d[48]*dq[48],d[56]*dq[56])
- // constants scaled things up by 1<<12; let's bring them back
- // down, but keep 2 extra bits of precision
- x0 += 512; x1 += 512; x2 += 512; x3 += 512;
- v[ 0] = (x0+t3) >> 10;
- v[56] = (x0-t3) >> 10;
- v[ 8] = (x1+t2) >> 10;
- v[48] = (x1-t2) >> 10;
- v[16] = (x2+t1) >> 10;
- v[40] = (x2-t1) >> 10;
- v[24] = (x3+t0) >> 10;
- v[32] = (x3-t0) >> 10;
- }
- }
-
- for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) {
- // no fast case since the first 1D IDCT spread components out
- IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7])
- // constants scaled things up by 1<<12, plus we had 1<<2 from first
- // loop, plus horizontal and vertical each scale by sqrt(8) so together
- // we've got an extra 1<<3, so 1<<17 total we need to remove.
- x0 += 65536; x1 += 65536; x2 += 65536; x3 += 65536;
- o[0] = clamp((x0+t3) >> 17);
- o[7] = clamp((x0-t3) >> 17);
- o[1] = clamp((x1+t2) >> 17);
- o[6] = clamp((x1-t2) >> 17);
- o[2] = clamp((x2+t1) >> 17);
- o[5] = clamp((x2-t1) >> 17);
- o[3] = clamp((x3+t0) >> 17);
- o[4] = clamp((x3-t0) >> 17);
- }
-}
-static stbi_idct_8x8 stbi_idct_installed = idct_block;
-
-extern void stbi_install_idct(stbi_idct_8x8 func)
-{
- stbi_idct_installed = func;
-}
-#endif
-
-#define MARKER_none 0xff
-// if there's a pending marker from the entropy stream, return that
-// otherwise, fetch from the stream and get a marker. if there's no
-// marker, return 0xff, which is never a valid marker value
-static uint8 get_marker(jpeg *j)
-{
- uint8 x;
- if (j->marker != MARKER_none) { x = j->marker; j->marker = MARKER_none; return x; }
- x = get8u(&j->s);
- if (x != 0xff) return MARKER_none;
- while (x == 0xff)
- x = get8u(&j->s);
- return x;
-}
-
-// in each scan, we'll have scan_n components, and the order
-// of the components is specified by order[]
-#define RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7)
-
-// after a restart interval, reset the entropy decoder and
-// the dc prediction
-static void reset(jpeg *j)
-{
- j->code_bits = 0;
- j->code_buffer = 0;
- j->nomore = 0;
- j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0;
- j->marker = MARKER_none;
- j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff;
- // no more than 1<<31 MCUs if no restart_interal? that's plenty safe,
- // since we don't even allow 1<<30 pixels
-}
-
-static int parse_entropy_coded_data(jpeg *z)
-{
- reset(z);
- if (z->scan_n == 1) {
- int i,j;
- #if STBI_SIMD
- __declspec(align(16))
- #endif
- short data[64];
- int n = z->order[0];
- // non-interleaved data, we just need to process one block at a time,
- // in trivial scanline order
- // number of blocks to do just depends on how many actual "pixels" this
- // component has, independent of interleaved MCU blocking and such
- int w = (z->img_comp[n].x+7) >> 3;
- int h = (z->img_comp[n].y+7) >> 3;
- for (j=0; j < h; ++j) {
- for (i=0; i < w; ++i) {
- if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0;
- #if STBI_SIMD
- stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]);
- #else
- idct_block(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]);
- #endif
- // every data block is an MCU, so countdown the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) grow_buffer_unsafe(z);
- // if it's NOT a restart, then just bail, so we get corrupt data
- // rather than no data
- if (!RESTART(z->marker)) return 1;
- reset(z);
- }
- }
- }
- } else { // interleaved!
- int i,j,k,x,y;
- short data[64];
- for (j=0; j < z->img_mcu_y; ++j) {
- for (i=0; i < z->img_mcu_x; ++i) {
- // scan an interleaved mcu... process scan_n components in order
- for (k=0; k < z->scan_n; ++k) {
- int n = z->order[k];
- // scan out an mcu's worth of this component; that's just determined
- // by the basic H and V specified for the component
- for (y=0; y < z->img_comp[n].v; ++y) {
- for (x=0; x < z->img_comp[n].h; ++x) {
- int x2 = (i*z->img_comp[n].h + x)*8;
- int y2 = (j*z->img_comp[n].v + y)*8;
- if (!decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+z->img_comp[n].ha, n)) return 0;
- #if STBI_SIMD
- stbi_idct_installed(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant2[z->img_comp[n].tq]);
- #else
- idct_block(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data, z->dequant[z->img_comp[n].tq]);
- #endif
- }
- }
- }
- // after all interleaved components, that's an interleaved MCU,
- // so now count down the restart interval
- if (--z->todo <= 0) {
- if (z->code_bits < 24) grow_buffer_unsafe(z);
- // if it's NOT a restart, then just bail, so we get corrupt data
- // rather than no data
- if (!RESTART(z->marker)) return 1;
- reset(z);
- }
- }
- }
- }
- return 1;
-}
-
-static int process_marker(jpeg *z, int m)
-{
- int L;
- switch (m) {
- case MARKER_none: // no marker found
- return e("expected marker","Corrupt JPEG");
-
- case 0xC2: // SOF - progressive
- return e("progressive jpeg","JPEG format not supported (progressive)");
-
- case 0xDD: // DRI - specify restart interval
- if (get16(&z->s) != 4) return e("bad DRI len","Corrupt JPEG");
- z->restart_interval = get16(&z->s);
- return 1;
-
- case 0xDB: // DQT - define quantization table
- L = get16(&z->s)-2;
- while (L > 0) {
- int q = get8(&z->s);
- int p = q >> 4;
- int t = q & 15,i;
- if (p != 0) return e("bad DQT type","Corrupt JPEG");
- if (t > 3) return e("bad DQT table","Corrupt JPEG");
- for (i=0; i < 64; ++i)
- z->dequant[t][dezigzag[i]] = get8u(&z->s);
- #if STBI_SIMD
- for (i=0; i < 64; ++i)
- z->dequant2[t][i] = z->dequant[t][i];
- #endif
- L -= 65;
- }
- return L==0;
-
- case 0xC4: // DHT - define huffman table
- L = get16(&z->s)-2;
- while (L > 0) {
- uint8 *v;
- int sizes[16],i,m=0;
- int q = get8(&z->s);
- int tc = q >> 4;
- int th = q & 15;
- if (tc > 1 || th > 3) return e("bad DHT header","Corrupt JPEG");
- for (i=0; i < 16; ++i) {
- sizes[i] = get8(&z->s);
- m += sizes[i];
- }
- L -= 17;
- if (tc == 0) {
- if (!build_huffman(z->huff_dc+th, sizes)) return 0;
- v = z->huff_dc[th].values;
- } else {
- if (!build_huffman(z->huff_ac+th, sizes)) return 0;
- v = z->huff_ac[th].values;
- }
- for (i=0; i < m; ++i)
- v[i] = get8u(&z->s);
- L -= m;
- }
- return L==0;
- }
- // check for comment block or APP blocks
- if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) {
- skip(&z->s, get16(&z->s)-2);
- return 1;
- }
- return 0;
-}
-
-// after we see SOS
-static int process_scan_header(jpeg *z)
-{
- int i;
- int Ls = get16(&z->s);
- z->scan_n = get8(&z->s);
- if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s.img_n) return e("bad SOS component count","Corrupt JPEG");
- if (Ls != 6+2*z->scan_n) return e("bad SOS len","Corrupt JPEG");
- for (i=0; i < z->scan_n; ++i) {
- int id = get8(&z->s), which;
- int q = get8(&z->s);
- for (which = 0; which < z->s.img_n; ++which)
- if (z->img_comp[which].id == id)
- break;
- if (which == z->s.img_n) return 0;
- z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return e("bad DC huff","Corrupt JPEG");
- z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return e("bad AC huff","Corrupt JPEG");
- z->order[i] = which;
- }
- if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG");
- get8(&z->s); // should be 63, but might be 0
- if (get8(&z->s) != 0) return e("bad SOS","Corrupt JPEG");
-
- return 1;
-}
-
-static int process_frame_header(jpeg *z, int scan)
-{
- stbi *s = &z->s;
- int Lf,p,i,q, h_max=1,v_max=1,c;
- Lf = get16(s); if (Lf < 11) return e("bad SOF len","Corrupt JPEG"); // JPEG
- p = get8(s); if (p != 8) return e("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline
- s->img_y = get16(s); if (s->img_y == 0) return e("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG
- s->img_x = get16(s); if (s->img_x == 0) return e("0 width","Corrupt JPEG"); // JPEG requires
- c = get8(s);
- if (c != 3 && c != 1) return e("bad component count","Corrupt JPEG"); // JFIF requires
- s->img_n = c;
- for (i=0; i < c; ++i) {
- z->img_comp[i].data = NULL;
- z->img_comp[i].linebuf = NULL;
- }
-
- if (Lf != 8+3*s->img_n) return e("bad SOF len","Corrupt JPEG");
-
- for (i=0; i < s->img_n; ++i) {
- z->img_comp[i].id = get8(s);
- if (z->img_comp[i].id != i+1) // JFIF requires
- if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files!
- return e("bad component ID","Corrupt JPEG");
- q = get8(s);
- z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return e("bad H","Corrupt JPEG");
- z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return e("bad V","Corrupt JPEG");
- z->img_comp[i].tq = get8(s); if (z->img_comp[i].tq > 3) return e("bad TQ","Corrupt JPEG");
- }
-
- if (scan != SCAN_load) return 1;
-
- if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode");
-
- for (i=0; i < s->img_n; ++i) {
- if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h;
- if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v;
- }
-
- // compute interleaved mcu info
- z->img_h_max = h_max;
- z->img_v_max = v_max;
- z->img_mcu_w = h_max * 8;
- z->img_mcu_h = v_max * 8;
- z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w;
- z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h;
-
- for (i=0; i < s->img_n; ++i) {
- // number of effective pixels (e.g. for non-interleaved MCU)
- z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max;
- z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max;
- // to simplify generation, we'll allocate enough memory to decode
- // the bogus oversized data from using interleaved MCUs and their
- // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't
- // discard the extra data until colorspace conversion
- z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8;
- z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8;
- z->img_comp[i].raw_data = malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15);
- if (z->img_comp[i].raw_data == NULL) {
- for(--i; i >= 0; --i) {
- free(z->img_comp[i].raw_data);
- z->img_comp[i].data = NULL;
- }
- return e("outofmem", "Out of memory");
- }
- // align blocks for installable-idct using mmx/sse
- z->img_comp[i].data = (uint8*) (((size_t) z->img_comp[i].raw_data + 15) & ~15);
- z->img_comp[i].linebuf = NULL;
- }
-
- return 1;
-}
-
-// use comparisons since in some cases we handle more than one case (e.g. SOF)
-#define DNL(x) ((x) == 0xdc)
-#define SOI(x) ((x) == 0xd8)
-#define EOI(x) ((x) == 0xd9)
-#define SOF(x) ((x) == 0xc0 || (x) == 0xc1)
-#define SOS(x) ((x) == 0xda)
-
-static int decode_jpeg_header(jpeg *z, int scan)
-{
- int m;
- z->marker = MARKER_none; // initialize cached marker to empty
- m = get_marker(z);
- if (!SOI(m)) return e("no SOI","Corrupt JPEG");
- if (scan == SCAN_type) return 1;
- m = get_marker(z);
- while (!SOF(m)) {
- if (!process_marker(z,m)) return 0;
- m = get_marker(z);
- while (m == MARKER_none) {
- // some files have extra padding after their blocks, so ok, we'll scan
- if (at_eof(&z->s)) return e("no SOF", "Corrupt JPEG");
- m = get_marker(z);
- }
- }
- if (!process_frame_header(z, scan)) return 0;
- return 1;
-}
-
-static int decode_jpeg_image(jpeg *j)
-{
- int m;
- j->restart_interval = 0;
- if (!decode_jpeg_header(j, SCAN_load)) return 0;
- m = get_marker(j);
- while (!EOI(m)) {
- if (SOS(m)) {
- if (!process_scan_header(j)) return 0;
- if (!parse_entropy_coded_data(j)) return 0;
- } else {
- if (!process_marker(j, m)) return 0;
- }
- m = get_marker(j);
- }
- return 1;
-}
-
-// static jfif-centered resampling (across block boundaries)
-
-typedef uint8 *(*resample_row_func)(uint8 *out, uint8 *in0, uint8 *in1,
- int w, int hs);
-
-#define div4(x) ((uint8) ((x) >> 2))
-
-static uint8 *resample_row_1(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs)
-{
- return in_near;
-}
-
-static uint8* resample_row_v_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs)
-{
- // need to generate two samples vertically for every one in input
- int i;
- for (i=0; i < w; ++i)
- out[i] = div4(3*in_near[i] + in_far[i] + 2);
- return out;
-}
-
-static uint8* resample_row_h_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs)
-{
- // need to generate two samples horizontally for every one in input
- int i;
- uint8 *input = in_near;
- if (w == 1) {
- // if only one sample, can't do any interpolation
- out[0] = out[1] = input[0];
- return out;
- }
-
- out[0] = input[0];
- out[1] = div4(input[0]*3 + input[1] + 2);
- for (i=1; i < w-1; ++i) {
- int n = 3*input[i]+2;
- out[i*2+0] = div4(n+input[i-1]);
- out[i*2+1] = div4(n+input[i+1]);
- }
- out[i*2+0] = div4(input[w-2]*3 + input[w-1] + 2);
- out[i*2+1] = input[w-1];
- return out;
-}
-
-#define div16(x) ((uint8) ((x) >> 4))
-
-static uint8 *resample_row_hv_2(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs)
-{
- // need to generate 2x2 samples for every one in input
- int i,t0,t1;
- if (w == 1) {
- out[0] = out[1] = div4(3*in_near[0] + in_far[0] + 2);
- return out;
- }
-
- t1 = 3*in_near[0] + in_far[0];
- out[0] = div4(t1+2);
- for (i=1; i < w; ++i) {
- t0 = t1;
- t1 = 3*in_near[i]+in_far[i];
- out[i*2-1] = div16(3*t0 + t1 + 8);
- out[i*2 ] = div16(3*t1 + t0 + 8);
- }
- out[w*2-1] = div4(t1+2);
- return out;
-}
-
-static uint8 *resample_row_generic(uint8 *out, uint8 *in_near, uint8 *in_far, int w, int hs)
-{
- // resample with nearest-neighbor
- int i,j;
- for (i=0; i < w; ++i)
- for (j=0; j < hs; ++j)
- out[i*hs+j] = in_near[i];
- return out;
-}
-
-#define float2fixed(x) ((int) ((x) * 65536 + 0.5))
-
-// 0.38 seconds on 3*anemones.jpg (0.25 with processor = Pro)
-// VC6 without processor=Pro is generating multiple LEAs per multiply!
-static void YCbCr_to_RGB_row(uint8 *out, const uint8 *y, const uint8 *pcb, const uint8 *pcr, int count, int step)
-{
- int i;
- for (i=0; i < count; ++i) {
- int y_fixed = (y[i] << 16) + 32768; // rounding
- int r,g,b;
- int cr = pcr[i] - 128;
- int cb = pcb[i] - 128;
- r = y_fixed + cr*float2fixed(1.40200f);
- g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f);
- b = y_fixed + cb*float2fixed(1.77200f);
- r >>= 16;
- g >>= 16;
- b >>= 16;
- if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; }
- if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; }
- if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; }
- out[0] = (uint8)r;
- out[1] = (uint8)g;
- out[2] = (uint8)b;
- out[3] = 255;
- out += step;
- }
-}
-
-#if STBI_SIMD
-static stbi_YCbCr_to_RGB_run stbi_YCbCr_installed = YCbCr_to_RGB_row;
-
-void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func)
-{
- stbi_YCbCr_installed = func;
-}
-#endif
-
-
-// clean up the temporary component buffers
-static void cleanup_jpeg(jpeg *j)
-{
- int i;
- for (i=0; i < j->s.img_n; ++i) {
- if (j->img_comp[i].data) {
- free(j->img_comp[i].raw_data);
- j->img_comp[i].data = NULL;
- }
- if (j->img_comp[i].linebuf) {
- free(j->img_comp[i].linebuf);
- j->img_comp[i].linebuf = NULL;
- }
- }
-}
-
-typedef struct
-{
- resample_row_func resample;
- uint8 *line0,*line1;
- int hs,vs; // expansion factor in each axis
- int w_lores; // horizontal pixels pre-expansion
- int ystep; // how far through vertical expansion we are
- int ypos; // which pre-expansion row we're on
-} stbi_resample;
-
-static uint8 *load_jpeg_image(jpeg *z, int *out_x, int *out_y, int *comp, int req_comp)
-{
- int n, decode_n;
- // validate req_comp
- if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error");
- z->s.img_n = 0;
-
- // load a jpeg image from whichever source
- if (!decode_jpeg_image(z)) { cleanup_jpeg(z); return NULL; }
-
- // determine actual number of components to generate
- n = req_comp ? req_comp : z->s.img_n;
-
- if (z->s.img_n == 3 && n < 3)
- decode_n = 1;
- else
- decode_n = z->s.img_n;
-
- // resample and color-convert
- {
- int k;
- uint i,j;
- uint8 *output;
- uint8 *coutput[4];
-
- stbi_resample res_comp[4];
-
- for (k=0; k < decode_n; ++k) {
- stbi_resample *r = &res_comp[k];
-
- // allocate line buffer big enough for upsampling off the edges
- // with upsample factor of 4
- z->img_comp[k].linebuf = (uint8 *) malloc(z->s.img_x + 3);
- if (!z->img_comp[k].linebuf) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); }
-
- r->hs = z->img_h_max / z->img_comp[k].h;
- r->vs = z->img_v_max / z->img_comp[k].v;
- r->ystep = r->vs >> 1;
- r->w_lores = (z->s.img_x + r->hs-1) / r->hs;
- r->ypos = 0;
- r->line0 = r->line1 = z->img_comp[k].data;
-
- if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1;
- else if (r->hs == 1 && r->vs == 2) r->resample = resample_row_v_2;
- else if (r->hs == 2 && r->vs == 1) r->resample = resample_row_h_2;
- else if (r->hs == 2 && r->vs == 2) r->resample = resample_row_hv_2;
- else r->resample = resample_row_generic;
- }
-
- // can't error after this so, this is safe
- output = (uint8 *) malloc(n * z->s.img_x * z->s.img_y + 1);
- if (!output) { cleanup_jpeg(z); return epuc("outofmem", "Out of memory"); }
-
- // now go ahead and resample
- for (j=0; j < z->s.img_y; ++j) {
- uint8 *out = output + n * z->s.img_x * j;
- for (k=0; k < decode_n; ++k) {
- stbi_resample *r = &res_comp[k];
- int y_bot = r->ystep >= (r->vs >> 1);
- coutput[k] = r->resample(z->img_comp[k].linebuf,
- y_bot ? r->line1 : r->line0,
- y_bot ? r->line0 : r->line1,
- r->w_lores, r->hs);
- if (++r->ystep >= r->vs) {
- r->ystep = 0;
- r->line0 = r->line1;
- if (++r->ypos < z->img_comp[k].y)
- r->line1 += z->img_comp[k].w2;
- }
- }
- if (n >= 3) {
- uint8 *y = coutput[0];
- if (z->s.img_n == 3) {
- #if STBI_SIMD
- stbi_YCbCr_installed(out, y, coutput[1], coutput[2], z->s.img_x, n);
- #else
- YCbCr_to_RGB_row(out, y, coutput[1], coutput[2], z->s.img_x, n);
- #endif
- } else
- for (i=0; i < z->s.img_x; ++i) {
- out[0] = out[1] = out[2] = y[i];
- out[3] = 255; // not used if n==3
- out += n;
- }
- } else {
- uint8 *y = coutput[0];
- if (n == 1)
- for (i=0; i < z->s.img_x; ++i) out[i] = y[i];
- else
- for (i=0; i < z->s.img_x; ++i) *out++ = y[i], *out++ = 255;
- }
- }
- cleanup_jpeg(z);
- *out_x = z->s.img_x;
- *out_y = z->s.img_y;
- if (comp) *comp = z->s.img_n; // report original components, not output
- return output;
- }
-}
-
-#ifndef STBI_NO_STDIO
-unsigned char *stbi_jpeg_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- jpeg j;
- start_file(&j.s, f);
- return load_jpeg_image(&j, x,y,comp,req_comp);
-}
-
-unsigned char *stbi_jpeg_load(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- unsigned char *data;
- FILE *f = fopen(filename, "rb");
- if (!f) return NULL;
- data = stbi_jpeg_load_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return data;
-}
-#endif
-
-unsigned char *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- jpeg j;
- start_mem(&j.s, buffer,len);
- return load_jpeg_image(&j, x,y,comp,req_comp);
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_jpeg_test_file(FILE *f)
-{
- int n,r;
- jpeg j;
- n = ftell(f);
- start_file(&j.s, f);
- r = decode_jpeg_header(&j, SCAN_type);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-int stbi_jpeg_test_memory(stbi_uc const *buffer, int len)
-{
- jpeg j;
- start_mem(&j.s, buffer,len);
- return decode_jpeg_header(&j, SCAN_type);
-}
-
-// @TODO:
-#ifndef STBI_NO_STDIO
-extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp);
-extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-
-// public domain zlib decode v0.2 Sean Barrett 2006-11-18
-// simple implementation
-// - all input must be provided in an upfront buffer
-// - all output is written to a single output buffer (can malloc/realloc)
-// performance
-// - fast huffman
-
-// fast-way is faster to check than jpeg huffman, but slow way is slower
-#define ZFAST_BITS 9 // accelerate all cases in default tables
-#define ZFAST_MASK ((1 << ZFAST_BITS) - 1)
-
-// zlib-style huffman encoding
-// (jpegs packs from left, zlib from right, so can't share code)
-typedef struct
-{
- uint16 fast[1 << ZFAST_BITS];
- uint16 firstcode[16];
- int maxcode[17];
- uint16 firstsymbol[16];
- uint8 size[288];
- uint16 value[288];
-} zhuffman;
-
-__forceinline static int bitreverse16(int n)
-{
- n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1);
- n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2);
- n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4);
- n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8);
- return n;
-}
-
-__forceinline static int bit_reverse(int v, int bits)
-{
- assert(bits <= 16);
- // to bit reverse n bits, reverse 16 and shift
- // e.g. 11 bits, bit reverse and shift away 5
- return bitreverse16(v) >> (16-bits);
-}
-
-static int zbuild_huffman(zhuffman *z, uint8 *sizelist, int num)
-{
- int i,k=0;
- int code, next_code[16], sizes[17];
-
- // DEFLATE spec for generating codes
- memset(sizes, 0, sizeof(sizes));
- memset(z->fast, 255, sizeof(z->fast));
- for (i=0; i < num; ++i)
- ++sizes[sizelist[i]];
- sizes[0] = 0;
- for (i=1; i < 16; ++i)
- assert(sizes[i] <= (1 << i));
- code = 0;
- for (i=1; i < 16; ++i) {
- next_code[i] = code;
- z->firstcode[i] = (uint16) code;
- z->firstsymbol[i] = (uint16) k;
- code = (code + sizes[i]);
- if (sizes[i])
- if (code-1 >= (1 << i)) return e("bad codelengths","Corrupt JPEG");
- z->maxcode[i] = code << (16-i); // preshift for inner loop
- code <<= 1;
- k += sizes[i];
- }
- z->maxcode[16] = 0x10000; // sentinel
- for (i=0; i < num; ++i) {
- int s = sizelist[i];
- if (s) {
- int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s];
- z->size[c] = (uint8)s;
- z->value[c] = (uint16)i;
- if (s <= ZFAST_BITS) {
- int k = bit_reverse(next_code[s],s);
- while (k < (1 << ZFAST_BITS)) {
- z->fast[k] = (uint16) c;
- k += (1 << s);
- }
- }
- ++next_code[s];
- }
- }
- return 1;
-}
-
-// zlib-from-memory implementation for PNG reading
-// because PNG allows splitting the zlib stream arbitrarily,
-// and it's annoying structurally to have PNG call ZLIB call PNG,
-// we require PNG read all the IDATs and combine them into a single
-// memory buffer
-
-typedef struct
-{
- uint8 *zbuffer, *zbuffer_end;
- int num_bits;
- uint32 code_buffer;
-
- char *zout;
- char *zout_start;
- char *zout_end;
- int z_expandable;
-
- zhuffman z_length, z_distance;
-} zbuf;
-
-__forceinline static int zget8(zbuf *z)
-{
- if (z->zbuffer >= z->zbuffer_end) return 0;
- return *z->zbuffer++;
-}
-
-static void fill_bits(zbuf *z)
-{
- do {
- assert(z->code_buffer < (1U << z->num_bits));
- z->code_buffer |= zget8(z) << z->num_bits;
- z->num_bits += 8;
- } while (z->num_bits <= 24);
-}
-
-__forceinline static unsigned int zreceive(zbuf *z, int n)
-{
- unsigned int k;
- if (z->num_bits < n) fill_bits(z);
- k = z->code_buffer & ((1 << n) - 1);
- z->code_buffer >>= n;
- z->num_bits -= n;
- return k;
-}
-
-__forceinline static int zhuffman_decode(zbuf *a, zhuffman *z)
-{
- int b,s,k;
- if (a->num_bits < 16) fill_bits(a);
- b = z->fast[a->code_buffer & ZFAST_MASK];
- if (b < 0xffff) {
- s = z->size[b];
- a->code_buffer >>= s;
- a->num_bits -= s;
- return z->value[b];
- }
-
- // not resolved by fast table, so compute it the slow way
- // use jpeg approach, which requires MSbits at top
- k = bit_reverse(a->code_buffer, 16);
- for (s=ZFAST_BITS+1; ; ++s)
- if (k < z->maxcode[s])
- break;
- if (s == 16) return -1; // invalid code!
- // code size is s, so:
- b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s];
- assert(z->size[b] == s);
- a->code_buffer >>= s;
- a->num_bits -= s;
- return z->value[b];
-}
-
-static int expand(zbuf *z, int n) // need to make room for n bytes
-{
- char *q;
- int cur, limit;
- if (!z->z_expandable) return e("output buffer limit","Corrupt PNG");
- cur = (int) (z->zout - z->zout_start);
- limit = (int) (z->zout_end - z->zout_start);
- while (cur + n > limit)
- limit *= 2;
- q = (char *) realloc(z->zout_start, limit);
- if (q == NULL) return e("outofmem", "Out of memory");
- z->zout_start = q;
- z->zout = q + cur;
- z->zout_end = q + limit;
- return 1;
-}
-
-static int length_base[31] = {
- 3,4,5,6,7,8,9,10,11,13,
- 15,17,19,23,27,31,35,43,51,59,
- 67,83,99,115,131,163,195,227,258,0,0 };
-
-static int length_extra[31]=
-{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 };
-
-static int dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,
-257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0};
-
-static int dist_extra[32] =
-{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
-
-static int parse_huffman_block(zbuf *a)
-{
- for(;;) {
- int z = zhuffman_decode(a, &a->z_length);
- if (z < 256) {
- if (z < 0) return e("bad huffman code","Corrupt PNG"); // error in huffman codes
- if (a->zout >= a->zout_end) if (!expand(a, 1)) return 0;
- *a->zout++ = (char) z;
- } else {
- uint8 *p;
- int len,dist;
- if (z == 256) return 1;
- z -= 257;
- len = length_base[z];
- if (length_extra[z]) len += zreceive(a, length_extra[z]);
- z = zhuffman_decode(a, &a->z_distance);
- if (z < 0) return e("bad huffman code","Corrupt PNG");
- dist = dist_base[z];
- if (dist_extra[z]) dist += zreceive(a, dist_extra[z]);
- if (a->zout - a->zout_start < dist) return e("bad dist","Corrupt PNG");
- if (a->zout + len > a->zout_end) if (!expand(a, len)) return 0;
- p = (uint8 *) (a->zout - dist);
- while (len--)
- *a->zout++ = *p++;
- }
- }
-}
-
-static int compute_huffman_codes(zbuf *a)
-{
- static uint8 length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
- zhuffman z_codelength;
- uint8 lencodes[286+32+137];//padding for maximum single op
- uint8 codelength_sizes[19];
- int i,n;
-
- int hlit = zreceive(a,5) + 257;
- int hdist = zreceive(a,5) + 1;
- int hclen = zreceive(a,4) + 4;
-
- memset(codelength_sizes, 0, sizeof(codelength_sizes));
- for (i=0; i < hclen; ++i) {
- int s = zreceive(a,3);
- codelength_sizes[length_dezigzag[i]] = (uint8) s;
- }
- if (!zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0;
-
- n = 0;
- while (n < hlit + hdist) {
- int c = zhuffman_decode(a, &z_codelength);
- assert(c >= 0 && c < 19);
- if (c < 16)
- lencodes[n++] = (uint8) c;
- else if (c == 16) {
- c = zreceive(a,2)+3;
- memset(lencodes+n, lencodes[n-1], c);
- n += c;
- } else if (c == 17) {
- c = zreceive(a,3)+3;
- memset(lencodes+n, 0, c);
- n += c;
- } else {
- assert(c == 18);
- c = zreceive(a,7)+11;
- memset(lencodes+n, 0, c);
- n += c;
- }
- }
- if (n != hlit+hdist) return e("bad codelengths","Corrupt PNG");
- if (!zbuild_huffman(&a->z_length, lencodes, hlit)) return 0;
- if (!zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0;
- return 1;
-}
-
-static int parse_uncompressed_block(zbuf *a)
-{
- uint8 header[4];
- int len,nlen,k;
- if (a->num_bits & 7)
- zreceive(a, a->num_bits & 7); // discard
- // drain the bit-packed data into header
- k = 0;
- while (a->num_bits > 0) {
- header[k++] = (uint8) (a->code_buffer & 255); // wtf this warns?
- a->code_buffer >>= 8;
- a->num_bits -= 8;
- }
- assert(a->num_bits == 0);
- // now fill header the normal way
- while (k < 4)
- header[k++] = (uint8) zget8(a);
- len = header[1] * 256 + header[0];
- nlen = header[3] * 256 + header[2];
- if (nlen != (len ^ 0xffff)) return e("zlib corrupt","Corrupt PNG");
- if (a->zbuffer + len > a->zbuffer_end) return e("read past buffer","Corrupt PNG");
- if (a->zout + len > a->zout_end)
- if (!expand(a, len)) return 0;
- memcpy(a->zout, a->zbuffer, len);
- a->zbuffer += len;
- a->zout += len;
- return 1;
-}
-
-static int parse_zlib_header(zbuf *a)
-{
- int cmf = zget8(a);
- int cm = cmf & 15;
- /* int cinfo = cmf >> 4; */
- int flg = zget8(a);
- if ((cmf*256+flg) % 31 != 0) return e("bad zlib header","Corrupt PNG"); // zlib spec
- if (flg & 32) return e("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png
- if (cm != 8) return e("bad compression","Corrupt PNG"); // DEFLATE required for png
- // window = 1 << (8 + cinfo)... but who cares, we fully buffer output
- return 1;
-}
-
-// @TODO: should statically initialize these for optimal thread safety
-static uint8 default_length[288], default_distance[32];
-static void init_defaults(void)
-{
- int i; // use <= to match clearly with spec
- for (i=0; i <= 143; ++i) default_length[i] = 8;
- for ( ; i <= 255; ++i) default_length[i] = 9;
- for ( ; i <= 279; ++i) default_length[i] = 7;
- for ( ; i <= 287; ++i) default_length[i] = 8;
-
- for (i=0; i <= 31; ++i) default_distance[i] = 5;
-}
-
-int stbi_png_partial; // a quick hack to only allow decoding some of a PNG... I should implement real streaming support instead
-static int parse_zlib(zbuf *a, int parse_header)
-{
- int final, type;
- if (parse_header)
- if (!parse_zlib_header(a)) return 0;
- a->num_bits = 0;
- a->code_buffer = 0;
- do {
- final = zreceive(a,1);
- type = zreceive(a,2);
- if (type == 0) {
- if (!parse_uncompressed_block(a)) return 0;
- } else if (type == 3) {
- return 0;
- } else {
- if (type == 1) {
- // use fixed code lengths
- if (!default_distance[31]) init_defaults();
- if (!zbuild_huffman(&a->z_length , default_length , 288)) return 0;
- if (!zbuild_huffman(&a->z_distance, default_distance, 32)) return 0;
- } else {
- if (!compute_huffman_codes(a)) return 0;
- }
- if (!parse_huffman_block(a)) return 0;
- }
- if (stbi_png_partial && a->zout - a->zout_start > 65536)
- break;
- } while (!final);
- return 1;
-}
-
-static int do_zlib(zbuf *a, char *obuf, int olen, int exp, int parse_header)
-{
- a->zout_start = obuf;
- a->zout = obuf;
- a->zout_end = obuf + olen;
- a->z_expandable = exp;
-
- return parse_zlib(a, parse_header);
-}
-
-char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen)
-{
- zbuf a;
- char *p = (char *) malloc(initial_size);
- if (p == NULL) return NULL;
- a.zbuffer = (uint8 *) buffer;
- a.zbuffer_end = (uint8 *) buffer + len;
- if (do_zlib(&a, p, initial_size, 1, 1)) {
- if (outlen) *outlen = (int) (a.zout - a.zout_start);
- return a.zout_start;
- } else {
- free(a.zout_start);
- return NULL;
- }
-}
-
-char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen)
-{
- return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen);
-}
-
-int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen)
-{
- zbuf a;
- a.zbuffer = (uint8 *) ibuffer;
- a.zbuffer_end = (uint8 *) ibuffer + ilen;
- if (do_zlib(&a, obuffer, olen, 0, 1))
- return (int) (a.zout - a.zout_start);
- else
- return -1;
-}
-
-char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen)
-{
- zbuf a;
- char *p = (char *) malloc(16384);
- if (p == NULL) return NULL;
- a.zbuffer = (uint8 *) buffer;
- a.zbuffer_end = (uint8 *) buffer+len;
- if (do_zlib(&a, p, 16384, 1, 0)) {
- if (outlen) *outlen = (int) (a.zout - a.zout_start);
- return a.zout_start;
- } else {
- free(a.zout_start);
- return NULL;
- }
-}
-
-int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen)
-{
- zbuf a;
- a.zbuffer = (uint8 *) ibuffer;
- a.zbuffer_end = (uint8 *) ibuffer + ilen;
- if (do_zlib(&a, obuffer, olen, 0, 0))
- return (int) (a.zout - a.zout_start);
- else
- return -1;
-}
-
-// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18
-// simple implementation
-// - only 8-bit samples
-// - no CRC checking
-// - allocates lots of intermediate memory
-// - avoids problem of streaming data between subsystems
-// - avoids explicit window management
-// performance
-// - uses stb_zlib, a PD zlib implementation with fast huffman decoding
-
-
-typedef struct
-{
- uint32 length;
- uint32 type;
-} chunk;
-
-#define PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d))
-
-static chunk get_chunk_header(stbi *s)
-{
- chunk c;
- c.length = get32(s);
- c.type = get32(s);
- return c;
-}
-
-static int check_png_header(stbi *s)
-{
- static uint8 png_sig[8] = { 137,80,78,71,13,10,26,10 };
- int i;
- for (i=0; i < 8; ++i)
- if (get8(s) != png_sig[i]) return e("bad png sig","Not a PNG");
- return 1;
-}
-
-typedef struct
-{
- stbi s;
- uint8 *idata, *expanded, *out;
-} png;
-
-
-enum {
- F_none=0, F_sub=1, F_up=2, F_avg=3, F_paeth=4,
- F_avg_first, F_paeth_first,
-};
-
-static uint8 first_row_filter[5] =
-{
- F_none, F_sub, F_none, F_avg_first, F_paeth_first
-};
-
-static int paeth(int a, int b, int c)
-{
- int p = a + b - c;
- int pa = abs(p-a);
- int pb = abs(p-b);
- int pc = abs(p-c);
- if (pa <= pb && pa <= pc) return a;
- if (pb <= pc) return b;
- return c;
-}
-
-// create the png data from post-deflated data
-static int create_png_image_raw(png *a, uint8 *raw, uint32 raw_len, int out_n, uint32 x, uint32 y)
-{
- stbi *s = &a->s;
- uint32 i,j,stride = x*out_n;
- int k;
- int img_n = s->img_n; // copy it into a local for later
- assert(out_n == s->img_n || out_n == s->img_n+1);
- if (stbi_png_partial) y = 1;
- a->out = (uint8 *) malloc(x * y * out_n);
- if (!a->out) return e("outofmem", "Out of memory");
- if (!stbi_png_partial) {
- if (s->img_x == x && s->img_y == y)
- if (raw_len != (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG");
- else // interlaced:
- if (raw_len < (img_n * x + 1) * y) return e("not enough pixels","Corrupt PNG");
- }
- for (j=0; j < y; ++j) {
- uint8 *cur = a->out + stride*j;
- uint8 *prior = cur - stride;
- int filter = *raw++;
- if (filter > 4) return e("invalid filter","Corrupt PNG");
- // if first row, use special filter that doesn't sample previous row
- if (j == 0) filter = first_row_filter[filter];
- // handle first pixel explicitly
- for (k=0; k < img_n; ++k) {
- switch(filter) {
- case F_none : cur[k] = raw[k]; break;
- case F_sub : cur[k] = raw[k]; break;
- case F_up : cur[k] = raw[k] + prior[k]; break;
- case F_avg : cur[k] = raw[k] + (prior[k]>>1); break;
- case F_paeth : cur[k] = (uint8) (raw[k] + paeth(0,prior[k],0)); break;
- case F_avg_first : cur[k] = raw[k]; break;
- case F_paeth_first: cur[k] = raw[k]; break;
- }
- }
- if (img_n != out_n) cur[img_n] = 255;
- raw += img_n;
- cur += out_n;
- prior += out_n;
- // this is a little gross, so that we don't switch per-pixel or per-component
- if (img_n == out_n) {
- #define CASE(f) \
- case f: \
- for (i=x-1; i >= 1; --i, raw+=img_n,cur+=img_n,prior+=img_n) \
- for (k=0; k < img_n; ++k)
- switch(filter) {
- CASE(F_none) cur[k] = raw[k]; break;
- CASE(F_sub) cur[k] = raw[k] + cur[k-img_n]; break;
- CASE(F_up) cur[k] = raw[k] + prior[k]; break;
- CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-img_n])>>1); break;
- CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],prior[k],prior[k-img_n])); break;
- CASE(F_avg_first) cur[k] = raw[k] + (cur[k-img_n] >> 1); break;
- CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-img_n],0,0)); break;
- }
- #undef CASE
- } else {
- assert(img_n+1 == out_n);
- #define CASE(f) \
- case f: \
- for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \
- for (k=0; k < img_n; ++k)
- switch(filter) {
- CASE(F_none) cur[k] = raw[k]; break;
- CASE(F_sub) cur[k] = raw[k] + cur[k-out_n]; break;
- CASE(F_up) cur[k] = raw[k] + prior[k]; break;
- CASE(F_avg) cur[k] = raw[k] + ((prior[k] + cur[k-out_n])>>1); break;
- CASE(F_paeth) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],prior[k],prior[k-out_n])); break;
- CASE(F_avg_first) cur[k] = raw[k] + (cur[k-out_n] >> 1); break;
- CASE(F_paeth_first) cur[k] = (uint8) (raw[k] + paeth(cur[k-out_n],0,0)); break;
- }
- #undef CASE
- }
- }
- return 1;
-}
-
-static int create_png_image(png *a, uint8 *raw, uint32 raw_len, int out_n, int interlaced)
-{
- uint8 *final;
- int p;
- int save;
- if (!interlaced)
- return create_png_image_raw(a, raw, raw_len, out_n, a->s.img_x, a->s.img_y);
- save = stbi_png_partial;
- stbi_png_partial = 0;
-
- // de-interlacing
- final = (uint8 *) malloc(a->s.img_x * a->s.img_y * out_n);
- for (p=0; p < 7; ++p) {
- int xorig[] = { 0,4,0,2,0,1,0 };
- int yorig[] = { 0,0,4,0,2,0,1 };
- int xspc[] = { 8,8,4,4,2,2,1 };
- int yspc[] = { 8,8,8,4,4,2,2 };
- int i,j,x,y;
- // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1
- x = (a->s.img_x - xorig[p] + xspc[p]-1) / xspc[p];
- y = (a->s.img_y - yorig[p] + yspc[p]-1) / yspc[p];
- if (x && y) {
- if (!create_png_image_raw(a, raw, raw_len, out_n, x, y)) {
- free(final);
- return 0;
- }
- for (j=0; j < y; ++j)
- for (i=0; i < x; ++i)
- memcpy(final + (j*yspc[p]+yorig[p])*a->s.img_x*out_n + (i*xspc[p]+xorig[p])*out_n,
- a->out + (j*x+i)*out_n, out_n);
- free(a->out);
- raw += (x*out_n+1)*y;
- raw_len -= (x*out_n+1)*y;
- }
- }
- a->out = final;
-
- stbi_png_partial = save;
- return 1;
-}
-
-static int compute_transparency(png *z, uint8 tc[3], int out_n)
-{
- stbi *s = &z->s;
- uint32 i, pixel_count = s->img_x * s->img_y;
- uint8 *p = z->out;
-
- // compute color-based transparency, assuming we've
- // already got 255 as the alpha value in the output
- assert(out_n == 2 || out_n == 4);
-
- if (out_n == 2) {
- for (i=0; i < pixel_count; ++i) {
- p[1] = (p[0] == tc[0] ? 0 : 255);
- p += 2;
- }
- } else {
- for (i=0; i < pixel_count; ++i) {
- if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
- p[3] = 0;
- p += 4;
- }
- }
- return 1;
-}
-
-static int expand_palette(png *a, uint8 *palette, int len, int pal_img_n)
-{
- uint32 i, pixel_count = a->s.img_x * a->s.img_y;
- uint8 *p, *temp_out, *orig = a->out;
-
- p = (uint8 *) malloc(pixel_count * pal_img_n);
- if (p == NULL) return e("outofmem", "Out of memory");
-
- // between here and free(out) below, exitting would leak
- temp_out = p;
-
- if (pal_img_n == 3) {
- for (i=0; i < pixel_count; ++i) {
- int n = orig[i]*4;
- p[0] = palette[n ];
- p[1] = palette[n+1];
- p[2] = palette[n+2];
- p += 3;
- }
- } else {
- for (i=0; i < pixel_count; ++i) {
- int n = orig[i]*4;
- p[0] = palette[n ];
- p[1] = palette[n+1];
- p[2] = palette[n+2];
- p[3] = palette[n+3];
- p += 4;
- }
- }
- free(a->out);
- a->out = temp_out;
- return 1;
-}
-
-static int parse_png_file(png *z, int scan, int req_comp)
-{
- uint8 palette[1024], pal_img_n=0;
- uint8 has_trans=0, tc[3];
- uint32 ioff=0, idata_limit=0, i, pal_len=0;
- int first=1,k,interlace=0;
- stbi *s = &z->s;
-
- if (!check_png_header(s)) return 0;
-
- if (scan == SCAN_type) return 1;
-
- for(;;first=0) {
- chunk c = get_chunk_header(s);
- if (first && c.type != PNG_TYPE('I','H','D','R'))
- return e("first not IHDR","Corrupt PNG");
- switch (c.type) {
- case PNG_TYPE('I','H','D','R'): {
- int depth,color,comp,filter;
- if (!first) return e("multiple IHDR","Corrupt PNG");
- if (c.length != 13) return e("bad IHDR len","Corrupt PNG");
- s->img_x = get32(s); if (s->img_x > (1 << 24)) return e("too large","Very large image (corrupt?)");
- s->img_y = get32(s); if (s->img_y > (1 << 24)) return e("too large","Very large image (corrupt?)");
- depth = get8(s); if (depth != 8) return e("8bit only","PNG not supported: 8-bit only");
- color = get8(s); if (color > 6) return e("bad ctype","Corrupt PNG");
- if (color == 3) pal_img_n = 3; else if (color & 1) return e("bad ctype","Corrupt PNG");
- comp = get8(s); if (comp) return e("bad comp method","Corrupt PNG");
- filter= get8(s); if (filter) return e("bad filter method","Corrupt PNG");
- interlace = get8(s); if (interlace>1) return e("bad interlace method","Corrupt PNG");
- if (!s->img_x || !s->img_y) return e("0-pixel image","Corrupt PNG");
- if (!pal_img_n) {
- s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
- if ((1 << 30) / s->img_x / s->img_n < s->img_y) return e("too large", "Image too large to decode");
- if (scan == SCAN_header) return 1;
- } else {
- // if paletted, then pal_n is our final components, and
- // img_n is # components to decompress/filter.
- s->img_n = 1;
- if ((1 << 30) / s->img_x / 4 < s->img_y) return e("too large","Corrupt PNG");
- // if SCAN_header, have to scan to see if we have a tRNS
- }
- break;
- }
-
- case PNG_TYPE('P','L','T','E'): {
- if (c.length > 256*3) return e("invalid PLTE","Corrupt PNG");
- pal_len = c.length / 3;
- if (pal_len * 3 != c.length) return e("invalid PLTE","Corrupt PNG");
- for (i=0; i < pal_len; ++i) {
- palette[i*4+0] = get8u(s);
- palette[i*4+1] = get8u(s);
- palette[i*4+2] = get8u(s);
- palette[i*4+3] = 255;
- }
- break;
- }
-
- case PNG_TYPE('t','R','N','S'): {
- if (z->idata) return e("tRNS after IDAT","Corrupt PNG");
- if (pal_img_n) {
- if (scan == SCAN_header) { s->img_n = 4; return 1; }
- if (pal_len == 0) return e("tRNS before PLTE","Corrupt PNG");
- if (c.length > pal_len) return e("bad tRNS len","Corrupt PNG");
- pal_img_n = 4;
- for (i=0; i < c.length; ++i)
- palette[i*4+3] = get8u(s);
- } else {
- if (!(s->img_n & 1)) return e("tRNS with alpha","Corrupt PNG");
- if (c.length != (uint32) s->img_n*2) return e("bad tRNS len","Corrupt PNG");
- has_trans = 1;
- for (k=0; k < s->img_n; ++k)
- tc[k] = (uint8) get16(s); // non 8-bit images will be larger
- }
- break;
- }
-
- case PNG_TYPE('I','D','A','T'): {
- if (pal_img_n && !pal_len) return e("no PLTE","Corrupt PNG");
- if (scan == SCAN_header) { s->img_n = pal_img_n; return 1; }
- if (ioff + c.length > idata_limit) {
- uint8 *p;
- if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
- while (ioff + c.length > idata_limit)
- idata_limit *= 2;
- p = (uint8 *) realloc(z->idata, idata_limit); if (p == NULL) return e("outofmem", "Out of memory");
- z->idata = p;
- }
- #ifndef STBI_NO_STDIO
- if (s->img_file)
- {
- if (fread(z->idata+ioff,1,c.length,s->img_file) != c.length) return e("outofdata","Corrupt PNG");
- }
- else
- #endif
- {
- memcpy(z->idata+ioff, s->img_buffer, c.length);
- s->img_buffer += c.length;
- }
- ioff += c.length;
- break;
- }
-
- case PNG_TYPE('I','E','N','D'): {
- uint32 raw_len;
- if (scan != SCAN_load) return 1;
- if (z->idata == NULL) return e("no IDAT","Corrupt PNG");
- z->expanded = (uint8 *) stbi_zlib_decode_malloc((char *) z->idata, ioff, (int *) &raw_len);
- if (z->expanded == NULL) return 0; // zlib should set error
- free(z->idata); z->idata = NULL;
- if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans)
- s->img_out_n = s->img_n+1;
- else
- s->img_out_n = s->img_n;
- if (!create_png_image(z, z->expanded, raw_len, s->img_out_n, interlace)) return 0;
- if (has_trans)
- if (!compute_transparency(z, tc, s->img_out_n)) return 0;
- if (pal_img_n) {
- // pal_img_n == 3 or 4
- s->img_n = pal_img_n; // record the actual colors we had
- s->img_out_n = pal_img_n;
- if (req_comp >= 3) s->img_out_n = req_comp;
- if (!expand_palette(z, palette, pal_len, s->img_out_n))
- return 0;
- }
- free(z->expanded); z->expanded = NULL;
- return 1;
- }
-
- default:
- // if critical, fail
- if ((c.type & (1 << 29)) == 0) {
- #ifndef STBI_NO_FAILURE_STRINGS
- // not threadsafe
- static char invalid_chunk[] = "XXXX chunk not known";
- invalid_chunk[0] = (uint8) (c.type >> 24);
- invalid_chunk[1] = (uint8) (c.type >> 16);
- invalid_chunk[2] = (uint8) (c.type >> 8);
- invalid_chunk[3] = (uint8) (c.type >> 0);
- #endif
- return e(invalid_chunk, "PNG not supported: unknown chunk type");
- }
- skip(s, c.length);
- break;
- }
- // end of chunk, read and skip CRC
- get32(s);
- }
-}
-
-static unsigned char *do_png(png *p, int *x, int *y, int *n, int req_comp)
-{
- unsigned char *result=NULL;
- p->expanded = NULL;
- p->idata = NULL;
- p->out = NULL;
- if (req_comp < 0 || req_comp > 4) return epuc("bad req_comp", "Internal error");
- if (parse_png_file(p, SCAN_load, req_comp)) {
- result = p->out;
- p->out = NULL;
- if (req_comp && req_comp != p->s.img_out_n) {
- result = convert_format(result, p->s.img_out_n, req_comp, p->s.img_x, p->s.img_y);
- p->s.img_out_n = req_comp;
- if (result == NULL) return result;
- }
- *x = p->s.img_x;
- *y = p->s.img_y;
- if (n) *n = p->s.img_n;
- }
- free(p->out); p->out = NULL;
- free(p->expanded); p->expanded = NULL;
- free(p->idata); p->idata = NULL;
-
- return result;
-}
-
-#ifndef STBI_NO_STDIO
-unsigned char *stbi_png_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- png p;
- start_file(&p.s, f);
- return do_png(&p, x,y,comp,req_comp);
-}
-
-unsigned char *stbi_png_load(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- unsigned char *data;
- FILE *f = fopen(filename, "rb");
- if (!f) return NULL;
- data = stbi_png_load_from_file(f,x,y,comp,req_comp);
- fclose(f);
- return data;
-}
-#endif
-
-unsigned char *stbi_png_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- png p;
- start_mem(&p.s, buffer,len);
- return do_png(&p, x,y,comp,req_comp);
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_png_test_file(FILE *f)
-{
- png p;
- int n,r;
- n = ftell(f);
- start_file(&p.s, f);
- r = parse_png_file(&p, SCAN_type,STBI_default);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-int stbi_png_test_memory(stbi_uc const *buffer, int len)
-{
- png p;
- start_mem(&p.s, buffer, len);
- return parse_png_file(&p, SCAN_type,STBI_default);
-}
-
-// TODO: load header from png
-#ifndef STBI_NO_STDIO
-int stbi_png_info (char const *filename, int *x, int *y, int *comp)
-{
- png p;
- FILE *f = fopen(filename, "rb");
- if (!f) return 0;
- start_file(&p.s, f);
- if (parse_png_file(&p, SCAN_header, 0)) {
- if(x) *x = p.s.img_x;
- if(y) *y = p.s.img_y;
- if (comp) *comp = p.s.img_n;
- fclose(f);
- return 1;
- }
- fclose(f);
- return 0;
-}
-
-extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp);
-#endif
-extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
-
-// Microsoft/Windows BMP image
-
-static int bmp_test(stbi *s)
-{
- int sz;
- if (get8(s) != 'B') return 0;
- if (get8(s) != 'M') return 0;
- get32le(s); // discard filesize
- get16le(s); // discard reserved
- get16le(s); // discard reserved
- get32le(s); // discard data offset
- sz = get32le(s);
- if (sz == 12 || sz == 40 || sz == 56 || sz == 108) return 1;
- return 0;
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_bmp_test_file (FILE *f)
-{
- stbi s;
- int r,n = ftell(f);
- start_file(&s,f);
- r = bmp_test(&s);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-int stbi_bmp_test_memory (stbi_uc const *buffer, int len)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return bmp_test(&s);
-}
-
-// returns 0..31 for the highest set bit
-static int high_bit(unsigned int z)
-{
- int n=0;
- if (z == 0) return -1;
- if (z >= 0x10000) n += 16, z >>= 16;
- if (z >= 0x00100) n += 8, z >>= 8;
- if (z >= 0x00010) n += 4, z >>= 4;
- if (z >= 0x00004) n += 2, z >>= 2;
- if (z >= 0x00002) n += 1, z >>= 1;
- return n;
-}
-
-static int bitcount(unsigned int a)
-{
- a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2
- a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4
- a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits
- a = (a + (a >> 8)); // max 16 per 8 bits
- a = (a + (a >> 16)); // max 32 per 8 bits
- return a & 0xff;
-}
-
-static int shiftsigned(int v, int shift, int bits)
-{
- int result;
- int z=0;
-
- if (shift < 0) v <<= -shift;
- else v >>= shift;
- result = v;
-
- z = bits;
- while (z < 8) {
- result += v >> z;
- z += bits;
- }
- return result;
-}
-
-static stbi_uc *bmp_load(stbi *s, int *x, int *y, int *comp, int req_comp)
-{
- uint8 *out;
- unsigned int mr=0,mg=0,mb=0,ma=0, fake_a=0;
- stbi_uc pal[256][4];
- int psize=0,i,j,compress=0,width;
- int bpp, flip_vertically, pad, target, offset, hsz;
- if (get8(s) != 'B' || get8(s) != 'M') return epuc("not BMP", "Corrupt BMP");
- get32le(s); // discard filesize
- get16le(s); // discard reserved
- get16le(s); // discard reserved
- offset = get32le(s);
- hsz = get32le(s);
- if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108) return epuc("unknown BMP", "BMP type not supported: unknown");
- failure_reason = "bad BMP";
- if (hsz == 12) {
- s->img_x = get16le(s);
- s->img_y = get16le(s);
- } else {
- s->img_x = get32le(s);
- s->img_y = get32le(s);
- }
- if (get16le(s) != 1) return 0;
- bpp = get16le(s);
- if (bpp == 1) return epuc("monochrome", "BMP type not supported: 1-bit");
- flip_vertically = ((int) s->img_y) > 0;
- s->img_y = abs((int) s->img_y);
- if (hsz == 12) {
- if (bpp < 24)
- psize = (offset - 14 - 24) / 3;
- } else {
- compress = get32le(s);
- if (compress == 1 || compress == 2) return epuc("BMP RLE", "BMP type not supported: RLE");
- get32le(s); // discard sizeof
- get32le(s); // discard hres
- get32le(s); // discard vres
- get32le(s); // discard colorsused
- get32le(s); // discard max important
- if (hsz == 40 || hsz == 56) {
- if (hsz == 56) {
- get32le(s);
- get32le(s);
- get32le(s);
- get32le(s);
- }
- if (bpp == 16 || bpp == 32) {
- mr = mg = mb = 0;
- if (compress == 0) {
- if (bpp == 32) {
- mr = 0xff << 16;
- mg = 0xff << 8;
- mb = 0xff << 0;
- ma = 0xff << 24;
- fake_a = 1; // @TODO: check for cases like alpha value is all 0 and switch it to 255
- } else {
- mr = 31 << 10;
- mg = 31 << 5;
- mb = 31 << 0;
- }
- } else if (compress == 3) {
- mr = get32le(s);
- mg = get32le(s);
- mb = get32le(s);
- // not documented, but generated by photoshop and handled by mspaint
- if (mr == mg && mg == mb) {
- // ?!?!?
- return NULL;
- }
- } else
- return NULL;
- }
- } else {
- assert(hsz == 108);
- mr = get32le(s);
- mg = get32le(s);
- mb = get32le(s);
- ma = get32le(s);
- get32le(s); // discard color space
- for (i=0; i < 12; ++i)
- get32le(s); // discard color space parameters
- }
- if (bpp < 16)
- psize = (offset - 14 - hsz) >> 2;
- }
- s->img_n = ma ? 4 : 3;
- if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
- target = req_comp;
- else
- target = s->img_n; // if they want monochrome, we'll post-convert
- out = (stbi_uc *) malloc(target * s->img_x * s->img_y);
- if (!out) return epuc("outofmem", "Out of memory");
- if (bpp < 16) {
- int z=0;
- if (psize == 0 || psize > 256) { free(out); return epuc("invalid", "Corrupt BMP"); }
- for (i=0; i < psize; ++i) {
- pal[i][2] = get8(s);
- pal[i][1] = get8(s);
- pal[i][0] = get8(s);
- if (hsz != 12) get8(s);
- pal[i][3] = 255;
- }
- skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4));
- if (bpp == 4) width = (s->img_x + 1) >> 1;
- else if (bpp == 8) width = s->img_x;
- else { free(out); return epuc("bad bpp", "Corrupt BMP"); }
- pad = (-width)&3;
- for (j=0; j < (int) s->img_y; ++j) {
- for (i=0; i < (int) s->img_x; i += 2) {
- int v=get8(s),v2=0;
- if (bpp == 4) {
- v2 = v & 15;
- v >>= 4;
- }
- out[z++] = pal[v][0];
- out[z++] = pal[v][1];
- out[z++] = pal[v][2];
- if (target == 4) out[z++] = 255;
- if (i+1 == (int) s->img_x) break;
- v = (bpp == 8) ? get8(s) : v2;
- out[z++] = pal[v][0];
- out[z++] = pal[v][1];
- out[z++] = pal[v][2];
- if (target == 4) out[z++] = 255;
- }
- skip(s, pad);
- }
- } else {
- int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
- int z = 0;
- int easy=0;
- skip(s, offset - 14 - hsz);
- if (bpp == 24) width = 3 * s->img_x;
- else if (bpp == 16) width = 2*s->img_x;
- else /* bpp = 32 and pad = 0 */ width=0;
- pad = (-width) & 3;
- if (bpp == 24) {
- easy = 1;
- } else if (bpp == 32) {
- if (mb == 0xff && mg == 0xff00 && mr == 0xff000000 && ma == 0xff000000)
- easy = 2;
- }
- if (!easy) {
- if (!mr || !mg || !mb) return epuc("bad masks", "Corrupt BMP");
- // right shift amt to put high bit in position #7
- rshift = high_bit(mr)-7; rcount = bitcount(mr);
- gshift = high_bit(mg)-7; gcount = bitcount(mr);
- bshift = high_bit(mb)-7; bcount = bitcount(mr);
- ashift = high_bit(ma)-7; acount = bitcount(mr);
- }
- for (j=0; j < (int) s->img_y; ++j) {
- if (easy) {
- for (i=0; i < (int) s->img_x; ++i) {
- int a;
- out[z+2] = get8(s);
- out[z+1] = get8(s);
- out[z+0] = get8(s);
- z += 3;
- a = (easy == 2 ? get8(s) : 255);
- if (target == 4) out[z++] = a;
- }
- } else {
- for (i=0; i < (int) s->img_x; ++i) {
- uint32 v = (bpp == 16 ? get16le(s) : get32le(s));
- int a;
- out[z++] = shiftsigned(v & mr, rshift, rcount);
- out[z++] = shiftsigned(v & mg, gshift, gcount);
- out[z++] = shiftsigned(v & mb, bshift, bcount);
- a = (ma ? shiftsigned(v & ma, ashift, acount) : 255);
- if (target == 4) out[z++] = a;
- }
- }
- skip(s, pad);
- }
- }
- if (flip_vertically) {
- stbi_uc t;
- for (j=0; j < (int) s->img_y>>1; ++j) {
- stbi_uc *p1 = out + j *s->img_x*target;
- stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target;
- for (i=0; i < (int) s->img_x*target; ++i) {
- t = p1[i], p1[i] = p2[i], p2[i] = t;
- }
- }
- }
-
- if (req_comp && req_comp != target) {
- out = convert_format(out, target, req_comp, s->img_x, s->img_y);
- if (out == NULL) return out; // convert_format frees input on failure
- }
-
- *x = s->img_x;
- *y = s->img_y;
- if (comp) *comp = target;
- return out;
-}
-
-#ifndef STBI_NO_STDIO
-stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- stbi_uc *data;
- FILE *f = fopen(filename, "rb");
- if (!f) return NULL;
- data = stbi_bmp_load_from_file(f, x,y,comp,req_comp);
- fclose(f);
- return data;
-}
-
-stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_file(&s, f);
- return bmp_load(&s, x,y,comp,req_comp);
-}
-#endif
-
-stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return bmp_load(&s, x,y,comp,req_comp);
-}
-
-// Targa Truevision - TGA
-// by Jonathan Dummer
-
-static int tga_test(stbi *s)
-{
- int sz;
- get8u(s); // discard Offset
- sz = get8u(s); // color type
- if( sz > 1 ) return 0; // only RGB or indexed allowed
- sz = get8u(s); // image type
- if( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE
- get16(s); // discard palette start
- get16(s); // discard palette length
- get8(s); // discard bits per palette color entry
- get16(s); // discard x origin
- get16(s); // discard y origin
- if( get16(s) < 1 ) return 0; // test width
- if( get16(s) < 1 ) return 0; // test height
- sz = get8(s); // bits per pixel
- if( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) return 0; // only RGB or RGBA or grey allowed
- return 1; // seems to have passed everything
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_tga_test_file (FILE *f)
-{
- stbi s;
- int r,n = ftell(f);
- start_file(&s, f);
- r = tga_test(&s);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-int stbi_tga_test_memory (stbi_uc const *buffer, int len)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return tga_test(&s);
-}
-
-static stbi_uc *tga_load(stbi *s, int *x, int *y, int *comp, int req_comp)
-{
- // read in the TGA header stuff
- int tga_offset = get8u(s);
- int tga_indexed = get8u(s);
- int tga_image_type = get8u(s);
- int tga_is_RLE = 0;
- int tga_palette_start = get16le(s);
- int tga_palette_len = get16le(s);
- int tga_palette_bits = get8u(s);
- int tga_x_origin = get16le(s);
- int tga_y_origin = get16le(s);
- int tga_width = get16le(s);
- int tga_height = get16le(s);
- int tga_bits_per_pixel = get8u(s);
- int tga_inverted = get8u(s);
- // image data
- unsigned char *tga_data;
- unsigned char *tga_palette = NULL;
- int i, j;
- unsigned char raw_data[4];
- unsigned char trans_data[4];
- int RLE_count = 0;
- int RLE_repeating = 0;
- int read_next_pixel = 1;
- // do a tiny bit of precessing
- if( tga_image_type >= 8 )
- {
- tga_image_type -= 8;
- tga_is_RLE = 1;
- }
- /* int tga_alpha_bits = tga_inverted & 15; */
- tga_inverted = 1 - ((tga_inverted >> 5) & 1);
-
- // error check
- if( //(tga_indexed) ||
- (tga_width < 1) || (tga_height < 1) ||
- (tga_image_type < 1) || (tga_image_type > 3) ||
- ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) &&
- (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
- )
- {
- return NULL;
- }
-
- // If I'm paletted, then I'll use the number of bits from the palette
- if( tga_indexed )
- {
- tga_bits_per_pixel = tga_palette_bits;
- }
-
- // tga info
- *x = tga_width;
- *y = tga_height;
- if( (req_comp < 1) || (req_comp > 4) )
- {
- // just use whatever the file was
- req_comp = tga_bits_per_pixel / 8;
- *comp = req_comp;
- } else
- {
- // force a new number of components
- *comp = tga_bits_per_pixel/8;
- }
- tga_data = (unsigned char*)malloc( tga_width * tga_height * req_comp );
-
- // skip to the data's starting position (offset usually = 0)
- skip(s, tga_offset );
- // do I need to load a palette?
- if( tga_indexed )
- {
- // any data to skip? (offset usually = 0)
- skip(s, tga_palette_start );
- // load the palette
- tga_palette = (unsigned char*)malloc( tga_palette_len * tga_palette_bits / 8 );
- getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 );
- }
- // load the data
- for( i = 0; i < tga_width * tga_height; ++i )
- {
- // if I'm in RLE mode, do I need to get a RLE chunk?
- if( tga_is_RLE )
- {
- if( RLE_count == 0 )
- {
- // yep, get the next byte as a RLE command
- int RLE_cmd = get8u(s);
- RLE_count = 1 + (RLE_cmd & 127);
- RLE_repeating = RLE_cmd >> 7;
- read_next_pixel = 1;
- } else if( !RLE_repeating )
- {
- read_next_pixel = 1;
- }
- } else
- {
- read_next_pixel = 1;
- }
- // OK, if I need to read a pixel, do it now
- if( read_next_pixel )
- {
- // load however much data we did have
- if( tga_indexed )
- {
- // read in 1 byte, then perform the lookup
- int pal_idx = get8u(s);
- if( pal_idx >= tga_palette_len )
- {
- // invalid index
- pal_idx = 0;
- }
- pal_idx *= tga_bits_per_pixel / 8;
- for( j = 0; j*8 < tga_bits_per_pixel; ++j )
- {
- raw_data[j] = tga_palette[pal_idx+j];
- }
- } else
- {
- // read in the data raw
- for( j = 0; j*8 < tga_bits_per_pixel; ++j )
- {
- raw_data[j] = get8u(s);
- }
- }
- // convert raw to the intermediate format
- switch( tga_bits_per_pixel )
- {
- case 8:
- // Luminous => RGBA
- trans_data[0] = raw_data[0];
- trans_data[1] = raw_data[0];
- trans_data[2] = raw_data[0];
- trans_data[3] = 255;
- break;
- case 16:
- // Luminous,Alpha => RGBA
- trans_data[0] = raw_data[0];
- trans_data[1] = raw_data[0];
- trans_data[2] = raw_data[0];
- trans_data[3] = raw_data[1];
- break;
- case 24:
- // BGR => RGBA
- trans_data[0] = raw_data[2];
- trans_data[1] = raw_data[1];
- trans_data[2] = raw_data[0];
- trans_data[3] = 255;
- break;
- case 32:
- // BGRA => RGBA
- trans_data[0] = raw_data[2];
- trans_data[1] = raw_data[1];
- trans_data[2] = raw_data[0];
- trans_data[3] = raw_data[3];
- break;
- }
- // clear the reading flag for the next pixel
- read_next_pixel = 0;
- } // end of reading a pixel
- // convert to final format
- switch( req_comp )
- {
- case 1:
- // RGBA => Luminance
- tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]);
- break;
- case 2:
- // RGBA => Luminance,Alpha
- tga_data[i*req_comp+0] = compute_y(trans_data[0],trans_data[1],trans_data[2]);
- tga_data[i*req_comp+1] = trans_data[3];
- break;
- case 3:
- // RGBA => RGB
- tga_data[i*req_comp+0] = trans_data[0];
- tga_data[i*req_comp+1] = trans_data[1];
- tga_data[i*req_comp+2] = trans_data[2];
- break;
- case 4:
- // RGBA => RGBA
- tga_data[i*req_comp+0] = trans_data[0];
- tga_data[i*req_comp+1] = trans_data[1];
- tga_data[i*req_comp+2] = trans_data[2];
- tga_data[i*req_comp+3] = trans_data[3];
- break;
- }
- // in case we're in RLE mode, keep counting down
- --RLE_count;
- }
- // do I need to invert the image?
- if( tga_inverted )
- {
- for( j = 0; j*2 < tga_height; ++j )
- {
- int index1 = j * tga_width * req_comp;
- int index2 = (tga_height - 1 - j) * tga_width * req_comp;
- for( i = tga_width * req_comp; i > 0; --i )
- {
- unsigned char temp = tga_data[index1];
- tga_data[index1] = tga_data[index2];
- tga_data[index2] = temp;
- ++index1;
- ++index2;
- }
- }
- }
- // clear my palette, if I had one
- if( tga_palette != NULL )
- {
- free( tga_palette );
- }
- // the things I do to get rid of an error message, and yet keep
- // Microsoft's C compilers happy... [8^(
- tga_palette_start = tga_palette_len = tga_palette_bits =
- tga_x_origin = tga_y_origin = 0;
- // OK, done
- return tga_data;
-}
-
-#ifndef STBI_NO_STDIO
-stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- stbi_uc *data;
- FILE *f = fopen(filename, "rb");
- if (!f) return NULL;
- data = stbi_tga_load_from_file(f, x,y,comp,req_comp);
- fclose(f);
- return data;
-}
-
-stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_file(&s, f);
- return tga_load(&s, x,y,comp,req_comp);
-}
-#endif
-
-stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return tga_load(&s, x,y,comp,req_comp);
-}
-
-
-// *************************************************************************************************
-// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicholas Schulz, tweaked by STB
-
-static int psd_test(stbi *s)
-{
- if (get32(s) != 0x38425053) return 0; // "8BPS"
- else return 1;
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_psd_test_file(FILE *f)
-{
- stbi s;
- int r,n = ftell(f);
- start_file(&s, f);
- r = psd_test(&s);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-int stbi_psd_test_memory(stbi_uc const *buffer, int len)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return psd_test(&s);
-}
-
-static stbi_uc *psd_load(stbi *s, int *x, int *y, int *comp, int req_comp)
-{
- int pixelCount;
- int channelCount, compression;
- int channel, i, count, len;
- int w,h;
- uint8 *out;
-
- // Check identifier
- if (get32(s) != 0x38425053) // "8BPS"
- return epuc("not PSD", "Corrupt PSD image");
-
- // Check file type version.
- if (get16(s) != 1)
- return epuc("wrong version", "Unsupported version of PSD image");
-
- // Skip 6 reserved bytes.
- skip(s, 6 );
-
- // Read the number of channels (R, G, B, A, etc).
- channelCount = get16(s);
- if (channelCount < 0 || channelCount > 16)
- return epuc("wrong channel count", "Unsupported number of channels in PSD image");
-
- // Read the rows and columns of the image.
- h = get32(s);
- w = get32(s);
-
- // Make sure the depth is 8 bits.
- if (get16(s) != 8)
- return epuc("unsupported bit depth", "PSD bit depth is not 8 bit");
-
- // Make sure the color mode is RGB.
- // Valid options are:
- // 0: Bitmap
- // 1: Grayscale
- // 2: Indexed color
- // 3: RGB color
- // 4: CMYK color
- // 7: Multichannel
- // 8: Duotone
- // 9: Lab color
- if (get16(s) != 3)
- return epuc("wrong color format", "PSD is not in RGB color format");
-
- // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.)
- skip(s,get32(s) );
-
- // Skip the image resources. (resolution, pen tool paths, etc)
- skip(s, get32(s) );
-
- // Skip the reserved data.
- skip(s, get32(s) );
-
- // Find out if the data is compressed.
- // Known values:
- // 0: no compression
- // 1: RLE compressed
- compression = get16(s);
- if (compression > 1)
- return epuc("bad compression", "PSD has an unknown compression format");
-
- // Create the destination image.
- out = (stbi_uc *) malloc(4 * w*h);
- if (!out) return epuc("outofmem", "Out of memory");
- pixelCount = w*h;
-
- // Initialize the data to zero.
- //memset( out, 0, pixelCount * 4 );
-
- // Finally, the image data.
- if (compression) {
- // RLE as used by .PSD and .TIFF
- // Loop until you get the number of unpacked bytes you are expecting:
- // Read the next source byte into n.
- // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally.
- // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times.
- // Else if n is 128, noop.
- // Endloop
-
- // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data,
- // which we're going to just skip.
- skip(s, h * channelCount * 2 );
-
- // Read the RLE data by channel.
- for (channel = 0; channel < 4; channel++) {
- uint8 *p;
-
- p = out+channel;
- if (channel >= channelCount) {
- // Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = (channel == 3 ? 255 : 0), p += 4;
- } else {
- // Read the RLE data.
- count = 0;
- while (count < pixelCount) {
- len = get8(s);
- if (len == 128) {
- // No-op.
- } else if (len < 128) {
- // Copy next len+1 bytes literally.
- len++;
- count += len;
- while (len) {
- *p = get8(s);
- p += 4;
- len--;
- }
- } else if (len > 128) {
- uint32 val;
- // Next -len+1 bytes in the dest are replicated from next source byte.
- // (Interpret len as a negative 8-bit int.)
- len ^= 0x0FF;
- len += 2;
- val = get8(s);
- count += len;
- while (len) {
- *p = val;
- p += 4;
- len--;
- }
- }
- }
- }
- }
-
- } else {
- // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
- // where each channel consists of an 8-bit value for each pixel in the image.
-
- // Read the data by channel.
- for (channel = 0; channel < 4; channel++) {
- uint8 *p;
-
- p = out + channel;
- if (channel > channelCount) {
- // Fill this channel with default data.
- for (i = 0; i < pixelCount; i++) *p = channel == 3 ? 255 : 0, p += 4;
- } else {
- // Read the data.
- count = 0;
- for (i = 0; i < pixelCount; i++)
- *p = get8(s), p += 4;
- }
- }
- }
-
- if (req_comp && req_comp != 4) {
- out = convert_format(out, 4, req_comp, w, h);
- if (out == NULL) return out; // convert_format frees input on failure
- }
-
- if (comp) *comp = channelCount;
- *y = h;
- *x = w;
-
- return out;
-}
-
-#ifndef STBI_NO_STDIO
-stbi_uc *stbi_psd_load(char const *filename, int *x, int *y, int *comp, int req_comp)
-{
- stbi_uc *data;
- FILE *f = fopen(filename, "rb");
- if (!f) return NULL;
- data = stbi_psd_load_from_file(f, x,y,comp,req_comp);
- fclose(f);
- return data;
-}
-
-stbi_uc *stbi_psd_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_file(&s, f);
- return psd_load(&s, x,y,comp,req_comp);
-}
-#endif
-
-stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return psd_load(&s, x,y,comp,req_comp);
-}
-
-
-// *************************************************************************************************
-// Radiance RGBE HDR loader
-// originally by Nicolas Schulz
-#ifndef STBI_NO_HDR
-static int hdr_test(stbi *s)
-{
- char *signature = "#?RADIANCE\n";
- int i;
- for (i=0; signature[i]; ++i)
- if (get8(s) != signature[i])
- return 0;
- return 1;
-}
-
-int stbi_hdr_test_memory(stbi_uc const *buffer, int len)
-{
- stbi s;
- start_mem(&s, buffer, len);
- return hdr_test(&s);
-}
-
-#ifndef STBI_NO_STDIO
-int stbi_hdr_test_file(FILE *f)
-{
- stbi s;
- int r,n = ftell(f);
- start_file(&s, f);
- r = hdr_test(&s);
- fseek(f,n,SEEK_SET);
- return r;
-}
-#endif
-
-#define HDR_BUFLEN 1024
-static char *hdr_gettoken(stbi *z, char *buffer)
-{
- int len=0;
- char *s = buffer, c = '\0';
-
- c = get8(z);
-
- while (!at_eof(z) && c != '\n') {
- buffer[len++] = c;
- if (len == HDR_BUFLEN-1) {
- // flush to end of line
- while (!at_eof(z) && get8(z) != '\n')
- ;
- break;
- }
- c = get8(z);
- }
-
- buffer[len] = 0;
- return buffer;
-}
-
-static void hdr_convert(float *output, stbi_uc *input, int req_comp)
-{
- if( input[3] != 0 ) {
- float f1;
- // Exponent
- f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8));
- if (req_comp <= 2)
- output[0] = (input[0] + input[1] + input[2]) * f1 / 3;
- else {
- output[0] = input[0] * f1;
- output[1] = input[1] * f1;
- output[2] = input[2] * f1;
- }
- if (req_comp == 2) output[1] = 1;
- if (req_comp == 4) output[3] = 1;
- } else {
- switch (req_comp) {
- case 4: output[3] = 1; /* fallthrough */
- case 3: output[0] = output[1] = output[2] = 0;
- break;
- case 2: output[1] = 1; /* fallthrough */
- case 1: output[0] = 0;
- break;
- }
- }
-}
-
-
-static float *hdr_load(stbi *s, int *x, int *y, int *comp, int req_comp)
-{
- char buffer[HDR_BUFLEN];
- char *token;
- int valid = 0;
- int width, height;
- stbi_uc *scanline;
- float *hdr_data;
- int len;
- unsigned char count, value;
- int i, j, k, c1,c2, z;
-
-
- // Check identifier
- if (strcmp(hdr_gettoken(s,buffer), "#?RADIANCE") != 0)
- return epf("not HDR", "Corrupt HDR image");
-
- // Parse header
- while(1) {
- token = hdr_gettoken(s,buffer);
- if (token[0] == 0) break;
- if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1;
- }
-
- if (!valid) return epf("unsupported format", "Unsupported HDR format");
-
- // Parse width and height
- // can't use sscanf() if we're not using stdio!
- token = hdr_gettoken(s,buffer);
- if (strncmp(token, "-Y ", 3)) return epf("unsupported data layout", "Unsupported HDR format");
- token += 3;
- height = strtol(token, &token, 10);
- while (*token == ' ') ++token;
- if (strncmp(token, "+X ", 3)) return epf("unsupported data layout", "Unsupported HDR format");
- token += 3;
- width = strtol(token, NULL, 10);
-
- *x = width;
- *y = height;
-
- *comp = 3;
- if (req_comp == 0) req_comp = 3;
-
- // Read data
- hdr_data = (float *) malloc(height * width * req_comp * sizeof(float));
-
- // Load image data
- // image data is stored as some number of sca
- if( width < 8 || width >= 32768) {
- // Read flat data
- for (j=0; j < height; ++j) {
- for (i=0; i < width; ++i) {
- stbi_uc rgbe[4];
- main_decode_loop:
- getn(s, rgbe, 4);
- hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp);
- }
- }
- } else {
- // Read RLE-encoded data
- scanline = NULL;
-
- for (j = 0; j < height; ++j) {
- c1 = get8(s);
- c2 = get8(s);
- len = get8(s);
- if (c1 != 2 || c2 != 2 || (len & 0x80)) {
- // not run-length encoded, so we have to actually use THIS data as a decoded
- // pixel (note this can't be a valid pixel--one of RGB must be >= 128)
- stbi_uc rgbe[4] = { c1,c2,len, get8(s) };
- hdr_convert(hdr_data, rgbe, req_comp);
- i = 1;
- j = 0;
- free(scanline);
- goto main_decode_loop; // yes, this is fucking insane; blame the fucking insane format
- }
- len <<= 8;
- len |= get8(s);
- if (len != width) { free(hdr_data); free(scanline); return epf("invalid decoded scanline length", "corrupt HDR"); }
- if (scanline == NULL) scanline = (stbi_uc *) malloc(width * 4);
-
- for (k = 0; k < 4; ++k) {
- i = 0;
- while (i < width) {
- count = get8(s);
- if (count > 128) {
- // Run
- value = get8(s);
- count -= 128;
- for (z = 0; z < count; ++z)
- scanline[i++ * 4 + k] = value;
- } else {
- // Dump
- for (z = 0; z < count; ++z)
- scanline[i++ * 4 + k] = get8(s);
- }
- }
- }
- for (i=0; i < width; ++i)
- hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp);
- }
- free(scanline);
- }
-
- return hdr_data;
-}
-
-#ifndef STBI_NO_STDIO
-float *stbi_hdr_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_file(&s,f);
- return hdr_load(&s,x,y,comp,req_comp);
-}
-#endif
-
-float *stbi_hdr_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
-{
- stbi s;
- start_mem(&s,buffer, len);
- return hdr_load(&s,x,y,comp,req_comp);
-}
-
-#endif // STBI_NO_HDR
-
-/////////////////////// write image ///////////////////////
-
-#ifndef STBI_NO_WRITE
-
-static void write8(FILE *f, int x) { uint8 z = (uint8) x; fwrite(&z,1,1,f); }
-
-static void writefv(FILE *f, char *fmt, va_list v)
-{
- while (*fmt) {
- switch (*fmt++) {
- case ' ': break;
- case '1': { uint8 x = va_arg(v, int); write8(f,x); break; }
- case '2': { int16 x = va_arg(v, int); write8(f,x); write8(f,x>>8); break; }
- case '4': { int32 x = va_arg(v, int); write8(f,x); write8(f,x>>8); write8(f,x>>16); write8(f,x>>24); break; }
- default:
- assert(0);
- va_end(v);
- return;
- }
- }
-}
-
-static void writef(FILE *f, char *fmt, ...)
-{
- va_list v;
- va_start(v, fmt);
- writefv(f,fmt,v);
- va_end(v);
-}
-
-static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad)
-{
- uint8 bg[3] = { 255, 0, 255}, px[3];
- uint32 zero = 0;
- int i,j,k, j_end;
-
- if (vdir < 0)
- j_end = -1, j = y-1;
- else
- j_end = y, j = 0;
-
- for (; j != j_end; j += vdir) {
- for (i=0; i < x; ++i) {
- uint8 *d = (uint8 *) data + (j*x+i)*comp;
- if (write_alpha < 0)
- fwrite(&d[comp-1], 1, 1, f);
- switch (comp) {
- case 1:
- case 2: writef(f, "111", d[0],d[0],d[0]);
- break;
- case 4:
- if (!write_alpha) {
- for (k=0; k < 3; ++k)
- px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
- writef(f, "111", px[1-rgb_dir],px[1],px[1+rgb_dir]);
- break;
- }
- /* FALLTHROUGH */
- case 3:
- writef(f, "111", d[1-rgb_dir],d[1],d[1+rgb_dir]);
- break;
- }
- if (write_alpha > 0)
- fwrite(&d[comp-1], 1, 1, f);
- }
- fwrite(&zero,scanline_pad,1,f);
- }
-}
-
-static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, char *fmt, ...)
-{
- FILE *f = fopen(filename, "wb");
- if (f) {
- va_list v;
- va_start(v, fmt);
- writefv(f, fmt, v);
- va_end(v);
- write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
- fclose(f);
- }
- return f != NULL;
-}
-
-int stbi_write_bmp(char const *filename, int x, int y, int comp, void *data)
-{
- int pad = (-x*3) & 3;
- return outfile(filename,-1,-1,x,y,comp,data,0,pad,
- "11 4 22 4" "4 44 22 444444",
- 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
- 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
-}
-
-int stbi_write_tga(char const *filename, int x, int y, int comp, void *data)
-{
- int has_alpha = !(comp & 1);
- return outfile(filename, -1,-1, x, y, comp, data, has_alpha, 0,
- "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha);
-}
-
-// any other image formats that do interleaved rgb data?
-// PNG: requires adler32,crc32 -- significant amount of code
-// PSD: no, channels output separately
-// TIFF: no, stripwise-interleaved... i think
-
-#endif // STBI_NO_WRITE
-
-#endif // STBI_HEADER_FILE_ONLY
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- */
-
-/* This is just a wrapper to use our simplified version of glu.h so
- that the tesselator code can still #include <GL/glu.h> */
-
-#include "../tesselator.h"
-
-/* These aren't defined on GLES and we don't really want the
- tesselator code to use them but we're also trying to avoid
- modifying the C files so we just force them to be empty here */
-
-#undef GLAPI
-#define GLAPI
-
-#undef GLAPIENTRY
-#define GLAPIENTRY
-
-/* GLES doesn't define a GLdouble type so lets just force it to a
- regular double */
-#define GLdouble double
+++ /dev/null
-/*
-*/
-
-General Polygon Tesselation
----------------------------
-
- This note describes a tesselator for polygons consisting of one or
- more closed contours. It is backward-compatible with the current
- OpenGL Utilities tesselator, and is intended to replace it. Here is
- a summary of the major differences:
-
- - input contours can be intersecting, self-intersecting, or degenerate.
-
- - supports a choice of several winding rules for determining which parts
- of the polygon are on the "interior". This makes it possible to do
- CSG operations on polygons.
-
- - boundary extraction: instead of tesselating the polygon, returns a
- set of closed contours which separate the interior from the exterior.
-
- - returns the output as a small number of triangle fans and strips,
- rather than a list of independent triangles (when possible).
-
- - output is available as an explicit mesh (a quad-edge structure),
- in addition to the normal callback interface.
-
- - the algorithm used is extremely robust.
-
-
-The interface
--------------
-
- The tesselator state is maintained in a "tesselator object".
- These are allocated and destroyed using
-
- GLUtesselator *gluNewTess( void );
- void gluDeleteTess( GLUtesselator *tess );
-
- Several tesselator objects may be used simultaneously.
-
- Inputs
- ------
-
- The input contours are specified with the following routines:
-
- void gluTessBeginPolygon( GLUtesselator *tess );
- void gluTessBeginContour( GLUtesselator *tess );
- void gluTessVertex( GLUtesselator *tess, GLUcoord coords[3], void *data );
- void gluTessEndContour( GLUtesselator *tess );
- void gluTessEndPolygon( GLUtesselator *tess );
-
- Within each BeginPolygon/EndPolygon pair, there can be zero or more
- calls to BeginContour/EndContour. Within each contour, there are zero
- or more calls to gluTessVertex(). The vertices specify a closed
- contour (the last vertex of each contour is automatically linked to
- the first).
-
- "coords" give the coordinates of the vertex in 3-space. For useful
- results, all vertices should lie in some plane, since the vertices
- are projected onto a plane before tesselation. "data" is a pointer
- to a user-defined vertex structure, which typically contains other
- information such as color, texture coordinates, normal, etc. It is
- used to refer to the vertex during rendering.
-
- The library can be compiled in single- or double-precision; the type
- GLUcoord represents either "float" or "double" accordingly. The GLU
- version will be available in double-precision only. Compile with
- GLU_TESS_API_FLOAT defined to get the single-precision version.
-
- When EndPolygon is called, the tesselation algorithm determines
- which regions are interior to the given contours, according to one
- of several "winding rules" described below. The interior regions
- are then tesselated, and the output is provided as callbacks.
-
-
- Rendering Callbacks
- -------------------
-
- Callbacks are specified by the client using
-
- void gluTessCallback( GLUtesselator *tess, GLenum which, void (*fn)());
-
- If "fn" is NULL, any previously defined callback is discarded.
-
- The callbacks used to provide output are: /* which == */
-
- void begin( GLenum type ); /* GLU_TESS_BEGIN */
- void edgeFlag( GLboolean flag ); /* GLU_TESS_EDGE_FLAG */
- void vertex( void *data ); /* GLU_TESS_VERTEX */
- void end( void ); /* GLU_TESS_END */
-
- Any of the callbacks may be left undefined; if so, the corresponding
- information will not be supplied during rendering.
-
- The "begin" callback indicates the start of a primitive; type is one
- of GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN, or GL_TRIANGLES (but see the
- notes on "boundary extraction" below).
-
- It is followed by any number of "vertex" callbacks, which supply the
- vertices in the same order as expected by the corresponding glBegin()
- call. After the last vertex of a given primitive, there is a callback
- to "end".
-
- If the "edgeFlag" callback is provided, no triangle fans or strips
- will be used. When edgeFlag is called, if "flag" is GL_TRUE then each
- vertex which follows begins an edge which lies on the polygon boundary
- (ie. an edge which separates an interior region from an exterior one).
- If "flag" is GL_FALSE, each vertex which follows begins an edge which lies
- in the polygon interior. "edgeFlag" will be called before the first
- call to "vertex".
-
- Other Callbacks
- ---------------
-
- void mesh( GLUmesh *mesh ); /* GLU_TESS_MESH */
-
- - Returns an explicit mesh, represented using the quad-edge structure
- (Guibas/Stolfi '85). Other implementations of this interface might
- use a different mesh structure, so this is available only only as an
- SGI extension. When the mesh is no longer needed, it should be freed
- using
-
- void gluDeleteMesh( GLUmesh *mesh );
-
- There is a brief description of this data structure in the include
- file "mesh.h". For the full details, see L. Guibas and J. Stolfi,
- Primitives for the manipulation of general subdivisions and the
- computation of Voronoi diagrams, ACM Transactions on Graphics,
- 4(2):74-123, April 1985. For an introduction, see the course notes
- for CS348a, "Mathematical Foundations of Computer Graphics",
- available at the Stanford bookstore (and taught during the fall
- quarter).
-
- void error( GLenum errno ); /* GLU_TESS_ERROR */
-
- - errno is one of GLU_TESS_MISSING_BEGIN_POLYGON,
- GLU_TESS_MISSING_END_POLYGON,
- GLU_TESS_MISSING_BEGIN_CONTOUR,
- GLU_TESS_MISSING_END_CONTOUR,
- GLU_TESS_COORD_TOO_LARGE,
- GLU_TESS_NEED_COMBINE_CALLBACK
-
- The first four are obvious. The interface recovers from these
- errors by inserting the missing call(s).
-
- GLU_TESS_COORD_TOO_LARGE says that some vertex coordinate exceeded
- the predefined constant GLU_TESS_MAX_COORD in absolute value, and
- that the value has been clamped. (Coordinate values must be small
- enough so that two can be multiplied together without overflow.)
-
- GLU_TESS_NEED_COMBINE_CALLBACK says that the algorithm detected an
- intersection between two edges in the input data, and the "combine"
- callback (below) was not provided. No output will be generated.
-
-
- void combine( GLUcoord coords[3], void *data[4], /* GLU_TESS_COMBINE */
- GLUcoord weight[4], void **outData );
-
- - When the algorithm detects an intersection, or wishes to merge
- features, it needs to create a new vertex. The vertex is defined
- as a linear combination of up to 4 existing vertices, referenced
- by data[0..3]. The coefficients of the linear combination are
- given by weight[0..3]; these weights always sum to 1.0. All vertex
- pointers are valid even when some of the weights are zero.
- "coords" gives the location of the new vertex.
-
- The user must allocate another vertex, interpolate parameters
- using "data" and "weights", and return the new vertex pointer in
- "outData". This handle is supplied during rendering callbacks.
- For example, if the polygon lies in an arbitrary plane in 3-space,
- and we associate a color with each vertex, the combine callback might
- look like this:
-
- void myCombine( GLUcoord coords[3], VERTEX *d[4],
- GLUcoord w[4], VERTEX **dataOut )
- {
- VERTEX *new = new_vertex();
-
- new->x = coords[0];
- new->y = coords[1];
- new->z = coords[2];
- new->r = w[0]*d[0]->r + w[1]*d[1]->r + w[2]*d[2]->r + w[3]*d[3]->r;
- new->g = w[0]*d[0]->g + w[1]*d[1]->g + w[2]*d[2]->g + w[3]*d[3]->g;
- new->b = w[0]*d[0]->b + w[1]*d[1]->b + w[2]*d[2]->b + w[3]*d[3]->b;
- new->a = w[0]*d[0]->a + w[1]*d[1]->a + w[2]*d[2]->a + w[3]*d[3]->a;
- *dataOut = new;
- }
-
- If the algorithm detects an intersection, then the "combine" callback
- must be defined, and must write a non-NULL pointer into "dataOut".
- Otherwise the GLU_TESS_NEED_COMBINE_CALLBACK error occurs, and no
- output is generated. This is the only error that can occur during
- tesselation and rendering.
-
-
- Control over Tesselation
- ------------------------
-
- void gluTessProperty( GLUtesselator *tess, GLenum which, GLUcoord value );
-
- Properties defined:
-
- - GLU_TESS_WINDING_RULE. Possible values:
-
- GLU_TESS_WINDING_ODD
- GLU_TESS_WINDING_NONZERO
- GLU_TESS_WINDING_POSITIVE
- GLU_TESS_WINDING_NEGATIVE
- GLU_TESS_WINDING_ABS_GEQ_TWO
-
- The input contours parition the plane into regions. A winding
- rule determines which of these regions are inside the polygon.
-
- For a single contour C, the winding number of a point x is simply
- the signed number of revolutions we make around x as we travel
- once around C (where CCW is positive). When there are several
- contours, the individual winding numbers are summed. This
- procedure associates a signed integer value with each point x in
- the plane. Note that the winding number is the same for all
- points in a single region.
-
- The winding rule classifies a region as "inside" if its winding
- number belongs to the chosen category (odd, nonzero, positive,
- negative, or absolute value of at least two). The current GLU
- tesselator implements the "odd" rule. The "nonzero" rule is another
- common way to define the interior. The other three rules are
- useful for polygon CSG operations (see below).
-
- - GLU_TESS_BOUNDARY_ONLY. Values: TRUE (non-zero) or FALSE (zero).
-
- If TRUE, returns a set of closed contours which separate the
- polygon interior and exterior (rather than a tesselation).
- Exterior contours are oriented CCW with respect to the normal,
- interior contours are oriented CW. The GLU_TESS_BEGIN callback
- uses the type GL_LINE_LOOP for each contour.
-
- - GLU_TESS_TOLERANCE. Value: a real number between 0.0 and 1.0.
-
- This specifies a tolerance for merging features to reduce the size
- of the output. For example, two vertices which are very close to
- each other might be replaced by a single vertex. The tolerance
- is multiplied by the largest coordinate magnitude of any input vertex;
- this specifies the maximum distance that any feature can move as the
- result of a single merge operation. If a single feature takes part
- in several merge operations, the total distance moved could be larger.
-
- Feature merging is completely optional; the tolerance is only a hint.
- The implementation is free to merge in some cases and not in others,
- or to never merge features at all. The default tolerance is zero.
-
- The current implementation merges vertices only if they are exactly
- coincident, regardless of the current tolerance. A vertex is
- spliced into an edge only if the implementation is unable to
- distinguish which side of the edge the vertex lies on.
- Two edges are merged only when both endpoints are identical.
-
-
- void gluTessNormal( GLUtesselator *tess,
- GLUcoord x, GLUcoord y, GLUcoord z )
-
- - Lets the user supply the polygon normal, if known. All input data
- is projected into a plane perpendicular to the normal before
- tesselation. All output triangles are oriented CCW with
- respect to the normal (CW orientation can be obtained by
- reversing the sign of the supplied normal). For example, if
- you know that all polygons lie in the x-y plane, call
- "gluTessNormal(tess, 0.0, 0.0, 1.0)" before rendering any polygons.
-
- - If the supplied normal is (0,0,0) (the default value), the
- normal is determined as follows. The direction of the normal,
- up to its sign, is found by fitting a plane to the vertices,
- without regard to how the vertices are connected. It is
- expected that the input data lies approximately in plane;
- otherwise projection perpendicular to the computed normal may
- substantially change the geometry. The sign of the normal is
- chosen so that the sum of the signed areas of all input contours
- is non-negative (where a CCW contour has positive area).
-
- - The supplied normal persists until it is changed by another
- call to gluTessNormal.
-
-
- Backward compatibility with the GLU tesselator
- ----------------------------------------------
-
- The preferred interface is the one described above. The following
- routines are obsolete, and are provided only for backward compatibility:
-
- typedef GLUtesselator GLUtriangulatorObj; /* obsolete name */
-
- void gluBeginPolygon( GLUtesselator *tess );
- void gluNextContour( GLUtesselator *tess, GLenum type );
- void gluEndPolygon( GLUtesselator *tess );
-
- "type" is one of GLU_EXTERIOR, GLU_INTERIOR, GLU_CCW, GLU_CW, or
- GLU_UNKNOWN. It is ignored by the current GLU tesselator.
-
- GLU_BEGIN, GLU_VERTEX, GLU_END, GLU_ERROR, and GLU_EDGE_FLAG are defined
- as synonyms for GLU_TESS_BEGIN, GLU_TESS_VERTEX, GLU_TESS_END,
- GLU_TESS_ERROR, and GLU_TESS_EDGE_FLAG.
-
-
-Polygon CSG operations
-----------------------
-
- The features of the tesselator make it easy to find the union, difference,
- or intersection of several polygons.
-
- First, assume that each polygon is defined so that the winding number
- is 0 for each exterior region, and 1 for each interior region. Under
- this model, CCW contours define the outer boundary of the polygon, and
- CW contours define holes. Contours may be nested, but a nested
- contour must be oriented oppositely from the contour that contains it.
-
- If the original polygons do not satisfy this description, they can be
- converted to this form by first running the tesselator with the
- GLU_TESS_BOUNDARY_ONLY property turned on. This returns a list of
- contours satisfying the restriction above. By allocating two
- tesselator objects, the callbacks from one tesselator can be fed
- directly to the input of another.
-
- Given two or more polygons of the form above, CSG operations can be
- implemented as follows:
-
- Union
- Draw all the input contours as a single polygon. The winding number
- of each resulting region is the number of original polygons
- which cover it. The union can be extracted using the
- GLU_TESS_WINDING_NONZERO or GLU_TESS_WINDING_POSITIVE winding rules.
- Note that with the nonzero rule, we would get the same result if
- all contour orientations were reversed.
-
- Intersection (two polygons at a time only)
- Draw a single polygon using the contours from both input polygons.
- Extract the result using GLU_TESS_WINDING_ABS_GEQ_TWO. (Since this
- winding rule looks at the absolute value, reversing all contour
- orientations does not change the result.)
-
- Difference
-
- Suppose we want to compute A \ (B union C union D). Draw a single
- polygon consisting of the unmodified contours from A, followed by
- the contours of B,C,D with the vertex order reversed (this changes
- the winding number of the interior regions to -1). To extract the
- result, use the GLU_TESS_WINDING_POSITIVE rule.
-
- If B,C,D are the result of a GLU_TESS_BOUNDARY_ONLY call, an
- alternative to reversing the vertex order is to reverse the sign of
- the supplied normal. For example in the x-y plane, call
- gluTessNormal( tess, 0.0, 0.0, -1.0 ).
-
-
-Performance
------------
-
- The tesselator is not intended for immediate-mode rendering; when
- possible the output should be cached in a user structure or display
- list. General polygon tesselation is an inherently difficult problem,
- especially given the goal of extreme robustness.
-
- The implementation makes an effort to output a small number of fans
- and strips; this should improve the rendering performance when the
- output is used in a display list.
-
- Single-contour input polygons are first tested to see whether they can
- be rendered as a triangle fan with respect to the first vertex (to
- avoid running the full decomposition algorithm on convex polygons).
- Non-convex polygons may be rendered by this "fast path" as well, if
- the algorithm gets lucky in its choice of a starting vertex.
-
- For best performance follow these guidelines:
-
- - supply the polygon normal, if available, using gluTessNormal().
- This represents about 10% of the computation time. For example,
- if all polygons lie in the x-y plane, use gluTessNormal(tess,0,0,1).
-
- - render many polygons using the same tesselator object, rather than
- allocating a new tesselator for each one. (In a multi-threaded,
- multi-processor environment you may get better performance using
- several tesselators.)
-
-
-Comparison with the GLU tesselator
-----------------------------------
-
- On polygons which make it through the "fast path", the tesselator is
- 3 to 5 times faster than the GLU tesselator.
-
- On polygons which don't make it through the fast path (but which don't
- have self-intersections or degeneracies), it is about 2 times slower.
-
- On polygons with self-intersections or degeneraces, there is nothing
- to compare against.
-
- The new tesselator generates many more fans and strips, reducing the
- number of vertices that need to be sent to the hardware.
-
- Key to the statistics:
-
- vert number of input vertices on all contours
- cntr number of input contours
- tri number of triangles in all output primitives
- strip number of triangle strips
- fan number of triangle fans
- ind number of independent triangles
- ms number of milliseconds for tesselation
- (on a 150MHz R4400 Indy)
-
- Convex polygon examples:
-
-New: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.0459 ms
-Old: 3 vert, 1 cntr, 1 tri, 0 strip, 0 fan, 1 ind, 0.149 ms
-New: 4 vert, 1 cntr, 2 tri, 0 strip, 1 fan, 0 ind, 0.0459 ms
-Old: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.161 ms
-New: 36 vert, 1 cntr, 34 tri, 0 strip, 1 fan, 0 ind, 0.153 ms
-Old: 36 vert, 1 cntr, 34 tri, 0 strip, 0 fan, 34 ind, 0.621 ms
-
- Concave single-contour polygons:
-
-New: 5 vert, 1 cntr, 3 tri, 0 strip, 1 fan, 0 ind, 0.052 ms
-Old: 5 vert, 1 cntr, 3 tri, 0 strip, 0 fan, 3 ind, 0.252 ms
-New: 19 vert, 1 cntr, 17 tri, 2 strip, 2 fan, 1 ind, 0.911 ms
-Old: 19 vert, 1 cntr, 17 tri, 0 strip, 0 fan, 17 ind, 0.529 ms
-New: 151 vert, 1 cntr, 149 tri, 13 strip, 18 fan, 3 ind, 6.82 ms
-Old: 151 vert, 1 cntr, 149 tri, 0 strip, 3 fan, 143 ind, 2.7 ms
-New: 574 vert, 1 cntr, 572 tri, 59 strip, 54 fan, 11 ind, 26.6 ms
-Old: 574 vert, 1 cntr, 572 tri, 0 strip, 31 fan, 499 ind, 12.4 ms
-
- Multiple contours, but no intersections:
-
-New: 7 vert, 2 cntr, 7 tri, 1 strip, 0 fan, 0 ind, 0.527 ms
-Old: 7 vert, 2 cntr, 7 tri, 0 strip, 0 fan, 7 ind, 0.274 ms
-New: 81 vert, 6 cntr, 89 tri, 9 strip, 7 fan, 6 ind, 3.88 ms
-Old: 81 vert, 6 cntr, 89 tri, 0 strip, 13 fan, 61 ind, 2.2 ms
-New: 391 vert, 19 cntr, 413 tri, 37 strip, 32 fan, 26 ind, 20.2 ms
-Old: 391 vert, 19 cntr, 413 tri, 0 strip, 25 fan, 363 ind, 8.68 ms
-
- Self-intersecting and degenerate examples:
-
-Bowtie: 4 vert, 1 cntr, 2 tri, 0 strip, 0 fan, 2 ind, 0.483 ms
-Star: 5 vert, 1 cntr, 5 tri, 0 strip, 0 fan, 5 ind, 0.91 ms
-Random: 24 vert, 7 cntr, 46 tri, 2 strip, 12 fan, 7 ind, 5.32 ms
-Font: 333 vert, 2 cntr, 331 tri, 32 strip, 16 fan, 3 ind, 14.1 ms
-: 167 vert, 35 cntr, 254 tri, 8 strip, 56 fan, 52 ind, 46.3 ms
-: 78 vert, 1 cntr, 2675 tri, 148 strip, 207 fan, 180 ind, 243 ms
-: 12480 vert, 2 cntr, 12478 tri, 736 strip,1275 fan, 5 ind, 1010 ms
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __dict_list_h_
-#define __dict_list_h_
-
-/* Use #define's so that another heap implementation can use this one */
-
-#define DictKey DictListKey
-#define Dict DictList
-#define DictNode DictListNode
-
-#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq)
-#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict)
-
-#define dictSearch(dict,key) __gl_dictListSearch(dict,key)
-#define dictInsert(dict,key) __gl_dictListInsert(dict,key)
-#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key)
-#define dictDelete(dict,node) __gl_dictListDelete(dict,node)
-
-#define dictKey(n) __gl_dictListKey(n)
-#define dictSucc(n) __gl_dictListSucc(n)
-#define dictPred(n) __gl_dictListPred(n)
-#define dictMin(d) __gl_dictListMin(d)
-#define dictMax(d) __gl_dictListMax(d)
-
-
-
-typedef void *DictKey;
-typedef struct Dict Dict;
-typedef struct DictNode DictNode;
-
-Dict *dictNewDict(
- void *frame,
- int (*leq)(void *frame, DictKey key1, DictKey key2) );
-
-void dictDeleteDict( Dict *dict );
-
-/* Search returns the node with the smallest key greater than or equal
- * to the given key. If there is no such key, returns a node whose
- * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc.
- */
-DictNode *dictSearch( Dict *dict, DictKey key );
-DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key );
-void dictDelete( Dict *dict, DictNode *node );
-
-#define __gl_dictListKey(n) ((n)->key)
-#define __gl_dictListSucc(n) ((n)->next)
-#define __gl_dictListPred(n) ((n)->prev)
-#define __gl_dictListMin(d) ((d)->head.next)
-#define __gl_dictListMax(d) ((d)->head.prev)
-#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k)))
-
-
-/*** Private data structures ***/
-
-struct DictNode {
- DictKey key;
- DictNode *next;
- DictNode *prev;
-};
-
-struct Dict {
- DictNode head;
- void *frame;
- int (*leq)(void *frame, DictKey key1, DictKey key2);
-};
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include <stddef.h>
-#include "dict-list.h"
-#include "memalloc.h"
-
-/* really __gl_dictListNewDict */
-Dict *dictNewDict( void *frame,
- int (*leq)(void *frame, DictKey key1, DictKey key2) )
-{
- Dict *dict = (Dict *) memAlloc( sizeof( Dict ));
- DictNode *head;
-
- if (dict == NULL) return NULL;
-
- head = &dict->head;
-
- head->key = NULL;
- head->next = head;
- head->prev = head;
-
- dict->frame = frame;
- dict->leq = leq;
-
- return dict;
-}
-
-/* really __gl_dictListDeleteDict */
-void dictDeleteDict( Dict *dict )
-{
- DictNode *node, *next;
-
- for( node = dict->head.next; node != &dict->head; node = next ) {
- next = node->next;
- memFree( node );
- }
- memFree( dict );
-}
-
-/* really __gl_dictListInsertBefore */
-DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key )
-{
- DictNode *newNode;
-
- do {
- node = node->prev;
- } while( node->key != NULL && ! (*dict->leq)(dict->frame, node->key, key));
-
- newNode = (DictNode *) memAlloc( sizeof( DictNode ));
- if (newNode == NULL) return NULL;
-
- newNode->key = key;
- newNode->next = node->next;
- node->next->prev = newNode;
- newNode->prev = node;
- node->next = newNode;
-
- return newNode;
-}
-
-/* really __gl_dictListDelete */
-void dictDelete( Dict *dict, DictNode *node ) /*ARGSUSED*/
-{
- node->next->prev = node->prev;
- node->prev->next = node->next;
- memFree( node );
-}
-
-/* really __gl_dictListSearch */
-DictNode *dictSearch( Dict *dict, DictKey key )
-{
- DictNode *node = &dict->head;
-
- do {
- node = node->next;
- } while( node->key != NULL && ! (*dict->leq)(dict->frame, key, node->key));
-
- return node;
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __dict_list_h_
-#define __dict_list_h_
-
-/* Use #define's so that another heap implementation can use this one */
-
-#define DictKey DictListKey
-#define Dict DictList
-#define DictNode DictListNode
-
-#define dictNewDict(frame,leq) __gl_dictListNewDict(frame,leq)
-#define dictDeleteDict(dict) __gl_dictListDeleteDict(dict)
-
-#define dictSearch(dict,key) __gl_dictListSearch(dict,key)
-#define dictInsert(dict,key) __gl_dictListInsert(dict,key)
-#define dictInsertBefore(dict,node,key) __gl_dictListInsertBefore(dict,node,key)
-#define dictDelete(dict,node) __gl_dictListDelete(dict,node)
-
-#define dictKey(n) __gl_dictListKey(n)
-#define dictSucc(n) __gl_dictListSucc(n)
-#define dictPred(n) __gl_dictListPred(n)
-#define dictMin(d) __gl_dictListMin(d)
-#define dictMax(d) __gl_dictListMax(d)
-
-
-
-typedef void *DictKey;
-typedef struct Dict Dict;
-typedef struct DictNode DictNode;
-
-Dict *dictNewDict(
- void *frame,
- int (*leq)(void *frame, DictKey key1, DictKey key2) );
-
-void dictDeleteDict( Dict *dict );
-
-/* Search returns the node with the smallest key greater than or equal
- * to the given key. If there is no such key, returns a node whose
- * key is NULL. Similarly, Succ(Max(d)) has a NULL key, etc.
- */
-DictNode *dictSearch( Dict *dict, DictKey key );
-DictNode *dictInsertBefore( Dict *dict, DictNode *node, DictKey key );
-void dictDelete( Dict *dict, DictNode *node );
-
-#define __gl_dictListKey(n) ((n)->key)
-#define __gl_dictListSucc(n) ((n)->next)
-#define __gl_dictListPred(n) ((n)->prev)
-#define __gl_dictListMin(d) ((d)->head.next)
-#define __gl_dictListMax(d) ((d)->head.prev)
-#define __gl_dictListInsert(d,k) (dictInsertBefore((d),&(d)->head,(k)))
-
-
-/*** Private data structures ***/
-
-struct DictNode {
- DictKey key;
- DictNode *next;
- DictNode *prev;
-};
-
-struct Dict {
- DictNode head;
- void *frame;
- int (*leq)(void *frame, DictKey key1, DictKey key2);
-};
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <assert.h>
-#include "mesh.h"
-#include "geom.h"
-
-int __gl_vertLeq( GLUvertex *u, GLUvertex *v )
-{
- /* Returns TRUE if u is lexicographically <= v. */
-
- return VertLeq( u, v );
-}
-
-GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
-{
- /* Given three vertices u,v,w such that VertLeq(u,v) && VertLeq(v,w),
- * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
- * Returns v->t - (uw)(v->s), ie. the signed distance from uw to v.
- * If uw is vertical (and thus passes thru v), the result is zero.
- *
- * The calculation is extremely accurate and stable, even when v
- * is very close to u or w. In particular if we set v->t = 0 and
- * let r be the negated result (this evaluates (uw)(v->s)), then
- * r is guaranteed to satisfy MIN(u->t,w->t) <= r <= MAX(u->t,w->t).
- */
- GLdouble gapL, gapR;
-
- assert( VertLeq( u, v ) && VertLeq( v, w ));
-
- gapL = v->s - u->s;
- gapR = w->s - v->s;
-
- if( gapL + gapR > 0 ) {
- if( gapL < gapR ) {
- return (v->t - u->t) + (u->t - w->t) * (gapL / (gapL + gapR));
- } else {
- return (v->t - w->t) + (w->t - u->t) * (gapR / (gapL + gapR));
- }
- }
- /* vertical line */
- return 0;
-}
-
-GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
-{
- /* Returns a number whose sign matches EdgeEval(u,v,w) but which
- * is cheaper to evaluate. Returns > 0, == 0 , or < 0
- * as v is above, on, or below the edge uw.
- */
- GLdouble gapL, gapR;
-
- assert( VertLeq( u, v ) && VertLeq( v, w ));
-
- gapL = v->s - u->s;
- gapR = w->s - v->s;
-
- if( gapL + gapR > 0 ) {
- return (v->t - w->t) * gapL + (v->t - u->t) * gapR;
- }
- /* vertical line */
- return 0;
-}
-
-
-/***********************************************************************
- * Define versions of EdgeSign, EdgeEval with s and t transposed.
- */
-
-GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w )
-{
- /* Given three vertices u,v,w such that TransLeq(u,v) && TransLeq(v,w),
- * evaluates the t-coord of the edge uw at the s-coord of the vertex v.
- * Returns v->s - (uw)(v->t), ie. the signed distance from uw to v.
- * If uw is vertical (and thus passes thru v), the result is zero.
- *
- * The calculation is extremely accurate and stable, even when v
- * is very close to u or w. In particular if we set v->s = 0 and
- * let r be the negated result (this evaluates (uw)(v->t)), then
- * r is guaranteed to satisfy MIN(u->s,w->s) <= r <= MAX(u->s,w->s).
- */
- GLdouble gapL, gapR;
-
- assert( TransLeq( u, v ) && TransLeq( v, w ));
-
- gapL = v->t - u->t;
- gapR = w->t - v->t;
-
- if( gapL + gapR > 0 ) {
- if( gapL < gapR ) {
- return (v->s - u->s) + (u->s - w->s) * (gapL / (gapL + gapR));
- } else {
- return (v->s - w->s) + (w->s - u->s) * (gapR / (gapL + gapR));
- }
- }
- /* vertical line */
- return 0;
-}
-
-GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w )
-{
- /* Returns a number whose sign matches TransEval(u,v,w) but which
- * is cheaper to evaluate. Returns > 0, == 0 , or < 0
- * as v is above, on, or below the edge uw.
- */
- GLdouble gapL, gapR;
-
- assert( TransLeq( u, v ) && TransLeq( v, w ));
-
- gapL = v->t - u->t;
- gapR = w->t - v->t;
-
- if( gapL + gapR > 0 ) {
- return (v->s - w->s) * gapL + (v->s - u->s) * gapR;
- }
- /* vertical line */
- return 0;
-}
-
-
-int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w )
-{
- /* For almost-degenerate situations, the results are not reliable.
- * Unless the floating-point arithmetic can be performed without
- * rounding errors, *any* implementation will give incorrect results
- * on some degenerate inputs, so the client must have some way to
- * handle this situation.
- */
- return (u->s*(v->t - w->t) + v->s*(w->t - u->t) + w->s*(u->t - v->t)) >= 0;
-}
-
-/* Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b),
- * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces
- * this in the rare case that one argument is slightly negative.
- * The implementation is extremely stable numerically.
- * In particular it guarantees that the result r satisfies
- * MIN(x,y) <= r <= MAX(x,y), and the results are very accurate
- * even when a and b differ greatly in magnitude.
- */
-#define RealInterpolate(a,x,b,y) \
- (a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, \
- ((a <= b) ? ((b == 0) ? ((x+y) / 2) \
- : (x + (y-x) * (a/(a+b)))) \
- : (y + (x-y) * (b/(a+b)))))
-
-#ifndef FOR_TRITE_TEST_PROGRAM
-#define Interpolate(a,x,b,y) RealInterpolate(a,x,b,y)
-#else
-
-/* Claim: the ONLY property the sweep algorithm relies on is that
- * MIN(x,y) <= r <= MAX(x,y). This is a nasty way to test that.
- */
-#include <stdlib.h>
-extern int RandomInterpolate;
-
-GLdouble Interpolate( GLdouble a, GLdouble x, GLdouble b, GLdouble y)
-{
-printf("*********************%d\n",RandomInterpolate);
- if( RandomInterpolate ) {
- a = 1.2 * drand48() - 0.1;
- a = (a < 0) ? 0 : ((a > 1) ? 1 : a);
- b = 1.0 - a;
- }
- return RealInterpolate(a,x,b,y);
-}
-
-#endif
-
-#define Swap(a,b) do { GLUvertex *t = a; a = b; b = t; } while (0)
-
-void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
- GLUvertex *o2, GLUvertex *d2,
- GLUvertex *v )
-/* Given edges (o1,d1) and (o2,d2), compute their point of intersection.
- * The computed point is guaranteed to lie in the intersection of the
- * bounding rectangles defined by each edge.
- */
-{
- GLdouble z1, z2;
-
- /* This is certainly not the most efficient way to find the intersection
- * of two line segments, but it is very numerically stable.
- *
- * Strategy: find the two middle vertices in the VertLeq ordering,
- * and interpolate the intersection s-value from these. Then repeat
- * using the TransLeq ordering to find the intersection t-value.
- */
-
- if( ! VertLeq( o1, d1 )) { Swap( o1, d1 ); }
- if( ! VertLeq( o2, d2 )) { Swap( o2, d2 ); }
- if( ! VertLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
-
- if( ! VertLeq( o2, d1 )) {
- /* Technically, no intersection -- do our best */
- v->s = (o2->s + d1->s) / 2;
- } else if( VertLeq( d1, d2 )) {
- /* Interpolate between o2 and d1 */
- z1 = EdgeEval( o1, o2, d1 );
- z2 = EdgeEval( o2, d1, d2 );
- if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
- v->s = Interpolate( z1, o2->s, z2, d1->s );
- } else {
- /* Interpolate between o2 and d2 */
- z1 = EdgeSign( o1, o2, d1 );
- z2 = -EdgeSign( o1, d2, d1 );
- if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
- v->s = Interpolate( z1, o2->s, z2, d2->s );
- }
-
- /* Now repeat the process for t */
-
- if( ! TransLeq( o1, d1 )) { Swap( o1, d1 ); }
- if( ! TransLeq( o2, d2 )) { Swap( o2, d2 ); }
- if( ! TransLeq( o1, o2 )) { Swap( o1, o2 ); Swap( d1, d2 ); }
-
- if( ! TransLeq( o2, d1 )) {
- /* Technically, no intersection -- do our best */
- v->t = (o2->t + d1->t) / 2;
- } else if( TransLeq( d1, d2 )) {
- /* Interpolate between o2 and d1 */
- z1 = TransEval( o1, o2, d1 );
- z2 = TransEval( o2, d1, d2 );
- if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
- v->t = Interpolate( z1, o2->t, z2, d1->t );
- } else {
- /* Interpolate between o2 and d2 */
- z1 = TransSign( o1, o2, d1 );
- z2 = -TransSign( o1, d2, d1 );
- if( z1+z2 < 0 ) { z1 = -z1; z2 = -z2; }
- v->t = Interpolate( z1, o2->t, z2, d2->t );
- }
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __geom_h_
-#define __geom_h_
-
-#include "mesh.h"
-
-#ifdef NO_BRANCH_CONDITIONS
-/* MIPS architecture has special instructions to evaluate boolean
- * conditions -- more efficient than branching, IF you can get the
- * compiler to generate the right instructions (SGI compiler doesn't)
- */
-#define VertEq(u,v) (((u)->s == (v)->s) & ((u)->t == (v)->t))
-#define VertLeq(u,v) (((u)->s < (v)->s) | \
- ((u)->s == (v)->s & (u)->t <= (v)->t))
-#else
-#define VertEq(u,v) ((u)->s == (v)->s && (u)->t == (v)->t)
-#define VertLeq(u,v) (((u)->s < (v)->s) || \
- ((u)->s == (v)->s && (u)->t <= (v)->t))
-#endif
-
-#define EdgeEval(u,v,w) __gl_edgeEval(u,v,w)
-#define EdgeSign(u,v,w) __gl_edgeSign(u,v,w)
-
-/* Versions of VertLeq, EdgeSign, EdgeEval with s and t transposed. */
-
-#define TransLeq(u,v) (((u)->t < (v)->t) || \
- ((u)->t == (v)->t && (u)->s <= (v)->s))
-#define TransEval(u,v,w) __gl_transEval(u,v,w)
-#define TransSign(u,v,w) __gl_transSign(u,v,w)
-
-
-#define EdgeGoesLeft(e) VertLeq( (e)->Dst, (e)->Org )
-#define EdgeGoesRight(e) VertLeq( (e)->Org, (e)->Dst )
-
-#undef ABS
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-#define VertL1dist(u,v) (ABS(u->s - v->s) + ABS(u->t - v->t))
-
-#define VertCCW(u,v,w) __gl_vertCCW(u,v,w)
-
-int __gl_vertLeq( GLUvertex *u, GLUvertex *v );
-GLdouble __gl_edgeEval( GLUvertex *u, GLUvertex *v, GLUvertex *w );
-GLdouble __gl_edgeSign( GLUvertex *u, GLUvertex *v, GLUvertex *w );
-GLdouble __gl_transEval( GLUvertex *u, GLUvertex *v, GLUvertex *w );
-GLdouble __gl_transSign( GLUvertex *u, GLUvertex *v, GLUvertex *w );
-int __gl_vertCCW( GLUvertex *u, GLUvertex *v, GLUvertex *w );
-void __gl_edgeIntersect( GLUvertex *o1, GLUvertex *d1,
- GLUvertex *o2, GLUvertex *d2,
- GLUvertex *v );
-
-#endif
+++ /dev/null
-/* This is a stub header to avoid having to change tess.c */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This is a simple replacement for memalloc from the SGI tesselator
- code to force it to use glib's allocation instead */
-
-#ifndef __MEMALLOC_H__
-#define __MEMALLOC_H__
-
-#include <glib.h>
-
-#define memRealloc g_realloc
-#define memAlloc g_malloc
-#define memFree g_free
-#define memInit(x) 1
-
-/* tess.c defines TRUE and FALSE itself unconditionally so we need to
- undefine it from the glib headers */
-#undef TRUE
-#undef FALSE
-
-#endif /* __MEMALLOC_H__ */
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <stddef.h>
-#include <assert.h>
-#include "mesh.h"
-#include "memalloc.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-static GLUvertex *allocVertex()
-{
- return (GLUvertex *)memAlloc( sizeof( GLUvertex ));
-}
-
-static GLUface *allocFace()
-{
- return (GLUface *)memAlloc( sizeof( GLUface ));
-}
-
-/************************ Utility Routines ************************/
-
-/* Allocate and free half-edges in pairs for efficiency.
- * The *only* place that should use this fact is allocation/free.
- */
-typedef struct { GLUhalfEdge e, eSym; } EdgePair;
-
-/* MakeEdge creates a new pair of half-edges which form their own loop.
- * No vertex or face structures are allocated, but these must be assigned
- * before the current edge operation is completed.
- */
-static GLUhalfEdge *MakeEdge( GLUhalfEdge *eNext )
-{
- GLUhalfEdge *e;
- GLUhalfEdge *eSym;
- GLUhalfEdge *ePrev;
- EdgePair *pair = (EdgePair *)memAlloc( sizeof( EdgePair ));
- if (pair == NULL) return NULL;
-
- e = &pair->e;
- eSym = &pair->eSym;
-
- /* Make sure eNext points to the first edge of the edge pair */
- if( eNext->Sym < eNext ) { eNext = eNext->Sym; }
-
- /* Insert in circular doubly-linked list before eNext.
- * Note that the prev pointer is stored in Sym->next.
- */
- ePrev = eNext->Sym->next;
- eSym->next = ePrev;
- ePrev->Sym->next = e;
- e->next = eNext;
- eNext->Sym->next = eSym;
-
- e->Sym = eSym;
- e->Onext = e;
- e->Lnext = eSym;
- e->Org = NULL;
- e->Lface = NULL;
- e->winding = 0;
- e->activeRegion = NULL;
-
- eSym->Sym = e;
- eSym->Onext = eSym;
- eSym->Lnext = e;
- eSym->Org = NULL;
- eSym->Lface = NULL;
- eSym->winding = 0;
- eSym->activeRegion = NULL;
-
- return e;
-}
-
-/* Splice( a, b ) is best described by the Guibas/Stolfi paper or the
- * CS348a notes (see mesh.h). Basically it modifies the mesh so that
- * a->Onext and b->Onext are exchanged. This can have various effects
- * depending on whether a and b belong to different face or vertex rings.
- * For more explanation see __gl_meshSplice() below.
- */
-static void Splice( GLUhalfEdge *a, GLUhalfEdge *b )
-{
- GLUhalfEdge *aOnext = a->Onext;
- GLUhalfEdge *bOnext = b->Onext;
-
- aOnext->Sym->Lnext = b;
- bOnext->Sym->Lnext = a;
- a->Onext = bOnext;
- b->Onext = aOnext;
-}
-
-/* MakeVertex( newVertex, eOrig, vNext ) attaches a new vertex and makes it the
- * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives
- * a place to insert the new vertex in the global vertex list. We insert
- * the new vertex *before* vNext so that algorithms which walk the vertex
- * list will not see the newly created vertices.
- */
-static void MakeVertex( GLUvertex *newVertex,
- GLUhalfEdge *eOrig, GLUvertex *vNext )
-{
- GLUhalfEdge *e;
- GLUvertex *vPrev;
- GLUvertex *vNew = newVertex;
-
- assert(vNew != NULL);
-
- /* insert in circular doubly-linked list before vNext */
- vPrev = vNext->prev;
- vNew->prev = vPrev;
- vPrev->next = vNew;
- vNew->next = vNext;
- vNext->prev = vNew;
-
- vNew->anEdge = eOrig;
- vNew->data = NULL;
- /* leave coords, s, t undefined */
-
- /* fix other edges on this vertex loop */
- e = eOrig;
- do {
- e->Org = vNew;
- e = e->Onext;
- } while( e != eOrig );
-}
-
-/* MakeFace( newFace, eOrig, fNext ) attaches a new face and makes it the left
- * face of all edges in the face loop to which eOrig belongs. "fNext" gives
- * a place to insert the new face in the global face list. We insert
- * the new face *before* fNext so that algorithms which walk the face
- * list will not see the newly created faces.
- */
-static void MakeFace( GLUface *newFace, GLUhalfEdge *eOrig, GLUface *fNext )
-{
- GLUhalfEdge *e;
- GLUface *fPrev;
- GLUface *fNew = newFace;
-
- assert(fNew != NULL);
-
- /* insert in circular doubly-linked list before fNext */
- fPrev = fNext->prev;
- fNew->prev = fPrev;
- fPrev->next = fNew;
- fNew->next = fNext;
- fNext->prev = fNew;
-
- fNew->anEdge = eOrig;
- fNew->data = NULL;
- fNew->trail = NULL;
- fNew->marked = FALSE;
-
- /* The new face is marked "inside" if the old one was. This is a
- * convenience for the common case where a face has been split in two.
- */
- fNew->inside = fNext->inside;
-
- /* fix other edges on this face loop */
- e = eOrig;
- do {
- e->Lface = fNew;
- e = e->Lnext;
- } while( e != eOrig );
-}
-
-/* KillEdge( eDel ) destroys an edge (the half-edges eDel and eDel->Sym),
- * and removes from the global edge list.
- */
-static void KillEdge( GLUhalfEdge *eDel )
-{
- GLUhalfEdge *ePrev, *eNext;
-
- /* Half-edges are allocated in pairs, see EdgePair above */
- if( eDel->Sym < eDel ) { eDel = eDel->Sym; }
-
- /* delete from circular doubly-linked list */
- eNext = eDel->next;
- ePrev = eDel->Sym->next;
- eNext->Sym->next = ePrev;
- ePrev->Sym->next = eNext;
-
- memFree( eDel );
-}
-
-
-/* KillVertex( vDel ) destroys a vertex and removes it from the global
- * vertex list. It updates the vertex loop to point to a given new vertex.
- */
-static void KillVertex( GLUvertex *vDel, GLUvertex *newOrg )
-{
- GLUhalfEdge *e, *eStart = vDel->anEdge;
- GLUvertex *vPrev, *vNext;
-
- /* change the origin of all affected edges */
- e = eStart;
- do {
- e->Org = newOrg;
- e = e->Onext;
- } while( e != eStart );
-
- /* delete from circular doubly-linked list */
- vPrev = vDel->prev;
- vNext = vDel->next;
- vNext->prev = vPrev;
- vPrev->next = vNext;
-
- memFree( vDel );
-}
-
-/* KillFace( fDel ) destroys a face and removes it from the global face
- * list. It updates the face loop to point to a given new face.
- */
-static void KillFace( GLUface *fDel, GLUface *newLface )
-{
- GLUhalfEdge *e, *eStart = fDel->anEdge;
- GLUface *fPrev, *fNext;
-
- /* change the left face of all affected edges */
- e = eStart;
- do {
- e->Lface = newLface;
- e = e->Lnext;
- } while( e != eStart );
-
- /* delete from circular doubly-linked list */
- fPrev = fDel->prev;
- fNext = fDel->next;
- fNext->prev = fPrev;
- fPrev->next = fNext;
-
- memFree( fDel );
-}
-
-
-/****************** Basic Edge Operations **********************/
-
-/* __gl_meshMakeEdge creates one edge, two vertices, and a loop (face).
- * The loop consists of the two new half-edges.
- */
-GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh )
-{
- GLUvertex *newVertex1= allocVertex();
- GLUvertex *newVertex2= allocVertex();
- GLUface *newFace= allocFace();
- GLUhalfEdge *e;
-
- /* if any one is null then all get freed */
- if (newVertex1 == NULL || newVertex2 == NULL || newFace == NULL) {
- if (newVertex1 != NULL) memFree(newVertex1);
- if (newVertex2 != NULL) memFree(newVertex2);
- if (newFace != NULL) memFree(newFace);
- return NULL;
- }
-
- e = MakeEdge( &mesh->eHead );
- if (e == NULL) {
- memFree(newVertex1);
- memFree(newVertex2);
- memFree(newFace);
- return NULL;
- }
-
- MakeVertex( newVertex1, e, &mesh->vHead );
- MakeVertex( newVertex2, e->Sym, &mesh->vHead );
- MakeFace( newFace, e, &mesh->fHead );
- return e;
-}
-
-
-/* __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
- * mesh connectivity and topology. It changes the mesh so that
- * eOrg->Onext <- OLD( eDst->Onext )
- * eDst->Onext <- OLD( eOrg->Onext )
- * where OLD(...) means the value before the meshSplice operation.
- *
- * This can have two effects on the vertex structure:
- * - if eOrg->Org != eDst->Org, the two vertices are merged together
- * - if eOrg->Org == eDst->Org, the origin is split into two vertices
- * In both cases, eDst->Org is changed and eOrg->Org is untouched.
- *
- * Similarly (and independently) for the face structure,
- * - if eOrg->Lface == eDst->Lface, one loop is split into two
- * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
- * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
- *
- * Some special cases:
- * If eDst == eOrg, the operation has no effect.
- * If eDst == eOrg->Lnext, the new face will have a single edge.
- * If eDst == eOrg->Lprev, the old face will have a single edge.
- * If eDst == eOrg->Onext, the new vertex will have a single edge.
- * If eDst == eOrg->Oprev, the old vertex will have a single edge.
- */
-int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
-{
- int joiningLoops = FALSE;
- int joiningVertices = FALSE;
-
- if( eOrg == eDst ) return 1;
-
- if( eDst->Org != eOrg->Org ) {
- /* We are merging two disjoint vertices -- destroy eDst->Org */
- joiningVertices = TRUE;
- KillVertex( eDst->Org, eOrg->Org );
- }
- if( eDst->Lface != eOrg->Lface ) {
- /* We are connecting two disjoint loops -- destroy eDst->Lface */
- joiningLoops = TRUE;
- KillFace( eDst->Lface, eOrg->Lface );
- }
-
- /* Change the edge structure */
- Splice( eDst, eOrg );
-
- if( ! joiningVertices ) {
- GLUvertex *newVertex= allocVertex();
- if (newVertex == NULL) return 0;
-
- /* We split one vertex into two -- the new vertex is eDst->Org.
- * Make sure the old vertex points to a valid half-edge.
- */
- MakeVertex( newVertex, eDst, eOrg->Org );
- eOrg->Org->anEdge = eOrg;
- }
- if( ! joiningLoops ) {
- GLUface *newFace= allocFace();
- if (newFace == NULL) return 0;
-
- /* We split one loop into two -- the new loop is eDst->Lface.
- * Make sure the old face points to a valid half-edge.
- */
- MakeFace( newFace, eDst, eOrg->Lface );
- eOrg->Lface->anEdge = eOrg;
- }
-
- return 1;
-}
-
-
-/* __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
- * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
- * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
- * the newly created loop will contain eDel->Dst. If the deletion of eDel
- * would create isolated vertices, those are deleted as well.
- *
- * This function could be implemented as two calls to __gl_meshSplice
- * plus a few calls to memFree, but this would allocate and delete
- * unnecessary vertices and faces.
- */
-int __gl_meshDelete( GLUhalfEdge *eDel )
-{
- GLUhalfEdge *eDelSym = eDel->Sym;
- int joiningLoops = FALSE;
-
- /* First step: disconnect the origin vertex eDel->Org. We make all
- * changes to get a consistent mesh in this "intermediate" state.
- */
- if( eDel->Lface != eDel->Rface ) {
- /* We are joining two loops into one -- remove the left face */
- joiningLoops = TRUE;
- KillFace( eDel->Lface, eDel->Rface );
- }
-
- if( eDel->Onext == eDel ) {
- KillVertex( eDel->Org, NULL );
- } else {
- /* Make sure that eDel->Org and eDel->Rface point to valid half-edges */
- eDel->Rface->anEdge = eDel->Oprev;
- eDel->Org->anEdge = eDel->Onext;
-
- Splice( eDel, eDel->Oprev );
- if( ! joiningLoops ) {
- GLUface *newFace= allocFace();
- if (newFace == NULL) return 0;
-
- /* We are splitting one loop into two -- create a new loop for eDel. */
- MakeFace( newFace, eDel, eDel->Lface );
- }
- }
-
- /* Claim: the mesh is now in a consistent state, except that eDel->Org
- * may have been deleted. Now we disconnect eDel->Dst.
- */
- if( eDelSym->Onext == eDelSym ) {
- KillVertex( eDelSym->Org, NULL );
- KillFace( eDelSym->Lface, NULL );
- } else {
- /* Make sure that eDel->Dst and eDel->Lface point to valid half-edges */
- eDel->Lface->anEdge = eDelSym->Oprev;
- eDelSym->Org->anEdge = eDelSym->Onext;
- Splice( eDelSym, eDelSym->Oprev );
- }
-
- /* Any isolated vertices or faces have already been freed. */
- KillEdge( eDel );
-
- return 1;
-}
-
-
-/******************** Other Edge Operations **********************/
-
-/* All these routines can be implemented with the basic edge
- * operations above. They are provided for convenience and efficiency.
- */
-
-
-/* __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
- * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
- * eOrg and eNew will have the same left face.
- */
-GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg )
-{
- GLUhalfEdge *eNewSym;
- GLUhalfEdge *eNew = MakeEdge( eOrg );
- if (eNew == NULL) return NULL;
-
- eNewSym = eNew->Sym;
-
- /* Connect the new edge appropriately */
- Splice( eNew, eOrg->Lnext );
-
- /* Set the vertex and face information */
- eNew->Org = eOrg->Dst;
- {
- GLUvertex *newVertex= allocVertex();
- if (newVertex == NULL) return NULL;
-
- MakeVertex( newVertex, eNewSym, eNew->Org );
- }
- eNew->Lface = eNewSym->Lface = eOrg->Lface;
-
- return eNew;
-}
-
-
-/* __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
- * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
- * eOrg and eNew will have the same left face.
- */
-GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg )
-{
- GLUhalfEdge *eNew;
- GLUhalfEdge *tempHalfEdge= __gl_meshAddEdgeVertex( eOrg );
- if (tempHalfEdge == NULL) return NULL;
-
- eNew = tempHalfEdge->Sym;
-
- /* Disconnect eOrg from eOrg->Dst and connect it to eNew->Org */
- Splice( eOrg->Sym, eOrg->Sym->Oprev );
- Splice( eOrg->Sym, eNew );
-
- /* Set the vertex and face information */
- eOrg->Dst = eNew->Org;
- eNew->Dst->anEdge = eNew->Sym; /* may have pointed to eOrg->Sym */
- eNew->Rface = eOrg->Rface;
- eNew->winding = eOrg->winding; /* copy old winding information */
- eNew->Sym->winding = eOrg->Sym->winding;
-
- return eNew;
-}
-
-
-/* __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
- * to eDst->Org, and returns the corresponding half-edge eNew.
- * If eOrg->Lface == eDst->Lface, this splits one loop into two,
- * and the newly created loop is eNew->Lface. Otherwise, two disjoint
- * loops are merged into one, and the loop eDst->Lface is destroyed.
- *
- * If (eOrg == eDst), the new face will have only two edges.
- * If (eOrg->Lnext == eDst), the old face is reduced to a single edge.
- * If (eOrg->Lnext->Lnext == eDst), the old face is reduced to two edges.
- */
-GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst )
-{
- GLUhalfEdge *eNewSym;
- int joiningLoops = FALSE;
- GLUhalfEdge *eNew = MakeEdge( eOrg );
- if (eNew == NULL) return NULL;
-
- eNewSym = eNew->Sym;
-
- if( eDst->Lface != eOrg->Lface ) {
- /* We are connecting two disjoint loops -- destroy eDst->Lface */
- joiningLoops = TRUE;
- KillFace( eDst->Lface, eOrg->Lface );
- }
-
- /* Connect the new edge appropriately */
- Splice( eNew, eOrg->Lnext );
- Splice( eNewSym, eDst );
-
- /* Set the vertex and face information */
- eNew->Org = eOrg->Dst;
- eNewSym->Org = eDst->Org;
- eNew->Lface = eNewSym->Lface = eOrg->Lface;
-
- /* Make sure the old face points to a valid half-edge */
- eOrg->Lface->anEdge = eNewSym;
-
- if( ! joiningLoops ) {
- GLUface *newFace= allocFace();
- if (newFace == NULL) return NULL;
-
- /* We split one loop into two -- the new loop is eNew->Lface */
- MakeFace( newFace, eNew, eOrg->Lface );
- }
- return eNew;
-}
-
-
-/******************** Other Operations **********************/
-
-/* __gl_meshZapFace( fZap ) destroys a face and removes it from the
- * global face list. All edges of fZap will have a NULL pointer as their
- * left face. Any edges which also have a NULL pointer as their right face
- * are deleted entirely (along with any isolated vertices this produces).
- * An entire mesh can be deleted by zapping its faces, one at a time,
- * in any order. Zapped faces cannot be used in further mesh operations!
- */
-void __gl_meshZapFace( GLUface *fZap )
-{
- GLUhalfEdge *eStart = fZap->anEdge;
- GLUhalfEdge *e, *eNext, *eSym;
- GLUface *fPrev, *fNext;
-
- /* walk around face, deleting edges whose right face is also NULL */
- eNext = eStart->Lnext;
- do {
- e = eNext;
- eNext = e->Lnext;
-
- e->Lface = NULL;
- if( e->Rface == NULL ) {
- /* delete the edge -- see __gl_MeshDelete above */
-
- if( e->Onext == e ) {
- KillVertex( e->Org, NULL );
- } else {
- /* Make sure that e->Org points to a valid half-edge */
- e->Org->anEdge = e->Onext;
- Splice( e, e->Oprev );
- }
- eSym = e->Sym;
- if( eSym->Onext == eSym ) {
- KillVertex( eSym->Org, NULL );
- } else {
- /* Make sure that eSym->Org points to a valid half-edge */
- eSym->Org->anEdge = eSym->Onext;
- Splice( eSym, eSym->Oprev );
- }
- KillEdge( e );
- }
- } while( e != eStart );
-
- /* delete from circular doubly-linked list */
- fPrev = fZap->prev;
- fNext = fZap->next;
- fNext->prev = fPrev;
- fPrev->next = fNext;
-
- memFree( fZap );
-}
-
-
-/* __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
- * and no loops (what we usually call a "face").
- */
-GLUmesh *__gl_meshNewMesh( void )
-{
- GLUvertex *v;
- GLUface *f;
- GLUhalfEdge *e;
- GLUhalfEdge *eSym;
- GLUmesh *mesh = (GLUmesh *)memAlloc( sizeof( GLUmesh ));
- if (mesh == NULL) {
- return NULL;
- }
-
- v = &mesh->vHead;
- f = &mesh->fHead;
- e = &mesh->eHead;
- eSym = &mesh->eHeadSym;
-
- v->next = v->prev = v;
- v->anEdge = NULL;
- v->data = NULL;
-
- f->next = f->prev = f;
- f->anEdge = NULL;
- f->data = NULL;
- f->trail = NULL;
- f->marked = FALSE;
- f->inside = FALSE;
-
- e->next = e;
- e->Sym = eSym;
- e->Onext = NULL;
- e->Lnext = NULL;
- e->Org = NULL;
- e->Lface = NULL;
- e->winding = 0;
- e->activeRegion = NULL;
-
- eSym->next = eSym;
- eSym->Sym = e;
- eSym->Onext = NULL;
- eSym->Lnext = NULL;
- eSym->Org = NULL;
- eSym->Lface = NULL;
- eSym->winding = 0;
- eSym->activeRegion = NULL;
-
- return mesh;
-}
-
-
-/* __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
- * both meshes, and returns the new mesh (the old meshes are destroyed).
- */
-GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 )
-{
- GLUface *f1 = &mesh1->fHead;
- GLUvertex *v1 = &mesh1->vHead;
- GLUhalfEdge *e1 = &mesh1->eHead;
- GLUface *f2 = &mesh2->fHead;
- GLUvertex *v2 = &mesh2->vHead;
- GLUhalfEdge *e2 = &mesh2->eHead;
-
- /* Add the faces, vertices, and edges of mesh2 to those of mesh1 */
- if( f2->next != f2 ) {
- f1->prev->next = f2->next;
- f2->next->prev = f1->prev;
- f2->prev->next = f1;
- f1->prev = f2->prev;
- }
-
- if( v2->next != v2 ) {
- v1->prev->next = v2->next;
- v2->next->prev = v1->prev;
- v2->prev->next = v1;
- v1->prev = v2->prev;
- }
-
- if( e2->next != e2 ) {
- e1->Sym->next->Sym->next = e2->next;
- e2->next->Sym->next = e1->Sym->next;
- e2->Sym->next->Sym->next = e1;
- e1->Sym->next = e2->Sym->next;
- }
-
- memFree( mesh2 );
- return mesh1;
-}
-
-
-#ifdef DELETE_BY_ZAPPING
-
-/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
- */
-void __gl_meshDeleteMesh( GLUmesh *mesh )
-{
- GLUface *fHead = &mesh->fHead;
-
- while( fHead->next != fHead ) {
- __gl_meshZapFace( fHead->next );
- }
- assert( mesh->vHead.next == &mesh->vHead );
-
- memFree( mesh );
-}
-
-#else
-
-/* __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
- */
-void __gl_meshDeleteMesh( GLUmesh *mesh )
-{
- GLUface *f, *fNext;
- GLUvertex *v, *vNext;
- GLUhalfEdge *e, *eNext;
-
- for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
- fNext = f->next;
- memFree( f );
- }
-
- for( v = mesh->vHead.next; v != &mesh->vHead; v = vNext ) {
- vNext = v->next;
- memFree( v );
- }
-
- for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
- /* One call frees both e and e->Sym (see EdgePair above) */
- eNext = e->next;
- memFree( e );
- }
-
- memFree( mesh );
-}
-
-#endif
-
-#ifndef NDEBUG
-
-/* __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
- */
-void __gl_meshCheckMesh( GLUmesh *mesh )
-{
- GLUface *fHead = &mesh->fHead;
- GLUvertex *vHead = &mesh->vHead;
- GLUhalfEdge *eHead = &mesh->eHead;
- GLUface *f, *fPrev;
- GLUvertex *v, *vPrev;
- GLUhalfEdge *e, *ePrev;
-
- fPrev = fHead;
- for( fPrev = fHead ; (f = fPrev->next) != fHead; fPrev = f) {
- assert( f->prev == fPrev );
- e = f->anEdge;
- do {
- assert( e->Sym != e );
- assert( e->Sym->Sym == e );
- assert( e->Lnext->Onext->Sym == e );
- assert( e->Onext->Sym->Lnext == e );
- assert( e->Lface == f );
- e = e->Lnext;
- } while( e != f->anEdge );
- }
- assert( f->prev == fPrev && f->anEdge == NULL && f->data == NULL );
-
- vPrev = vHead;
- for( vPrev = vHead ; (v = vPrev->next) != vHead; vPrev = v) {
- assert( v->prev == vPrev );
- e = v->anEdge;
- do {
- assert( e->Sym != e );
- assert( e->Sym->Sym == e );
- assert( e->Lnext->Onext->Sym == e );
- assert( e->Onext->Sym->Lnext == e );
- assert( e->Org == v );
- e = e->Onext;
- } while( e != v->anEdge );
- }
- assert( v->prev == vPrev && v->anEdge == NULL && v->data == NULL );
-
- ePrev = eHead;
- for( ePrev = eHead ; (e = ePrev->next) != eHead; ePrev = e) {
- assert( e->Sym->next == ePrev->Sym );
- assert( e->Sym != e );
- assert( e->Sym->Sym == e );
- assert( e->Org != NULL );
- assert( e->Dst != NULL );
- assert( e->Lnext->Onext->Sym == e );
- assert( e->Onext->Sym->Lnext == e );
- }
- assert( e->Sym->next == ePrev->Sym
- && e->Sym == &mesh->eHeadSym
- && e->Sym->Sym == e
- && e->Org == NULL && e->Dst == NULL
- && e->Lface == NULL && e->Rface == NULL );
-}
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __mesh_h_
-#define __mesh_h_
-
-#include <GL/glu.h>
-
-typedef struct GLUmesh GLUmesh;
-
-typedef struct GLUvertex GLUvertex;
-typedef struct GLUface GLUface;
-typedef struct GLUhalfEdge GLUhalfEdge;
-
-typedef struct ActiveRegion ActiveRegion; /* Internal data */
-
-/* The mesh structure is similar in spirit, notation, and operations
- * to the "quad-edge" structure (see L. Guibas and J. Stolfi, Primitives
- * for the manipulation of general subdivisions and the computation of
- * Voronoi diagrams, ACM Transactions on Graphics, 4(2):74-123, April 1985).
- * For a simplified description, see the course notes for CS348a,
- * "Mathematical Foundations of Computer Graphics", available at the
- * Stanford bookstore (and taught during the fall quarter).
- * The implementation also borrows a tiny subset of the graph-based approach
- * use in Mantyla's Geometric Work Bench (see M. Mantyla, An Introduction
- * to Sold Modeling, Computer Science Press, Rockville, Maryland, 1988).
- *
- * The fundamental data structure is the "half-edge". Two half-edges
- * go together to make an edge, but they point in opposite directions.
- * Each half-edge has a pointer to its mate (the "symmetric" half-edge Sym),
- * its origin vertex (Org), the face on its left side (Lface), and the
- * adjacent half-edges in the CCW direction around the origin vertex
- * (Onext) and around the left face (Lnext). There is also a "next"
- * pointer for the global edge list (see below).
- *
- * The notation used for mesh navigation:
- * Sym = the mate of a half-edge (same edge, but opposite direction)
- * Onext = edge CCW around origin vertex (keep same origin)
- * Dnext = edge CCW around destination vertex (keep same dest)
- * Lnext = edge CCW around left face (dest becomes new origin)
- * Rnext = edge CCW around right face (origin becomes new dest)
- *
- * "prev" means to substitute CW for CCW in the definitions above.
- *
- * The mesh keeps global lists of all vertices, faces, and edges,
- * stored as doubly-linked circular lists with a dummy header node.
- * The mesh stores pointers to these dummy headers (vHead, fHead, eHead).
- *
- * The circular edge list is special; since half-edges always occur
- * in pairs (e and e->Sym), each half-edge stores a pointer in only
- * one direction. Starting at eHead and following the e->next pointers
- * will visit each *edge* once (ie. e or e->Sym, but not both).
- * e->Sym stores a pointer in the opposite direction, thus it is
- * always true that e->Sym->next->Sym->next == e.
- *
- * Each vertex has a pointer to next and previous vertices in the
- * circular list, and a pointer to a half-edge with this vertex as
- * the origin (NULL if this is the dummy header). There is also a
- * field "data" for client data.
- *
- * Each face has a pointer to the next and previous faces in the
- * circular list, and a pointer to a half-edge with this face as
- * the left face (NULL if this is the dummy header). There is also
- * a field "data" for client data.
- *
- * Note that what we call a "face" is really a loop; faces may consist
- * of more than one loop (ie. not simply connected), but there is no
- * record of this in the data structure. The mesh may consist of
- * several disconnected regions, so it may not be possible to visit
- * the entire mesh by starting at a half-edge and traversing the edge
- * structure.
- *
- * The mesh does NOT support isolated vertices; a vertex is deleted along
- * with its last edge. Similarly when two faces are merged, one of the
- * faces is deleted (see __gl_meshDelete below). For mesh operations,
- * all face (loop) and vertex pointers must not be NULL. However, once
- * mesh manipulation is finished, __gl_MeshZapFace can be used to delete
- * faces of the mesh, one at a time. All external faces can be "zapped"
- * before the mesh is returned to the client; then a NULL face indicates
- * a region which is not part of the output polygon.
- */
-
-struct GLUvertex {
- GLUvertex *next; /* next vertex (never NULL) */
- GLUvertex *prev; /* previous vertex (never NULL) */
- GLUhalfEdge *anEdge; /* a half-edge with this origin */
- void *data; /* client's data */
-
- /* Internal data (keep hidden) */
- GLdouble coords[3]; /* vertex location in 3D */
- GLdouble s, t; /* projection onto the sweep plane */
- long pqHandle; /* to allow deletion from priority queue */
-};
-
-struct GLUface {
- GLUface *next; /* next face (never NULL) */
- GLUface *prev; /* previous face (never NULL) */
- GLUhalfEdge *anEdge; /* a half edge with this left face */
- void *data; /* room for client's data */
-
- /* Internal data (keep hidden) */
- GLUface *trail; /* "stack" for conversion to strips */
- GLboolean marked; /* flag for conversion to strips */
- GLboolean inside; /* this face is in the polygon interior */
-};
-
-struct GLUhalfEdge {
- GLUhalfEdge *next; /* doubly-linked list (prev==Sym->next) */
- GLUhalfEdge *Sym; /* same edge, opposite direction */
- GLUhalfEdge *Onext; /* next edge CCW around origin */
- GLUhalfEdge *Lnext; /* next edge CCW around left face */
- GLUvertex *Org; /* origin vertex (Overtex too long) */
- GLUface *Lface; /* left face */
-
- /* Internal data (keep hidden) */
- ActiveRegion *activeRegion; /* a region with this upper edge (sweep.c) */
- int winding; /* change in winding number when crossing
- from the right face to the left face */
-};
-
-#define Rface Sym->Lface
-#define Dst Sym->Org
-
-#define Oprev Sym->Lnext
-#define Lprev Onext->Sym
-#define Dprev Lnext->Sym
-#define Rprev Sym->Onext
-#define Dnext Rprev->Sym /* 3 pointers */
-#define Rnext Oprev->Sym /* 3 pointers */
-
-
-struct GLUmesh {
- GLUvertex vHead; /* dummy header for vertex list */
- GLUface fHead; /* dummy header for face list */
- GLUhalfEdge eHead; /* dummy header for edge list */
- GLUhalfEdge eHeadSym; /* and its symmetric counterpart */
-};
-
-/* The mesh operations below have three motivations: completeness,
- * convenience, and efficiency. The basic mesh operations are MakeEdge,
- * Splice, and Delete. All the other edge operations can be implemented
- * in terms of these. The other operations are provided for convenience
- * and/or efficiency.
- *
- * When a face is split or a vertex is added, they are inserted into the
- * global list *before* the existing vertex or face (ie. e->Org or e->Lface).
- * This makes it easier to process all vertices or faces in the global lists
- * without worrying about processing the same data twice. As a convenience,
- * when a face is split, the "inside" flag is copied from the old face.
- * Other internal data (v->data, v->activeRegion, f->data, f->marked,
- * f->trail, e->winding) is set to zero.
- *
- * ********************** Basic Edge Operations **************************
- *
- * __gl_meshMakeEdge( mesh ) creates one edge, two vertices, and a loop.
- * The loop (face) consists of the two new half-edges.
- *
- * __gl_meshSplice( eOrg, eDst ) is the basic operation for changing the
- * mesh connectivity and topology. It changes the mesh so that
- * eOrg->Onext <- OLD( eDst->Onext )
- * eDst->Onext <- OLD( eOrg->Onext )
- * where OLD(...) means the value before the meshSplice operation.
- *
- * This can have two effects on the vertex structure:
- * - if eOrg->Org != eDst->Org, the two vertices are merged together
- * - if eOrg->Org == eDst->Org, the origin is split into two vertices
- * In both cases, eDst->Org is changed and eOrg->Org is untouched.
- *
- * Similarly (and independently) for the face structure,
- * - if eOrg->Lface == eDst->Lface, one loop is split into two
- * - if eOrg->Lface != eDst->Lface, two distinct loops are joined into one
- * In both cases, eDst->Lface is changed and eOrg->Lface is unaffected.
- *
- * __gl_meshDelete( eDel ) removes the edge eDel. There are several cases:
- * if (eDel->Lface != eDel->Rface), we join two loops into one; the loop
- * eDel->Lface is deleted. Otherwise, we are splitting one loop into two;
- * the newly created loop will contain eDel->Dst. If the deletion of eDel
- * would create isolated vertices, those are deleted as well.
- *
- * ********************** Other Edge Operations **************************
- *
- * __gl_meshAddEdgeVertex( eOrg ) creates a new edge eNew such that
- * eNew == eOrg->Lnext, and eNew->Dst is a newly created vertex.
- * eOrg and eNew will have the same left face.
- *
- * __gl_meshSplitEdge( eOrg ) splits eOrg into two edges eOrg and eNew,
- * such that eNew == eOrg->Lnext. The new vertex is eOrg->Dst == eNew->Org.
- * eOrg and eNew will have the same left face.
- *
- * __gl_meshConnect( eOrg, eDst ) creates a new edge from eOrg->Dst
- * to eDst->Org, and returns the corresponding half-edge eNew.
- * If eOrg->Lface == eDst->Lface, this splits one loop into two,
- * and the newly created loop is eNew->Lface. Otherwise, two disjoint
- * loops are merged into one, and the loop eDst->Lface is destroyed.
- *
- * ************************ Other Operations *****************************
- *
- * __gl_meshNewMesh() creates a new mesh with no edges, no vertices,
- * and no loops (what we usually call a "face").
- *
- * __gl_meshUnion( mesh1, mesh2 ) forms the union of all structures in
- * both meshes, and returns the new mesh (the old meshes are destroyed).
- *
- * __gl_meshDeleteMesh( mesh ) will free all storage for any valid mesh.
- *
- * __gl_meshZapFace( fZap ) destroys a face and removes it from the
- * global face list. All edges of fZap will have a NULL pointer as their
- * left face. Any edges which also have a NULL pointer as their right face
- * are deleted entirely (along with any isolated vertices this produces).
- * An entire mesh can be deleted by zapping its faces, one at a time,
- * in any order. Zapped faces cannot be used in further mesh operations!
- *
- * __gl_meshCheckMesh( mesh ) checks a mesh for self-consistency.
- */
-
-GLUhalfEdge *__gl_meshMakeEdge( GLUmesh *mesh );
-int __gl_meshSplice( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
-int __gl_meshDelete( GLUhalfEdge *eDel );
-
-GLUhalfEdge *__gl_meshAddEdgeVertex( GLUhalfEdge *eOrg );
-GLUhalfEdge *__gl_meshSplitEdge( GLUhalfEdge *eOrg );
-GLUhalfEdge *__gl_meshConnect( GLUhalfEdge *eOrg, GLUhalfEdge *eDst );
-
-GLUmesh *__gl_meshNewMesh( void );
-GLUmesh *__gl_meshUnion( GLUmesh *mesh1, GLUmesh *mesh2 );
-void __gl_meshDeleteMesh( GLUmesh *mesh );
-void __gl_meshZapFace( GLUface *fZap );
-
-#ifdef NDEBUG
-#define __gl_meshCheckMesh( mesh )
-#else
-void __gl_meshCheckMesh( GLUmesh *mesh );
-#endif
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include "mesh.h"
-#include "tess.h"
-#include "normal.h"
-#include <math.h>
-#include <assert.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#define Dot(u,v) (u[0]*v[0] + u[1]*v[1] + u[2]*v[2])
-
-#if 0
-static void Normalize( GLdouble v[3] )
-{
- GLdouble len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
-
- assert( len > 0 );
- len = sqrt( len );
- v[0] /= len;
- v[1] /= len;
- v[2] /= len;
-}
-#endif
-
-#undef ABS
-#define ABS(x) ((x) < 0 ? -(x) : (x))
-
-static int LongAxis( GLdouble v[3] )
-{
- int i = 0;
-
- if( ABS(v[1]) > ABS(v[0]) ) { i = 1; }
- if( ABS(v[2]) > ABS(v[i]) ) { i = 2; }
- return i;
-}
-
-static void ComputeNormal( GLUtesselator *tess, GLdouble norm[3] )
-{
- GLUvertex *v, *v1, *v2;
- GLdouble c, tLen2, maxLen2;
- GLdouble maxVal[3], minVal[3], d1[3], d2[3], tNorm[3];
- GLUvertex *maxVert[3], *minVert[3];
- GLUvertex *vHead = &tess->mesh->vHead;
- int i;
-
- maxVal[0] = maxVal[1] = maxVal[2] = -2 * GLU_TESS_MAX_COORD;
- minVal[0] = minVal[1] = minVal[2] = 2 * GLU_TESS_MAX_COORD;
-
- for( v = vHead->next; v != vHead; v = v->next ) {
- for( i = 0; i < 3; ++i ) {
- c = v->coords[i];
- if( c < minVal[i] ) { minVal[i] = c; minVert[i] = v; }
- if( c > maxVal[i] ) { maxVal[i] = c; maxVert[i] = v; }
- }
- }
-
- /* Find two vertices separated by at least 1/sqrt(3) of the maximum
- * distance between any two vertices
- */
- i = 0;
- if( maxVal[1] - minVal[1] > maxVal[0] - minVal[0] ) { i = 1; }
- if( maxVal[2] - minVal[2] > maxVal[i] - minVal[i] ) { i = 2; }
- if( minVal[i] >= maxVal[i] ) {
- /* All vertices are the same -- normal doesn't matter */
- norm[0] = 0; norm[1] = 0; norm[2] = 1;
- return;
- }
-
- /* Look for a third vertex which forms the triangle with maximum area
- * (Length of normal == twice the triangle area)
- */
- maxLen2 = 0;
- v1 = minVert[i];
- v2 = maxVert[i];
- d1[0] = v1->coords[0] - v2->coords[0];
- d1[1] = v1->coords[1] - v2->coords[1];
- d1[2] = v1->coords[2] - v2->coords[2];
- for( v = vHead->next; v != vHead; v = v->next ) {
- d2[0] = v->coords[0] - v2->coords[0];
- d2[1] = v->coords[1] - v2->coords[1];
- d2[2] = v->coords[2] - v2->coords[2];
- tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1];
- tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2];
- tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0];
- tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2];
- if( tLen2 > maxLen2 ) {
- maxLen2 = tLen2;
- norm[0] = tNorm[0];
- norm[1] = tNorm[1];
- norm[2] = tNorm[2];
- }
- }
-
- if( maxLen2 <= 0 ) {
- /* All points lie on a single line -- any decent normal will do */
- norm[0] = norm[1] = norm[2] = 0;
- norm[LongAxis(d1)] = 1;
- }
-}
-
-
-static void CheckOrientation( GLUtesselator *tess )
-{
- GLdouble area;
- GLUface *f, *fHead = &tess->mesh->fHead;
- GLUvertex *v, *vHead = &tess->mesh->vHead;
- GLUhalfEdge *e;
-
- /* When we compute the normal automatically, we choose the orientation
- * so that the sum of the signed areas of all contours is non-negative.
- */
- area = 0;
- for( f = fHead->next; f != fHead; f = f->next ) {
- e = f->anEdge;
- if( e->winding <= 0 ) continue;
- do {
- area += (e->Org->s - e->Dst->s) * (e->Org->t + e->Dst->t);
- e = e->Lnext;
- } while( e != f->anEdge );
- }
- if( area < 0 ) {
- /* Reverse the orientation by flipping all the t-coordinates */
- for( v = vHead->next; v != vHead; v = v->next ) {
- v->t = - v->t;
- }
- tess->tUnit[0] = - tess->tUnit[0];
- tess->tUnit[1] = - tess->tUnit[1];
- tess->tUnit[2] = - tess->tUnit[2];
- }
-}
-
-#ifdef FOR_TRITE_TEST_PROGRAM
-#include <stdlib.h>
-extern int RandomSweep;
-#define S_UNIT_X (RandomSweep ? (2*drand48()-1) : 1.0)
-#define S_UNIT_Y (RandomSweep ? (2*drand48()-1) : 0.0)
-#else
-#if defined(SLANTED_SWEEP)
-/* The "feature merging" is not intended to be complete. There are
- * special cases where edges are nearly parallel to the sweep line
- * which are not implemented. The algorithm should still behave
- * robustly (ie. produce a reasonable tesselation) in the presence
- * of such edges, however it may miss features which could have been
- * merged. We could minimize this effect by choosing the sweep line
- * direction to be something unusual (ie. not parallel to one of the
- * coordinate axes).
- */
-#define S_UNIT_X 0.50941539564955385 /* Pre-normalized */
-#define S_UNIT_Y 0.86052074622010633
-#else
-#define S_UNIT_X 1.0
-#define S_UNIT_Y 0.0
-#endif
-#endif
-
-/* Determine the polygon normal and project vertices onto the plane
- * of the polygon.
- */
-void __gl_projectPolygon( GLUtesselator *tess )
-{
- GLUvertex *v, *vHead = &tess->mesh->vHead;
- GLdouble norm[3];
- GLdouble *sUnit, *tUnit;
- int i, computedNormal = FALSE;
-
- norm[0] = tess->normal[0];
- norm[1] = tess->normal[1];
- norm[2] = tess->normal[2];
- if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
- ComputeNormal( tess, norm );
- computedNormal = TRUE;
- }
- sUnit = tess->sUnit;
- tUnit = tess->tUnit;
- i = LongAxis( norm );
-
-#if defined(FOR_TRITE_TEST_PROGRAM) || defined(TRUE_PROJECT)
- /* Choose the initial sUnit vector to be approximately perpendicular
- * to the normal.
- */
- Normalize( norm );
-
- sUnit[i] = 0;
- sUnit[(i+1)%3] = S_UNIT_X;
- sUnit[(i+2)%3] = S_UNIT_Y;
-
- /* Now make it exactly perpendicular */
- w = Dot( sUnit, norm );
- sUnit[0] -= w * norm[0];
- sUnit[1] -= w * norm[1];
- sUnit[2] -= w * norm[2];
- Normalize( sUnit );
-
- /* Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame */
- tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1];
- tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2];
- tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0];
- Normalize( tUnit );
-#else
- /* Project perpendicular to a coordinate axis -- better numerically */
- sUnit[i] = 0;
- sUnit[(i+1)%3] = S_UNIT_X;
- sUnit[(i+2)%3] = S_UNIT_Y;
-
- tUnit[i] = 0;
- tUnit[(i+1)%3] = (norm[i] > 0) ? -S_UNIT_Y : S_UNIT_Y;
- tUnit[(i+2)%3] = (norm[i] > 0) ? S_UNIT_X : -S_UNIT_X;
-#endif
-
- /* Project the vertices onto the sweep plane */
- for( v = vHead->next; v != vHead; v = v->next ) {
- v->s = Dot( v->coords, sUnit );
- v->t = Dot( v->coords, tUnit );
- }
- if( computedNormal ) {
- CheckOrientation( tess );
- }
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __normal_h_
-#define __normal_h_
-
-#include "tess.h"
-
-/* __gl_projectPolygon( tess ) determines the polygon normal
- * and project vertices onto the plane of the polygon.
- */
-void __gl_projectPolygon( GLUtesselator *tess );
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include <stddef.h>
-#include <assert.h>
-#include "priorityq-heap.h"
-#include "memalloc.h"
-
-#define INIT_SIZE 32
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifdef FOR_TRITE_TEST_PROGRAM
-#define LEQ(x,y) (*pq->leq)(x,y)
-#else
-/* Violates modularity, but a little faster */
-#include "geom.h"
-#define LEQ(x,y) VertLeq((GLUvertex *)x, (GLUvertex *)y)
-#endif
-
-/* really __gl_pqHeapNewPriorityQ */
-PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
-{
- PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
- if (pq == NULL) return NULL;
-
- pq->size = 0;
- pq->max = INIT_SIZE;
- pq->nodes = (PQnode *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->nodes[0]) );
- if (pq->nodes == NULL) {
- memFree(pq);
- return NULL;
- }
-
- pq->handles = (PQhandleElem *)memAlloc( (INIT_SIZE + 1) * sizeof(pq->handles[0]) );
- if (pq->handles == NULL) {
- memFree(pq->nodes);
- memFree(pq);
- return NULL;
- }
-
- pq->initialized = FALSE;
- pq->freeList = 0;
- pq->leq = leq;
-
- pq->nodes[1].handle = 1; /* so that Minimum() returns NULL */
- pq->handles[1].key = NULL;
- return pq;
-}
-
-/* really __gl_pqHeapDeletePriorityQ */
-void pqDeletePriorityQ( PriorityQ *pq )
-{
- memFree( pq->handles );
- memFree( pq->nodes );
- memFree( pq );
-}
-
-
-static void FloatDown( PriorityQ *pq, long curr )
-{
- PQnode *n = pq->nodes;
- PQhandleElem *h = pq->handles;
- PQhandle hCurr, hChild;
- long child;
-
- hCurr = n[curr].handle;
- for( ;; ) {
- child = curr << 1;
- if( child < pq->size && LEQ( h[n[child+1].handle].key,
- h[n[child].handle].key )) {
- ++child;
- }
-
- assert(child <= pq->max);
-
- hChild = n[child].handle;
- if( child > pq->size || LEQ( h[hCurr].key, h[hChild].key )) {
- n[curr].handle = hCurr;
- h[hCurr].node = curr;
- break;
- }
- n[curr].handle = hChild;
- h[hChild].node = curr;
- curr = child;
- }
-}
-
-
-static void FloatUp( PriorityQ *pq, long curr )
-{
- PQnode *n = pq->nodes;
- PQhandleElem *h = pq->handles;
- PQhandle hCurr, hParent;
- long parent;
-
- hCurr = n[curr].handle;
- for( ;; ) {
- parent = curr >> 1;
- hParent = n[parent].handle;
- if( parent == 0 || LEQ( h[hParent].key, h[hCurr].key )) {
- n[curr].handle = hCurr;
- h[hCurr].node = curr;
- break;
- }
- n[curr].handle = hParent;
- h[hParent].node = curr;
- curr = parent;
- }
-}
-
-/* really __gl_pqHeapInit */
-void pqInit( PriorityQ *pq )
-{
- long i;
-
- /* This method of building a heap is O(n), rather than O(n lg n). */
-
- for( i = pq->size; i >= 1; --i ) {
- FloatDown( pq, i );
- }
- pq->initialized = TRUE;
-}
-
-/* really __gl_pqHeapInsert */
-/* returns LONG_MAX iff out of memory */
-PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
-{
- long curr;
- PQhandle free_handle;
-
- curr = ++ pq->size;
- if( (curr*2) > pq->max ) {
- PQnode *saveNodes= pq->nodes;
- PQhandleElem *saveHandles= pq->handles;
-
- /* If the heap overflows, double its size. */
- pq->max <<= 1;
- pq->nodes = (PQnode *)memRealloc( pq->nodes,
- (size_t)
- ((pq->max + 1) * sizeof( pq->nodes[0] )));
- if (pq->nodes == NULL) {
- pq->nodes = saveNodes; /* restore ptr to free upon return */
- return LONG_MAX;
- }
- pq->handles = (PQhandleElem *)memRealloc( pq->handles,
- (size_t)
- ((pq->max + 1) *
- sizeof( pq->handles[0] )));
- if (pq->handles == NULL) {
- pq->handles = saveHandles; /* restore ptr to free upon return */
- return LONG_MAX;
- }
- }
-
- if( pq->freeList == 0 ) {
- free_handle = curr;
- } else {
- free_handle = pq->freeList;
- pq->freeList = pq->handles[free_handle].node;
- }
-
- pq->nodes[curr].handle = free_handle;
- pq->handles[free_handle].node = curr;
- pq->handles[free_handle].key = keyNew;
-
- if( pq->initialized ) {
- FloatUp( pq, curr );
- }
- assert(free_handle != LONG_MAX);
- return free_handle;
-}
-
-/* really __gl_pqHeapExtractMin */
-PQkey pqExtractMin( PriorityQ *pq )
-{
- PQnode *n = pq->nodes;
- PQhandleElem *h = pq->handles;
- PQhandle hMin = n[1].handle;
- PQkey min = h[hMin].key;
-
- if( pq->size > 0 ) {
- n[1].handle = n[pq->size].handle;
- h[n[1].handle].node = 1;
-
- h[hMin].key = NULL;
- h[hMin].node = pq->freeList;
- pq->freeList = hMin;
-
- if( -- pq->size > 0 ) {
- FloatDown( pq, 1 );
- }
- }
- return min;
-}
-
-/* really __gl_pqHeapDelete */
-void pqDelete( PriorityQ *pq, PQhandle hCurr )
-{
- PQnode *n = pq->nodes;
- PQhandleElem *h = pq->handles;
- long curr;
-
- assert( hCurr >= 1 && hCurr <= pq->max && h[hCurr].key != NULL );
-
- curr = h[hCurr].node;
- n[curr].handle = n[pq->size].handle;
- h[n[curr].handle].node = curr;
-
- if( curr <= -- pq->size ) {
- if( curr <= 1 || LEQ( h[n[curr>>1].handle].key, h[n[curr].handle].key )) {
- FloatDown( pq, curr );
- } else {
- FloatUp( pq, curr );
- }
- }
- h[hCurr].key = NULL;
- h[hCurr].node = pq->freeList;
- pq->freeList = hCurr;
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __priorityq_heap_h_
-#define __priorityq_heap_h_
-
-/* Use #define's so that another heap implementation can use this one */
-
-#define PQkey PQHeapKey
-#define PQhandle PQHeapHandle
-#define PriorityQ PriorityQHeap
-
-#define pqNewPriorityQ(leq) __gl_pqHeapNewPriorityQ(leq)
-#define pqDeletePriorityQ(pq) __gl_pqHeapDeletePriorityQ(pq)
-
-/* The basic operations are insertion of a new key (pqInsert),
- * and examination/extraction of a key whose value is minimum
- * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
- * for this purpose pqInsert returns a "handle" which is supplied
- * as the argument.
- *
- * An initial heap may be created efficiently by calling pqInsert
- * repeatedly, then calling pqInit. In any case pqInit must be called
- * before any operations other than pqInsert are used.
- *
- * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
- * This may also be tested with pqIsEmpty.
- */
-#define pqInit(pq) __gl_pqHeapInit(pq)
-#define pqInsert(pq,key) __gl_pqHeapInsert(pq,key)
-#define pqMinimum(pq) __gl_pqHeapMinimum(pq)
-#define pqExtractMin(pq) __gl_pqHeapExtractMin(pq)
-#define pqDelete(pq,handle) __gl_pqHeapDelete(pq,handle)
-#define pqIsEmpty(pq) __gl_pqHeapIsEmpty(pq)
-
-
-/* Since we support deletion the data structure is a little more
- * complicated than an ordinary heap. "nodes" is the heap itself;
- * active nodes are stored in the range 1..pq->size. When the
- * heap exceeds its allocated size (pq->max), its size doubles.
- * The children of node i are nodes 2i and 2i+1.
- *
- * Each node stores an index into an array "handles". Each handle
- * stores a key, plus a pointer back to the node which currently
- * represents that key (ie. nodes[handles[i].node].handle == i).
- */
-
-typedef void *PQkey;
-typedef long PQhandle;
-typedef struct PriorityQ PriorityQ;
-
-typedef struct { PQhandle handle; } PQnode;
-typedef struct { PQkey key; PQhandle node; } PQhandleElem;
-
-struct PriorityQ {
- PQnode *nodes;
- PQhandleElem *handles;
- long size, max;
- PQhandle freeList;
- int initialized;
- int (*leq)(PQkey key1, PQkey key2);
-};
-
-PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
-void pqDeletePriorityQ( PriorityQ *pq );
-
-void pqInit( PriorityQ *pq );
-PQhandle pqInsert( PriorityQ *pq, PQkey key );
-PQkey pqExtractMin( PriorityQ *pq );
-void pqDelete( PriorityQ *pq, PQhandle handle );
-
-
-#define __gl_pqHeapMinimum(pq) ((pq)->handles[(pq)->nodes[1].handle].key)
-#define __gl_pqHeapIsEmpty(pq) ((pq)->size == 0)
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __priorityq_sort_h_
-#define __priorityq_sort_h_
-
-#include "priorityq-heap.h"
-
-#undef PQkey
-#undef PQhandle
-#undef PriorityQ
-#undef pqNewPriorityQ
-#undef pqDeletePriorityQ
-#undef pqInit
-#undef pqInsert
-#undef pqMinimum
-#undef pqExtractMin
-#undef pqDelete
-#undef pqIsEmpty
-
-/* Use #define's so that another heap implementation can use this one */
-
-#define PQkey PQSortKey
-#define PQhandle PQSortHandle
-#define PriorityQ PriorityQSort
-
-#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq)
-#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq)
-
-/* The basic operations are insertion of a new key (pqInsert),
- * and examination/extraction of a key whose value is minimum
- * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
- * for this purpose pqInsert returns a "handle" which is supplied
- * as the argument.
- *
- * An initial heap may be created efficiently by calling pqInsert
- * repeatedly, then calling pqInit. In any case pqInit must be called
- * before any operations other than pqInsert are used.
- *
- * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
- * This may also be tested with pqIsEmpty.
- */
-#define pqInit(pq) __gl_pqSortInit(pq)
-#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
-#define pqMinimum(pq) __gl_pqSortMinimum(pq)
-#define pqExtractMin(pq) __gl_pqSortExtractMin(pq)
-#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle)
-#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq)
-
-
-/* Since we support deletion the data structure is a little more
- * complicated than an ordinary heap. "nodes" is the heap itself;
- * active nodes are stored in the range 1..pq->size. When the
- * heap exceeds its allocated size (pq->max), its size doubles.
- * The children of node i are nodes 2i and 2i+1.
- *
- * Each node stores an index into an array "handles". Each handle
- * stores a key, plus a pointer back to the node which currently
- * represents that key (ie. nodes[handles[i].node].handle == i).
- */
-
-typedef PQHeapKey PQkey;
-typedef PQHeapHandle PQhandle;
-typedef struct PriorityQ PriorityQ;
-
-struct PriorityQ {
- PriorityQHeap *heap;
- PQkey *keys;
- PQkey **order;
- PQhandle size, max;
- int initialized;
- int (*leq)(PQkey key1, PQkey key2);
-};
-
-PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
-void pqDeletePriorityQ( PriorityQ *pq );
-
-int pqInit( PriorityQ *pq );
-PQhandle pqInsert( PriorityQ *pq, PQkey key );
-PQkey pqExtractMin( PriorityQ *pq );
-void pqDelete( PriorityQ *pq, PQhandle handle );
-
-PQkey pqMinimum( PriorityQ *pq );
-int pqIsEmpty( PriorityQ *pq );
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <stddef.h>
-#include <assert.h>
-#include <limits.h> /* LONG_MAX */
-#include "memalloc.h"
-
-/* Include all the code for the regular heap-based queue here. */
-
-#include "priorityq-heap.c"
-
-/* Now redefine all the function names to map to their "Sort" versions. */
-
-#include "priorityq-sort.h"
-
-/* really __gl_pqSortNewPriorityQ */
-PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) )
-{
- PriorityQ *pq = (PriorityQ *)memAlloc( sizeof( PriorityQ ));
- if (pq == NULL) return NULL;
-
- pq->heap = __gl_pqHeapNewPriorityQ( leq );
- if (pq->heap == NULL) {
- memFree(pq);
- return NULL;
- }
-
- pq->keys = (PQHeapKey *)memAlloc( INIT_SIZE * sizeof(pq->keys[0]) );
- if (pq->keys == NULL) {
- __gl_pqHeapDeletePriorityQ(pq->heap);
- memFree(pq);
- return NULL;
- }
-
- pq->size = 0;
- pq->max = INIT_SIZE;
- pq->initialized = FALSE;
- pq->leq = leq;
- return pq;
-}
-
-/* really __gl_pqSortDeletePriorityQ */
-void pqDeletePriorityQ( PriorityQ *pq )
-{
- assert(pq != NULL);
- if (pq->heap != NULL) __gl_pqHeapDeletePriorityQ( pq->heap );
- if (pq->order != NULL) memFree( pq->order );
- if (pq->keys != NULL) memFree( pq->keys );
- memFree( pq );
-}
-
-
-#define LT(x,y) (! LEQ(y,x))
-#define GT(x,y) (! LEQ(x,y))
-#define Swap(a,b) do{PQkey *tmp = *a; *a = *b; *b = tmp;}while(0)
-
-/* really __gl_pqSortInit */
-int pqInit( PriorityQ *pq )
-{
- PQkey **p, **r, **i, **j, *piv;
- struct { PQkey **p, **r; } Stack[50], *top = Stack;
- unsigned long seed = 2016473283;
-
- /* Create an array of indirect pointers to the keys, so that we
- * the handles we have returned are still valid.
- */
-/*
- pq->order = (PQHeapKey **)memAlloc( (size_t)
- (pq->size * sizeof(pq->order[0])) );
-*/
- pq->order = (PQHeapKey **)memAlloc( (size_t)
- ((pq->size+1) * sizeof(pq->order[0])) );
-/* the previous line is a patch to compensate for the fact that IBM */
-/* machines return a null on a malloc of zero bytes (unlike SGI), */
-/* so we have to put in this defense to guard against a memory */
-/* fault four lines down. from fossum@austin.ibm.com. */
- if (pq->order == NULL) return 0;
-
- p = pq->order;
- r = p + pq->size - 1;
- for( piv = pq->keys, i = p; i <= r; ++piv, ++i ) {
- *i = piv;
- }
-
- /* Sort the indirect pointers in descending order,
- * using randomized Quicksort
- */
- top->p = p; top->r = r; ++top;
- while( --top >= Stack ) {
- p = top->p;
- r = top->r;
- while( r > p + 10 ) {
- seed = seed * 1539415821 + 1;
- i = p + seed % (r - p + 1);
- piv = *i;
- *i = *p;
- *p = piv;
- i = p - 1;
- j = r + 1;
- do {
- do { ++i; } while( GT( **i, *piv ));
- do { --j; } while( LT( **j, *piv ));
- Swap( i, j );
- } while( i < j );
- Swap( i, j ); /* Undo last swap */
- if( i - p < r - j ) {
- top->p = j+1; top->r = r; ++top;
- r = i-1;
- } else {
- top->p = p; top->r = i-1; ++top;
- p = j+1;
- }
- }
- /* Insertion sort small lists */
- for( i = p+1; i <= r; ++i ) {
- piv = *i;
- for( j = i; j > p && LT( **(j-1), *piv ); --j ) {
- *j = *(j-1);
- }
- *j = piv;
- }
- }
- pq->max = pq->size;
- pq->initialized = TRUE;
- __gl_pqHeapInit( pq->heap ); /* always succeeds */
-
-#ifndef NDEBUG
- p = pq->order;
- r = p + pq->size - 1;
- for( i = p; i < r; ++i ) {
- assert( LEQ( **(i+1), **i ));
- }
-#endif
-
- return 1;
-}
-
-/* really __gl_pqSortInsert */
-/* returns LONG_MAX iff out of memory */
-PQhandle pqInsert( PriorityQ *pq, PQkey keyNew )
-{
- long curr;
-
- if( pq->initialized ) {
- return __gl_pqHeapInsert( pq->heap, keyNew );
- }
- curr = pq->size;
- if( ++ pq->size >= pq->max ) {
- PQkey *saveKey= pq->keys;
-
- /* If the heap overflows, double its size. */
- pq->max <<= 1;
- pq->keys = (PQHeapKey *)memRealloc( pq->keys,
- (size_t)
- (pq->max * sizeof( pq->keys[0] )));
- if (pq->keys == NULL) {
- pq->keys = saveKey; /* restore ptr to free upon return */
- return LONG_MAX;
- }
- }
- assert(curr != LONG_MAX);
- pq->keys[curr] = keyNew;
-
- /* Negative handles index the sorted array. */
- return -(curr+1);
-}
-
-/* really __gl_pqSortExtractMin */
-PQkey pqExtractMin( PriorityQ *pq )
-{
- PQkey sortMin, heapMin;
-
- if( pq->size == 0 ) {
- return __gl_pqHeapExtractMin( pq->heap );
- }
- sortMin = *(pq->order[pq->size-1]);
- if( ! __gl_pqHeapIsEmpty( pq->heap )) {
- heapMin = __gl_pqHeapMinimum( pq->heap );
- if( LEQ( heapMin, sortMin )) {
- return __gl_pqHeapExtractMin( pq->heap );
- }
- }
- do {
- -- pq->size;
- } while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL );
- return sortMin;
-}
-
-/* really __gl_pqSortMinimum */
-PQkey pqMinimum( PriorityQ *pq )
-{
- PQkey sortMin, heapMin;
-
- if( pq->size == 0 ) {
- return __gl_pqHeapMinimum( pq->heap );
- }
- sortMin = *(pq->order[pq->size-1]);
- if( ! __gl_pqHeapIsEmpty( pq->heap )) {
- heapMin = __gl_pqHeapMinimum( pq->heap );
- if( LEQ( heapMin, sortMin )) {
- return heapMin;
- }
- }
- return sortMin;
-}
-
-/* really __gl_pqSortIsEmpty */
-int pqIsEmpty( PriorityQ *pq )
-{
- return (pq->size == 0) && __gl_pqHeapIsEmpty( pq->heap );
-}
-
-/* really __gl_pqSortDelete */
-void pqDelete( PriorityQ *pq, PQhandle curr )
-{
- if( curr >= 0 ) {
- __gl_pqHeapDelete( pq->heap, curr );
- return;
- }
- curr = -(curr+1);
- assert( curr < pq->max && pq->keys[curr] != NULL );
-
- pq->keys[curr] = NULL;
- while( pq->size > 0 && *(pq->order[pq->size-1]) == NULL ) {
- -- pq->size;
- }
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __priorityq_sort_h_
-#define __priorityq_sort_h_
-
-#include "priorityq-heap.h"
-
-#undef PQkey
-#undef PQhandle
-#undef PriorityQ
-#undef pqNewPriorityQ
-#undef pqDeletePriorityQ
-#undef pqInit
-#undef pqInsert
-#undef pqMinimum
-#undef pqExtractMin
-#undef pqDelete
-#undef pqIsEmpty
-
-/* Use #define's so that another heap implementation can use this one */
-
-#define PQkey PQSortKey
-#define PQhandle PQSortHandle
-#define PriorityQ PriorityQSort
-
-#define pqNewPriorityQ(leq) __gl_pqSortNewPriorityQ(leq)
-#define pqDeletePriorityQ(pq) __gl_pqSortDeletePriorityQ(pq)
-
-/* The basic operations are insertion of a new key (pqInsert),
- * and examination/extraction of a key whose value is minimum
- * (pqMinimum/pqExtractMin). Deletion is also allowed (pqDelete);
- * for this purpose pqInsert returns a "handle" which is supplied
- * as the argument.
- *
- * An initial heap may be created efficiently by calling pqInsert
- * repeatedly, then calling pqInit. In any case pqInit must be called
- * before any operations other than pqInsert are used.
- *
- * If the heap is empty, pqMinimum/pqExtractMin will return a NULL key.
- * This may also be tested with pqIsEmpty.
- */
-#define pqInit(pq) __gl_pqSortInit(pq)
-#define pqInsert(pq,key) __gl_pqSortInsert(pq,key)
-#define pqMinimum(pq) __gl_pqSortMinimum(pq)
-#define pqExtractMin(pq) __gl_pqSortExtractMin(pq)
-#define pqDelete(pq,handle) __gl_pqSortDelete(pq,handle)
-#define pqIsEmpty(pq) __gl_pqSortIsEmpty(pq)
-
-
-/* Since we support deletion the data structure is a little more
- * complicated than an ordinary heap. "nodes" is the heap itself;
- * active nodes are stored in the range 1..pq->size. When the
- * heap exceeds its allocated size (pq->max), its size doubles.
- * The children of node i are nodes 2i and 2i+1.
- *
- * Each node stores an index into an array "handles". Each handle
- * stores a key, plus a pointer back to the node which currently
- * represents that key (ie. nodes[handles[i].node].handle == i).
- */
-
-typedef PQHeapKey PQkey;
-typedef PQHeapHandle PQhandle;
-typedef struct PriorityQ PriorityQ;
-
-struct PriorityQ {
- PriorityQHeap *heap;
- PQkey *keys;
- PQkey **order;
- PQhandle size, max;
- int initialized;
- int (*leq)(PQkey key1, PQkey key2);
-};
-
-PriorityQ *pqNewPriorityQ( int (*leq)(PQkey key1, PQkey key2) );
-void pqDeletePriorityQ( PriorityQ *pq );
-
-int pqInit( PriorityQ *pq );
-PQhandle pqInsert( PriorityQ *pq, PQkey key );
-PQkey pqExtractMin( PriorityQ *pq );
-void pqDelete( PriorityQ *pq, PQhandle handle );
-
-PQkey pqMinimum( PriorityQ *pq );
-int pqIsEmpty( PriorityQ *pq );
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <assert.h>
-#include <stddef.h>
-#include "mesh.h"
-#include "tess.h"
-#include "render.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/* This structure remembers the information we need about a primitive
- * to be able to render it later, once we have determined which
- * primitive is able to use the most triangles.
- */
-struct FaceCount {
- long size; /* number of triangles used */
- GLUhalfEdge *eStart; /* edge where this primitive starts */
- void (*render)(GLUtesselator *, GLUhalfEdge *, long);
- /* routine to render this primitive */
-};
-
-static struct FaceCount MaximumFan( GLUhalfEdge *eOrig );
-static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig );
-
-static void RenderFan( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
-static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *eStart, long size );
-static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *eStart,
- long size );
-
-static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig );
-static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *head );
-
-
-
-/************************ Strips and Fans decomposition ******************/
-
-/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
- * fans, strips, and separate triangles. A substantial effort is made
- * to use as few rendering primitives as possible (ie. to make the fans
- * and strips as large as possible).
- *
- * The rendering output is provided as callbacks (see the api).
- */
-void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh )
-{
- GLUface *f;
-
- /* Make a list of separate triangles so we can render them all at once */
- tess->lonelyTriList = NULL;
-
- for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
- f->marked = FALSE;
- }
- for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
-
- /* We examine all faces in an arbitrary order. Whenever we find
- * an unprocessed face F, we output a group of faces including F
- * whose size is maximum.
- */
- if( f->inside && ! f->marked ) {
- RenderMaximumFaceGroup( tess, f );
- assert( f->marked );
- }
- }
- if( tess->lonelyTriList != NULL ) {
- RenderLonelyTriangles( tess, tess->lonelyTriList );
- tess->lonelyTriList = NULL;
- }
-}
-
-
-static void RenderMaximumFaceGroup( GLUtesselator *tess, GLUface *fOrig )
-{
- /* We want to find the largest triangle fan or strip of unmarked faces
- * which includes the given face fOrig. There are 3 possible fans
- * passing through fOrig (one centered at each vertex), and 3 possible
- * strips (one for each CCW permutation of the vertices). Our strategy
- * is to try all of these, and take the primitive which uses the most
- * triangles (a greedy approach).
- */
- GLUhalfEdge *e = fOrig->anEdge;
- struct FaceCount max, newFace;
-
- max.size = 1;
- max.eStart = e;
- max.render = &RenderTriangle;
-
- if( ! tess->flagBoundary ) {
- newFace = MaximumFan( e ); if( newFace.size > max.size ) { max = newFace; }
- newFace = MaximumFan( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
- newFace = MaximumFan( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
-
- newFace = MaximumStrip( e ); if( newFace.size > max.size ) { max = newFace; }
- newFace = MaximumStrip( e->Lnext ); if( newFace.size > max.size ) { max = newFace; }
- newFace = MaximumStrip( e->Lprev ); if( newFace.size > max.size ) { max = newFace; }
- }
- (*(max.render))( tess, max.eStart, max.size );
-}
-
-
-/* Macros which keep track of faces we have marked temporarily, and allow
- * us to backtrack when necessary. With triangle fans, this is not
- * really necessary, since the only awkward case is a loop of triangles
- * around a single origin vertex. However with strips the situation is
- * more complicated, and we need a general tracking method like the
- * one here.
- */
-#define Marked(f) (! (f)->inside || (f)->marked)
-
-#define AddToTrail(f,t) ((f)->trail = (t), (t) = (f), (f)->marked = TRUE)
-
-#define FreeTrail(t) do { \
- while( (t) != NULL ) { \
- (t)->marked = FALSE; t = (t)->trail; \
- } \
- } while(0) /* absorb trailing semicolon */
-
-
-
-static struct FaceCount MaximumFan( GLUhalfEdge *eOrig )
-{
- /* eOrig->Lface is the face we want to render. We want to find the size
- * of a maximal fan around eOrig->Org. To do this we just walk around
- * the origin vertex as far as possible in both directions.
- */
- struct FaceCount newFace = { 0, NULL, &RenderFan };
- GLUface *trail = NULL;
- GLUhalfEdge *e;
-
- for( e = eOrig; ! Marked( e->Lface ); e = e->Onext ) {
- AddToTrail( e->Lface, trail );
- ++newFace.size;
- }
- for( e = eOrig; ! Marked( e->Rface ); e = e->Oprev ) {
- AddToTrail( e->Rface, trail );
- ++newFace.size;
- }
- newFace.eStart = e;
- /*LINTED*/
- FreeTrail( trail );
- return newFace;
-}
-
-
-#define IsEven(n) (((n) & 1) == 0)
-
-static struct FaceCount MaximumStrip( GLUhalfEdge *eOrig )
-{
- /* Here we are looking for a maximal strip that contains the vertices
- * eOrig->Org, eOrig->Dst, eOrig->Lnext->Dst (in that order or the
- * reverse, such that all triangles are oriented CCW).
- *
- * Again we walk forward and backward as far as possible. However for
- * strips there is a twist: to get CCW orientations, there must be
- * an *even* number of triangles in the strip on one side of eOrig.
- * We walk the strip starting on a side with an even number of triangles;
- * if both side have an odd number, we are forced to shorten one side.
- */
- struct FaceCount newFace = { 0, NULL, &RenderStrip };
- long headSize = 0, tailSize = 0;
- GLUface *trail = NULL;
- GLUhalfEdge *e, *eTail, *eHead;
-
- for( e = eOrig; ! Marked( e->Lface ); ++tailSize, e = e->Onext ) {
- AddToTrail( e->Lface, trail );
- ++tailSize;
- e = e->Dprev;
- if( Marked( e->Lface )) break;
- AddToTrail( e->Lface, trail );
- }
- eTail = e;
-
- for( e = eOrig; ! Marked( e->Rface ); ++headSize, e = e->Dnext ) {
- AddToTrail( e->Rface, trail );
- ++headSize;
- e = e->Oprev;
- if( Marked( e->Rface )) break;
- AddToTrail( e->Rface, trail );
- }
- eHead = e;
-
- newFace.size = tailSize + headSize;
- if( IsEven( tailSize )) {
- newFace.eStart = eTail->Sym;
- } else if( IsEven( headSize )) {
- newFace.eStart = eHead;
- } else {
- /* Both sides have odd length, we must shorten one of them. In fact,
- * we must start from eHead to guarantee inclusion of eOrig->Lface.
- */
- --newFace.size;
- newFace.eStart = eHead->Onext;
- }
- /*LINTED*/
- FreeTrail( trail );
- return newFace;
-}
-
-
-static void RenderTriangle( GLUtesselator *tess, GLUhalfEdge *e, long size )
-{
- /* Just add the triangle to a triangle list, so we can render all
- * the separate triangles at once.
- */
- assert( size == 1 );
- AddToTrail( e->Lface, tess->lonelyTriList );
-}
-
-
-static void RenderLonelyTriangles( GLUtesselator *tess, GLUface *f )
-{
- /* Now we render all the separate triangles which could not be
- * grouped into a triangle fan or strip.
- */
- GLUhalfEdge *e;
- int newState;
- int edgeState = -1; /* force edge state output for first vertex */
-
- CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLES );
-
- for( ; f != NULL; f = f->trail ) {
- /* Loop once for each edge (there will always be 3 edges) */
-
- e = f->anEdge;
- do {
- if( tess->flagBoundary ) {
- /* Set the "edge state" to TRUE just before we output the
- * first vertex of each edge on the polygon boundary.
- */
- newState = ! e->Rface->inside;
- if( edgeState != newState ) {
- edgeState = newState;
- CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA( edgeState );
- }
- }
- CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
-
- e = e->Lnext;
- } while( e != f->anEdge );
- }
- CALL_END_OR_END_DATA();
-}
-
-
-static void RenderFan( GLUtesselator *tess, GLUhalfEdge *e, long size )
-{
- /* Render as many CCW triangles as possible in a fan starting from
- * edge "e". The fan *should* contain exactly "size" triangles
- * (otherwise we've goofed up somewhere).
- */
- CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_FAN );
- CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
- CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
-
- while( ! Marked( e->Lface )) {
- e->Lface->marked = TRUE;
- --size;
- e = e->Onext;
- CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
- }
-
- assert( size == 0 );
- CALL_END_OR_END_DATA();
-}
-
-
-static void RenderStrip( GLUtesselator *tess, GLUhalfEdge *e, long size )
-{
- /* Render as many CCW triangles as possible in a strip starting from
- * edge "e". The strip *should* contain exactly "size" triangles
- * (otherwise we've goofed up somewhere).
- */
- CALL_BEGIN_OR_BEGIN_DATA( GL_TRIANGLE_STRIP );
- CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
- CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
-
- while( ! Marked( e->Lface )) {
- e->Lface->marked = TRUE;
- --size;
- e = e->Dprev;
- CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
- if( Marked( e->Lface )) break;
-
- e->Lface->marked = TRUE;
- --size;
- e = e->Onext;
- CALL_VERTEX_OR_VERTEX_DATA( e->Dst->data );
- }
-
- assert( size == 0 );
- CALL_END_OR_END_DATA();
-}
-
-
-/************************ Boundary contour decomposition ******************/
-
-/* __gl_renderBoundary( tess, mesh ) takes a mesh, and outputs one
- * contour for each face marked "inside". The rendering output is
- * provided as callbacks (see the api).
- */
-void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh )
-{
- GLUface *f;
- GLUhalfEdge *e;
-
- for( f = mesh->fHead.next; f != &mesh->fHead; f = f->next ) {
- if( f->inside ) {
- CALL_BEGIN_OR_BEGIN_DATA( GL_LINE_LOOP );
- e = f->anEdge;
- do {
- CALL_VERTEX_OR_VERTEX_DATA( e->Org->data );
- e = e->Lnext;
- } while( e != f->anEdge );
- CALL_END_OR_END_DATA();
- }
- }
-}
-
-
-/************************ Quick-and-dirty decomposition ******************/
-
-#define SIGN_INCONSISTENT 2
-
-static int ComputeNormal( GLUtesselator *tess, GLdouble norm[3], int check )
-/*
- * If check==FALSE, we compute the polygon normal and place it in norm[].
- * If check==TRUE, we check that each triangle in the fan from v0 has a
- * consistent orientation with respect to norm[]. If triangles are
- * consistently oriented CCW, return 1; if CW, return -1; if all triangles
- * are degenerate return 0; otherwise (no consistent orientation) return
- * SIGN_INCONSISTENT.
- */
-{
- CachedVertex *v0 = tess->cache;
- CachedVertex *vn = v0 + tess->cacheCount;
- CachedVertex *vc;
- GLdouble dot, xc, yc, zc, xp, yp, zp, n[3];
- int sign = 0;
-
- /* Find the polygon normal. It is important to get a reasonable
- * normal even when the polygon is self-intersecting (eg. a bowtie).
- * Otherwise, the computed normal could be very tiny, but perpendicular
- * to the true plane of the polygon due to numerical noise. Then all
- * the triangles would appear to be degenerate and we would incorrectly
- * decompose the polygon as a fan (or simply not render it at all).
- *
- * We use a sum-of-triangles normal algorithm rather than the more
- * efficient sum-of-trapezoids method (used in CheckOrientation()
- * in normal.c). This lets us explicitly reverse the signed area
- * of some triangles to get a reasonable normal in the self-intersecting
- * case.
- */
- if( ! check ) {
- norm[0] = norm[1] = norm[2] = 0.0;
- }
-
- vc = v0 + 1;
- xc = vc->coords[0] - v0->coords[0];
- yc = vc->coords[1] - v0->coords[1];
- zc = vc->coords[2] - v0->coords[2];
- while( ++vc < vn ) {
- xp = xc; yp = yc; zp = zc;
- xc = vc->coords[0] - v0->coords[0];
- yc = vc->coords[1] - v0->coords[1];
- zc = vc->coords[2] - v0->coords[2];
-
- /* Compute (vp - v0) cross (vc - v0) */
- n[0] = yp*zc - zp*yc;
- n[1] = zp*xc - xp*zc;
- n[2] = xp*yc - yp*xc;
-
- dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2];
- if( ! check ) {
- /* Reverse the contribution of back-facing triangles to get
- * a reasonable normal for self-intersecting polygons (see above)
- */
- if( dot >= 0 ) {
- norm[0] += n[0]; norm[1] += n[1]; norm[2] += n[2];
- } else {
- norm[0] -= n[0]; norm[1] -= n[1]; norm[2] -= n[2];
- }
- } else if( dot != 0 ) {
- /* Check the new orientation for consistency with previous triangles */
- if( dot > 0 ) {
- if( sign < 0 ) return SIGN_INCONSISTENT;
- sign = 1;
- } else {
- if( sign > 0 ) return SIGN_INCONSISTENT;
- sign = -1;
- }
- }
- }
- return sign;
-}
-
-/* __gl_renderCache( tess ) takes a single contour and tries to render it
- * as a triangle fan. This handles convex polygons, as well as some
- * non-convex polygons if we get lucky.
- *
- * Returns TRUE if the polygon was successfully rendered. The rendering
- * output is provided as callbacks (see the api).
- */
-GLboolean __gl_renderCache( GLUtesselator *tess )
-{
- CachedVertex *v0 = tess->cache;
- CachedVertex *vn = v0 + tess->cacheCount;
- CachedVertex *vc;
- GLdouble norm[3];
- int sign;
-
- if( tess->cacheCount < 3 ) {
- /* Degenerate contour -- no output */
- return TRUE;
- }
-
- norm[0] = tess->normal[0];
- norm[1] = tess->normal[1];
- norm[2] = tess->normal[2];
- if( norm[0] == 0 && norm[1] == 0 && norm[2] == 0 ) {
- ComputeNormal( tess, norm, FALSE );
- }
-
- sign = ComputeNormal( tess, norm, TRUE );
- if( sign == SIGN_INCONSISTENT ) {
- /* Fan triangles did not have a consistent orientation */
- return FALSE;
- }
- if( sign == 0 ) {
- /* All triangles were degenerate */
- return TRUE;
- }
-
- /* Make sure we do the right thing for each winding rule */
- switch( tess->windingRule ) {
- case GLU_TESS_WINDING_ODD:
- case GLU_TESS_WINDING_NONZERO:
- break;
- case GLU_TESS_WINDING_POSITIVE:
- if( sign < 0 ) return TRUE;
- break;
- case GLU_TESS_WINDING_NEGATIVE:
- if( sign > 0 ) return TRUE;
- break;
- case GLU_TESS_WINDING_ABS_GEQ_TWO:
- return TRUE;
- }
-
- CALL_BEGIN_OR_BEGIN_DATA( tess->boundaryOnly ? GL_LINE_LOOP
- : (tess->cacheCount > 3) ? GL_TRIANGLE_FAN
- : GL_TRIANGLES );
-
- CALL_VERTEX_OR_VERTEX_DATA( v0->data );
- if( sign > 0 ) {
- for( vc = v0+1; vc < vn; ++vc ) {
- CALL_VERTEX_OR_VERTEX_DATA( vc->data );
- }
- } else {
- for( vc = vn-1; vc > v0; --vc ) {
- CALL_VERTEX_OR_VERTEX_DATA( vc->data );
- }
- }
- CALL_END_OR_END_DATA();
- return TRUE;
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __render_h_
-#define __render_h_
-
-#include "mesh.h"
-
-/* __gl_renderMesh( tess, mesh ) takes a mesh and breaks it into triangle
- * fans, strips, and separate triangles. A substantial effort is made
- * to use as few rendering primitives as possible (ie. to make the fans
- * and strips as large as possible).
- *
- * The rendering output is provided as callbacks (see the api).
- */
-void __gl_renderMesh( GLUtesselator *tess, GLUmesh *mesh );
-void __gl_renderBoundary( GLUtesselator *tess, GLUmesh *mesh );
-
-GLboolean __gl_renderCache( GLUtesselator *tess );
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <assert.h>
-#include <stddef.h>
-#include <setjmp.h> /* longjmp */
-#include <limits.h> /* LONG_MAX */
-
-#include "mesh.h"
-#include "geom.h"
-#include "tess.h"
-#include "dict.h"
-#include "priorityq.h"
-#include "memalloc.h"
-#include "sweep.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifdef FOR_TRITE_TEST_PROGRAM
-extern void DebugEvent( GLUtesselator *tess );
-#else
-#define DebugEvent( tess )
-#endif
-
-/*
- * Invariants for the Edge Dictionary.
- * - each pair of adjacent edges e2=Succ(e1) satisfies EdgeLeq(e1,e2)
- * at any valid location of the sweep event
- * - if EdgeLeq(e2,e1) as well (at any valid sweep event), then e1 and e2
- * share a common endpoint
- * - for each e, e->Dst has been processed, but not e->Org
- * - each edge e satisfies VertLeq(e->Dst,event) && VertLeq(event,e->Org)
- * where "event" is the current sweep line event.
- * - no edge e has zero length
- *
- * Invariants for the Mesh (the processed portion).
- * - the portion of the mesh left of the sweep line is a planar graph,
- * ie. there is *some* way to embed it in the plane
- * - no processed edge has zero length
- * - no two processed vertices have identical coordinates
- * - each "inside" region is monotone, ie. can be broken into two chains
- * of monotonically increasing vertices according to VertLeq(v1,v2)
- * - a non-invariant: these chains may intersect (very slightly)
- *
- * Invariants for the Sweep.
- * - if none of the edges incident to the event vertex have an activeRegion
- * (ie. none of these edges are in the edge dictionary), then the vertex
- * has only right-going edges.
- * - if an edge is marked "fixUpperEdge" (it is a temporary edge introduced
- * by ConnectRightVertex), then it is the only right-going edge from
- * its associated vertex. (This says that these edges exist only
- * when it is necessary.)
- */
-
-#undef MAX
-#undef MIN
-#define MAX(x,y) ((x) >= (y) ? (x) : (y))
-#define MIN(x,y) ((x) <= (y) ? (x) : (y))
-
-/* When we merge two edges into one, we need to compute the combined
- * winding of the new edge.
- */
-#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \
- eDst->Sym->winding += eSrc->Sym->winding)
-
-static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent );
-static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp );
-static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp );
-
-static int EdgeLeq( GLUtesselator *tess, ActiveRegion *reg1,
- ActiveRegion *reg2 )
-/*
- * Both edges must be directed from right to left (this is the canonical
- * direction for the upper edge of each region).
- *
- * The strategy is to evaluate a "t" value for each edge at the
- * current sweep line position, given by tess->event. The calculations
- * are designed to be very stable, but of course they are not perfect.
- *
- * Special case: if both edge destinations are at the sweep event,
- * we sort the edges by slope (they would otherwise compare equally).
- */
-{
- GLUvertex *event = tess->event;
- GLUhalfEdge *e1, *e2;
- GLdouble t1, t2;
-
- e1 = reg1->eUp;
- e2 = reg2->eUp;
-
- if( e1->Dst == event ) {
- if( e2->Dst == event ) {
- /* Two edges right of the sweep line which meet at the sweep event.
- * Sort them by slope.
- */
- if( VertLeq( e1->Org, e2->Org )) {
- return EdgeSign( e2->Dst, e1->Org, e2->Org ) <= 0;
- }
- return EdgeSign( e1->Dst, e2->Org, e1->Org ) >= 0;
- }
- return EdgeSign( e2->Dst, event, e2->Org ) <= 0;
- }
- if( e2->Dst == event ) {
- return EdgeSign( e1->Dst, event, e1->Org ) >= 0;
- }
-
- /* General case - compute signed distance *from* e1, e2 to event */
- t1 = EdgeEval( e1->Dst, event, e1->Org );
- t2 = EdgeEval( e2->Dst, event, e2->Org );
- return (t1 >= t2);
-}
-
-
-static void DeleteRegion( GLUtesselator *tess, ActiveRegion *reg )
-{
- if( reg->fixUpperEdge ) {
- /* It was created with zero winding number, so it better be
- * deleted with zero winding number (ie. it better not get merged
- * with a real edge).
- */
- assert( reg->eUp->winding == 0 );
- }
- reg->eUp->activeRegion = NULL;
- dictDelete( tess->dict, reg->nodeUp ); /* __gl_dictListDelete */
- memFree( reg );
-}
-
-
-static int FixUpperEdge( ActiveRegion *reg, GLUhalfEdge *newEdge )
-/*
- * Replace an upper edge which needs fixing (see ConnectRightVertex).
- */
-{
- assert( reg->fixUpperEdge );
- if ( !__gl_meshDelete( reg->eUp ) ) return 0;
- reg->fixUpperEdge = FALSE;
- reg->eUp = newEdge;
- newEdge->activeRegion = reg;
-
- return 1;
-}
-
-static ActiveRegion *TopLeftRegion( ActiveRegion *reg )
-{
- GLUvertex *org = reg->eUp->Org;
- GLUhalfEdge *e;
-
- /* Find the region above the uppermost edge with the same origin */
- do {
- reg = RegionAbove( reg );
- } while( reg->eUp->Org == org );
-
- /* If the edge above was a temporary edge introduced by ConnectRightVertex,
- * now is the time to fix it.
- */
- if( reg->fixUpperEdge ) {
- e = __gl_meshConnect( RegionBelow(reg)->eUp->Sym, reg->eUp->Lnext );
- if (e == NULL) return NULL;
- if ( !FixUpperEdge( reg, e ) ) return NULL;
- reg = RegionAbove( reg );
- }
- return reg;
-}
-
-static ActiveRegion *TopRightRegion( ActiveRegion *reg )
-{
- GLUvertex *dst = reg->eUp->Dst;
-
- /* Find the region above the uppermost edge with the same destination */
- do {
- reg = RegionAbove( reg );
- } while( reg->eUp->Dst == dst );
- return reg;
-}
-
-static ActiveRegion *AddRegionBelow( GLUtesselator *tess,
- ActiveRegion *regAbove,
- GLUhalfEdge *eNewUp )
-/*
- * Add a new active region to the sweep line, *somewhere* below "regAbove"
- * (according to where the new edge belongs in the sweep-line dictionary).
- * The upper edge of the new region will be "eNewUp".
- * Winding number and "inside" flag are not updated.
- */
-{
- ActiveRegion *regNew = (ActiveRegion *)memAlloc( sizeof( ActiveRegion ));
- if (regNew == NULL) longjmp(tess->env,1);
-
- regNew->eUp = eNewUp;
- /* __gl_dictListInsertBefore */
- regNew->nodeUp = dictInsertBefore( tess->dict, regAbove->nodeUp, regNew );
- if (regNew->nodeUp == NULL) longjmp(tess->env,1);
- regNew->fixUpperEdge = FALSE;
- regNew->sentinel = FALSE;
- regNew->dirty = FALSE;
-
- eNewUp->activeRegion = regNew;
- return regNew;
-}
-
-static GLboolean IsWindingInside( GLUtesselator *tess, int n )
-{
- switch( tess->windingRule ) {
- case GLU_TESS_WINDING_ODD:
- return (n & 1);
- case GLU_TESS_WINDING_NONZERO:
- return (n != 0);
- case GLU_TESS_WINDING_POSITIVE:
- return (n > 0);
- case GLU_TESS_WINDING_NEGATIVE:
- return (n < 0);
- case GLU_TESS_WINDING_ABS_GEQ_TWO:
- return (n >= 2) || (n <= -2);
- }
- /*LINTED*/
- assert( FALSE );
- /*NOTREACHED*/
- return GL_FALSE; /* avoid compiler complaints */
-}
-
-
-static void ComputeWinding( GLUtesselator *tess, ActiveRegion *reg )
-{
- reg->windingNumber = RegionAbove(reg)->windingNumber + reg->eUp->winding;
- reg->inside = IsWindingInside( tess, reg->windingNumber );
-}
-
-
-static void FinishRegion( GLUtesselator *tess, ActiveRegion *reg )
-/*
- * Delete a region from the sweep line. This happens when the upper
- * and lower chains of a region meet (at a vertex on the sweep line).
- * The "inside" flag is copied to the appropriate mesh face (we could
- * not do this before -- since the structure of the mesh is always
- * changing, this face may not have even existed until now).
- */
-{
- GLUhalfEdge *e = reg->eUp;
- GLUface *f = e->Lface;
-
- f->inside = reg->inside;
- f->anEdge = e; /* optimization for __gl_meshTessellateMonoRegion() */
- DeleteRegion( tess, reg );
-}
-
-
-static GLUhalfEdge *FinishLeftRegions( GLUtesselator *tess,
- ActiveRegion *regFirst, ActiveRegion *regLast )
-/*
- * We are given a vertex with one or more left-going edges. All affected
- * edges should be in the edge dictionary. Starting at regFirst->eUp,
- * we walk down deleting all regions where both edges have the same
- * origin vOrg. At the same time we copy the "inside" flag from the
- * active region to the face, since at this point each face will belong
- * to at most one region (this was not necessarily true until this point
- * in the sweep). The walk stops at the region above regLast; if regLast
- * is NULL we walk as far as possible. At the same time we relink the
- * mesh if necessary, so that the ordering of edges around vOrg is the
- * same as in the dictionary.
- */
-{
- ActiveRegion *reg, *regPrev;
- GLUhalfEdge *e, *ePrev;
-
- regPrev = regFirst;
- ePrev = regFirst->eUp;
- while( regPrev != regLast ) {
- regPrev->fixUpperEdge = FALSE; /* placement was OK */
- reg = RegionBelow( regPrev );
- e = reg->eUp;
- if( e->Org != ePrev->Org ) {
- if( ! reg->fixUpperEdge ) {
- /* Remove the last left-going edge. Even though there are no further
- * edges in the dictionary with this origin, there may be further
- * such edges in the mesh (if we are adding left edges to a vertex
- * that has already been processed). Thus it is important to call
- * FinishRegion rather than just DeleteRegion.
- */
- FinishRegion( tess, regPrev );
- break;
- }
- /* If the edge below was a temporary edge introduced by
- * ConnectRightVertex, now is the time to fix it.
- */
- e = __gl_meshConnect( ePrev->Lprev, e->Sym );
- if (e == NULL) longjmp(tess->env,1);
- if ( !FixUpperEdge( reg, e ) ) longjmp(tess->env,1);
- }
-
- /* Relink edges so that ePrev->Onext == e */
- if( ePrev->Onext != e ) {
- if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1);
- if ( !__gl_meshSplice( ePrev, e ) ) longjmp(tess->env,1);
- }
- FinishRegion( tess, regPrev ); /* may change reg->eUp */
- ePrev = reg->eUp;
- regPrev = reg;
- }
- return ePrev;
-}
-
-
-static void AddRightEdges( GLUtesselator *tess, ActiveRegion *regUp,
- GLUhalfEdge *eFirst, GLUhalfEdge *eLast, GLUhalfEdge *eTopLeft,
- GLboolean cleanUp )
-/*
- * Purpose: insert right-going edges into the edge dictionary, and update
- * winding numbers and mesh connectivity appropriately. All right-going
- * edges share a common origin vOrg. Edges are inserted CCW starting at
- * eFirst; the last edge inserted is eLast->Oprev. If vOrg has any
- * left-going edges already processed, then eTopLeft must be the edge
- * such that an imaginary upward vertical segment from vOrg would be
- * contained between eTopLeft->Oprev and eTopLeft; otherwise eTopLeft
- * should be NULL.
- */
-{
- ActiveRegion *reg, *regPrev;
- GLUhalfEdge *e, *ePrev;
- int firstTime = TRUE;
-
- /* Insert the new right-going edges in the dictionary */
- e = eFirst;
- do {
- assert( VertLeq( e->Org, e->Dst ));
- AddRegionBelow( tess, regUp, e->Sym );
- e = e->Onext;
- } while ( e != eLast );
-
- /* Walk *all* right-going edges from e->Org, in the dictionary order,
- * updating the winding numbers of each region, and re-linking the mesh
- * edges to match the dictionary ordering (if necessary).
- */
- if( eTopLeft == NULL ) {
- eTopLeft = RegionBelow( regUp )->eUp->Rprev;
- }
- regPrev = regUp;
- ePrev = eTopLeft;
- for( ;; ) {
- reg = RegionBelow( regPrev );
- e = reg->eUp->Sym;
- if( e->Org != ePrev->Org ) break;
-
- if( e->Onext != ePrev ) {
- /* Unlink e from its current position, and relink below ePrev */
- if ( !__gl_meshSplice( e->Oprev, e ) ) longjmp(tess->env,1);
- if ( !__gl_meshSplice( ePrev->Oprev, e ) ) longjmp(tess->env,1);
- }
- /* Compute the winding number and "inside" flag for the new regions */
- reg->windingNumber = regPrev->windingNumber - e->winding;
- reg->inside = IsWindingInside( tess, reg->windingNumber );
-
- /* Check for two outgoing edges with same slope -- process these
- * before any intersection tests (see example in __gl_computeInterior).
- */
- regPrev->dirty = TRUE;
- if( ! firstTime && CheckForRightSplice( tess, regPrev )) {
- AddWinding( e, ePrev );
- DeleteRegion( tess, regPrev );
- if ( !__gl_meshDelete( ePrev ) ) longjmp(tess->env,1);
- }
- firstTime = FALSE;
- regPrev = reg;
- ePrev = e;
- }
- regPrev->dirty = TRUE;
- assert( regPrev->windingNumber - e->winding == reg->windingNumber );
-
- if( cleanUp ) {
- /* Check for intersections between newly adjacent edges. */
- WalkDirtyRegions( tess, regPrev );
- }
-}
-
-
-static void CallCombine( GLUtesselator *tess, GLUvertex *isect,
- void *data[4], GLfloat weights[4], int needed )
-{
- GLdouble coords[3];
-
- /* Copy coord data in case the callback changes it. */
- coords[0] = isect->coords[0];
- coords[1] = isect->coords[1];
- coords[2] = isect->coords[2];
-
- isect->data = NULL;
- CALL_COMBINE_OR_COMBINE_DATA( coords, data, weights, &isect->data );
- if( isect->data == NULL ) {
- if( ! needed ) {
- isect->data = data[0];
- } else if( ! tess->fatalError ) {
- /* The only way fatal error is when two edges are found to intersect,
- * but the user has not provided the callback necessary to handle
- * generated intersection points.
- */
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_NEED_COMBINE_CALLBACK );
- tess->fatalError = TRUE;
- }
- }
-}
-
-static void SpliceMergeVertices( GLUtesselator *tess, GLUhalfEdge *e1,
- GLUhalfEdge *e2 )
-/*
- * Two vertices with idential coordinates are combined into one.
- * e1->Org is kept, while e2->Org is discarded.
- */
-{
- void *data[4] = { NULL, NULL, NULL, NULL };
- GLfloat weights[4] = { 0.5, 0.5, 0.0, 0.0 };
-
- data[0] = e1->Org->data;
- data[1] = e2->Org->data;
- CallCombine( tess, e1->Org, data, weights, FALSE );
- if ( !__gl_meshSplice( e1, e2 ) ) longjmp(tess->env,1);
-}
-
-static void VertexWeights( GLUvertex *isect, GLUvertex *org, GLUvertex *dst,
- GLfloat *weights )
-/*
- * Find some weights which describe how the intersection vertex is
- * a linear combination of "org" and "dest". Each of the two edges
- * which generated "isect" is allocated 50% of the weight; each edge
- * splits the weight between its org and dst according to the
- * relative distance to "isect".
- */
-{
- GLdouble t1 = VertL1dist( org, isect );
- GLdouble t2 = VertL1dist( dst, isect );
-
- weights[0] = 0.5 * t2 / (t1 + t2);
- weights[1] = 0.5 * t1 / (t1 + t2);
- isect->coords[0] += weights[0]*org->coords[0] + weights[1]*dst->coords[0];
- isect->coords[1] += weights[0]*org->coords[1] + weights[1]*dst->coords[1];
- isect->coords[2] += weights[0]*org->coords[2] + weights[1]*dst->coords[2];
-}
-
-
-static void GetIntersectData( GLUtesselator *tess, GLUvertex *isect,
- GLUvertex *orgUp, GLUvertex *dstUp,
- GLUvertex *orgLo, GLUvertex *dstLo )
-/*
- * We've computed a new intersection point, now we need a "data" pointer
- * from the user so that we can refer to this new vertex in the
- * rendering callbacks.
- */
-{
- void *data[4];
- GLfloat weights[4];
-
- data[0] = orgUp->data;
- data[1] = dstUp->data;
- data[2] = orgLo->data;
- data[3] = dstLo->data;
-
- isect->coords[0] = isect->coords[1] = isect->coords[2] = 0;
- VertexWeights( isect, orgUp, dstUp, &weights[0] );
- VertexWeights( isect, orgLo, dstLo, &weights[2] );
-
- CallCombine( tess, isect, data, weights, TRUE );
-}
-
-static int CheckForRightSplice( GLUtesselator *tess, ActiveRegion *regUp )
-/*
- * Check the upper and lower edge of "regUp", to make sure that the
- * eUp->Org is above eLo, or eLo->Org is below eUp (depending on which
- * origin is leftmost).
- *
- * The main purpose is to splice right-going edges with the same
- * dest vertex and nearly identical slopes (ie. we can't distinguish
- * the slopes numerically). However the splicing can also help us
- * to recover from numerical errors. For example, suppose at one
- * point we checked eUp and eLo, and decided that eUp->Org is barely
- * above eLo. Then later, we split eLo into two edges (eg. from
- * a splice operation like this one). This can change the result of
- * our test so that now eUp->Org is incident to eLo, or barely below it.
- * We must correct this condition to maintain the dictionary invariants.
- *
- * One possibility is to check these edges for intersection again
- * (ie. CheckForIntersect). This is what we do if possible. However
- * CheckForIntersect requires that tess->event lies between eUp and eLo,
- * so that it has something to fall back on when the intersection
- * calculation gives us an unusable answer. So, for those cases where
- * we can't check for intersection, this routine fixes the problem
- * by just splicing the offending vertex into the other edge.
- * This is a guaranteed solution, no matter how degenerate things get.
- * Basically this is a combinatorial solution to a numerical problem.
- */
-{
- ActiveRegion *regLo = RegionBelow(regUp);
- GLUhalfEdge *eUp = regUp->eUp;
- GLUhalfEdge *eLo = regLo->eUp;
-
- if( VertLeq( eUp->Org, eLo->Org )) {
- if( EdgeSign( eLo->Dst, eUp->Org, eLo->Org ) > 0 ) return FALSE;
-
- /* eUp->Org appears to be below eLo */
- if( ! VertEq( eUp->Org, eLo->Org )) {
- /* Splice eUp->Org into eLo */
- if ( __gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eUp, eLo->Oprev ) ) longjmp(tess->env,1);
- regUp->dirty = regLo->dirty = TRUE;
-
- } else if( eUp->Org != eLo->Org ) {
- /* merge the two vertices, discarding eUp->Org */
- pqDelete( tess->pq, eUp->Org->pqHandle ); /* __gl_pqSortDelete */
- SpliceMergeVertices( tess, eLo->Oprev, eUp );
- }
- } else {
- if( EdgeSign( eUp->Dst, eLo->Org, eUp->Org ) < 0 ) return FALSE;
-
- /* eLo->Org appears to be above eUp, so splice eLo->Org into eUp */
- RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
- if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1);
- }
- return TRUE;
-}
-
-static int CheckForLeftSplice( GLUtesselator *tess, ActiveRegion *regUp )
-/*
- * Check the upper and lower edge of "regUp", to make sure that the
- * eUp->Dst is above eLo, or eLo->Dst is below eUp (depending on which
- * destination is rightmost).
- *
- * Theoretically, this should always be true. However, splitting an edge
- * into two pieces can change the results of previous tests. For example,
- * suppose at one point we checked eUp and eLo, and decided that eUp->Dst
- * is barely above eLo. Then later, we split eLo into two edges (eg. from
- * a splice operation like this one). This can change the result of
- * the test so that now eUp->Dst is incident to eLo, or barely below it.
- * We must correct this condition to maintain the dictionary invariants
- * (otherwise new edges might get inserted in the wrong place in the
- * dictionary, and bad stuff will happen).
- *
- * We fix the problem by just splicing the offending vertex into the
- * other edge.
- */
-{
- ActiveRegion *regLo = RegionBelow(regUp);
- GLUhalfEdge *eUp = regUp->eUp;
- GLUhalfEdge *eLo = regLo->eUp;
- GLUhalfEdge *e;
-
- assert( ! VertEq( eUp->Dst, eLo->Dst ));
-
- if( VertLeq( eUp->Dst, eLo->Dst )) {
- if( EdgeSign( eUp->Dst, eLo->Dst, eUp->Org ) < 0 ) return FALSE;
-
- /* eLo->Dst is above eUp, so splice eLo->Dst into eUp */
- RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
- e = __gl_meshSplitEdge( eUp );
- if (e == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eLo->Sym, e ) ) longjmp(tess->env,1);
- e->Lface->inside = regUp->inside;
- } else {
- if( EdgeSign( eLo->Dst, eUp->Dst, eLo->Org ) > 0 ) return FALSE;
-
- /* eUp->Dst is below eLo, so splice eUp->Dst into eLo */
- regUp->dirty = regLo->dirty = TRUE;
- e = __gl_meshSplitEdge( eLo );
- if (e == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eUp->Lnext, eLo->Sym ) ) longjmp(tess->env,1);
- e->Rface->inside = regUp->inside;
- }
- return TRUE;
-}
-
-
-static int CheckForIntersect( GLUtesselator *tess, ActiveRegion *regUp )
-/*
- * Check the upper and lower edges of the given region to see if
- * they intersect. If so, create the intersection and add it
- * to the data structures.
- *
- * Returns TRUE if adding the new intersection resulted in a recursive
- * call to AddRightEdges(); in this case all "dirty" regions have been
- * checked for intersections, and possibly regUp has been deleted.
- */
-{
- ActiveRegion *regLo = RegionBelow(regUp);
- GLUhalfEdge *eUp = regUp->eUp;
- GLUhalfEdge *eLo = regLo->eUp;
- GLUvertex *orgUp = eUp->Org;
- GLUvertex *orgLo = eLo->Org;
- GLUvertex *dstUp = eUp->Dst;
- GLUvertex *dstLo = eLo->Dst;
- GLdouble tMinUp, tMaxLo;
- GLUvertex isect, *orgMin;
- GLUhalfEdge *e;
-
- assert( ! VertEq( dstLo, dstUp ));
- assert( EdgeSign( dstUp, tess->event, orgUp ) <= 0 );
- assert( EdgeSign( dstLo, tess->event, orgLo ) >= 0 );
- assert( orgUp != tess->event && orgLo != tess->event );
- assert( ! regUp->fixUpperEdge && ! regLo->fixUpperEdge );
-
- if( orgUp == orgLo ) return FALSE; /* right endpoints are the same */
-
- tMinUp = MIN( orgUp->t, dstUp->t );
- tMaxLo = MAX( orgLo->t, dstLo->t );
- if( tMinUp > tMaxLo ) return FALSE; /* t ranges do not overlap */
-
- if( VertLeq( orgUp, orgLo )) {
- if( EdgeSign( dstLo, orgUp, orgLo ) > 0 ) return FALSE;
- } else {
- if( EdgeSign( dstUp, orgLo, orgUp ) < 0 ) return FALSE;
- }
-
- /* At this point the edges intersect, at least marginally */
- DebugEvent( tess );
-
- __gl_edgeIntersect( dstUp, orgUp, dstLo, orgLo, &isect );
- /* The following properties are guaranteed: */
- assert( MIN( orgUp->t, dstUp->t ) <= isect.t );
- assert( isect.t <= MAX( orgLo->t, dstLo->t ));
- assert( MIN( dstLo->s, dstUp->s ) <= isect.s );
- assert( isect.s <= MAX( orgLo->s, orgUp->s ));
-
- if( VertLeq( &isect, tess->event )) {
- /* The intersection point lies slightly to the left of the sweep line,
- * so move it until it''s slightly to the right of the sweep line.
- * (If we had perfect numerical precision, this would never happen
- * in the first place). The easiest and safest thing to do is
- * replace the intersection by tess->event.
- */
- isect.s = tess->event->s;
- isect.t = tess->event->t;
- }
- /* Similarly, if the computed intersection lies to the right of the
- * rightmost origin (which should rarely happen), it can cause
- * unbelievable inefficiency on sufficiently degenerate inputs.
- * (If you have the test program, try running test54.d with the
- * "X zoom" option turned on).
- */
- orgMin = VertLeq( orgUp, orgLo ) ? orgUp : orgLo;
- if( VertLeq( orgMin, &isect )) {
- isect.s = orgMin->s;
- isect.t = orgMin->t;
- }
-
- if( VertEq( &isect, orgUp ) || VertEq( &isect, orgLo )) {
- /* Easy case -- intersection at one of the right endpoints */
- (void) CheckForRightSplice( tess, regUp );
- return FALSE;
- }
-
- if( (! VertEq( dstUp, tess->event )
- && EdgeSign( dstUp, tess->event, &isect ) >= 0)
- || (! VertEq( dstLo, tess->event )
- && EdgeSign( dstLo, tess->event, &isect ) <= 0 ))
- {
- /* Very unusual -- the new upper or lower edge would pass on the
- * wrong side of the sweep event, or through it. This can happen
- * due to very small numerical errors in the intersection calculation.
- */
- if( dstLo == tess->event ) {
- /* Splice dstLo into eUp, and process the new region(s) */
- if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eLo->Sym, eUp ) ) longjmp(tess->env,1);
- regUp = TopLeftRegion( regUp );
- if (regUp == NULL) longjmp(tess->env,1);
- eUp = RegionBelow(regUp)->eUp;
- FinishLeftRegions( tess, RegionBelow(regUp), regLo );
- AddRightEdges( tess, regUp, eUp->Oprev, eUp, eUp, TRUE );
- return TRUE;
- }
- if( dstUp == tess->event ) {
- /* Splice dstUp into eLo, and process the new region(s) */
- if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eUp->Lnext, eLo->Oprev ) ) longjmp(tess->env,1);
- regLo = regUp;
- regUp = TopRightRegion( regUp );
- e = RegionBelow(regUp)->eUp->Rprev;
- regLo->eUp = eLo->Oprev;
- eLo = FinishLeftRegions( tess, regLo, NULL );
- AddRightEdges( tess, regUp, eLo->Onext, eUp->Rprev, e, TRUE );
- return TRUE;
- }
- /* Special case: called from ConnectRightVertex. If either
- * edge passes on the wrong side of tess->event, split it
- * (and wait for ConnectRightVertex to splice it appropriately).
- */
- if( EdgeSign( dstUp, tess->event, &isect ) >= 0 ) {
- RegionAbove(regUp)->dirty = regUp->dirty = TRUE;
- if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
- eUp->Org->s = tess->event->s;
- eUp->Org->t = tess->event->t;
- }
- if( EdgeSign( dstLo, tess->event, &isect ) <= 0 ) {
- regUp->dirty = regLo->dirty = TRUE;
- if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
- eLo->Org->s = tess->event->s;
- eLo->Org->t = tess->event->t;
- }
- /* leave the rest for ConnectRightVertex */
- return FALSE;
- }
-
- /* General case -- split both edges, splice into new vertex.
- * When we do the splice operation, the order of the arguments is
- * arbitrary as far as correctness goes. However, when the operation
- * creates a new face, the work done is proportional to the size of
- * the new face. We expect the faces in the processed part of
- * the mesh (ie. eUp->Lface) to be smaller than the faces in the
- * unprocessed original contours (which will be eLo->Oprev->Lface).
- */
- if (__gl_meshSplitEdge( eUp->Sym ) == NULL) longjmp(tess->env,1);
- if (__gl_meshSplitEdge( eLo->Sym ) == NULL) longjmp(tess->env,1);
- if ( !__gl_meshSplice( eLo->Oprev, eUp ) ) longjmp(tess->env,1);
- eUp->Org->s = isect.s;
- eUp->Org->t = isect.t;
- eUp->Org->pqHandle = pqInsert( tess->pq, eUp->Org ); /* __gl_pqSortInsert */
- if (eUp->Org->pqHandle == LONG_MAX) {
- pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */
- tess->pq = NULL;
- longjmp(tess->env,1);
- }
- GetIntersectData( tess, eUp->Org, orgUp, dstUp, orgLo, dstLo );
- RegionAbove(regUp)->dirty = regUp->dirty = regLo->dirty = TRUE;
- return FALSE;
-}
-
-static void WalkDirtyRegions( GLUtesselator *tess, ActiveRegion *regUp )
-/*
- * When the upper or lower edge of any region changes, the region is
- * marked "dirty". This routine walks through all the dirty regions
- * and makes sure that the dictionary invariants are satisfied
- * (see the comments at the beginning of this file). Of course
- * new dirty regions can be created as we make changes to restore
- * the invariants.
- */
-{
- ActiveRegion *regLo = RegionBelow(regUp);
- GLUhalfEdge *eUp, *eLo;
-
- for( ;; ) {
- /* Find the lowest dirty region (we walk from the bottom up). */
- while( regLo->dirty ) {
- regUp = regLo;
- regLo = RegionBelow(regLo);
- }
- if( ! regUp->dirty ) {
- regLo = regUp;
- regUp = RegionAbove( regUp );
- if( regUp == NULL || ! regUp->dirty ) {
- /* We've walked all the dirty regions */
- return;
- }
- }
- regUp->dirty = FALSE;
- eUp = regUp->eUp;
- eLo = regLo->eUp;
-
- if( eUp->Dst != eLo->Dst ) {
- /* Check that the edge ordering is obeyed at the Dst vertices. */
- if( CheckForLeftSplice( tess, regUp )) {
-
- /* If the upper or lower edge was marked fixUpperEdge, then
- * we no longer need it (since these edges are needed only for
- * vertices which otherwise have no right-going edges).
- */
- if( regLo->fixUpperEdge ) {
- DeleteRegion( tess, regLo );
- if ( !__gl_meshDelete( eLo ) ) longjmp(tess->env,1);
- regLo = RegionBelow( regUp );
- eLo = regLo->eUp;
- } else if( regUp->fixUpperEdge ) {
- DeleteRegion( tess, regUp );
- if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);
- regUp = RegionAbove( regLo );
- eUp = regUp->eUp;
- }
- }
- }
- if( eUp->Org != eLo->Org ) {
- if( eUp->Dst != eLo->Dst
- && ! regUp->fixUpperEdge && ! regLo->fixUpperEdge
- && (eUp->Dst == tess->event || eLo->Dst == tess->event) )
- {
- /* When all else fails in CheckForIntersect(), it uses tess->event
- * as the intersection location. To make this possible, it requires
- * that tess->event lie between the upper and lower edges, and also
- * that neither of these is marked fixUpperEdge (since in the worst
- * case it might splice one of these edges into tess->event, and
- * violate the invariant that fixable edges are the only right-going
- * edge from their associated vertex).
- */
- if( CheckForIntersect( tess, regUp )) {
- /* WalkDirtyRegions() was called recursively; we're done */
- return;
- }
- } else {
- /* Even though we can't use CheckForIntersect(), the Org vertices
- * may violate the dictionary edge ordering. Check and correct this.
- */
- (void) CheckForRightSplice( tess, regUp );
- }
- }
- if( eUp->Org == eLo->Org && eUp->Dst == eLo->Dst ) {
- /* A degenerate loop consisting of only two edges -- delete it. */
- AddWinding( eLo, eUp );
- DeleteRegion( tess, regUp );
- if ( !__gl_meshDelete( eUp ) ) longjmp(tess->env,1);
- regUp = RegionAbove( regLo );
- }
- }
-}
-
-
-static void ConnectRightVertex( GLUtesselator *tess, ActiveRegion *regUp,
- GLUhalfEdge *eBottomLeft )
-/*
- * Purpose: connect a "right" vertex vEvent (one where all edges go left)
- * to the unprocessed portion of the mesh. Since there are no right-going
- * edges, two regions (one above vEvent and one below) are being merged
- * into one. "regUp" is the upper of these two regions.
- *
- * There are two reasons for doing this (adding a right-going edge):
- * - if the two regions being merged are "inside", we must add an edge
- * to keep them separated (the combined region would not be monotone).
- * - in any case, we must leave some record of vEvent in the dictionary,
- * so that we can merge vEvent with features that we have not seen yet.
- * For example, maybe there is a vertical edge which passes just to
- * the right of vEvent; we would like to splice vEvent into this edge.
- *
- * However, we don't want to connect vEvent to just any vertex. We don''t
- * want the new edge to cross any other edges; otherwise we will create
- * intersection vertices even when the input data had no self-intersections.
- * (This is a bad thing; if the user's input data has no intersections,
- * we don't want to generate any false intersections ourselves.)
- *
- * Our eventual goal is to connect vEvent to the leftmost unprocessed
- * vertex of the combined region (the union of regUp and regLo).
- * But because of unseen vertices with all right-going edges, and also
- * new vertices which may be created by edge intersections, we don''t
- * know where that leftmost unprocessed vertex is. In the meantime, we
- * connect vEvent to the closest vertex of either chain, and mark the region
- * as "fixUpperEdge". This flag says to delete and reconnect this edge
- * to the next processed vertex on the boundary of the combined region.
- * Quite possibly the vertex we connected to will turn out to be the
- * closest one, in which case we won''t need to make any changes.
- */
-{
- GLUhalfEdge *eNew;
- GLUhalfEdge *eTopLeft = eBottomLeft->Onext;
- ActiveRegion *regLo = RegionBelow(regUp);
- GLUhalfEdge *eUp = regUp->eUp;
- GLUhalfEdge *eLo = regLo->eUp;
- int degenerate = FALSE;
-
- if( eUp->Dst != eLo->Dst ) {
- (void) CheckForIntersect( tess, regUp );
- }
-
- /* Possible new degeneracies: upper or lower edge of regUp may pass
- * through vEvent, or may coincide with new intersection vertex
- */
- if( VertEq( eUp->Org, tess->event )) {
- if ( !__gl_meshSplice( eTopLeft->Oprev, eUp ) ) longjmp(tess->env,1);
- regUp = TopLeftRegion( regUp );
- if (regUp == NULL) longjmp(tess->env,1);
- eTopLeft = RegionBelow( regUp )->eUp;
- FinishLeftRegions( tess, RegionBelow(regUp), regLo );
- degenerate = TRUE;
- }
- if( VertEq( eLo->Org, tess->event )) {
- if ( !__gl_meshSplice( eBottomLeft, eLo->Oprev ) ) longjmp(tess->env,1);
- eBottomLeft = FinishLeftRegions( tess, regLo, NULL );
- degenerate = TRUE;
- }
- if( degenerate ) {
- AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );
- return;
- }
-
- /* Non-degenerate situation -- need to add a temporary, fixable edge.
- * Connect to the closer of eLo->Org, eUp->Org.
- */
- if( VertLeq( eLo->Org, eUp->Org )) {
- eNew = eLo->Oprev;
- } else {
- eNew = eUp;
- }
- eNew = __gl_meshConnect( eBottomLeft->Lprev, eNew );
- if (eNew == NULL) longjmp(tess->env,1);
-
- /* Prevent cleanup, otherwise eNew might disappear before we've even
- * had a chance to mark it as a temporary edge.
- */
- AddRightEdges( tess, regUp, eNew, eNew->Onext, eNew->Onext, FALSE );
- eNew->Sym->activeRegion->fixUpperEdge = TRUE;
- WalkDirtyRegions( tess, regUp );
-}
-
-/* Because vertices at exactly the same location are merged together
- * before we process the sweep event, some degenerate cases can't occur.
- * However if someone eventually makes the modifications required to
- * merge features which are close together, the cases below marked
- * TOLERANCE_NONZERO will be useful. They were debugged before the
- * code to merge identical vertices in the main loop was added.
- */
-#define TOLERANCE_NONZERO FALSE
-
-static void ConnectLeftDegenerate( GLUtesselator *tess,
- ActiveRegion *regUp, GLUvertex *vEvent )
-/*
- * The event vertex lies exacty on an already-processed edge or vertex.
- * Adding the new vertex involves splicing it into the already-processed
- * part of the mesh.
- */
-{
- GLUhalfEdge *e, *eTopLeft, *eTopRight, *eLast;
- ActiveRegion *reg;
-
- e = regUp->eUp;
- if( VertEq( e->Org, vEvent )) {
- /* e->Org is an unprocessed vertex - just combine them, and wait
- * for e->Org to be pulled from the queue
- */
- assert( TOLERANCE_NONZERO );
- SpliceMergeVertices( tess, e, vEvent->anEdge );
- return;
- }
-
- if( ! VertEq( e->Dst, vEvent )) {
- /* General case -- splice vEvent into edge e which passes through it */
- if (__gl_meshSplitEdge( e->Sym ) == NULL) longjmp(tess->env,1);
- if( regUp->fixUpperEdge ) {
- /* This edge was fixable -- delete unused portion of original edge */
- if ( !__gl_meshDelete( e->Onext ) ) longjmp(tess->env,1);
- regUp->fixUpperEdge = FALSE;
- }
- if ( !__gl_meshSplice( vEvent->anEdge, e ) ) longjmp(tess->env,1);
- SweepEvent( tess, vEvent ); /* recurse */
- return;
- }
-
- /* vEvent coincides with e->Dst, which has already been processed.
- * Splice in the additional right-going edges.
- */
- assert( TOLERANCE_NONZERO );
- regUp = TopRightRegion( regUp );
- reg = RegionBelow( regUp );
- eTopRight = reg->eUp->Sym;
- eTopLeft = eLast = eTopRight->Onext;
- if( reg->fixUpperEdge ) {
- /* Here e->Dst has only a single fixable edge going right.
- * We can delete it since now we have some real right-going edges.
- */
- assert( eTopLeft != eTopRight ); /* there are some left edges too */
- DeleteRegion( tess, reg );
- if ( !__gl_meshDelete( eTopRight ) ) longjmp(tess->env,1);
- eTopRight = eTopLeft->Oprev;
- }
- if ( !__gl_meshSplice( vEvent->anEdge, eTopRight ) ) longjmp(tess->env,1);
- if( ! EdgeGoesLeft( eTopLeft )) {
- /* e->Dst had no left-going edges -- indicate this to AddRightEdges() */
- eTopLeft = NULL;
- }
- AddRightEdges( tess, regUp, eTopRight->Onext, eLast, eTopLeft, TRUE );
-}
-
-
-static void ConnectLeftVertex( GLUtesselator *tess, GLUvertex *vEvent )
-/*
- * Purpose: connect a "left" vertex (one where both edges go right)
- * to the processed portion of the mesh. Let R be the active region
- * containing vEvent, and let U and L be the upper and lower edge
- * chains of R. There are two possibilities:
- *
- * - the normal case: split R into two regions, by connecting vEvent to
- * the rightmost vertex of U or L lying to the left of the sweep line
- *
- * - the degenerate case: if vEvent is close enough to U or L, we
- * merge vEvent into that edge chain. The subcases are:
- * - merging with the rightmost vertex of U or L
- * - merging with the active edge of U or L
- * - merging with an already-processed portion of U or L
- */
-{
- ActiveRegion *regUp, *regLo, *reg;
- GLUhalfEdge *eUp, *eLo, *eNew;
- ActiveRegion tmp;
-
- /* assert( vEvent->anEdge->Onext->Onext == vEvent->anEdge ); */
-
- /* Get a pointer to the active region containing vEvent */
- tmp.eUp = vEvent->anEdge->Sym;
- /* __GL_DICTLISTKEY */ /* __gl_dictListSearch */
- regUp = (ActiveRegion *)dictKey( dictSearch( tess->dict, &tmp ));
- regLo = RegionBelow( regUp );
- eUp = regUp->eUp;
- eLo = regLo->eUp;
-
- /* Try merging with U or L first */
- if( EdgeSign( eUp->Dst, vEvent, eUp->Org ) == 0 ) {
- ConnectLeftDegenerate( tess, regUp, vEvent );
- return;
- }
-
- /* Connect vEvent to rightmost processed vertex of either chain.
- * e->Dst is the vertex that we will connect to vEvent.
- */
- reg = VertLeq( eLo->Dst, eUp->Dst ) ? regUp : regLo;
-
- if( regUp->inside || reg->fixUpperEdge) {
- if( reg == regUp ) {
- eNew = __gl_meshConnect( vEvent->anEdge->Sym, eUp->Lnext );
- if (eNew == NULL) longjmp(tess->env,1);
- } else {
- GLUhalfEdge *tempHalfEdge= __gl_meshConnect( eLo->Dnext, vEvent->anEdge);
- if (tempHalfEdge == NULL) longjmp(tess->env,1);
-
- eNew = tempHalfEdge->Sym;
- }
- if( reg->fixUpperEdge ) {
- if ( !FixUpperEdge( reg, eNew ) ) longjmp(tess->env,1);
- } else {
- ComputeWinding( tess, AddRegionBelow( tess, regUp, eNew ));
- }
- SweepEvent( tess, vEvent );
- } else {
- /* The new vertex is in a region which does not belong to the polygon.
- * We don''t need to connect this vertex to the rest of the mesh.
- */
- AddRightEdges( tess, regUp, vEvent->anEdge, vEvent->anEdge, NULL, TRUE );
- }
-}
-
-
-static void SweepEvent( GLUtesselator *tess, GLUvertex *vEvent )
-/*
- * Does everything necessary when the sweep line crosses a vertex.
- * Updates the mesh and the edge dictionary.
- */
-{
- ActiveRegion *regUp, *reg;
- GLUhalfEdge *e, *eTopLeft, *eBottomLeft;
-
- tess->event = vEvent; /* for access in EdgeLeq() */
- DebugEvent( tess );
-
- /* Check if this vertex is the right endpoint of an edge that is
- * already in the dictionary. In this case we don't need to waste
- * time searching for the location to insert new edges.
- */
- e = vEvent->anEdge;
- while( e->activeRegion == NULL ) {
- e = e->Onext;
- if( e == vEvent->anEdge ) {
- /* All edges go right -- not incident to any processed edges */
- ConnectLeftVertex( tess, vEvent );
- return;
- }
- }
-
- /* Processing consists of two phases: first we "finish" all the
- * active regions where both the upper and lower edges terminate
- * at vEvent (ie. vEvent is closing off these regions).
- * We mark these faces "inside" or "outside" the polygon according
- * to their winding number, and delete the edges from the dictionary.
- * This takes care of all the left-going edges from vEvent.
- */
- regUp = TopLeftRegion( e->activeRegion );
- if (regUp == NULL) longjmp(tess->env,1);
- reg = RegionBelow( regUp );
- eTopLeft = reg->eUp;
- eBottomLeft = FinishLeftRegions( tess, reg, NULL );
-
- /* Next we process all the right-going edges from vEvent. This
- * involves adding the edges to the dictionary, and creating the
- * associated "active regions" which record information about the
- * regions between adjacent dictionary edges.
- */
- if( eBottomLeft->Onext == eTopLeft ) {
- /* No right-going edges -- add a temporary "fixable" edge */
- ConnectRightVertex( tess, regUp, eBottomLeft );
- } else {
- AddRightEdges( tess, regUp, eBottomLeft->Onext, eTopLeft, eTopLeft, TRUE );
- }
-}
-
-
-/* Make the sentinel coordinates big enough that they will never be
- * merged with real input features. (Even with the largest possible
- * input contour and the maximum tolerance of 1.0, no merging will be
- * done with coordinates larger than 3 * GLU_TESS_MAX_COORD).
- */
-#define SENTINEL_COORD (4 * GLU_TESS_MAX_COORD)
-
-static void AddSentinel( GLUtesselator *tess, GLdouble t )
-/*
- * We add two sentinel edges above and below all other edges,
- * to avoid special cases at the top and bottom.
- */
-{
- GLUhalfEdge *e;
- ActiveRegion *reg = (ActiveRegion *)memAlloc( sizeof( ActiveRegion ));
- if (reg == NULL) longjmp(tess->env,1);
-
- e = __gl_meshMakeEdge( tess->mesh );
- if (e == NULL) longjmp(tess->env,1);
-
- e->Org->s = SENTINEL_COORD;
- e->Org->t = t;
- e->Dst->s = -SENTINEL_COORD;
- e->Dst->t = t;
- tess->event = e->Dst; /* initialize it */
-
- reg->eUp = e;
- reg->windingNumber = 0;
- reg->inside = FALSE;
- reg->fixUpperEdge = FALSE;
- reg->sentinel = TRUE;
- reg->dirty = FALSE;
- reg->nodeUp = dictInsert( tess->dict, reg ); /* __gl_dictListInsertBefore */
- if (reg->nodeUp == NULL) longjmp(tess->env,1);
-}
-
-
-static void InitEdgeDict( GLUtesselator *tess )
-/*
- * We maintain an ordering of edge intersections with the sweep line.
- * This order is maintained in a dynamic dictionary.
- */
-{
- /* __gl_dictListNewDict */
- tess->dict = dictNewDict( tess, (int (*)(void *, DictKey, DictKey)) EdgeLeq );
- if (tess->dict == NULL) longjmp(tess->env,1);
-
- AddSentinel( tess, -SENTINEL_COORD );
- AddSentinel( tess, SENTINEL_COORD );
-}
-
-
-static void DoneEdgeDict( GLUtesselator *tess )
-{
- ActiveRegion *reg;
-#ifndef NDEBUG
- int fixedEdges = 0;
-#endif
-
- /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
- while( (reg = (ActiveRegion *)dictKey( dictMin( tess->dict ))) != NULL ) {
- /*
- * At the end of all processing, the dictionary should contain
- * only the two sentinel edges, plus at most one "fixable" edge
- * created by ConnectRightVertex().
- */
- if( ! reg->sentinel ) {
- assert( reg->fixUpperEdge );
- assert( ++fixedEdges == 1 );
- }
- assert( reg->windingNumber == 0 );
- DeleteRegion( tess, reg );
-/* __gl_meshDelete( reg->eUp );*/
- }
- dictDeleteDict( tess->dict ); /* __gl_dictListDeleteDict */
-}
-
-
-static void RemoveDegenerateEdges( GLUtesselator *tess )
-/*
- * Remove zero-length edges, and contours with fewer than 3 vertices.
- */
-{
- GLUhalfEdge *e, *eNext, *eLnext;
- GLUhalfEdge *eHead = &tess->mesh->eHead;
-
- /*LINTED*/
- for( e = eHead->next; e != eHead; e = eNext ) {
- eNext = e->next;
- eLnext = e->Lnext;
-
- if( VertEq( e->Org, e->Dst ) && e->Lnext->Lnext != e ) {
- /* Zero-length edge, contour has at least 3 edges */
-
- SpliceMergeVertices( tess, eLnext, e ); /* deletes e->Org */
- if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1); /* e is a self-loop */
- e = eLnext;
- eLnext = e->Lnext;
- }
- if( eLnext->Lnext == e ) {
- /* Degenerate contour (one or two edges) */
-
- if( eLnext != e ) {
- if( eLnext == eNext || eLnext == eNext->Sym ) { eNext = eNext->next; }
- if ( !__gl_meshDelete( eLnext ) ) longjmp(tess->env,1);
- }
- if( e == eNext || e == eNext->Sym ) { eNext = eNext->next; }
- if ( !__gl_meshDelete( e ) ) longjmp(tess->env,1);
- }
- }
-}
-
-static int InitPriorityQ( GLUtesselator *tess )
-/*
- * Insert all vertices into the priority queue which determines the
- * order in which vertices cross the sweep line.
- */
-{
- PriorityQ *pq;
- GLUvertex *v, *vHead;
-
- /* __gl_pqSortNewPriorityQ */
- pq = tess->pq = pqNewPriorityQ( (int (*)(PQkey, PQkey)) __gl_vertLeq );
- if (pq == NULL) return 0;
-
- vHead = &tess->mesh->vHead;
- for( v = vHead->next; v != vHead; v = v->next ) {
- v->pqHandle = pqInsert( pq, v ); /* __gl_pqSortInsert */
- if (v->pqHandle == LONG_MAX) break;
- }
- if (v != vHead || !pqInit( pq ) ) { /* __gl_pqSortInit */
- pqDeletePriorityQ(tess->pq); /* __gl_pqSortDeletePriorityQ */
- tess->pq = NULL;
- return 0;
- }
-
- return 1;
-}
-
-
-static void DonePriorityQ( GLUtesselator *tess )
-{
- pqDeletePriorityQ( tess->pq ); /* __gl_pqSortDeletePriorityQ */
-}
-
-
-static int RemoveDegenerateFaces( GLUmesh *mesh )
-/*
- * Delete any degenerate faces with only two edges. WalkDirtyRegions()
- * will catch almost all of these, but it won't catch degenerate faces
- * produced by splice operations on already-processed edges.
- * The two places this can happen are in FinishLeftRegions(), when
- * we splice in a "temporary" edge produced by ConnectRightVertex(),
- * and in CheckForLeftSplice(), where we splice already-processed
- * edges to ensure that our dictionary invariants are not violated
- * by numerical errors.
- *
- * In both these cases it is *very* dangerous to delete the offending
- * edge at the time, since one of the routines further up the stack
- * will sometimes be keeping a pointer to that edge.
- */
-{
- GLUface *f, *fNext;
- GLUhalfEdge *e;
-
- /*LINTED*/
- for( f = mesh->fHead.next; f != &mesh->fHead; f = fNext ) {
- fNext = f->next;
- e = f->anEdge;
- assert( e->Lnext != e );
-
- if( e->Lnext->Lnext == e ) {
- /* A face with only two edges */
- AddWinding( e->Onext, e );
- if ( !__gl_meshDelete( e ) ) return 0;
- }
- }
- return 1;
-}
-
-int __gl_computeInterior( GLUtesselator *tess )
-/*
- * __gl_computeInterior( tess ) computes the planar arrangement specified
- * by the given contours, and further subdivides this arrangement
- * into regions. Each region is marked "inside" if it belongs
- * to the polygon, according to the rule given by tess->windingRule.
- * Each interior region is guaranteed be monotone.
- */
-{
- GLUvertex *v, *vNext;
-
- tess->fatalError = FALSE;
-
- /* Each vertex defines an event for our sweep line. Start by inserting
- * all the vertices in a priority queue. Events are processed in
- * lexicographic order, ie.
- *
- * e1 < e2 iff e1.x < e2.x || (e1.x == e2.x && e1.y < e2.y)
- */
- RemoveDegenerateEdges( tess );
- if ( !InitPriorityQ( tess ) ) return 0; /* if error */
- InitEdgeDict( tess );
-
- /* __gl_pqSortExtractMin */
- while( (v = (GLUvertex *)pqExtractMin( tess->pq )) != NULL ) {
- for( ;; ) {
- vNext = (GLUvertex *)pqMinimum( tess->pq ); /* __gl_pqSortMinimum */
- if( vNext == NULL || ! VertEq( vNext, v )) break;
-
- /* Merge together all vertices at exactly the same location.
- * This is more efficient than processing them one at a time,
- * simplifies the code (see ConnectLeftDegenerate), and is also
- * important for correct handling of certain degenerate cases.
- * For example, suppose there are two identical edges A and B
- * that belong to different contours (so without this code they would
- * be processed by separate sweep events). Suppose another edge C
- * crosses A and B from above. When A is processed, we split it
- * at its intersection point with C. However this also splits C,
- * so when we insert B we may compute a slightly different
- * intersection point. This might leave two edges with a small
- * gap between them. This kind of error is especially obvious
- * when using boundary extraction (GLU_TESS_BOUNDARY_ONLY).
- */
- vNext = (GLUvertex *)pqExtractMin( tess->pq ); /* __gl_pqSortExtractMin*/
- SpliceMergeVertices( tess, v->anEdge, vNext->anEdge );
- }
- SweepEvent( tess, v );
- }
-
- /* Set tess->event for debugging purposes */
- /* __GL_DICTLISTKEY */ /* __GL_DICTLISTMIN */
- tess->event = ((ActiveRegion *) dictKey( dictMin( tess->dict )))->eUp->Org;
- DebugEvent( tess );
- DoneEdgeDict( tess );
- DonePriorityQ( tess );
-
- if ( !RemoveDegenerateFaces( tess->mesh ) ) return 0;
- __gl_meshCheckMesh( tess->mesh );
-
- return 1;
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __sweep_h_
-#define __sweep_h_
-
-#include "mesh.h"
-
-/* __gl_computeInterior( tess ) computes the planar arrangement specified
- * by the given contours, and further subdivides this arrangement
- * into regions. Each region is marked "inside" if it belongs
- * to the polygon, according to the rule given by tess->windingRule.
- * Each interior region is guaranteed be monotone.
- */
-int __gl_computeInterior( GLUtesselator *tess );
-
-
-/* The following is here *only* for access by debugging routines */
-
-#include "dict.h"
-
-/* For each pair of adjacent edges crossing the sweep line, there is
- * an ActiveRegion to represent the region between them. The active
- * regions are kept in sorted order in a dynamic dictionary. As the
- * sweep line crosses each vertex, we update the affected regions.
- */
-
-struct ActiveRegion {
- GLUhalfEdge *eUp; /* upper edge, directed right to left */
- DictNode *nodeUp; /* dictionary node corresponding to eUp */
- int windingNumber; /* used to determine which regions are
- * inside the polygon */
- GLboolean inside; /* is this region inside the polygon? */
- GLboolean sentinel; /* marks fake edges at t = +/-infinity */
- GLboolean dirty; /* marks regions where the upper or lower
- * edge has changed, but we haven't checked
- * whether they intersect yet */
- GLboolean fixUpperEdge; /* marks temporary edges introduced when
- * we process a "right vertex" (one without
- * any edges leaving to the right) */
-};
-
-#define RegionBelow(r) ((ActiveRegion *) dictKey(dictPred((r)->nodeUp)))
-#define RegionAbove(r) ((ActiveRegion *) dictKey(dictSucc((r)->nodeUp)))
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <stddef.h>
-#include <assert.h>
-#include <setjmp.h>
-#include "memalloc.h"
-#include "tess.h"
-#include "mesh.h"
-#include "normal.h"
-#include "sweep.h"
-#include "tessmono.h"
-#include "render.h"
-
-#define GLU_TESS_DEFAULT_TOLERANCE 0.0
-#define GLU_TESS_MESH 100112 /* void (*)(GLUmesh *mesh) */
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/*ARGSUSED*/ static void GLAPIENTRY noBegin( GLenum type ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noEdgeFlag( GLboolean boundaryEdge ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noVertex( void *data ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noEnd( void ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noError( GLenum errnum ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noCombine( GLdouble coords[3], void *data[4],
- GLfloat weight[4], void **dataOut ) {}
-/*ARGSUSED*/ static void GLAPIENTRY noMesh( GLUmesh *mesh ) {}
-
-
-/*ARGSUSED*/ void GLAPIENTRY __gl_noBeginData( GLenum type,
- void *polygonData ) {}
-/*ARGSUSED*/ void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge,
- void *polygonData ) {}
-/*ARGSUSED*/ void GLAPIENTRY __gl_noVertexData( void *data,
- void *polygonData ) {}
-/*ARGSUSED*/ void GLAPIENTRY __gl_noEndData( void *polygonData ) {}
-/*ARGSUSED*/ void GLAPIENTRY __gl_noErrorData( GLenum errnum,
- void *polygonData ) {}
-/*ARGSUSED*/ void GLAPIENTRY __gl_noCombineData( GLdouble coords[3],
- void *data[4],
- GLfloat weight[4],
- void **outData,
- void *polygonData ) {}
-
-/* Half-edges are allocated in pairs (see mesh.c) */
-typedef struct { GLUhalfEdge e, eSym; } EdgePair;
-
-#undef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define MAX_FAST_ALLOC (MAX(sizeof(EdgePair), \
- MAX(sizeof(GLUvertex),sizeof(GLUface))))
-
-
-GLUtesselator * GLAPIENTRY
-gluNewTess( void )
-{
- GLUtesselator *tess;
-
- /* Only initialize fields which can be changed by the api. Other fields
- * are initialized where they are used.
- */
-
- if (memInit( MAX_FAST_ALLOC ) == 0) {
- return 0; /* out of memory */
- }
- tess = (GLUtesselator *)memAlloc( sizeof( GLUtesselator ));
- if (tess == NULL) {
- return 0; /* out of memory */
- }
-
- tess->state = T_DORMANT;
-
- tess->normal[0] = 0;
- tess->normal[1] = 0;
- tess->normal[2] = 0;
-
- tess->relTolerance = GLU_TESS_DEFAULT_TOLERANCE;
- tess->windingRule = GLU_TESS_WINDING_ODD;
- tess->flagBoundary = FALSE;
- tess->boundaryOnly = FALSE;
-
- tess->callBegin = &noBegin;
- tess->callEdgeFlag = &noEdgeFlag;
- tess->callVertex = &noVertex;
- tess->callEnd = &noEnd;
-
- tess->callError = &noError;
- tess->callCombine = &noCombine;
- tess->callMesh = &noMesh;
-
- tess->callBeginData= &__gl_noBeginData;
- tess->callEdgeFlagData= &__gl_noEdgeFlagData;
- tess->callVertexData= &__gl_noVertexData;
- tess->callEndData= &__gl_noEndData;
- tess->callErrorData= &__gl_noErrorData;
- tess->callCombineData= &__gl_noCombineData;
-
- tess->polygonData= NULL;
-
- return tess;
-}
-
-static void MakeDormant( GLUtesselator *tess )
-{
- /* Return the tessellator to its original dormant state. */
-
- if( tess->mesh != NULL ) {
- __gl_meshDeleteMesh( tess->mesh );
- }
- tess->state = T_DORMANT;
- tess->lastEdge = NULL;
- tess->mesh = NULL;
-}
-
-#define RequireState( tess, s ) if( tess->state != s ) GotoState(tess,s)
-
-static void GotoState( GLUtesselator *tess, enum TessState newState )
-{
- while( tess->state != newState ) {
- /* We change the current state one level at a time, to get to
- * the desired state.
- */
- if( tess->state < newState ) {
- switch( tess->state ) {
- case T_DORMANT:
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_POLYGON );
- gluTessBeginPolygon( tess, NULL );
- break;
- case T_IN_POLYGON:
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_BEGIN_CONTOUR );
- gluTessBeginContour( tess );
- break;
- default:
- ;
- }
- } else {
- switch( tess->state ) {
- case T_IN_CONTOUR:
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_CONTOUR );
- gluTessEndContour( tess );
- break;
- case T_IN_POLYGON:
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_MISSING_END_POLYGON );
- /* gluTessEndPolygon( tess ) is too much work! */
- MakeDormant( tess );
- break;
- default:
- ;
- }
- }
- }
-}
-
-
-void GLAPIENTRY
-gluDeleteTess( GLUtesselator *tess )
-{
- RequireState( tess, T_DORMANT );
- memFree( tess );
-}
-
-
-void GLAPIENTRY
-gluTessProperty( GLUtesselator *tess, GLenum which, GLdouble value )
-{
- GLenum windingRule;
-
- switch( which ) {
- case GLU_TESS_TOLERANCE:
- if( value < 0.0 || value > 1.0 ) break;
- tess->relTolerance = value;
- return;
-
- case GLU_TESS_WINDING_RULE:
- windingRule = (GLenum) value;
- if( windingRule != value ) break; /* not an integer */
-
- switch( windingRule ) {
- case GLU_TESS_WINDING_ODD:
- case GLU_TESS_WINDING_NONZERO:
- case GLU_TESS_WINDING_POSITIVE:
- case GLU_TESS_WINDING_NEGATIVE:
- case GLU_TESS_WINDING_ABS_GEQ_TWO:
- tess->windingRule = windingRule;
- return;
- default:
- break;
- }
-
- case GLU_TESS_BOUNDARY_ONLY:
- tess->boundaryOnly = (value != 0);
- return;
-
- default:
- CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
- return;
- }
- CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_VALUE );
-}
-
-/* Returns tessellator property */
-void GLAPIENTRY
-gluGetTessProperty( GLUtesselator *tess, GLenum which, GLdouble *value )
-{
- switch (which) {
- case GLU_TESS_TOLERANCE:
- /* tolerance should be in range [0..1] */
- assert(0.0 <= tess->relTolerance && tess->relTolerance <= 1.0);
- *value= tess->relTolerance;
- break;
- case GLU_TESS_WINDING_RULE:
- assert(tess->windingRule == GLU_TESS_WINDING_ODD ||
- tess->windingRule == GLU_TESS_WINDING_NONZERO ||
- tess->windingRule == GLU_TESS_WINDING_POSITIVE ||
- tess->windingRule == GLU_TESS_WINDING_NEGATIVE ||
- tess->windingRule == GLU_TESS_WINDING_ABS_GEQ_TWO);
- *value= tess->windingRule;
- break;
- case GLU_TESS_BOUNDARY_ONLY:
- assert(tess->boundaryOnly == TRUE || tess->boundaryOnly == FALSE);
- *value= tess->boundaryOnly;
- break;
- default:
- *value= 0.0;
- CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
- break;
- }
-} /* gluGetTessProperty() */
-
-void GLAPIENTRY
-gluTessNormal( GLUtesselator *tess, GLdouble x, GLdouble y, GLdouble z )
-{
- tess->normal[0] = x;
- tess->normal[1] = y;
- tess->normal[2] = z;
-}
-
-void GLAPIENTRY
-gluTessCallback( GLUtesselator *tess, GLenum which, _GLUfuncptr fn)
-{
- switch( which ) {
- case GLU_TESS_BEGIN:
- tess->callBegin = (fn == NULL) ? &noBegin : (void (GLAPIENTRY *)(GLenum)) fn;
- return;
- case GLU_TESS_BEGIN_DATA:
- tess->callBeginData = (fn == NULL) ?
- &__gl_noBeginData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
- return;
- case GLU_TESS_EDGE_FLAG:
- tess->callEdgeFlag = (fn == NULL) ? &noEdgeFlag :
- (void (GLAPIENTRY *)(GLboolean)) fn;
- /* If the client wants boundary edges to be flagged,
- * we render everything as separate triangles (no strips or fans).
- */
- tess->flagBoundary = (fn != NULL);
- return;
- case GLU_TESS_EDGE_FLAG_DATA:
- tess->callEdgeFlagData= (fn == NULL) ?
- &__gl_noEdgeFlagData : (void (GLAPIENTRY *)(GLboolean, void *)) fn;
- /* If the client wants boundary edges to be flagged,
- * we render everything as separate triangles (no strips or fans).
- */
- tess->flagBoundary = (fn != NULL);
- return;
- case GLU_TESS_VERTEX:
- tess->callVertex = (fn == NULL) ? &noVertex :
- (void (GLAPIENTRY *)(void *)) fn;
- return;
- case GLU_TESS_VERTEX_DATA:
- tess->callVertexData = (fn == NULL) ?
- &__gl_noVertexData : (void (GLAPIENTRY *)(void *, void *)) fn;
- return;
- case GLU_TESS_END:
- tess->callEnd = (fn == NULL) ? &noEnd : (void (GLAPIENTRY *)(void)) fn;
- return;
- case GLU_TESS_END_DATA:
- tess->callEndData = (fn == NULL) ? &__gl_noEndData :
- (void (GLAPIENTRY *)(void *)) fn;
- return;
- case GLU_TESS_ERROR:
- tess->callError = (fn == NULL) ? &noError : (void (GLAPIENTRY *)(GLenum)) fn;
- return;
- case GLU_TESS_ERROR_DATA:
- tess->callErrorData = (fn == NULL) ?
- &__gl_noErrorData : (void (GLAPIENTRY *)(GLenum, void *)) fn;
- return;
- case GLU_TESS_COMBINE:
- tess->callCombine = (fn == NULL) ? &noCombine :
- (void (GLAPIENTRY *)(GLdouble [3],void *[4], GLfloat [4], void ** )) fn;
- return;
- case GLU_TESS_COMBINE_DATA:
- tess->callCombineData = (fn == NULL) ? &__gl_noCombineData :
- (void (GLAPIENTRY *)(GLdouble [3],
- void *[4],
- GLfloat [4],
- void **,
- void *)) fn;
- return;
- case GLU_TESS_MESH:
- tess->callMesh = (fn == NULL) ? &noMesh : (void (GLAPIENTRY *)(GLUmesh *)) fn;
- return;
- default:
- CALL_ERROR_OR_ERROR_DATA( GLU_INVALID_ENUM );
- return;
- }
-}
-
-static int AddVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
-{
- GLUhalfEdge *e;
-
- e = tess->lastEdge;
- if( e == NULL ) {
- /* Make a self-loop (one vertex, one edge). */
-
- e = __gl_meshMakeEdge( tess->mesh );
- if (e == NULL) return 0;
- if ( !__gl_meshSplice( e, e->Sym ) ) return 0;
- } else {
- /* Create a new vertex and edge which immediately follow e
- * in the ordering around the left face.
- */
- if (__gl_meshSplitEdge( e ) == NULL) return 0;
- e = e->Lnext;
- }
-
- /* The new vertex is now e->Org. */
- e->Org->data = data;
- e->Org->coords[0] = coords[0];
- e->Org->coords[1] = coords[1];
- e->Org->coords[2] = coords[2];
-
- /* The winding of an edge says how the winding number changes as we
- * cross from the edge''s right face to its left face. We add the
- * vertices in such an order that a CCW contour will add +1 to
- * the winding number of the region inside the contour.
- */
- e->winding = 1;
- e->Sym->winding = -1;
-
- tess->lastEdge = e;
-
- return 1;
-}
-
-
-static void CacheVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
-{
- CachedVertex *v = &tess->cache[tess->cacheCount];
-
- v->data = data;
- v->coords[0] = coords[0];
- v->coords[1] = coords[1];
- v->coords[2] = coords[2];
- ++tess->cacheCount;
-}
-
-
-static int EmptyCache( GLUtesselator *tess )
-{
- CachedVertex *v = tess->cache;
- CachedVertex *vLast;
-
- tess->mesh = __gl_meshNewMesh();
- if (tess->mesh == NULL) return 0;
-
- for( vLast = v + tess->cacheCount; v < vLast; ++v ) {
- if ( !AddVertex( tess, v->coords, v->data ) ) return 0;
- }
- tess->cacheCount = 0;
- tess->emptyCache = FALSE;
-
- return 1;
-}
-
-
-void GLAPIENTRY
-gluTessVertex( GLUtesselator *tess, GLdouble coords[3], void *data )
-{
- int i, tooLarge = FALSE;
- GLdouble x, clamped[3];
-
- RequireState( tess, T_IN_CONTOUR );
-
- if( tess->emptyCache ) {
- if ( !EmptyCache( tess ) ) {
- CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
- return;
- }
- tess->lastEdge = NULL;
- }
- for( i = 0; i < 3; ++i ) {
- x = coords[i];
- if( x < - GLU_TESS_MAX_COORD ) {
- x = - GLU_TESS_MAX_COORD;
- tooLarge = TRUE;
- }
- if( x > GLU_TESS_MAX_COORD ) {
- x = GLU_TESS_MAX_COORD;
- tooLarge = TRUE;
- }
- clamped[i] = x;
- }
- if( tooLarge ) {
- CALL_ERROR_OR_ERROR_DATA( GLU_TESS_COORD_TOO_LARGE );
- }
-
- if( tess->mesh == NULL ) {
- if( tess->cacheCount < TESS_MAX_CACHE ) {
- CacheVertex( tess, clamped, data );
- return;
- }
- if ( !EmptyCache( tess ) ) {
- CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
- return;
- }
- }
- if ( !AddVertex( tess, clamped, data ) ) {
- CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
- }
-}
-
-
-void GLAPIENTRY
-gluTessBeginPolygon( GLUtesselator *tess, void *data )
-{
- RequireState( tess, T_DORMANT );
-
- tess->state = T_IN_POLYGON;
- tess->cacheCount = 0;
- tess->emptyCache = FALSE;
- tess->mesh = NULL;
-
- tess->polygonData= data;
-}
-
-
-void GLAPIENTRY
-gluTessBeginContour( GLUtesselator *tess )
-{
- RequireState( tess, T_IN_POLYGON );
-
- tess->state = T_IN_CONTOUR;
- tess->lastEdge = NULL;
- if( tess->cacheCount > 0 ) {
- /* Just set a flag so we don't get confused by empty contours
- * -- these can be generated accidentally with the obsolete
- * NextContour() interface.
- */
- tess->emptyCache = TRUE;
- }
-}
-
-
-void GLAPIENTRY
-gluTessEndContour( GLUtesselator *tess )
-{
- RequireState( tess, T_IN_CONTOUR );
- tess->state = T_IN_POLYGON;
-}
-
-void GLAPIENTRY
-gluTessEndPolygon( GLUtesselator *tess )
-{
- GLUmesh *mesh;
-
- if (setjmp(tess->env) != 0) {
- /* come back here if out of memory */
- CALL_ERROR_OR_ERROR_DATA( GLU_OUT_OF_MEMORY );
- return;
- }
-
- RequireState( tess, T_IN_POLYGON );
- tess->state = T_DORMANT;
-
- if( tess->mesh == NULL ) {
- if( ! tess->flagBoundary && tess->callMesh == &noMesh ) {
-
- /* Try some special code to make the easy cases go quickly
- * (eg. convex polygons). This code does NOT handle multiple contours,
- * intersections, edge flags, and of course it does not generate
- * an explicit mesh either.
- */
- if( __gl_renderCache( tess )) {
- tess->polygonData= NULL;
- return;
- }
- }
- if ( !EmptyCache( tess ) ) longjmp(tess->env,1); /* could've used a label*/
- }
-
- /* Determine the polygon normal and project vertices onto the plane
- * of the polygon.
- */
- __gl_projectPolygon( tess );
-
- /* __gl_computeInterior( tess ) computes the planar arrangement specified
- * by the given contours, and further subdivides this arrangement
- * into regions. Each region is marked "inside" if it belongs
- * to the polygon, according to the rule given by tess->windingRule.
- * Each interior region is guaranteed be monotone.
- */
- if ( !__gl_computeInterior( tess ) ) {
- longjmp(tess->env,1); /* could've used a label */
- }
-
- mesh = tess->mesh;
- if( ! tess->fatalError ) {
- int rc = 1;
-
- /* If the user wants only the boundary contours, we throw away all edges
- * except those which separate the interior from the exterior.
- * Otherwise we tessellate all the regions marked "inside".
- */
- if( tess->boundaryOnly ) {
- rc = __gl_meshSetWindingNumber( mesh, 1, TRUE );
- } else {
- rc = __gl_meshTessellateInterior( mesh );
- }
- if (rc == 0) longjmp(tess->env,1); /* could've used a label */
-
- __gl_meshCheckMesh( mesh );
-
- if( tess->callBegin != &noBegin || tess->callEnd != &noEnd
- || tess->callVertex != &noVertex || tess->callEdgeFlag != &noEdgeFlag
- || tess->callBeginData != &__gl_noBeginData
- || tess->callEndData != &__gl_noEndData
- || tess->callVertexData != &__gl_noVertexData
- || tess->callEdgeFlagData != &__gl_noEdgeFlagData )
- {
- if( tess->boundaryOnly ) {
- __gl_renderBoundary( tess, mesh ); /* output boundary contours */
- } else {
- __gl_renderMesh( tess, mesh ); /* output strips and fans */
- }
- }
- if( tess->callMesh != &noMesh ) {
-
- /* Throw away the exterior faces, so that all faces are interior.
- * This way the user doesn't have to check the "inside" flag,
- * and we don't need to even reveal its existence. It also leaves
- * the freedom for an implementation to not generate the exterior
- * faces in the first place.
- */
- __gl_meshDiscardExterior( mesh );
- (*tess->callMesh)( mesh ); /* user wants the mesh itself */
- tess->mesh = NULL;
- tess->polygonData= NULL;
- return;
- }
- }
- __gl_meshDeleteMesh( mesh );
- tess->polygonData= NULL;
- tess->mesh = NULL;
-}
-
-
-/*XXXblythe unused function*/
-#if 0
-void GLAPIENTRY
-gluDeleteMesh( GLUmesh *mesh )
-{
- __gl_meshDeleteMesh( mesh );
-}
-#endif
-
-
-
-/*******************************************************/
-
-/* Obsolete calls -- for backward compatibility */
-
-void GLAPIENTRY
-gluBeginPolygon( GLUtesselator *tess )
-{
- gluTessBeginPolygon( tess, NULL );
- gluTessBeginContour( tess );
-}
-
-
-/*ARGSUSED*/
-void GLAPIENTRY
-gluNextContour( GLUtesselator *tess, GLenum type )
-{
- gluTessEndContour( tess );
- gluTessBeginContour( tess );
-}
-
-
-void GLAPIENTRY
-gluEndPolygon( GLUtesselator *tess )
-{
- gluTessEndContour( tess );
- gluTessEndPolygon( tess );
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __tess_h_
-#define __tess_h_
-
-#include <GL/glu.h>
-#include <setjmp.h>
-#include "mesh.h"
-#include "dict.h"
-#include "priorityq.h"
-
-/* The begin/end calls must be properly nested. We keep track of
- * the current state to enforce the ordering.
- */
-enum TessState { T_DORMANT, T_IN_POLYGON, T_IN_CONTOUR };
-
-/* We cache vertex data for single-contour polygons so that we can
- * try a quick-and-dirty decomposition first.
- */
-#define TESS_MAX_CACHE 100
-
-typedef struct CachedVertex {
- GLdouble coords[3];
- void *data;
-} CachedVertex;
-
-struct GLUtesselator {
-
- /*** state needed for collecting the input data ***/
-
- enum TessState state; /* what begin/end calls have we seen? */
-
- GLUhalfEdge *lastEdge; /* lastEdge->Org is the most recent vertex */
- GLUmesh *mesh; /* stores the input contours, and eventually
- the tessellation itself */
-
- void (GLAPIENTRY *callError)( GLenum errnum );
-
- /*** state needed for projecting onto the sweep plane ***/
-
- GLdouble normal[3]; /* user-specified normal (if provided) */
- GLdouble sUnit[3]; /* unit vector in s-direction (debugging) */
- GLdouble tUnit[3]; /* unit vector in t-direction (debugging) */
-
- /*** state needed for the line sweep ***/
-
- GLdouble relTolerance; /* tolerance for merging features */
- GLenum windingRule; /* rule for determining polygon interior */
- GLboolean fatalError; /* fatal error: needed combine callback */
-
- Dict *dict; /* edge dictionary for sweep line */
- PriorityQ *pq; /* priority queue of vertex events */
- GLUvertex *event; /* current sweep event being processed */
-
- void (GLAPIENTRY *callCombine)( GLdouble coords[3], void *data[4],
- GLfloat weight[4], void **outData );
-
- /*** state needed for rendering callbacks (see render.c) ***/
-
- GLboolean flagBoundary; /* mark boundary edges (use EdgeFlag) */
- GLboolean boundaryOnly; /* Extract contours, not triangles */
- GLUface *lonelyTriList;
- /* list of triangles which could not be rendered as strips or fans */
-
- void (GLAPIENTRY *callBegin)( GLenum type );
- void (GLAPIENTRY *callEdgeFlag)( GLboolean boundaryEdge );
- void (GLAPIENTRY *callVertex)( void *data );
- void (GLAPIENTRY *callEnd)( void );
- void (GLAPIENTRY *callMesh)( GLUmesh *mesh );
-
-
- /*** state needed to cache single-contour polygons for renderCache() */
-
- GLboolean emptyCache; /* empty cache on next vertex() call */
- int cacheCount; /* number of cached vertices */
- CachedVertex cache[TESS_MAX_CACHE]; /* the vertex data */
-
- /*** rendering callbacks that also pass polygon data ***/
- void (GLAPIENTRY *callBeginData)( GLenum type, void *polygonData );
- void (GLAPIENTRY *callEdgeFlagData)( GLboolean boundaryEdge,
- void *polygonData );
- void (GLAPIENTRY *callVertexData)( void *data, void *polygonData );
- void (GLAPIENTRY *callEndData)( void *polygonData );
- void (GLAPIENTRY *callErrorData)( GLenum errnum, void *polygonData );
- void (GLAPIENTRY *callCombineData)( GLdouble coords[3], void *data[4],
- GLfloat weight[4], void **outData,
- void *polygonData );
-
- jmp_buf env; /* place to jump to when memAllocs fail */
-
- void *polygonData; /* client data for current polygon */
-};
-
-void GLAPIENTRY __gl_noBeginData( GLenum type, void *polygonData );
-void GLAPIENTRY __gl_noEdgeFlagData( GLboolean boundaryEdge, void *polygonData );
-void GLAPIENTRY __gl_noVertexData( void *data, void *polygonData );
-void GLAPIENTRY __gl_noEndData( void *polygonData );
-void GLAPIENTRY __gl_noErrorData( GLenum errnum, void *polygonData );
-void GLAPIENTRY __gl_noCombineData( GLdouble coords[3], void *data[4],
- GLfloat weight[4], void **outData,
- void *polygonData );
-
-#define CALL_BEGIN_OR_BEGIN_DATA(a) \
- if (tess->callBeginData != &__gl_noBeginData) \
- (*tess->callBeginData)((a),tess->polygonData); \
- else (*tess->callBegin)((a));
-
-#define CALL_VERTEX_OR_VERTEX_DATA(a) \
- if (tess->callVertexData != &__gl_noVertexData) \
- (*tess->callVertexData)((a),tess->polygonData); \
- else (*tess->callVertex)((a));
-
-#define CALL_EDGE_FLAG_OR_EDGE_FLAG_DATA(a) \
- if (tess->callEdgeFlagData != &__gl_noEdgeFlagData) \
- (*tess->callEdgeFlagData)((a),tess->polygonData); \
- else (*tess->callEdgeFlag)((a));
-
-#define CALL_END_OR_END_DATA() \
- if (tess->callEndData != &__gl_noEndData) \
- (*tess->callEndData)(tess->polygonData); \
- else (*tess->callEnd)();
-
-#define CALL_COMBINE_OR_COMBINE_DATA(a,b,c,d) \
- if (tess->callCombineData != &__gl_noCombineData) \
- (*tess->callCombineData)((a),(b),(c),(d),tess->polygonData); \
- else (*tess->callCombine)((a),(b),(c),(d));
-
-#define CALL_ERROR_OR_ERROR_DATA(a) \
- if (tess->callErrorData != &__gl_noErrorData) \
- (*tess->callErrorData)((a),tess->polygonData); \
- else (*tess->callError)((a));
-
-#endif
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- * Copyright (C) 2010 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifndef __TESSELATOR_H__
-#define __TESSELATOR_H__
-
-/* This just includes the defines needed by the tesselator code */
-
-#include "cogl/cogl-defines.h"
-
-typedef struct GLUtesselator GLUtesselator;
-
-#define GLU_TESS_MAX_COORD 1.0e150
-
-void gluBeginPolygon (GLUtesselator* tess);
-void gluDeleteTess (GLUtesselator* tess);
-void gluEndPolygon (GLUtesselator* tess);
-
-typedef void (_GLUfuncptr)();
-
-void gluGetTessProperty (GLUtesselator* tess, GLenum which, double* data);
-
-GLUtesselator *gluNewTess (void);
-void gluNextContour (GLUtesselator* tess, GLenum type);
-
-void gluTessBeginContour (GLUtesselator* tess);
-void gluTessBeginPolygon (GLUtesselator* tess, GLvoid* data);
-void gluTessCallback (GLUtesselator* tess, GLenum which, _GLUfuncptr CallBackFunc);
-void gluTessEndContour (GLUtesselator* tess);
-void gluTessEndPolygon (GLUtesselator* tess);
-void gluTessNormal (GLUtesselator* tess, double valueX, double valueY, double valueZ);
-void gluTessProperty (GLUtesselator* tess, GLenum which, double data);
-void gluTessVertex (GLUtesselator* tess, double *location, GLvoid* data);
-
-/* ErrorCode */
-#define GLU_INVALID_ENUM 100900
-#define GLU_INVALID_VALUE 100901
-#define GLU_OUT_OF_MEMORY 100902
-
-/* TessCallback */
-#define GLU_TESS_BEGIN 100100
-#define GLU_BEGIN 100100
-#define GLU_TESS_VERTEX 100101
-#define GLU_VERTEX 100101
-#define GLU_TESS_END 100102
-#define GLU_END 100102
-#define GLU_TESS_ERROR 100103
-#define GLU_TESS_EDGE_FLAG 100104
-#define GLU_EDGE_FLAG 100104
-#define GLU_TESS_COMBINE 100105
-#define GLU_TESS_BEGIN_DATA 100106
-#define GLU_TESS_VERTEX_DATA 100107
-#define GLU_TESS_END_DATA 100108
-#define GLU_TESS_ERROR_DATA 100109
-#define GLU_TESS_EDGE_FLAG_DATA 100110
-#define GLU_TESS_COMBINE_DATA 100111
-
-/* TessContour */
-#define GLU_CW 100120
-#define GLU_CCW 100121
-#define GLU_INTERIOR 100122
-#define GLU_EXTERIOR 100123
-#define GLU_UNKNOWN 100124
-
-/* TessProperty */
-#define GLU_TESS_WINDING_RULE 100140
-#define GLU_TESS_BOUNDARY_ONLY 100141
-#define GLU_TESS_TOLERANCE 100142
-
-/* TessError */
-#define GLU_TESS_ERROR1 100151
-#define GLU_TESS_ERROR2 100152
-#define GLU_TESS_ERROR3 100153
-#define GLU_TESS_ERROR4 100154
-#define GLU_TESS_ERROR5 100155
-#define GLU_TESS_ERROR6 100156
-#define GLU_TESS_ERROR7 100157
-#define GLU_TESS_ERROR8 100158
-#define GLU_TESS_MISSING_BEGIN_POLYGON 100151
-#define GLU_TESS_MISSING_BEGIN_CONTOUR 100152
-#define GLU_TESS_MISSING_END_POLYGON 100153
-#define GLU_TESS_MISSING_END_CONTOUR 100154
-#define GLU_TESS_COORD_TOO_LARGE 100155
-#define GLU_TESS_NEED_COMBINE_CALLBACK 100156
-
-/* TessWinding */
-#define GLU_TESS_WINDING_ODD 100130
-#define GLU_TESS_WINDING_NONZERO 100131
-#define GLU_TESS_WINDING_POSITIVE 100132
-#define GLU_TESS_WINDING_NEGATIVE 100133
-#define GLU_TESS_WINDING_ABS_GEQ_TWO 100134
-
-#endif /* __TESSELATOR_H__ */
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#include "gluos.h"
-#include <stdlib.h>
-#include "geom.h"
-#include "mesh.h"
-#include "tessmono.h"
-#include <assert.h>
-
-#define AddWinding(eDst,eSrc) (eDst->winding += eSrc->winding, \
- eDst->Sym->winding += eSrc->Sym->winding)
-
-/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
- * (what else would it do??) The region must consist of a single
- * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
- * case means that any vertical line intersects the interior of the
- * region in a single interval.
- *
- * Tessellation consists of adding interior edges (actually pairs of
- * half-edges), to split the region into non-overlapping triangles.
- *
- * The basic idea is explained in Preparata and Shamos (which I don''t
- * have handy right now), although their implementation is more
- * complicated than this one. The are two edge chains, an upper chain
- * and a lower chain. We process all vertices from both chains in order,
- * from right to left.
- *
- * The algorithm ensures that the following invariant holds after each
- * vertex is processed: the untessellated region consists of two
- * chains, where one chain (say the upper) is a single edge, and
- * the other chain is concave. The left vertex of the single edge
- * is always to the left of all vertices in the concave chain.
- *
- * Each step consists of adding the rightmost unprocessed vertex to one
- * of the two chains, and forming a fan of triangles from the rightmost
- * of two chain endpoints. Determining whether we can add each triangle
- * to the fan is a simple orientation test. By making the fan as large
- * as possible, we restore the invariant (check it yourself).
- */
-int __gl_meshTessellateMonoRegion( GLUface *face )
-{
- GLUhalfEdge *up, *lo;
-
- /* All edges are oriented CCW around the boundary of the region.
- * First, find the half-edge whose origin vertex is rightmost.
- * Since the sweep goes from left to right, face->anEdge should
- * be close to the edge we want.
- */
- up = face->anEdge;
- assert( up->Lnext != up && up->Lnext->Lnext != up );
-
- for( ; VertLeq( up->Dst, up->Org ); up = up->Lprev )
- ;
- for( ; VertLeq( up->Org, up->Dst ); up = up->Lnext )
- ;
- lo = up->Lprev;
-
- while( up->Lnext != lo ) {
- if( VertLeq( up->Dst, lo->Org )) {
- /* up->Dst is on the left. It is safe to form triangles from lo->Org.
- * The EdgeGoesLeft test guarantees progress even when some triangles
- * are CW, given that the upper and lower chains are truly monotone.
- */
- while( lo->Lnext != up && (EdgeGoesLeft( lo->Lnext )
- || EdgeSign( lo->Org, lo->Dst, lo->Lnext->Dst ) <= 0 )) {
- GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
- if (tempHalfEdge == NULL) return 0;
- lo = tempHalfEdge->Sym;
- }
- lo = lo->Lprev;
- } else {
- /* lo->Org is on the left. We can make CCW triangles from up->Dst. */
- while( lo->Lnext != up && (EdgeGoesRight( up->Lprev )
- || EdgeSign( up->Dst, up->Org, up->Lprev->Org ) >= 0 )) {
- GLUhalfEdge *tempHalfEdge= __gl_meshConnect( up, up->Lprev );
- if (tempHalfEdge == NULL) return 0;
- up = tempHalfEdge->Sym;
- }
- up = up->Lnext;
- }
- }
-
- /* Now lo->Org == up->Dst == the leftmost vertex. The remaining region
- * can be tessellated in a fan from this leftmost vertex.
- */
- assert( lo->Lnext != up );
- while( lo->Lnext->Lnext != up ) {
- GLUhalfEdge *tempHalfEdge= __gl_meshConnect( lo->Lnext, lo );
- if (tempHalfEdge == NULL) return 0;
- lo = tempHalfEdge->Sym;
- }
-
- return 1;
-}
-
-
-/* __gl_meshTessellateInterior( mesh ) tessellates each region of
- * the mesh which is marked "inside" the polygon. Each such region
- * must be monotone.
- */
-int __gl_meshTessellateInterior( GLUmesh *mesh )
-{
- GLUface *f, *next;
-
- /*LINTED*/
- for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
- /* Make sure we don''t try to tessellate the new triangles. */
- next = f->next;
- if( f->inside ) {
- if ( !__gl_meshTessellateMonoRegion( f ) ) return 0;
- }
- }
-
- return 1;
-}
-
-
-/* __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
- * which are not marked "inside" the polygon. Since further mesh operations
- * on NULL faces are not allowed, the main purpose is to clean up the
- * mesh so that exterior loops are not represented in the data structure.
- */
-void __gl_meshDiscardExterior( GLUmesh *mesh )
-{
- GLUface *f, *next;
-
- /*LINTED*/
- for( f = mesh->fHead.next; f != &mesh->fHead; f = next ) {
- /* Since f will be destroyed, save its next pointer. */
- next = f->next;
- if( ! f->inside ) {
- __gl_meshZapFace( f );
- }
- }
-}
-
-#define MARKED_FOR_DELETION 0x7fffffff
-
-/* __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
- * winding numbers on all edges so that regions marked "inside" the
- * polygon have a winding number of "value", and regions outside
- * have a winding number of 0.
- *
- * If keepOnlyBoundary is TRUE, it also deletes all edges which do not
- * separate an interior region from an exterior one.
- */
-int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
- GLboolean keepOnlyBoundary )
-{
- GLUhalfEdge *e, *eNext;
-
- for( e = mesh->eHead.next; e != &mesh->eHead; e = eNext ) {
- eNext = e->next;
- if( e->Rface->inside != e->Lface->inside ) {
-
- /* This is a boundary edge (one side is interior, one is exterior). */
- e->winding = (e->Lface->inside) ? value : -value;
- } else {
-
- /* Both regions are interior, or both are exterior. */
- if( ! keepOnlyBoundary ) {
- e->winding = 0;
- } else {
- if ( !__gl_meshDelete( e ) ) return 0;
- }
- }
- }
- return 1;
-}
+++ /dev/null
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Except as contained in this notice, the name of Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-/*
-** Author: Eric Veach, July 1994.
-**
-*/
-
-#ifndef __tessmono_h_
-#define __tessmono_h_
-
-/* __gl_meshTessellateMonoRegion( face ) tessellates a monotone region
- * (what else would it do??) The region must consist of a single
- * loop of half-edges (see mesh.h) oriented CCW. "Monotone" in this
- * case means that any vertical line intersects the interior of the
- * region in a single interval.
- *
- * Tessellation consists of adding interior edges (actually pairs of
- * half-edges), to split the region into non-overlapping triangles.
- *
- * __gl_meshTessellateInterior( mesh ) tessellates each region of
- * the mesh which is marked "inside" the polygon. Each such region
- * must be monotone.
- *
- * __gl_meshDiscardExterior( mesh ) zaps (ie. sets to NULL) all faces
- * which are not marked "inside" the polygon. Since further mesh operations
- * on NULL faces are not allowed, the main purpose is to clean up the
- * mesh so that exterior loops are not represented in the data structure.
- *
- * __gl_meshSetWindingNumber( mesh, value, keepOnlyBoundary ) resets the
- * winding numbers on all edges so that regions marked "inside" the
- * polygon have a winding number of "value", and regions outside
- * have a winding number of 0.
- *
- * If keepOnlyBoundary is TRUE, it also deletes all edges which do not
- * separate an interior region from an exterior one.
- */
-
-int __gl_meshTessellateMonoRegion( GLUface *face );
-int __gl_meshTessellateInterior( GLUmesh *mesh );
-void __gl_meshDiscardExterior( GLUmesh *mesh );
-int __gl_meshSetWindingNumber( GLUmesh *mesh, int value,
- GLboolean keepOnlyBoundary );
-
-#endif
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H
-#define __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H
-
-#include <X11/Xlib.h>
-#include <X11/extensions/XShm.h>
-#include <X11/extensions/Xdamage.h>
-
-#include <sys/shm.h>
-
-#ifdef COGL_HAS_GLX_SUPPORT
-#include <GL/glx.h>
-#endif
-
-#include "cogl-handle.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-pixmap-x11.h"
-
-#define COGL_TEXTURE_PIXMAP_X11(tex) ((CoglTexturePixmapX11 *) tex)
-
-typedef struct _CoglDamageRectangle CoglDamageRectangle;
-
-struct _CoglDamageRectangle
-{
- unsigned int x1;
- unsigned int y1;
- unsigned int x2;
- unsigned int y2;
-};
-
-typedef struct _CoglTexturePixmapX11 CoglTexturePixmapX11;
-
-struct _CoglTexturePixmapX11
-{
- CoglTexture _parent;
-
- Pixmap pixmap;
- CoglHandle tex;
-
- unsigned int depth;
- Visual *visual;
- unsigned int width;
- unsigned int height;
-
- XImage *image;
-
- XShmSegmentInfo shm_info;
-
- Damage damage;
- CoglTexturePixmapX11ReportLevel damage_report_level;
- gboolean damage_owned;
- CoglDamageRectangle damage_rect;
-
- void *winsys;
-
- /* During the pre_paint method, this will be set to TRUE if we
- should use the winsys texture, otherwise we will use the regular
- texture */
- gboolean use_winsys_texture;
-};
-
-GQuark
-_cogl_handle_texture_pixmap_x11_get_type (void);
-
-#endif /* __COGL_TEXTURE_PIXMAP_X11_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- * Johan Bilien <johan.bilien@nokia.com>
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-debug.h"
-#include "cogl-internal.h"
-#include "cogl-util.h"
-#include "cogl-texture-pixmap-x11.h"
-#include "cogl-texture-pixmap-x11-private.h"
-#include "cogl-bitmap-private.h"
-#include "cogl-texture-private.h"
-#include "cogl-texture-driver.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-rectangle-private.h"
-#include "cogl-context-private.h"
-#include "cogl-display-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-handle.h"
-#include "cogl-winsys-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <X11/extensions/XShm.h>
-
-#include <string.h>
-#include <math.h>
-
-static void _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
-
-COGL_TEXTURE_DEFINE (TexturePixmapX11, texture_pixmap_x11);
-
-static const CoglTextureVtable cogl_texture_pixmap_x11_vtable;
-
-static void
-cogl_damage_rectangle_union (CoglDamageRectangle *damage_rect,
- int x,
- int y,
- int width,
- int height)
-{
- /* If the damage region is empty then we'll just copy the new
- rectangle directly */
- if (damage_rect->x1 == damage_rect->x2 ||
- damage_rect->y1 == damage_rect->y2)
- {
- damage_rect->x1 = x;
- damage_rect->y1 = y;
- damage_rect->x2 = x + width;
- damage_rect->y2 = y + height;
- }
- else
- {
- if (damage_rect->x1 > x)
- damage_rect->x1 = x;
- if (damage_rect->y1 > y)
- damage_rect->y1 = y;
- if (damage_rect->x2 < x + width)
- damage_rect->x2 = x + width;
- if (damage_rect->y2 < y + height)
- damage_rect->y2 = y + height;
- }
-}
-
-static gboolean
-cogl_damage_rectangle_is_whole (const CoglDamageRectangle *damage_rect,
- unsigned int width,
- unsigned int height)
-{
- return (damage_rect->x1 == 0 && damage_rect->y1 == 0
- && damage_rect->x2 == width && damage_rect->y2 == height);
-}
-
-static const CoglWinsysVtable *
-_cogl_texture_pixmap_x11_get_winsys (CoglTexturePixmapX11 *tex_pixmap)
-{
- /* FIXME: A CoglContext should be reachable from a CoglTexture
- * pointer */
- _COGL_GET_CONTEXT (ctx, NULL);
-
- return ctx->display->renderer->winsys_vtable;
-}
-
-static void
-process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
- XDamageNotifyEvent *damage_event)
-{
- Display *display;
- enum { DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
- const CoglWinsysVtable *winsys;
-
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- display = cogl_xlib_get_display ();
-
- COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);
-
- switch (tex_pixmap->damage_report_level)
- {
- case COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES:
- /* For raw rectangles we don't need do look at the damage region
- at all because the damage area is directly given in the event
- struct and the reporting of events is not affected by
- clearing the damage region */
- handle_mode = DO_NOTHING;
- break;
-
- case COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES:
- case COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY:
- /* For delta rectangles and non empty we'll query the damage
- region for the bounding box */
- handle_mode = NEED_BOUNDING_BOX;
- break;
-
- case COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX:
- /* For bounding box we need to clear the damage region but we
- don't actually care what it was because the damage event
- itself contains the bounding box of the region */
- handle_mode = NEEDS_SUBTRACT;
- break;
-
- default:
- g_assert_not_reached ();
- }
-
- /* If the damage already covers the whole rectangle then we don't
- need to request the bounding box of the region because we're
- going to update the whole texture anyway. */
- if (cogl_damage_rectangle_is_whole (&tex_pixmap->damage_rect,
- tex_pixmap->width,
- tex_pixmap->height))
- {
- if (handle_mode != DO_NOTHING)
- XDamageSubtract (display, tex_pixmap->damage, None, None);
- }
- else if (handle_mode == NEED_BOUNDING_BOX)
- {
- XserverRegion parts;
- int r_count;
- XRectangle r_bounds;
- XRectangle *r_damage;
-
- /* We need to extract the damage region so we can get the
- bounding box */
-
- parts = XFixesCreateRegion (display, 0, 0);
- XDamageSubtract (display, tex_pixmap->damage, None, parts);
- r_damage = XFixesFetchRegionAndBounds (display,
- parts,
- &r_count,
- &r_bounds);
- cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
- r_bounds.x,
- r_bounds.y,
- r_bounds.width,
- r_bounds.height);
- if (r_damage)
- XFree (r_damage);
-
- XFixesDestroyRegion (display, parts);
- }
- else
- {
- if (handle_mode == NEEDS_SUBTRACT)
- /* We still need to subtract from the damage region but we
- don't care what the region actually was */
- XDamageSubtract (display, tex_pixmap->damage, None, None);
-
- cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
- damage_event->area.x,
- damage_event->area.y,
- damage_event->area.width,
- damage_event->area.height);
- }
-
- /* If we're using the texture from pixmap extension then there's no
- point in getting the region and we can just mark that the texture
- needs updating */
- winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
- winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
-}
-
-static CoglFilterReturn
-_cogl_texture_pixmap_x11_filter (void *native_event, void *data)
-{
- XEvent *event = native_event;
- CoglTexturePixmapX11 *tex_pixmap = data;
- int damage_base;
-
- _COGL_GET_CONTEXT (ctxt, COGL_FILTER_CONTINUE);
-
- damage_base = _cogl_xlib_get_damage_base ();
- if (event->type == damage_base + XDamageNotify)
- {
- XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) event;
-
- if (damage_event->damage == tex_pixmap->damage)
- process_damage_event (tex_pixmap, damage_event);
- }
-
- return COGL_FILTER_CONTINUE;
-}
-
-static void
-set_damage_object_internal (CoglTexturePixmapX11 *tex_pixmap,
- Damage damage,
- CoglTexturePixmapX11ReportLevel report_level)
-{
- if (tex_pixmap->damage)
- {
- _cogl_xlib_remove_filter (_cogl_texture_pixmap_x11_filter, tex_pixmap);
-
- if (tex_pixmap->damage_owned)
- {
- XDamageDestroy (cogl_xlib_get_display (), tex_pixmap->damage);
- tex_pixmap->damage_owned = FALSE;
- }
- }
-
- tex_pixmap->damage = damage;
- tex_pixmap->damage_report_level = report_level;
-
- if (damage)
- _cogl_xlib_add_filter (_cogl_texture_pixmap_x11_filter, tex_pixmap);
-}
-
-CoglHandle
-cogl_texture_pixmap_x11_new (guint32 pixmap,
- gboolean automatic_updates)
-{
- CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
- Display *display = cogl_xlib_get_display ();
- Window pixmap_root_window;
- int pixmap_x, pixmap_y;
- unsigned int pixmap_border_width;
- CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
- XWindowAttributes window_attributes;
- int damage_base;
- const CoglWinsysVtable *winsys;
-
- _COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);
-
- _cogl_texture_init (tex, &cogl_texture_pixmap_x11_vtable);
-
- tex_pixmap->pixmap = pixmap;
- tex_pixmap->image = NULL;
- tex_pixmap->shm_info.shmid = -1;
- tex_pixmap->tex = COGL_INVALID_HANDLE;
- tex_pixmap->damage_owned = FALSE;
- tex_pixmap->damage = 0;
-
- if (!XGetGeometry (display, pixmap, &pixmap_root_window,
- &pixmap_x, &pixmap_y,
- &tex_pixmap->width, &tex_pixmap->height,
- &pixmap_border_width, &tex_pixmap->depth))
- {
- g_free (tex_pixmap);
- g_warning ("Unable to query pixmap size");
- return COGL_INVALID_HANDLE;
- }
-
- /* We need a visual to use for shared memory images so we'll query
- it from the pixmap's root window */
- if (!XGetWindowAttributes (display, pixmap_root_window, &window_attributes))
- {
- g_free (tex_pixmap);
- g_warning ("Unable to query root window attributes");
- return COGL_INVALID_HANDLE;
- }
- tex_pixmap->visual = window_attributes.visual;
-
- /* If automatic updates are requested and the Xlib connection
- supports damage events then we'll register a damage object on the
- pixmap */
- damage_base = _cogl_xlib_get_damage_base ();
- if (automatic_updates && damage_base >= 0)
- {
- Damage damage = XDamageCreate (display,
- pixmap,
- XDamageReportBoundingBox);
- set_damage_object_internal (tex_pixmap,
- damage,
- COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX);
- tex_pixmap->damage_owned = TRUE;
- }
-
- /* Assume the entire pixmap is damaged to begin with */
- tex_pixmap->damage_rect.x1 = 0;
- tex_pixmap->damage_rect.x2 = tex_pixmap->width;
- tex_pixmap->damage_rect.y1 = 0;
- tex_pixmap->damage_rect.y2 = tex_pixmap->height;
-
- winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
- if (winsys->texture_pixmap_x11_create)
- winsys->texture_pixmap_x11_create (tex_pixmap);
-
- return _cogl_texture_pixmap_x11_handle_new (tex_pixmap);
-}
-
-/* Tries to allocate enough shared mem to handle a full size
- * update size of the X Pixmap. */
-static void
-try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap)
-{
- XImage *dummy_image;
- Display *display;
-
- display = cogl_xlib_get_display ();
-
- if (!XShmQueryExtension (display))
- return;
-
- /* We are creating a dummy_image so we can have Xlib calculate
- * image->bytes_per_line - including any magic padding it may
- * want - for the largest possible ximage we might need to use
- * when handling updates to the texture.
- *
- * Note: we pass a NULL shminfo here, but that has no bearing
- * on the setup of the XImage, except that ximage->obdata will
- * == NULL.
- */
- dummy_image =
- XShmCreateImage (display,
- tex_pixmap->visual,
- tex_pixmap->depth,
- ZPixmap,
- NULL,
- NULL, /* shminfo, */
- tex_pixmap->width,
- tex_pixmap->height);
- if (!dummy_image)
- goto failed_image_create;
-
- tex_pixmap->shm_info.shmid = shmget (IPC_PRIVATE,
- dummy_image->bytes_per_line
- * dummy_image->height,
- IPC_CREAT | 0777);
- if (tex_pixmap->shm_info.shmid == -1)
- goto failed_shmget;
-
- tex_pixmap->shm_info.shmaddr = shmat (tex_pixmap->shm_info.shmid, 0, 0);
- if (tex_pixmap->shm_info.shmaddr == (void *) -1)
- goto failed_shmat;
-
- tex_pixmap->shm_info.readOnly = False;
-
- if (XShmAttach (display, &tex_pixmap->shm_info) == 0)
- goto failed_xshmattach;
-
- XDestroyImage (dummy_image);
-
- return;
-
- failed_xshmattach:
- g_warning ("XShmAttach failed");
- shmdt (tex_pixmap->shm_info.shmaddr);
-
- failed_shmat:
- g_warning ("shmat failed");
- shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
-
- failed_shmget:
- g_warning ("shmget failed");
- XDestroyImage (dummy_image);
-
- failed_image_create:
- tex_pixmap->shm_info.shmid = -1;
-}
-
-void
-cogl_texture_pixmap_x11_update_area (CoglHandle handle,
- int x,
- int y,
- int width,
- int height)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
- const CoglWinsysVtable *winsys;
-
- if (!cogl_is_texture_pixmap_x11 (handle))
- return;
-
- /* We'll queue the update for both the GLX texture and the regular
- texture because we can't determine which will be needed until we
- actually render something */
-
- winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
- winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
-
- cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
- x, y, width, height);
-}
-
-gboolean
-cogl_texture_pixmap_x11_is_using_tfp_extension (CoglHandle handle)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
-
- if (!cogl_is_texture_pixmap_x11 (tex_pixmap))
- return FALSE;
-
- return !!tex_pixmap->winsys;
-}
-
-void
-cogl_texture_pixmap_x11_set_damage_object (CoglHandle handle,
- guint32 damage,
- CoglTexturePixmapX11ReportLevel
- report_level)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
- int damage_base;
-
- _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
-
- if (!cogl_is_texture_pixmap_x11 (tex_pixmap))
- return;
-
- damage_base = _cogl_xlib_get_damage_base ();
- if (damage_base >= 0)
- set_damage_object_internal (tex_pixmap, damage, report_level);
-}
-
-static void
-_cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
-{
- Display *display;
- CoglPixelFormat image_format;
- XImage *image;
- int src_x, src_y;
- int x, y, width, height;
-
- display = cogl_xlib_get_display ();
-
- /* If the damage region is empty then there's nothing to do */
- if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1)
- return;
-
- x = tex_pixmap->damage_rect.x1;
- y = tex_pixmap->damage_rect.y1;
- width = tex_pixmap->damage_rect.x2 - x;
- height = tex_pixmap->damage_rect.y2 - y;
-
- /* We lazily create the texture the first time it is needed in case
- this texture can be entirely handled using the GLX texture
- instead */
- if (tex_pixmap->tex == COGL_INVALID_HANDLE)
- {
- CoglPixelFormat texture_format;
-
- texture_format = (tex_pixmap->depth >= 32
- ? COGL_PIXEL_FORMAT_RGBA_8888_PRE
- : COGL_PIXEL_FORMAT_RGB_888);
-
- tex_pixmap->tex = cogl_texture_new_with_size (tex_pixmap->width,
- tex_pixmap->height,
- COGL_TEXTURE_NONE,
- texture_format);
- }
-
- if (tex_pixmap->image == NULL)
- {
- /* If we also haven't got a shm segment then this must be the
- first time we've tried to update, so lets try allocating shm
- first */
- if (tex_pixmap->shm_info.shmid == -1)
- try_alloc_shm (tex_pixmap);
-
- if (tex_pixmap->shm_info.shmid == -1)
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap);
-
- /* We'll fallback to using a regular XImage. We'll download
- the entire area instead of a sub region because presumably
- if this is the first update then the entire pixmap is
- needed anyway and it saves trying to manually allocate an
- XImage at the right size */
- tex_pixmap->image = XGetImage (display,
- tex_pixmap->pixmap,
- 0, 0,
- tex_pixmap->width, tex_pixmap->height,
- AllPlanes, ZPixmap);
- image = tex_pixmap->image;
- src_x = x;
- src_y = y;
- }
- else
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage",
- tex_pixmap);
-
- /* Create a temporary image using the beginning of the
- shared memory segment and the right size for the region
- we want to update. We need to reallocate the XImage every
- time because there is no XShmGetSubImage. */
- image = XShmCreateImage (display,
- tex_pixmap->visual,
- tex_pixmap->depth,
- ZPixmap,
- NULL,
- &tex_pixmap->shm_info,
- width,
- height);
- image->data = tex_pixmap->shm_info.shmaddr;
- src_x = 0;
- src_y = 0;
-
- XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes);
- }
- }
- else
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap);
-
- image = tex_pixmap->image;
- src_x = x;
- src_y = y;
-
- XGetSubImage (display,
- tex_pixmap->pixmap,
- x, y, width, height,
- AllPlanes, ZPixmap,
- image,
- x, y);
- }
-
- /* xlib doesn't appear to fill in image->{red,green,blue}_mask so
- this just assumes that the image is stored as ARGB from most
- significant byte to to least significant. If the format is little
- endian that means the order will be BGRA in memory */
-
- switch (image->bits_per_pixel)
- {
- default:
- case 32:
- {
- /* If the pixmap is actually non-packed-pixel RGB format then
- the texture would have been created in RGB_888 format so Cogl
- will ignore the alpha channel and effectively pack it for
- us */
- image_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
-
- /* If the format is actually big endian then the alpha
- component will come first */
- if (image->byte_order == MSBFirst)
- image_format |= COGL_AFIRST_BIT;
- }
- break;
-
- case 24:
- image_format = COGL_PIXEL_FORMAT_RGB_888;
- break;
-
- case 16:
- /* FIXME: this should probably swap the orders around if the
- endianness does not match */
- image_format = COGL_PIXEL_FORMAT_RGB_565;
- break;
- }
-
- if (image->bits_per_pixel != 16)
- {
- /* If the image is in little-endian then the order in memory is
- reversed */
- if (image->byte_order == LSBFirst)
- image_format |= COGL_BGR_BIT;
- }
-
- cogl_texture_set_region (tex_pixmap->tex,
- src_x, src_y,
- x, y, width, height,
- image->width,
- image->height,
- image_format,
- image->bytes_per_line,
- (const guint8 *) image->data);
-
- /* If we have a shared memory segment then the XImage would be a
- temporary one with no data allocated so we can just XFree it */
- if (tex_pixmap->shm_info.shmid != -1)
- XFree (image);
-
- memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle));
-}
-
-static void
-_cogl_texture_pixmap_x11_set_use_winsys_texture (CoglTexturePixmapX11 *tex_pixmap,
- gboolean new_value)
-{
- if (tex_pixmap->use_winsys_texture != new_value)
- {
- /* Notify cogl-pipeline.c that the texture's underlying GL texture
- * storage is changing so it knows it may need to bind a new texture
- * if the CoglTexture is reused with the same texture unit. */
- _cogl_pipeline_texture_storage_change_notify (tex_pixmap);
-
- tex_pixmap->use_winsys_texture = new_value;
- }
-}
-
-static void
-_cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
- gboolean needs_mipmap)
-{
- if (tex_pixmap->winsys)
- {
- const CoglWinsysVtable *winsys =
- _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
-
- if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
- {
- _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
- return;
- }
- }
-
- /* If it didn't work then fallback to using XGetImage. This may be
- temporary */
- _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, FALSE);
-
- _cogl_texture_pixmap_x11_update_image_texture (tex_pixmap);
-}
-
-static CoglHandle
-_cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
-{
- CoglHandle tex;
- int i;
-
- /* We try getting the texture twice, once without flushing the
- updates and once with. If pre_paint has been called already then
- we should have a good idea of which texture to use so we don't
- want to mess with that by ensuring the updates. However, if we
- couldn't find a texture then we'll just make a best guess by
- flushing without expecting mipmap support and try again. This
- would happen for example if an application calls
- get_gl_texture before the first paint */
-
- for (i = 0; i < 2; i++)
- {
- if (tex_pixmap->use_winsys_texture)
- {
- const CoglWinsysVtable *winsys =
- _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
- tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap);
- }
- else
- tex = tex_pixmap->tex;
-
- if (tex)
- return tex;
-
- _cogl_texture_pixmap_x11_update (tex_pixmap, FALSE);
- }
-
- g_assert_not_reached ();
-
- return COGL_INVALID_HANDLE;
-}
-
-static gboolean
-_cogl_texture_pixmap_x11_set_region (CoglTexture *tex,
- int src_x,
- int src_y,
- int dst_x,
- int dst_y,
- unsigned int dst_width,
- unsigned int dst_height,
- CoglBitmap *bmp)
-{
- /* This doesn't make much sense for texture from pixmap so it's not
- supported */
- return FALSE;
-}
-
-static gboolean
-_cogl_texture_pixmap_x11_get_data (CoglTexture *tex,
- CoglPixelFormat format,
- unsigned int rowstride,
- guint8 *data)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- return cogl_texture_get_data (child_tex, format, rowstride, data);
-}
-
-static void
-_cogl_texture_pixmap_x11_foreach_sub_texture_in_region
- (CoglTexture *tex,
- float virtual_tx_1,
- float virtual_ty_1,
- float virtual_tx_2,
- float virtual_ty_2,
- CoglTextureSliceCallback callback,
- void *user_data)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- _cogl_texture_foreach_sub_texture_in_region (child_tex,
- virtual_tx_1,
- virtual_ty_1,
- virtual_tx_2,
- virtual_ty_2,
- callback,
- user_data);
-}
-
-static int
-_cogl_texture_pixmap_x11_get_max_waste (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- return cogl_texture_get_max_waste (child_tex);
-}
-
-static gboolean
-_cogl_texture_pixmap_x11_is_sliced (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- return cogl_texture_is_sliced (child_tex);
-}
-
-static gboolean
-_cogl_texture_pixmap_x11_can_hardware_repeat (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- return cogl_texture_get_max_waste (child_tex);
-}
-
-static void
-_cogl_texture_pixmap_x11_transform_coords_to_gl (CoglTexture *tex,
- float *s,
- float *t)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- _cogl_texture_transform_coords_to_gl (child_tex, s, t);
-}
-
-static CoglTransformResult
-_cogl_texture_pixmap_x11_transform_quad_coords_to_gl (CoglTexture *tex,
- float *coords)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- return _cogl_texture_transform_quad_coords_to_gl (child_tex, coords);
-}
-
-static gboolean
-_cogl_texture_pixmap_x11_get_gl_texture (CoglTexture *tex,
- GLuint *out_gl_handle,
- GLenum *out_gl_target)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- return cogl_texture_get_gl_texture (child_tex,
- out_gl_handle,
- out_gl_target);
-}
-
-static void
-_cogl_texture_pixmap_x11_set_filters (CoglTexture *tex,
- GLenum min_filter,
- GLenum mag_filter)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- _cogl_texture_set_filters (child_tex, min_filter, mag_filter);
-}
-
-static void
-_cogl_texture_pixmap_x11_pre_paint (CoglTexture *tex,
- CoglTexturePrePaintFlags flags)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- _cogl_texture_pixmap_x11_update (tex_pixmap,
- !!(flags & COGL_TEXTURE_NEEDS_MIPMAP));
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- _cogl_texture_pre_paint (child_tex, flags);
-}
-
-static void
-_cogl_texture_pixmap_x11_ensure_non_quad_rendering (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- _cogl_texture_ensure_non_quad_rendering (child_tex);
-}
-
-static void
-_cogl_texture_pixmap_x11_set_wrap_mode_parameters (CoglTexture *tex,
- GLenum wrap_mode_s,
- GLenum wrap_mode_t,
- GLenum wrap_mode_p)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- _cogl_texture_set_wrap_mode_parameters (child_tex,
- wrap_mode_s,
- wrap_mode_t,
- wrap_mode_p);
-}
-
-static CoglPixelFormat
-_cogl_texture_pixmap_x11_get_format (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- /* Forward on to the child texture */
- return cogl_texture_get_format (child_tex);
-}
-
-static GLenum
-_cogl_texture_pixmap_x11_get_gl_format (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
- CoglHandle child_tex;
-
- child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
-
- return _cogl_texture_get_gl_format (child_tex);
-}
-
-static int
-_cogl_texture_pixmap_x11_get_width (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
-
- return tex_pixmap->width;
-}
-
-static int
-_cogl_texture_pixmap_x11_get_height (CoglTexture *tex)
-{
- CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
-
- return tex_pixmap->height;
-}
-
-static void
-_cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
-{
- set_damage_object_internal (tex_pixmap, 0, 0);
-
- if (tex_pixmap->image)
- XDestroyImage (tex_pixmap->image);
-
- if (tex_pixmap->shm_info.shmid != -1)
- {
- XShmDetach (cogl_xlib_get_display (), &tex_pixmap->shm_info);
- shmdt (tex_pixmap->shm_info.shmaddr);
- shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
- }
-
- if (tex_pixmap->tex)
- cogl_handle_unref (tex_pixmap->tex);
-
- if (tex_pixmap->winsys)
- {
- const CoglWinsysVtable *winsys =
- _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
- winsys->texture_pixmap_x11_free (tex_pixmap);
- }
-
- /* Chain up */
- _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
-}
-
-static const CoglTextureVtable
-cogl_texture_pixmap_x11_vtable =
- {
- _cogl_texture_pixmap_x11_set_region,
- _cogl_texture_pixmap_x11_get_data,
- _cogl_texture_pixmap_x11_foreach_sub_texture_in_region,
- _cogl_texture_pixmap_x11_get_max_waste,
- _cogl_texture_pixmap_x11_is_sliced,
- _cogl_texture_pixmap_x11_can_hardware_repeat,
- _cogl_texture_pixmap_x11_transform_coords_to_gl,
- _cogl_texture_pixmap_x11_transform_quad_coords_to_gl,
- _cogl_texture_pixmap_x11_get_gl_texture,
- _cogl_texture_pixmap_x11_set_filters,
- _cogl_texture_pixmap_x11_pre_paint,
- _cogl_texture_pixmap_x11_ensure_non_quad_rendering,
- _cogl_texture_pixmap_x11_set_wrap_mode_parameters,
- _cogl_texture_pixmap_x11_get_format,
- _cogl_texture_pixmap_x11_get_gl_format,
- _cogl_texture_pixmap_x11_get_width,
- _cogl_texture_pixmap_x11_get_height,
- NULL /* is_foreign */
- };
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_TEXTURE_PIXMAP_X11_H
-#define __COGL_TEXTURE_PIXMAP_X11_H
-
-#include <cogl/cogl.h>
-
-#ifdef COGL_ENABLE_EXPERIMENTAL_API
-
-/* All of the cogl-texture-pixmap-x11 API is currently experimental so
- * we suffix the actual symbols with _EXP so if somone is monitoring
- * for ABI changes it will hopefully be clearer to them what's going
- * on if any of the symbols dissapear at a later date.
- */
-#define cogl_texture_pixmap_x11_new cogl_texture_pixmap_x11_new_EXP
-#define cogl_texture_pixmap_x11_update_area \
- cogl_texture_pixmap_x11_update_area_EXP
-#define cogl_texture_pixmap_x11_is_using_tfp_extension \
- cogl_texture_pixmap_x11_is_using_tfp_extension_EXP
-#define cogl_texture_pixmap_x11_set_damage_object \
- cogl_texture_pixmap_x11_set_damage_object_EXP
-#define cogl_is_texture_pixmap_x11 cogl_is_texture_pixmap_x11_EXP
-
-typedef enum
-{
- COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES,
- COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES,
- COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX,
- COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY
-} CoglTexturePixmapX11ReportLevel;
-
-/**
- * cogl_texture_pixmap_x11_new:
- * @pixmap: A X11 pixmap ID
- * @automatic_updates: Whether to automatically copy the contents of
- * the pixmap to the texture.
- *
- * Creates a texture that contains the contents of @pixmap. If
- * @automatic_updates is %TRUE then Cogl will attempt to listen for
- * damage events on the pixmap and automatically update the texture
- * when it changes.
- *
- * Return value: a CoglHandle to a texture
- *
- * Since: 1.4
- * Stability: Unstable
- */
-CoglHandle
-cogl_texture_pixmap_x11_new (guint32 pixmap,
- gboolean automatic_updates);
-
-/**
- * cogl_texture_pixmap_x11_update_area:
- * @handle: A CoglHandle to a CoglTexturePixmapX11 instance
- * @x: x coordinate of the area to update
- * @y: y coordinate of the area to update
- * @width: width of the area to update
- * @height: height of the area to update
- *
- * Forces an update of the texture pointed to by @handle so that it is
- * refreshed with the contents of the pixmap that was given to
- * cogl_texture_pixmap_x11_new().
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_texture_pixmap_x11_update_area (CoglHandle handle,
- int x,
- int y,
- int width,
- int height);
-
-/**
- * cogl_texture_pixmap_x11_is_using_tfp_extension:
- * @handle: A CoglHandle to a CoglTexturePixmapX11 instance
- *
- * Checks whether the texture is using the GLX_EXT_texture_from_pixmap
- * or similar extension to copy the contents of the pixmap to the texture.
- * This extension is usually implemented as zero-copy operation so it
- * implies the updates are working efficiently.
- *
- * Return value: %TRUE if the texture is using an efficient extension
- * and %FALSE otherwise
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_texture_pixmap_x11_is_using_tfp_extension (CoglHandle handle);
-
-/**
- * cogl_texture_pixmap_x11_set_damage_object:
- * @handle: A CoglHandle
- * @damage: A X11 Damage object or 0
- * @report_level: The report level which describes how to interpret
- * the damage events. This should match the level that the damage
- * object was created with.
- *
- * Sets the damage object that will be used to track automatic updates
- * to the texture. Damage tracking can be disabled by passing 0 for
- * @damage. Otherwise this damage will replace the one used if %TRUE
- * was passed for automatic_updates to cogl_texture_pixmap_x11_new().
- *
- * Note that Cogl will subtract from the damage region as it processes
- * damage events.
- *
- * Since: 1.4
- * Stability: Unstable
- */
-void
-cogl_texture_pixmap_x11_set_damage_object (CoglHandle handle,
- guint32 damage,
- CoglTexturePixmapX11ReportLevel
- report_level);
-
-/**
- * cogl_is_texture_pixmap_x11:
- * @handle: A CoglHandle
- *
- * Checks whether @handle points to a CoglTexturePixmapX11 instance.
- *
- * Return value: %TRUE if the handle is a CoglTexturePixmapX11, and
- * %FALSE otherwise
- *
- * Since: 1.4
- * Stability: Unstable
- */
-gboolean
-cogl_is_texture_pixmap_x11 (CoglHandle handle);
-
-#endif /* COGL_ENABLE_EXPERIMENTAL_API */
-
-#endif /* __COGL_TEXTURE_PIXMAP_X11_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This can be included multiple times with different definitions for
- * the COGL_WINSYS_FEATURE_* functions.
- */
-
-/* Macro prototypes:
- * COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
- * implied_public_feature_flags,
- * implied_private_feature_flags,
- * implied_winsys_feature)
- * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
- * (arguments))
- * ...
- * COGL_WINSYS_FEATURE_END ()
- *
- * Note: You can list multiple namespace and extension names if the
- * corresponding _FEATURE_FUNCTIONS have the same semantics accross
- * the different extension variants.
- *
- * XXX: NB: Don't add a trailing semicolon when using these macros
- */
-
-COGL_WINSYS_FEATURE_BEGIN (swap_region,
- "NOK\0",
- "swap_region\0",
- 0,
- 0,
- COGL_WINSYS_FEATURE_SWAP_REGION)
-COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersRegion,
- (EGLDisplay dpy,
- EGLSurface surface,
- EGLint numRects,
- const EGLint *rects))
-COGL_WINSYS_FEATURE_END ()
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-#include "cogl-winsys-private.h"
-#include "cogl-feature-private.h"
-#include "cogl-context-private.h"
-#include "cogl-framebuffer.h"
-#include "cogl-swap-chain-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-onscreen-template-private.h"
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-#include "cogl-renderer-xlib-private.h"
-#include "cogl-display-xlib-private.h"
-#endif
-#include "cogl-private.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <glib/gi18n-lib.h>
-
-#ifdef COGL_HAS_GLES1
-
-#include <GLES/gl.h>
-#include <GLES/egl.h>
-
-#else
-
-#include <EGL/egl.h>
-#define NativeDisplayType EGLNativeDisplayType
-#define NativeWindowType EGLNativeWindowType
-
-#endif
-
-
-#include <EGL/egl.h>
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-#include <X11/Xlib.h>
-
-#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
-#endif
-
-typedef struct _CoglRendererEGL
-{
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglRendererXlib _parent;
-#endif
-
- EGLDisplay edpy;
-
- EGLint egl_version_major;
- EGLint egl_version_minor;
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- gboolean gdl_initialized;
-#endif
-
- /* Function pointers for GLX specific extensions */
-#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
-
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- ret (APIENTRY * pf_ ## name) args;
-
-#define COGL_WINSYS_FEATURE_END()
-
-#include "cogl-winsys-egl-feature-functions.h"
-
-#undef COGL_WINSYS_FEATURE_BEGIN
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#undef COGL_WINSYS_FEATURE_END
-} CoglRendererEGL;
-
-typedef struct _CoglDisplayEGL
-{
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglDisplayXlib _parent;
-#endif
-
- EGLContext egl_context;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- EGLSurface dummy_surface;
-#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
- defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT)
- EGLSurface egl_surface;
- int egl_surface_width;
- int egl_surface_height;
- gboolean have_onscreen;
-#else
-#error "Unknown EGL platform"
-#endif
-
- EGLConfig egl_config;
- gboolean found_egl_config;
-} CoglDisplayEGL;
-
-typedef struct _CoglContextEGL
-{
- EGLSurface current_surface;
-} CoglContextEGL;
-
-typedef struct _CoglOnscreenXlib
-{
- Window xwin;
- gboolean is_foreign_xwin;
-} CoglOnscreenXlib;
-
-typedef struct _CoglOnscreenEGL
-{
- CoglOnscreenXlib _parent;
- EGLSurface egl_surface;
-} CoglOnscreenEGL;
-
-/* Define a set of arrays containing the functions required from GL
- for each winsys feature */
-#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature) \
- static const CoglFeatureFunction \
- cogl_egl_feature_ ## name ## _funcs[] = {
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererEGL, pf_ ## name) },
-#define COGL_WINSYS_FEATURE_END() \
- { NULL, 0 }, \
- };
-#include "cogl-winsys-egl-feature-functions.h"
-
-/* Define an array of features */
-#undef COGL_WINSYS_FEATURE_BEGIN
-#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature) \
- { 255, 255, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature, \
- cogl_egl_feature_ ## name ## _funcs },
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
-#undef COGL_WINSYS_FEATURE_END
-#define COGL_WINSYS_FEATURE_END()
-
-static const CoglFeatureData winsys_feature_data[] =
- {
-#include "cogl-winsys-egl-feature-functions.h"
- };
-
-static CoglFuncPtr
-_cogl_winsys_get_proc_address (const char *name)
-{
- return (CoglFuncPtr) eglGetProcAddress (name);
-}
-
-#undef COGL_WINSYS_FEATURE_BEGIN
-#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- egl_renderer->pf_ ## name = NULL;
-#undef COGL_WINSYS_FEATURE_END
-#define COGL_WINSYS_FEATURE_END()
-
-static void
-initialize_function_table (CoglRenderer *renderer)
-{
- CoglRendererEGL *egl_renderer = renderer->winsys;
-
-#include "cogl-winsys-egl-feature-functions.h"
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-static CoglOnscreen *
-find_onscreen_for_xid (CoglContext *context, guint32 xid)
-{
- GList *l;
-
- for (l = context->framebuffers; l; l = l->next)
- {
- CoglFramebuffer *framebuffer = l->data;
- CoglOnscreenXlib *xlib_onscreen;
-
- if (!framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN)
- continue;
-
- xlib_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
- if (xlib_onscreen->xwin == (Window)xid)
- return COGL_ONSCREEN (framebuffer);
- }
-
- return NULL;
-}
-
-static CoglFilterReturn
-event_filter_cb (void *event, void *data)
-{
- XEvent *xevent = event;
- CoglContext *context = data;
-
- if (xevent->type == ConfigureNotify)
- {
- CoglOnscreen *onscreen =
- find_onscreen_for_xid (context, xevent->xconfigure.window);
-
- if (onscreen)
- {
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-
- /* XXX: consider adding an abstraction for this... */
- framebuffer->width = xevent->xconfigure.width;
- framebuffer->height = xevent->xconfigure.height;
- }
- }
-
- return COGL_FILTER_CONTINUE;
-}
-#endif /* COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT */
-
-static void
-_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
-{
- CoglRendererEGL *egl_renderer = renderer->winsys;
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- if (egl_renderer->gdl_initialized)
- gdl_close ();
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- _cogl_renderer_xlib_disconnect (renderer);
-#endif
-
- eglTerminate (egl_renderer->edpy);
-
- g_slice_free (CoglRendererEGL, egl_renderer);
-}
-
-static gboolean
-_cogl_winsys_renderer_connect (CoglRenderer *renderer,
- GError **error)
-{
- CoglRendererEGL *egl_renderer;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglRendererXlib *xlib_renderer;
-#endif
- EGLBoolean status;
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- gdl_ret_t rc = GDL_SUCCESS;
- gdl_display_info_t gdl_display_info;
-#endif
-
- renderer->winsys = g_slice_new0 (CoglRendererEGL);
-
- egl_renderer = renderer->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- xlib_renderer = renderer->winsys;
-
- if (!_cogl_renderer_xlib_connect (renderer, error))
- goto error;
-
- egl_renderer->edpy =
- eglGetDisplay ((NativeDisplayType) xlib_renderer->xdpy);
-
- status = eglInitialize (egl_renderer->edpy,
- &egl_renderer->egl_version_major,
- &egl_renderer->egl_version_minor);
-#else
- egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
-
- status = eglInitialize (egl_renderer->edpy,
- &egl_renderer->egl_version_major,
- &egl_renderer->egl_version_minor);
-#endif
-
- if (status != EGL_TRUE)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "Failed to initialize EGL");
- goto error;
- }
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- /* Check we can talk to the GDL library */
-
- rc = gdl_init (NULL);
- if (rc != GDL_SUCCESS)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "GDL initialize failed. %s",
- gdl_get_error_string (rc));
- goto error;
- }
-
- rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &gdl_display_info);
- if (rc != GDL_SUCCESS)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "GDL failed to get display information: %s",
- gdl_get_error_string (rc));
- gdl_close ();
- goto error;
- }
-
- gdl_close ();
-#endif
-
- return TRUE;
-
-error:
- _cogl_winsys_renderer_disconnect (renderer);
- return FALSE;
-}
-
-static void
-update_winsys_features (CoglContext *context)
-{
- CoglDisplayEGL *egl_display = context->display->winsys;
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
- const char *egl_extensions;
- int i;
-
- g_return_if_fail (egl_display->egl_context);
-
- _cogl_gl_update_features (context);
-
- memset (context->winsys_features, 0, sizeof (context->winsys_features));
-
- egl_extensions = eglQueryString (egl_renderer->edpy, EGL_EXTENSIONS);
-
- COGL_NOTE (WINSYS, " EGL Extensions: %s", egl_extensions);
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
- TRUE);
-#endif
-
- initialize_function_table (context->display->renderer);
-
- for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
- if (_cogl_feature_check ("EGL", winsys_feature_data + i, 0, 0,
- egl_extensions,
- egl_renderer))
- {
- context->feature_flags |= winsys_feature_data[i].feature_flags;
- if (winsys_feature_data[i].winsys_feature)
- COGL_FLAGS_SET (context->winsys_features,
- winsys_feature_data[i].winsys_feature,
- TRUE);
- }
-
- /* FIXME: the winsys_feature_data can currently only have one
- * winsys feature per extension... */
- if (egl_renderer->pf_eglSwapBuffersRegion)
- {
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
- }
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-static XVisualInfo *
-get_visual_info (CoglDisplay *display, EGLConfig egl_config)
-{
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
- CoglRendererEGL *egl_renderer = display->renderer->winsys;
- XVisualInfo visinfo_template;
- int template_mask = 0;
- XVisualInfo *visinfo = NULL;
- int visinfos_count;
- EGLint visualid, red_size, green_size, blue_size, alpha_size;
-
- eglGetConfigAttrib (egl_renderer->edpy, egl_config,
- EGL_NATIVE_VISUAL_ID, &visualid);
-
- if (visualid != 0)
- {
- visinfo_template.visualid = visualid;
- template_mask |= VisualIDMask;
- }
- else
- {
- /* some EGL drivers don't implement the EGL_NATIVE_VISUAL_ID
- * attribute, so attempt to find the closest match. */
-
- eglGetConfigAttrib (egl_renderer->edpy, egl_config,
- EGL_RED_SIZE, &red_size);
- eglGetConfigAttrib (egl_renderer->edpy, egl_config,
- EGL_GREEN_SIZE, &green_size);
- eglGetConfigAttrib (egl_renderer->edpy, egl_config,
- EGL_BLUE_SIZE, &blue_size);
- eglGetConfigAttrib (egl_renderer->edpy, egl_config,
- EGL_ALPHA_SIZE, &alpha_size);
-
- visinfo_template.depth = red_size + green_size + blue_size + alpha_size;
- template_mask |= VisualDepthMask;
-
- visinfo_template.screen = DefaultScreen (xlib_renderer->xdpy);
- template_mask |= VisualScreenMask;
- }
-
- visinfo = XGetVisualInfo (xlib_renderer->xdpy,
- template_mask,
- &visinfo_template,
- &visinfos_count);
-
- return visinfo;
-}
-#endif
-
-static gboolean
-try_create_context (CoglDisplay *display,
- int retry_cookie,
- gboolean *try_fallback,
- GError **error)
-{
- CoglDisplayEGL *egl_display = display->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglDisplayXlib *xlib_display = display->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
-#endif
- CoglRendererEGL *egl_renderer = display->renderer->winsys;
- EGLDisplay edpy;
- EGLConfig config;
- EGLint config_count = 0;
- EGLBoolean status;
- EGLint cfg_attribs[] = {
- /* NB: This must be the first attribute, since we may
- * try and fallback to no stencil buffer */
- EGL_STENCIL_SIZE, 2,
-
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_ALPHA_SIZE, EGL_DONT_CARE,
-
- EGL_DEPTH_SIZE, 1,
-
- /* XXX: Why does the GDL platform choose these by default? */
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
- EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE,
-#endif
-
- EGL_BUFFER_SIZE, EGL_DONT_CARE,
-
-#if defined (HAVE_COGL_GL)
- EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
-#elif defined (HAVE_COGL_GLES2)
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-#else
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
-#endif
-
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-
- EGL_NONE
- };
-#if defined (HAVE_COGL_GLES2)
- EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
-#else
- EGLint *attribs = NULL;
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- XVisualInfo *xvisinfo;
- XSetWindowAttributes attrs;
-#endif
- const char *error_message;
-
- edpy = egl_renderer->edpy;
-
-#ifdef HAVE_COGL_GL
- eglBindAPI (EGL_OPENGL_API);
-#endif
-
- /* Some GLES hardware can't support a stencil buffer: */
- if (retry_cookie == 1)
- {
- g_warning ("Trying with stencil buffer disabled...");
- cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
- }
- /* XXX: at this point we only have one fallback */
-
- status = eglChooseConfig (edpy,
- cfg_attribs,
- &config, 1,
- &config_count);
- if (status != EGL_TRUE || config_count == 0)
- {
- error_message = "Unable to find a usable EGL configuration";
- goto fail;
- }
-
- egl_display->egl_config = config;
-
- egl_display->egl_context = eglCreateContext (edpy,
- config,
- EGL_NO_CONTEXT,
- attribs);
- if (egl_display->egl_context == EGL_NO_CONTEXT)
- {
- error_message = "Unable to create a suitable EGL context";
- goto fail;
- }
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-
- xvisinfo = get_visual_info (display, config);
- if (xvisinfo == NULL)
- {
- error_message = "Unable to find suitable X visual";
- goto fail;
- }
-
- attrs.override_redirect = True;
- attrs.colormap = XCreateColormap (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- xvisinfo->visual,
- AllocNone);
- attrs.border_pixel = 0;
-
- xlib_display->dummy_xwin =
- XCreateWindow (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- -100, -100, 1, 1,
- 0,
- xvisinfo->depth,
- CopyFromParent,
- xvisinfo->visual,
- CWOverrideRedirect |
- CWColormap |
- CWBorderPixel,
- &attrs);
-
- XFree (xvisinfo);
-
- egl_display->dummy_surface =
- eglCreateWindowSurface (edpy,
- egl_display->egl_config,
- (NativeWindowType) xlib_display->dummy_xwin,
- NULL);
-
- if (egl_display->dummy_surface == EGL_NO_SURFACE)
- {
- /* FIXME: we shouldn't be calling g_set_error here we should
- * just set error_message same goes for below. */
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to create an EGL surface");
- goto fail;
- }
-
- if (!eglMakeCurrent (edpy,
- egl_display->dummy_surface,
- egl_display->dummy_surface,
- egl_display->egl_context))
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to eglMakeCurrent with dummy surface");
- goto fail;
- }
-
-#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
-
- egl_display->egl_surface =
- eglCreateWindowSurface (edpy,
- config,
- (NativeWindowType) NULL,
- NULL);
- if (egl_display->egl_surface == EGL_NO_SURFACE)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to create EGL window surface");
- goto fail;
- }
-
- if (!eglMakeCurrent (egl_renderer->edpy,
- egl_display->egl_surface,
- egl_display->egl_surface,
- egl_display->egl_context))
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to eglMakeCurrent with egl surface");
- goto fail;
- }
-
- eglQuerySurface (egl_renderer->edpy,
- egl_display->egl_surface,
- EGL_WIDTH,
- &egl_display->egl_surface_width);
-
- eglQuerySurface (egl_renderer->edpy,
- egl_display->egl_surface,
- EGL_HEIGHT,
- &egl_display->egl_surface_height);
-
-#else
-#error "Unknown EGL platform"
-#endif
-
- return TRUE;
-
-fail:
-
- /* Currently we only have one fallback path... */
- if (retry_cookie == 0)
- {
- *try_fallback = TRUE;
- return FALSE;
- }
- else
- {
- *try_fallback = FALSE;
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "%s", error_message);
- return FALSE;
- }
-}
-
-static void
-cleanup_context (CoglDisplay *display)
-{
- CoglDisplayEGL *egl_display = display->winsys;
- CoglRendererEGL *egl_renderer = display->renderer->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglDisplayXlib *xlib_display = display->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
-#endif
-
- if (egl_display->egl_context != EGL_NO_CONTEXT)
- {
- eglMakeCurrent (egl_renderer->edpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
- eglDestroyContext (egl_renderer->edpy, egl_display->egl_context);
- egl_display->egl_context = EGL_NO_CONTEXT;
- }
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- if (egl_display->dummy_surface != EGL_NO_SURFACE)
- {
- eglDestroySurface (egl_renderer->edpy, egl_display->dummy_surface);
- egl_display->dummy_surface = EGL_NO_SURFACE;
- }
-
- if (xlib_display->dummy_xwin)
- {
- XDestroyWindow (xlib_renderer->xdpy, xlib_display->dummy_xwin);
- xlib_display->dummy_xwin = None;
- }
-#endif
-}
-
-static gboolean
-create_context (CoglDisplay *display, GError **error)
-{
- CoglDisplayEGL *egl_display = display->winsys;
- gboolean support_transparent_windows;
- int retry_cookie = 0;
- gboolean status;
- gboolean try_fallback;
- GError *try_error = NULL;
-
- g_return_val_if_fail (egl_display->egl_context == NULL, TRUE);
-
- if (display->onscreen_template &&
- display->onscreen_template->swap_chain &&
- display->onscreen_template->swap_chain->has_alpha)
- support_transparent_windows = TRUE;
- else
- support_transparent_windows = FALSE;
-
- retry_cookie = 0;
- while (!(status = try_create_context (display,
- retry_cookie,
- &try_fallback,
- &try_error)) &&
- try_fallback)
- {
- g_error_free (try_error);
- cleanup_context (display);
- try_error = NULL;
- retry_cookie++;
- }
- if (!status)
- g_propagate_error (error, try_error);
-
- return status;
-}
-
-static void
-_cogl_winsys_display_destroy (CoglDisplay *display)
-{
- CoglDisplayEGL *egl_display = display->winsys;
-
- g_return_if_fail (egl_display != NULL);
-
- cleanup_context (display);
-
- g_slice_free (CoglDisplayEGL, display->winsys);
- display->winsys = NULL;
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
-static gboolean
-gdl_plane_init (CoglDisplay *display, GError **error)
-{
- gboolean ret = TRUE;
- gdl_color_space_t colorSpace = GDL_COLOR_SPACE_RGB;
- gdl_rectangle_t dstRect;
- gdl_display_info_t display_info;
- gdl_ret_t rc = GDL_SUCCESS;
-
- if (!display->gdl_plane)
- {
- g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "No GDL plane specified with "
- "cogl_gdl_display_set_plane");
- return FALSE;
- }
-
- rc = gdl_init (NULL);
- if (rc != GDL_SUCCESS)
- {
- g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "GDL initialize failed. %s", gdl_get_error_string (rc));
- return FALSE;
- }
-
- rc = gdl_get_display_info (GDL_DISPLAY_ID_0, &display_info);
- if (rc != GDL_SUCCESS)
- {
- g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "GDL failed to get display infomation: %s",
- gdl_get_error_string (rc));
- gdl_close ();
- return FALSE;
- }
-
- dstRect.origin.x = 0;
- dstRect.origin.y = 0;
- dstRect.width = display_info.tvmode.width;
- dstRect.height = display_info.tvmode.height;
-
- /* Configure the plane attribute. */
- rc = gdl_plane_reset (plane);
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_config_begin (plane);
-
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_set_attr (GDL_PLANE_SRC_COLOR_SPACE, &colorSpace);
-
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_set_attr (GDL_PLANE_PIXEL_FORMAT, &pixfmt);
-
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_set_attr (GDL_PLANE_DST_RECT, &dstRect);
-
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_set_uint (GDL_PLANE_NUM_GFX_SURFACES,
- display->swap_chain->length);
-
- if (rc == GDL_SUCCESS)
- rc = gdl_plane_config_end (GDL_FALSE);
- else
- gdl_plane_config_end (GDL_TRUE);
-
- if (rc != GDL_SUCCESS)
- {
- g_set_error (error, COGL_WINSYS_ERROR, COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "GDL configuration failed: %s.", gdl_get_error_string (rc));
- ret = FALSE;
- }
-
- gdl_close ();
-}
-#endif
-
-static gboolean
-_cogl_winsys_display_setup (CoglDisplay *display,
- GError **error)
-{
- CoglDisplayEGL *egl_display;
-
- g_return_val_if_fail (display->winsys == NULL, FALSE);
-
- egl_display = g_slice_new0 (CoglDisplayEGL);
- display->winsys = egl_display;
-
-#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
- if (!gdl_plane_init (display, error))
- goto error;
-#endif
-
- if (!create_context (display, error))
- goto error;
-
- egl_display->found_egl_config = TRUE;
-
- return TRUE;
-
-error:
- _cogl_winsys_display_destroy (display);
- return FALSE;
-}
-
-static gboolean
-_cogl_winsys_context_init (CoglContext *context, GError **error)
-{
- context->winsys = g_new0 (CoglContextEGL, 1);
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- cogl_renderer_add_native_filter (context->display->renderer,
- event_filter_cb,
- context);
-#endif
- update_winsys_features (context);
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_context_deinit (CoglContext *context)
-{
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- cogl_renderer_remove_native_filter (context->display->renderer,
- event_filter_cb,
- context);
-#endif
- g_free (context->winsys);
-}
-
-static gboolean
-_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
- GError **error)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
- CoglDisplay *display = context->display;
- CoglDisplayEGL *egl_display = display->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglRendererEGL *egl_renderer = display->renderer->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen;
- Window xwin;
-#endif
- CoglOnscreenEGL *egl_onscreen;
-
- g_return_val_if_fail (egl_display->egl_context, FALSE);
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-
- /* FIXME: We need to explicitly Select for ConfigureNotify events.
- * For foreign windows we need to be careful not to mess up any
- * existing event mask.
- * We need to document that for windows we create then toolkits
- * must be careful not to clear event mask bits that we select.
- */
-
- /* XXX: Note we ignore the user's original width/height when
- * given a foreign X window. */
- if (onscreen->foreign_xid)
- {
- Status status;
- CoglXlibTrapState state;
- XWindowAttributes attr;
- int xerror;
-
- xwin = onscreen->foreign_xid;
-
- _cogl_renderer_xlib_trap_errors (display->renderer, &state);
-
- status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr);
- xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
- if (status == 0 || xerror)
- {
- char message[1000];
- XGetErrorText (xlib_renderer->xdpy, xerror,
- message, sizeof (message));
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "Unable to query geometry of foreign xid 0x%08lX: %s",
- xwin, message);
- return FALSE;
- }
-
- _cogl_framebuffer_winsys_update_size (framebuffer,
- attr.width, attr.height);
-
- /* Make sure the app selects for the events we require... */
- onscreen->foreign_update_mask_callback (onscreen,
- COGL_ONSCREEN_X11_EVENT_MASK,
- onscreen->foreign_update_mask_data);
- }
- else
- {
- int width;
- int height;
- CoglXlibTrapState state;
- XVisualInfo *xvisinfo;
- XSetWindowAttributes xattr;
- unsigned long mask;
- int xerror;
-
- width = cogl_framebuffer_get_width (framebuffer);
- height = cogl_framebuffer_get_height (framebuffer);
-
- _cogl_renderer_xlib_trap_errors (display->renderer, &state);
-
- xvisinfo = get_visual_info (display, egl_display->egl_config);
- if (xvisinfo == NULL)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "Unable to retrieve the X11 visual of context's "
- "fbconfig");
- return FALSE;
- }
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (xlib_renderer->xdpy,
- DefaultScreen (xlib_renderer->xdpy));
- xattr.border_pixel = 0;
- /* XXX: is this an X resource that we are leaking‽... */
- xattr.colormap = XCreateColormap (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- xvisinfo->visual,
- AllocNone);
- attr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
-
- mask = CWBorderPixel | CWColormap | CWEventMask;
-
- xwin = XCreateWindow (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- 0, 0,
- width, height,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- XFree (xvisinfo);
-
- XSync (xlib_renderer->xdpy, False);
- xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
- if (xerror)
- {
- char message[1000];
- XGetErrorText (xlib_renderer->xdpy, xerror,
- message, sizeof (message));
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "X error while creating Window for CoglOnscreen: %s",
- message);
- return FALSE;
- }
- }
-#endif
-
- onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
- egl_onscreen = onscreen->winsys;
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- xlib_onscreen = onscreen->winsys;
-
- xlib_onscreen->xwin = xwin;
- xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE;
-
- egl_onscreen->egl_surface =
- eglCreateWindowSurface (egl_renderer->edpy,
- egl_display->egl_config,
- (NativeWindowType) xlib_onscreen->xwin,
- NULL);
-#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
- if (egl_display->have_onscreen)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "EGL platform only supports a single onscreen window");
- return FALSE;
- }
-
- egl_onscreen->egl_surface = egl_display->egl_surface;
-
- _cogl_framebuffer_winsys_update_size (framebuffer,
- egl_display->egl_surface_width,
- egl_display->egl_surface_height);
- egl_display->have_onscreen = TRUE;
-#else
-#error "Unknown EGL platform"
-#endif
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglXlibTrapState old_state;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
-#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
- CoglDisplayEGL *egl_display = context->display->winsys;
-#endif
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-
- if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
- {
- if (eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface)
- == EGL_FALSE)
- g_warning ("Failed to destroy EGL surface");
- egl_onscreen->egl_surface = EGL_NO_SURFACE;
- }
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT
- egl_display->have_onscreen = FALSE;
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- _cogl_xlib_trap_errors (&old_state);
-
- if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None)
- {
- XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
- xlib_onscreen->xwin = None;
- }
- else
- xlib_onscreen->xwin = None;
-
- XSync (xlib_renderer->xdpy, False);
-
- if (_cogl_xlib_untrap_errors (&old_state) != Success)
- g_warning ("X Error while destroying X window");
-#endif
-}
-
-static void
-_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglContextEGL *egl_context = context->winsys;
- CoglDisplayEGL *egl_display = context->display->winsys;
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-
- if (egl_context->current_surface == egl_onscreen->egl_surface)
- return;
-
- if (G_UNLIKELY (!onscreen))
- {
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- eglMakeCurrent (egl_renderer->edpy,
- egl_display->dummy_surface,
- egl_display->dummy_surface,
- egl_display->egl_context);
- egl_context->current_surface = egl_display->dummy_surface;
-#elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT)
- return;
-#else
-#error "Unknown EGL platform"
-#endif
- }
- else
- {
- eglMakeCurrent (egl_renderer->edpy,
- egl_onscreen->egl_surface,
- egl_onscreen->egl_surface,
- egl_display->egl_context);
- egl_context->current_surface = egl_onscreen->egl_surface;
- }
-
- if (onscreen->swap_throttled)
- eglSwapInterval (egl_renderer->edpy, 1);
- else
- eglSwapInterval (egl_renderer->edpy, 0);
-}
-
-static void
-_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
- int *rectangles,
- int n_rectangles)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-
- if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
- egl_onscreen->egl_surface,
- n_rectangles,
- rectangles) == EGL_FALSE)
- g_warning ("Error reported by eglSwapBuffersRegion");
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-static void
-_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
- gboolean visibility)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
-
- if (visibility)
- XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
- else
- XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
-}
-#endif
-
-static guint32
-_cogl_winsys_get_vsync_counter (void)
-{
- /* Unsupported feature */
- return 0;
-}
-
-static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-
- eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
-}
-
-static guint32
-_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
-{
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- return xlib_onscreen->xwin;
-}
-
-static unsigned int
-_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
- CoglSwapBuffersNotify callback,
- void *user_data)
-{
- /* Unsupported feature */
- return 0;
-}
-
-static void
-_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
- unsigned int id)
-{
- /* Unsupported feature */
-}
-
-static void
-_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglContextEGL *egl_context = context->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-
- if (egl_context->current_surface != egl_onscreen->egl_surface)
- return;
-
- egl_context->current_surface = EGL_NO_SURFACE;
- _cogl_winsys_onscreen_bind (onscreen);
-}
-
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-/* XXX: This is a particularly hacky _cogl_winsys interface... */
-static XVisualInfo *
-_cogl_winsys_xlib_get_visual_info (void)
-{
- CoglDisplayEGL *egl_display;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_return_val_if_fail (ctx->display->winsys, FALSE);
-
- egl_display = ctx->display->winsys;
-
- if (!egl_display->found_egl_config)
- return NULL;
-
- return get_visual_info (ctx->display, egl_display->egl_config);
-}
-#endif
-
-static EGLDisplay
-_cogl_winsys_context_egl_get_egl_display (CoglContext *context)
-{
- CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
-
- return egl_renderer->edpy;
-}
-
-static CoglWinsysVtable _cogl_winsys_vtable =
- {
- .name = "EGL",
- .get_proc_address = _cogl_winsys_get_proc_address,
- .renderer_connect = _cogl_winsys_renderer_connect,
- .renderer_disconnect = _cogl_winsys_renderer_disconnect,
- .display_setup = _cogl_winsys_display_setup,
- .display_destroy = _cogl_winsys_display_destroy,
- .context_init = _cogl_winsys_context_init,
- .context_deinit = _cogl_winsys_context_deinit,
- .context_egl_get_egl_display =
- _cogl_winsys_context_egl_get_egl_display,
-#ifdef COGL_HAS_XLIB_SUPPORT
- .xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
-#endif
- .onscreen_init = _cogl_winsys_onscreen_init,
- .onscreen_deinit = _cogl_winsys_onscreen_deinit,
- .onscreen_bind = _cogl_winsys_onscreen_bind,
- .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
- .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility,
-#endif
- .onscreen_update_swap_throttled =
- _cogl_winsys_onscreen_update_swap_throttled,
- .onscreen_x11_get_window_xid =
- _cogl_winsys_onscreen_x11_get_window_xid,
- .onscreen_add_swap_buffers_callback =
- _cogl_winsys_onscreen_add_swap_buffers_callback,
- .onscreen_remove_swap_buffers_callback =
- _cogl_winsys_onscreen_remove_swap_buffers_callback,
- .get_vsync_counter = _cogl_winsys_get_vsync_counter
- };
-
-/* XXX: we use a function because no doubt someone will complain
- * about using c99 member initializers because they aren't portable
- * to windows. We want to avoid having to rigidly follow the real
- * order of members since some members are #ifdefd and we'd have
- * to mirror the #ifdefing to add padding etc. For any winsys that
- * can assume the platform has a sane compiler then we can just use
- * c99 initializers for insane platforms they can initialize
- * the members by name in a function.
- */
-const CoglWinsysVtable *
-_cogl_winsys_egl_get_vtable (void)
-{
- return &_cogl_winsys_vtable;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-/* This can be included multiple times with different definitions for
- * the COGL_WINSYS_FEATURE_* functions.
- */
-
-/* Macro prototypes:
- * COGL_WINSYS_FEATURE_BEGIN (name, namespaces, extension_names,
- * implied_public_feature_flags,
- * implied_private_feature_flags,
- * implied_winsys_feature)
- * COGL_WINSYS_FEATURE_FUNCTION (return_type, function_name,
- * (arguments))
- * ...
- * COGL_WINSYS_FEATURE_END ()
- *
- * Note: You can list multiple namespace and extension names if the
- * corresponding _FEATURE_FUNCTIONS have the same semantics accross
- * the different extension variants.
- *
- * XXX: NB: Don't add a trailing semicolon when using these macros
- */
-
-COGL_WINSYS_FEATURE_BEGIN (texture_from_pixmap,
- "EXT\0",
- "texture_from_pixmap\0",
- 0,
- 0,
- COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP)
-COGL_WINSYS_FEATURE_FUNCTION (void, glXBindTexImage,
- (Display *display,
- GLXDrawable drawable,
- int buffer,
- int *attribList))
-COGL_WINSYS_FEATURE_FUNCTION (void, glXReleaseTexImage,
- (Display *display,
- GLXDrawable drawable,
- int buffer))
-COGL_WINSYS_FEATURE_END ()
-
-COGL_WINSYS_FEATURE_BEGIN (video_sync,
- "SGI\0",
- "video_sync\0",
- 0,
- 0,
- COGL_WINSYS_FEATURE_VBLANK_COUNTER)
-COGL_WINSYS_FEATURE_FUNCTION (int, glXGetVideoSync,
- (unsigned int *count))
-COGL_WINSYS_FEATURE_FUNCTION (int, glXWaitVideoSync,
- (int divisor,
- int remainder,
- unsigned int *count))
-COGL_WINSYS_FEATURE_END ()
-
-COGL_WINSYS_FEATURE_BEGIN (swap_control,
- "SGI\0",
- "swap_control\0",
- 0,
- 0,
- COGL_WINSYS_FEATURE_SWAP_THROTTLE)
-COGL_WINSYS_FEATURE_FUNCTION (int, glXSwapInterval,
- (int interval))
-COGL_WINSYS_FEATURE_END ()
-
-COGL_WINSYS_FEATURE_BEGIN (copy_sub_buffer,
- "MESA\0",
- "copy_sub_buffer\0",
- 0,
- 0,
- 0)
-COGL_WINSYS_FEATURE_FUNCTION (void, glXCopySubBuffer,
- (Display *dpy,
- GLXDrawable drawable,
- int x, int y, int width, int height))
-COGL_WINSYS_FEATURE_END ()
-
-COGL_WINSYS_FEATURE_BEGIN (swap_event,
- "INTEL\0",
- "swap_event\0",
- 0,
- 0,
- COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT)
-COGL_WINSYS_FEATURE_END ()
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010,2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- * Authors:
- * Robert Bragg <robert@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-#include "cogl-winsys-private.h"
-#include "cogl-feature-private.h"
-#include "cogl-context-private.h"
-#include "cogl-framebuffer.h"
-#include "cogl-swap-chain-private.h"
-#include "cogl-renderer-private.h"
-#include "cogl-renderer-glx-private.h"
-#include "cogl-onscreen-template-private.h"
-#include "cogl-display-xlib-private.h"
-#include "cogl-display-glx-private.h"
-#include "cogl-private.h"
-#include "cogl-texture-2d-private.h"
-#include "cogl-texture-rectangle-private.h"
-#include "cogl-pipeline-opengl-private.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <glib/gi18n-lib.h>
-
-#include <dlfcn.h>
-#include <GL/glx.h>
-#include <X11/Xlib.h>
-
-typedef CoglFuncPtr (*GLXGetProcAddressProc) (const GLubyte *procName);
-
-#ifdef HAVE_DRM
-#include <drm.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-#endif
-
-#define COGL_ONSCREEN_X11_EVENT_MASK StructureNotifyMask
-
-typedef struct _CoglContextGLX
-{
- GLXDrawable current_drawable;
-} CoglContextGLX;
-
-typedef struct _CoglOnscreenXlib
-{
- Window xwin;
- gboolean is_foreign_xwin;
-} CoglOnscreenXlib;
-
-typedef struct _CoglOnscreenGLX
-{
- CoglOnscreenXlib _parent;
- GLXDrawable glxwin;
- guint32 last_swap_vsync_counter;
- GList *swap_callbacks;
-} CoglOnscreenGLX;
-
-typedef struct _CoglSwapBuffersNotifyEntry
-{
- CoglSwapBuffersNotify callback;
- void *user_data;
- unsigned int id;
-} CoglSwapBuffersNotifyEntry;
-
-typedef struct _CoglTexturePixmapGLX
-{
- GLXPixmap glx_pixmap;
- gboolean has_mipmap_space;
- gboolean can_mipmap;
-
- CoglHandle glx_tex;
-
- gboolean bind_tex_image_queued;
- gboolean pixmap_bound;
-} CoglTexturePixmapGLX;
-
-/* Define a set of arrays containing the functions required from GL
- for each winsys feature */
-#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature) \
- static const CoglFeatureFunction \
- cogl_glx_feature_ ## name ## _funcs[] = {
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- { G_STRINGIFY (name), G_STRUCT_OFFSET (CoglRendererGLX, pf_ ## name) },
-#define COGL_WINSYS_FEATURE_END() \
- { NULL, 0 }, \
- };
-#include "cogl-winsys-glx-feature-functions.h"
-
-/* Define an array of features */
-#undef COGL_WINSYS_FEATURE_BEGIN
-#define COGL_WINSYS_FEATURE_BEGIN(name, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature) \
- { 255, 255, namespaces, extension_names, \
- feature_flags, feature_flags_private, \
- winsys_feature, \
- cogl_glx_feature_ ## name ## _funcs },
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args)
-#undef COGL_WINSYS_FEATURE_END
-#define COGL_WINSYS_FEATURE_END()
-
-static const CoglFeatureData winsys_feature_data[] =
- {
-#include "cogl-winsys-glx-feature-functions.h"
- };
-
-CoglFuncPtr
-_cogl_winsys_get_proc_address (const char *name)
-{
- static GLXGetProcAddressProc get_proc_func = NULL;
- static void *dlhand = NULL;
-
- if (get_proc_func == NULL && dlhand == NULL)
- {
- dlhand = dlopen (NULL, RTLD_LAZY);
-
- if (!dlhand)
- {
- g_warning ("Failed to dlopen (NULL, RTDL_LAZY): %s", dlerror ());
- return NULL;
- }
-
- dlerror ();
-
- get_proc_func =
- (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
-
- if (dlerror () != NULL)
- {
- get_proc_func =
- (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
- }
-
- if (dlerror () != NULL)
- {
- get_proc_func = NULL;
- g_warning ("failed to bind GLXGetProcAddress "
- "or GLXGetProcAddressARB");
- }
- }
-
- if (get_proc_func)
- return get_proc_func ((GLubyte *) name);
-
- return NULL;
-}
-
-#undef COGL_WINSYS_FEATURE_BEGIN
-#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d, e, f)
-#undef COGL_WINSYS_FEATURE_FUNCTION
-#define COGL_WINSYS_FEATURE_FUNCTION(ret, name, args) \
- glx_renderer->pf_ ## name = NULL;
-#undef COGL_WINSYS_FEATURE_END
-#define COGL_WINSYS_FEATURE_END()
-
-static void
-initialize_function_table (CoglRenderer *renderer)
-{
- CoglRendererGLX *glx_renderer = renderer->winsys;
-
-#include "cogl-winsys-glx-feature-functions.h"
-}
-
-static CoglOnscreen *
-find_onscreen_for_xid (CoglContext *context, guint32 xid)
-{
- GList *l;
-
- for (l = context->framebuffers; l; l = l->next)
- {
- CoglFramebuffer *framebuffer = l->data;
- CoglOnscreenXlib *xlib_onscreen;
-
- if (framebuffer->type != COGL_FRAMEBUFFER_TYPE_ONSCREEN)
- continue;
-
- /* Does the GLXEvent have the GLXDrawable or the X Window? */
- xlib_onscreen = COGL_ONSCREEN (framebuffer)->winsys;
- if (xlib_onscreen->xwin == (Window)xid)
- return COGL_ONSCREEN (framebuffer);
- }
-
- return NULL;
-}
-
-static void
-notify_swap_buffers (CoglContext *context, GLXDrawable drawable)
-{
- CoglOnscreen *onscreen = find_onscreen_for_xid (context, (guint32)drawable);
- CoglOnscreenGLX *glx_onscreen;
- GList *l;
-
- if (!onscreen)
- return;
-
- glx_onscreen = onscreen->winsys;
-
- for (l = glx_onscreen->swap_callbacks; l; l = l->next)
- {
- CoglSwapBuffersNotifyEntry *entry = l->data;
- entry->callback (COGL_FRAMEBUFFER (onscreen), entry->user_data);
- }
-}
-
-static CoglFilterReturn
-glx_event_filter_cb (void *native_event, void *data)
-{
- XEvent *xevent = native_event;
- CoglContext *context = data;
-#ifdef GLX_INTEL_swap_event
- CoglRendererGLX *glx_renderer;
-#endif
-
- if (xevent->type == ConfigureNotify)
- {
- CoglOnscreen *onscreen =
- find_onscreen_for_xid (context, xevent->xconfigure.window);
-
- if (onscreen)
- {
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-
- _cogl_framebuffer_winsys_update_size (framebuffer,
- xevent->xconfigure.width,
- xevent->xconfigure.height);
- }
-
- /* we let ConfigureNotify pass through */
- return COGL_FILTER_CONTINUE;
- }
-
-#ifdef GLX_INTEL_swap_event
- glx_renderer = context->display->renderer->winsys;
-
- if (xevent->type == (glx_renderer->glx_event_base + GLX_BufferSwapComplete))
- {
- GLXBufferSwapComplete *swap_event = (GLXBufferSwapComplete *) xevent;
-
- notify_swap_buffers (context, swap_event->drawable);
-
- /* remove SwapComplete events from the queue */
- return COGL_FILTER_REMOVE;
- }
-#endif /* GLX_INTEL_swap_event */
-
- return COGL_FILTER_CONTINUE;
-}
-
-static void
-_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
-{
- _cogl_renderer_xlib_disconnect (renderer);
-
- g_slice_free (CoglRendererGLX, renderer->winsys);
-}
-
-static gboolean
-_cogl_winsys_renderer_connect (CoglRenderer *renderer,
- GError **error)
-{
- CoglRendererGLX *glx_renderer;
- CoglRendererXlib *xlib_renderer;
-
- renderer->winsys = g_slice_new0 (CoglRendererGLX);
-
- glx_renderer = renderer->winsys;
- xlib_renderer = renderer->winsys;
-
- if (!_cogl_renderer_xlib_connect (renderer, error))
- goto error;
-
- if (!glXQueryExtension (xlib_renderer->xdpy,
- &glx_renderer->glx_error_base,
- &glx_renderer->glx_event_base))
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "XServer appears to lack required GLX support");
- goto error;
- }
-
- /* XXX: Note: For a long time Mesa exported a hybrid GLX, exporting
- * extensions specified to require GLX 1.3, but still reporting 1.2
- * via glXQueryVersion. */
- if (!glXQueryVersion (xlib_renderer->xdpy,
- &glx_renderer->glx_major,
- &glx_renderer->glx_minor)
- || !(glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 2))
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_INIT,
- "XServer appears to lack required GLX 1.2 support");
- goto error;
- }
-
- glx_renderer->dri_fd = -1;
-
- return TRUE;
-
-error:
- _cogl_winsys_renderer_disconnect (renderer);
- return FALSE;
-}
-
-static void
-update_winsys_features (CoglContext *context)
-{
- CoglDisplayGLX *glx_display = context->display->winsys;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
- const char *glx_extensions;
- int i;
-
- g_return_if_fail (glx_display->glx_context);
-
- _cogl_gl_update_features (context);
-
- memset (context->winsys_features, 0, sizeof (context->winsys_features));
-
- glx_extensions =
- glXQueryExtensionsString (xlib_renderer->xdpy,
- DefaultScreen (xlib_renderer->xdpy));
-
- COGL_NOTE (WINSYS, " GLX Extensions: %s", glx_extensions);
-
- context->feature_flags |= COGL_FEATURE_ONSCREEN_MULTIPLE;
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_MULTIPLE_ONSCREEN,
- TRUE);
-
- initialize_function_table (context->display->renderer);
-
- for (i = 0; i < G_N_ELEMENTS (winsys_feature_data); i++)
- if (_cogl_feature_check ("GLX", winsys_feature_data + i, 0, 0,
- glx_extensions,
- glx_renderer))
- {
- context->feature_flags |= winsys_feature_data[i].feature_flags;
- if (winsys_feature_data[i].winsys_feature)
- COGL_FLAGS_SET (context->winsys_features,
- winsys_feature_data[i].winsys_feature,
- TRUE);
- }
-
- /* Note: the GLX_SGI_video_sync spec explicitly states this extension
- * only works for direct contexts. */
- if (!glx_renderer->is_direct)
- {
- glx_renderer->pf_glXGetVideoSync = NULL;
- glx_renderer->pf_glXWaitVideoSync = NULL;
- }
-
- if (glx_renderer->pf_glXWaitVideoSync)
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_VBLANK_WAIT,
- TRUE);
-
-#ifdef HAVE_DRM
- /* drm is really an extreme fallback -rumoured to work with Via
- * chipsets... */
- if (!glx_renderer->pf_glXWaitVideoSync)
- {
- if (glx_renderer->dri_fd < 0)
- glx_renderer->dri_fd = open("/dev/dri/card0", O_RDWR);
- if (glx_renderer->dri_fd >= 0)
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_VBLANK_WAIT,
- TRUE);
- }
-#endif
-
- if (glx_renderer->pf_glXCopySubBuffer || context->drv.pf_glBlitFramebuffer)
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_SWAP_REGION, TRUE);
-
- /* Note: glXCopySubBuffer and glBlitFramebuffer won't be throttled
- * by the SwapInterval so we have to throttle swap_region requests
- * manually... */
- if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_REGION) &&
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT))
- COGL_FLAGS_SET (context->winsys_features,
- COGL_WINSYS_FEATURE_SWAP_REGION_THROTTLE, TRUE);
-}
-
-/* It seems the GLX spec never defined an invalid GLXFBConfig that
- * we could overload as an indication of error, so we have to return
- * an explicit boolean status. */
-static gboolean
-find_fbconfig (CoglDisplay *display,
- gboolean with_alpha,
- GLXFBConfig *config_ret,
- GError **error)
-{
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
- GLXFBConfig *configs = NULL;
- int n_configs, i;
- static const int attributes[] = {
- GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
- GLX_RENDER_TYPE, GLX_RGBA_BIT,
- GLX_DOUBLEBUFFER, GL_TRUE,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_ALPHA_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- GLX_STENCIL_SIZE, 1,
- None
- };
- gboolean ret = TRUE;
- int xscreen_num = DefaultScreen (xlib_renderer->xdpy);
-
- configs = glXChooseFBConfig (xlib_renderer->xdpy,
- xscreen_num,
- attributes,
- &n_configs);
- if (!configs || n_configs == 0)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Failed to find any compatible fbconfigs");
- ret = FALSE;
- goto done;
- }
-
- if (with_alpha)
- {
- for (i = 0; i < n_configs; i++)
- {
- XVisualInfo *vinfo;
-
- vinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, configs[i]);
- if (vinfo == NULL)
- continue;
-
- if (vinfo->depth == 32 &&
- (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask)
- != 0xffffffff)
- {
- COGL_NOTE (WINSYS, "Found an ARGB FBConfig [index:%d]", i);
- *config_ret = configs[i];
- goto done;
- }
- }
-
- /* If we make it here then we didn't find an RGBA config so
- we'll fall back to using an RGB config */
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to find fbconfig with rgba visual");
- ret = FALSE;
- goto done;
- }
- else
- {
- COGL_NOTE (WINSYS, "Using the first available FBConfig");
- *config_ret = configs[0];
- }
-
-done:
- XFree (configs);
- return ret;
-}
-
-static gboolean
-create_context (CoglDisplay *display, GError **error)
-{
- CoglDisplayGLX *glx_display = display->winsys;
- CoglDisplayXlib *xlib_display = display->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
- CoglRendererGLX *glx_renderer = display->renderer->winsys;
- gboolean support_transparent_windows;
- GLXFBConfig config;
- GError *fbconfig_error = NULL;
- XSetWindowAttributes attrs;
- XVisualInfo *xvisinfo;
- GLXDrawable dummy_drawable;
- CoglXlibTrapState old_state;
-
- g_return_val_if_fail (glx_display->glx_context == NULL, TRUE);
-
- if (display->onscreen_template &&
- display->onscreen_template->swap_chain &&
- display->onscreen_template->swap_chain->has_alpha)
- support_transparent_windows = TRUE;
- else
- support_transparent_windows = FALSE;
-
- glx_display->found_fbconfig =
- find_fbconfig (display, support_transparent_windows, &config,
- &fbconfig_error);
- if (!glx_display->found_fbconfig)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to find suitable fbconfig for the GLX context: %s",
- fbconfig_error->message);
- g_error_free (fbconfig_error);
- return FALSE;
- }
-
- glx_display->fbconfig = config;
- glx_display->fbconfig_has_rgba_visual = support_transparent_windows;
-
- COGL_NOTE (WINSYS, "Creating GLX Context (display: %p)",
- xlib_renderer->xdpy);
-
- glx_display->glx_context = glXCreateNewContext (xlib_renderer->xdpy,
- config,
- GLX_RGBA_TYPE,
- NULL,
- True);
- if (glx_display->glx_context == NULL)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to create suitable GL context");
- return FALSE;
- }
-
- glx_renderer->is_direct =
- glXIsDirect (xlib_renderer->xdpy, glx_display->glx_context);
-
- COGL_NOTE (WINSYS, "Setting %s context",
- glx_renderer->is_direct ? "direct" : "indirect");
-
- /* XXX: GLX doesn't let us make a context current without a window
- * so we create a dummy window that we can use while no CoglOnscreen
- * framebuffer is in use.
- */
-
- xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy, config);
- if (xvisinfo == NULL)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to retrieve the X11 visual");
- return FALSE;
- }
-
- _cogl_renderer_xlib_trap_errors (display->renderer, &old_state);
-
- attrs.override_redirect = True;
- attrs.colormap = XCreateColormap (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- xvisinfo->visual,
- AllocNone);
- attrs.border_pixel = 0;
-
- xlib_display->dummy_xwin =
- XCreateWindow (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- -100, -100, 1, 1,
- 0,
- xvisinfo->depth,
- CopyFromParent,
- xvisinfo->visual,
- CWOverrideRedirect | CWColormap | CWBorderPixel,
- &attrs);
-
- /* Try and create a GLXWindow to use with extensions dependent on
- * GLX versions >= 1.3 that don't accept regular X Windows as GLX
- * drawables. */
- if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3)
- {
- glx_display->dummy_glxwin = glXCreateWindow (xlib_renderer->xdpy,
- config,
- xlib_display->dummy_xwin,
- NULL);
- }
-
- if (glx_display->dummy_glxwin)
- dummy_drawable = glx_display->dummy_glxwin;
- else
- dummy_drawable = xlib_display->dummy_xwin;
-
- COGL_NOTE (WINSYS, "Selecting dummy 0x%x for the GLX context",
- (unsigned int) dummy_drawable);
-
- glXMakeContextCurrent (xlib_renderer->xdpy,
- dummy_drawable,
- dummy_drawable,
- glx_display->glx_context);
-
- XFree (xvisinfo);
-
- if (_cogl_renderer_xlib_untrap_errors (display->renderer, &old_state))
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- "Unable to select the newly created GLX context");
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_display_destroy (CoglDisplay *display)
-{
- CoglDisplayGLX *glx_display = display->winsys;
- CoglDisplayXlib *xlib_display = display->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
-
- g_return_if_fail (glx_display != NULL);
-
- if (glx_display->glx_context)
- {
- glXMakeContextCurrent (xlib_renderer->xdpy, None, None, NULL);
- glXDestroyContext (xlib_renderer->xdpy, glx_display->glx_context);
- glx_display->glx_context = NULL;
- }
-
- if (glx_display->dummy_glxwin)
- {
- glXDestroyWindow (xlib_renderer->xdpy, glx_display->dummy_glxwin);
- glx_display->dummy_glxwin = None;
- }
-
- if (xlib_display->dummy_xwin)
- {
- XDestroyWindow (xlib_renderer->xdpy, xlib_display->dummy_xwin);
- xlib_display->dummy_xwin = None;
- }
-
- g_slice_free (CoglDisplayGLX, display->winsys);
- display->winsys = NULL;
-}
-
-static gboolean
-_cogl_winsys_display_setup (CoglDisplay *display,
- GError **error)
-{
- CoglDisplayGLX *glx_display;
- int i;
-
- g_return_val_if_fail (display->winsys == NULL, FALSE);
-
- glx_display = g_slice_new0 (CoglDisplayGLX);
- display->winsys = glx_display;
-
- if (!create_context (display, error))
- goto error;
-
- for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
- glx_display->glx_cached_configs[i].depth = -1;
-
- return TRUE;
-
-error:
- _cogl_winsys_display_destroy (display);
- return FALSE;
-}
-
-static gboolean
-_cogl_winsys_context_init (CoglContext *context, GError **error)
-{
- context->winsys = g_new0 (CoglContextGLX, 1);
-
- cogl_renderer_add_native_filter (context->display->renderer,
- glx_event_filter_cb,
- context);
- update_winsys_features (context);
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_context_deinit (CoglContext *context)
-{
- cogl_renderer_remove_native_filter (context->display->renderer,
- glx_event_filter_cb,
- context);
- g_free (context->winsys);
-}
-
-static gboolean
-_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
- GError **error)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
- CoglDisplay *display = context->display;
- CoglDisplayGLX *glx_display = display->winsys;
- CoglRendererXlib *xlib_renderer = display->renderer->winsys;
- CoglRendererGLX *glx_renderer = display->renderer->winsys;
- Window xwin;
- CoglOnscreenXlib *xlib_onscreen;
- CoglOnscreenGLX *glx_onscreen;
-
- g_return_val_if_fail (glx_display->glx_context, FALSE);
-
- /* FIXME: We need to explicitly Select for ConfigureNotify events.
- * For foreign windows we need to be careful not to mess up any
- * existing event mask.
- * We need to document that for windows we create then toolkits
- * must be careful not to clear event mask bits that we select.
- */
-
- /* XXX: Note we ignore the user's original width/height when
- * given a foreign X window. */
- if (onscreen->foreign_xid)
- {
- Status status;
- CoglXlibTrapState state;
- XWindowAttributes attr;
- int xerror;
-
- xwin = onscreen->foreign_xid;
-
- _cogl_renderer_xlib_trap_errors (display->renderer, &state);
-
- status = XGetWindowAttributes (xlib_renderer->xdpy, xwin, &attr);
- XSync (xlib_renderer->xdpy, False);
- xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
- if (status == 0 || xerror)
- {
- char message[1000];
- XGetErrorText (xlib_renderer->xdpy, xerror, message, sizeof(message));
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "Unable to query geometry of foreign xid 0x%08lX: %s",
- xwin, message);
- return FALSE;
- }
-
- _cogl_framebuffer_winsys_update_size (framebuffer,
- attr.width, attr.height);
-
- /* Make sure the app selects for the events we require... */
- onscreen->foreign_update_mask_callback (onscreen,
- COGL_ONSCREEN_X11_EVENT_MASK,
- onscreen->foreign_update_mask_data);
- }
- else
- {
- int width;
- int height;
- CoglXlibTrapState state;
- XVisualInfo *xvisinfo;
- XSetWindowAttributes xattr;
- unsigned long mask;
- int xerror;
-
- width = cogl_framebuffer_get_width (framebuffer);
- height = cogl_framebuffer_get_height (framebuffer);
-
- _cogl_renderer_xlib_trap_errors (display->renderer, &state);
-
- xvisinfo = glXGetVisualFromFBConfig (xlib_renderer->xdpy,
- glx_display->fbconfig);
- if (xvisinfo == NULL)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "Unable to retrieve the X11 visual of context's "
- "fbconfig");
- return FALSE;
- }
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (xlib_renderer->xdpy,
- DefaultScreen (xlib_renderer->xdpy));
- xattr.border_pixel = 0;
- /* XXX: is this an X resource that we are leaking‽... */
- xattr.colormap = XCreateColormap (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- xvisinfo->visual,
- AllocNone);
- xattr.event_mask = COGL_ONSCREEN_X11_EVENT_MASK;
-
- mask = CWBorderPixel | CWColormap | CWEventMask;
-
- xwin = XCreateWindow (xlib_renderer->xdpy,
- DefaultRootWindow (xlib_renderer->xdpy),
- 0, 0,
- width, height,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- XFree (xvisinfo);
-
- XSync (xlib_renderer->xdpy, False);
- xerror = _cogl_renderer_xlib_untrap_errors (display->renderer, &state);
- if (xerror)
- {
- char message[1000];
- XGetErrorText (xlib_renderer->xdpy, xerror,
- message, sizeof (message));
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "X error while creating Window for CoglOnscreen: %s",
- message);
- return FALSE;
- }
- }
-
- onscreen->winsys = g_slice_new0 (CoglOnscreenGLX);
- xlib_onscreen = onscreen->winsys;
- glx_onscreen = onscreen->winsys;
-
- xlib_onscreen->xwin = xwin;
- xlib_onscreen->is_foreign_xwin = onscreen->foreign_xid ? TRUE : FALSE;
-
- /* Try and create a GLXWindow to use with extensions dependent on
- * GLX versions >= 1.3 that don't accept regular X Windows as GLX
- * drawables. */
- if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 3)
- {
- glx_onscreen->glxwin =
- glXCreateWindow (xlib_renderer->xdpy,
- glx_display->fbconfig,
- xlib_onscreen->xwin,
- NULL);
- }
-
-#ifdef GLX_INTEL_swap_event
- if (_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT))
- {
- GLXDrawable drawable =
- glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
-
- /* similarly to above, we unconditionally select this event
- * because we rely on it to advance the master clock, and
- * drive redraw/relayout, animations and event handling.
- */
- glXSelectEvent (xlib_renderer->xdpy,
- drawable,
- GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK);
- }
-#endif /* GLX_INTEL_swap_event */
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglXlibTrapState old_state;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
-
- _cogl_xlib_trap_errors (&old_state);
-
- if (glx_onscreen->glxwin != None)
- {
- glXDestroyWindow (xlib_renderer->xdpy, glx_onscreen->glxwin);
- glx_onscreen->glxwin = None;
- }
-
- if (!xlib_onscreen->is_foreign_xwin && xlib_onscreen->xwin != None)
- {
- XDestroyWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
- xlib_onscreen->xwin = None;
- }
- else
- xlib_onscreen->xwin = None;
-
- XSync (xlib_renderer->xdpy, False);
-
- _cogl_xlib_untrap_errors (&old_state);
-}
-
-static void
-_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglContextGLX *glx_context = context->winsys;
- CoglDisplayXlib *xlib_display = context->display->winsys;
- CoglDisplayGLX *glx_display = context->display->winsys;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- CoglXlibTrapState old_state;
- GLXDrawable drawable;
-
- if (G_UNLIKELY (!onscreen))
- {
- drawable =
- glx_display->dummy_glxwin ?
- glx_display->dummy_glxwin : xlib_display->dummy_xwin;
-
- if (glx_context->current_drawable == drawable)
- return;
-
- _cogl_xlib_trap_errors (&old_state);
-
- glXMakeContextCurrent (xlib_renderer->xdpy,
- drawable, drawable,
- glx_display->glx_context);
- }
- else
- {
- drawable =
- glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
-
- if (glx_context->current_drawable == drawable)
- return;
-
- _cogl_xlib_trap_errors (&old_state);
-
- COGL_NOTE (WINSYS,
- "MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
- xlib_renderer->xdpy,
- (unsigned int) drawable,
- xlib_onscreen->is_foreign_xwin ? "foreign" : "native",
- glx_display->glx_context);
-
- glXMakeContextCurrent (xlib_renderer->xdpy,
- drawable,
- drawable,
- glx_display->glx_context);
-
- /* In case we are using GLX_SGI_swap_control for vblank syncing
- * we need call glXSwapIntervalSGI here to make sure that it
- * affects the current drawable.
- *
- * Note: we explicitly set to 0 when we aren't using the swap
- * interval to synchronize since some drivers have a default
- * swap interval of 1. Sadly some drivers even ignore requests
- * to disable the swap interval.
- *
- * NB: glXSwapIntervalSGI applies to the context not the
- * drawable which is why we can't just do this once when the
- * framebuffer is allocated.
- *
- * FIXME: We should check for GLX_EXT_swap_control which allows
- * per framebuffer swap intervals. GLX_MESA_swap_control also
- * allows per-framebuffer swap intervals but the semantics tend
- * to be more muddled since Mesa drivers tend to expose both the
- * MESA and SGI extensions which should technically be mutually
- * exclusive.
- */
- if (glx_renderer->pf_glXSwapInterval)
- {
- if (onscreen->swap_throttled)
- glx_renderer->pf_glXSwapInterval (1);
- else
- glx_renderer->pf_glXSwapInterval (0);
- }
- }
-
- XSync (xlib_renderer->xdpy, False);
-
- /* FIXME: We should be reporting a GError here
- */
- if (_cogl_xlib_untrap_errors (&old_state))
- {
- g_warning ("X Error received while making drawable 0x%08lX current",
- drawable);
- return;
- }
-
- glx_context->current_drawable = drawable;
-}
-
-#ifdef HAVE_DRM
-static int
-drm_wait_vblank (int fd, drm_wait_vblank_t *vbl)
-{
- int ret, rc;
-
- do
- {
- ret = ioctl (fd, DRM_IOCTL_WAIT_VBLANK, vbl);
- vbl->request.type &= ~_DRM_VBLANK_RELATIVE;
- rc = errno;
- }
- while (ret && rc == EINTR);
-
- return rc;
-}
-#endif /* HAVE_DRM */
-
-static void
-_cogl_winsys_wait_for_vblank (void)
-{
- CoglRendererGLX *glx_renderer;
-
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- glx_renderer = ctx->display->renderer->winsys;
-
- if (glx_renderer->pf_glXGetVideoSync)
- {
- guint32 current_count;
-
- glx_renderer->pf_glXGetVideoSync (¤t_count);
- glx_renderer->pf_glXWaitVideoSync (2,
- (current_count + 1) % 2,
- ¤t_count);
- }
-#ifdef HAVE_DRM
- else
- {
- drm_wait_vblank_t blank;
-
- COGL_NOTE (WINSYS, "Waiting for vblank (drm)");
- blank.request.type = _DRM_VBLANK_RELATIVE;
- blank.request.sequence = 1;
- blank.request.signal = 0;
- drm_wait_vblank (glx_renderer->dri_fd, &blank);
- }
-#endif /* HAVE_DRM */
-}
-
-static guint32
-_cogl_winsys_get_vsync_counter (void)
-{
- guint32 video_sync_count;
- CoglRendererGLX *glx_renderer;
-
- _COGL_GET_CONTEXT (ctx, 0);
-
- glx_renderer = ctx->display->renderer->winsys;
-
- glx_renderer->pf_glXGetVideoSync (&video_sync_count);
-
- return video_sync_count;
-}
-
-static void
-_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
- int *rectangles,
- int n_rectangles)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- GLXDrawable drawable =
- glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
- guint32 end_frame_vsync_counter = 0;
- gboolean have_counter;
- gboolean can_wait;
-
- _cogl_framebuffer_flush_state (framebuffer,
- framebuffer,
- COGL_FRAMEBUFFER_FLUSH_BIND_ONLY);
-
- if (onscreen->swap_throttled)
- {
- have_counter =
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
- can_wait = _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
- }
- else
- {
- have_counter = FALSE;
- can_wait = FALSE;
- }
-
- /* We need to ensure that all the rendering is done, otherwise
- * redraw operations that are slower than the framerate can
- * queue up in the pipeline during a heavy animation, causing a
- * larger and larger backlog of rendering visible as lag to the
- * user.
- *
- * For an exaggerated example consider rendering at 60fps (so 16ms
- * per frame) and you have a really slow frame that takes 160ms to
- * render, even though painting the scene and issuing the commands
- * to the GPU takes no time at all. If all we did was use the
- * video_sync extension to throttle the painting done by the CPU
- * then every 16ms we would have another frame queued up even though
- * the GPU has only rendered one tenth of the current frame. By the
- * time the GPU would get to the 2nd frame there would be 9 frames
- * waiting to be rendered.
- *
- * The problem is that we don't currently have a good way to throttle
- * the GPU, only the CPU so we have to resort to synchronizing the
- * GPU with the CPU to throttle it.
- *
- * Note: since calling glFinish() and synchronizing the CPU with
- * the GPU is far from ideal, we hope that this is only a short
- * term solution.
- * - One idea is to using sync objects to track render
- * completion so we can throttle the backlog (ideally with an
- * additional extension that lets us get notifications in our
- * mainloop instead of having to busy wait for the
- * completion.)
- * - Another option is to support clipped redraws by reusing the
- * contents of old back buffers such that we can flip instead
- * of using a blit and then we can use GLX_INTEL_swap_events
- * to throttle. For this though we would still probably want an
- * additional extension so we can report the limited region of
- * the window damage to X/compositors.
- */
- glFinish ();
-
- if (have_counter && can_wait)
- {
- end_frame_vsync_counter = _cogl_winsys_get_vsync_counter ();
-
- /* If we have the GLX_SGI_video_sync extension then we can
- * be a bit smarter about how we throttle blits by avoiding
- * any waits if we can see that the video sync count has
- * already progressed. */
- if (glx_onscreen->last_swap_vsync_counter == end_frame_vsync_counter)
- _cogl_winsys_wait_for_vblank ();
- }
- else if (can_wait)
- _cogl_winsys_wait_for_vblank ();
-
- if (glx_renderer->pf_glXCopySubBuffer)
- {
- Display *xdpy = xlib_renderer->xdpy;
- int i;
- for (i = 0; i < n_rectangles; i++)
- {
- int *rect = &rectangles[4 * i];
- glx_renderer->pf_glXCopySubBuffer (xdpy, drawable,
- rect[0], rect[1], rect[2], rect[3]);
- }
- }
- else if (context->drv.pf_glBlitFramebuffer)
- {
- int i;
- /* XXX: checkout how this state interacts with the code to use
- * glBlitFramebuffer in Neil's texture atlasing branch */
- glDrawBuffer (GL_FRONT);
- for (i = 0; i < n_rectangles; i++)
- {
- int *rect = &rectangles[4 * i];
- int x2 = rect[0] + rect[2];
- int y2 = rect[1] + rect[3];
- context->drv.pf_glBlitFramebuffer (rect[0], rect[1], x2, y2,
- rect[0], rect[1], x2, y2,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
- }
- glDrawBuffer (GL_BACK);
- }
-
- /* NB: unlike glXSwapBuffers, glXCopySubBuffer and
- * glBlitFramebuffer don't issue an implicit glFlush() so we
- * have to flush ourselves if we want the request to complete in
- * a finite amount of time since otherwise the driver can batch
- * the command indefinitely. */
- glFlush ();
-
- /* NB: It's important we save the counter we read before acting on
- * the swap request since if we are mixing and matching different
- * swap methods between frames we don't want to read the timer e.g.
- * after calling glFinish() some times and not for others.
- *
- * In other words; this way we consistently save the time at the end
- * of the applications frame such that the counter isn't muddled by
- * the varying costs of different swap methods.
- */
- if (have_counter)
- glx_onscreen->last_swap_vsync_counter = end_frame_vsync_counter;
-}
-
-static void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
-{
- CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
- CoglContext *context = framebuffer->context;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglRendererGLX *glx_renderer = context->display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- gboolean have_counter;
- GLXDrawable drawable;
-
- /* XXX: theoretically this shouldn't be necessary but at least with
- * the Intel drivers we have see that if we don't call
- * glXMakeContextCurrent for the drawable we are swapping then
- * we get a BadDrawable error from the X server. */
- _cogl_framebuffer_flush_state (framebuffer,
- framebuffer,
- COGL_FRAMEBUFFER_FLUSH_BIND_ONLY);
-
- drawable = glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
-
- if (onscreen->swap_throttled)
- {
- guint32 end_frame_vsync_counter = 0;
-
- have_counter =
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_COUNTER);
-
- /* If the swap_region API is also being used then we need to track
- * the vsync counter for each swap request so we can manually
- * throttle swap_region requests. */
- if (have_counter)
- end_frame_vsync_counter = _cogl_winsys_get_vsync_counter ();
-
- if (!glx_renderer->pf_glXSwapInterval)
- {
- gboolean can_wait =
- _cogl_winsys_has_feature (COGL_WINSYS_FEATURE_VBLANK_WAIT);
-
- /* If we are going to wait for VBLANK manually, we not only
- * need to flush out pending drawing to the GPU before we
- * sleep, we need to wait for it to finish. Otherwise, we
- * may end up with the situation:
- *
- * - We finish drawing - GPU drawing continues
- * - We go to sleep - GPU drawing continues
- * VBLANK - We call glXSwapBuffers - GPU drawing continues
- * - GPU drawing continues
- * - Swap buffers happens
- *
- * Producing a tear. Calling glFinish() first will cause us
- * to properly wait for the next VBLANK before we swap. This
- * obviously does not happen when we use _GLX_SWAP and let
- * the driver do the right thing
- */
- glFinish ();
-
- if (have_counter && can_wait)
- {
- if (glx_onscreen->last_swap_vsync_counter ==
- end_frame_vsync_counter)
- _cogl_winsys_wait_for_vblank ();
- }
- else if (can_wait)
- _cogl_winsys_wait_for_vblank ();
- }
- }
- else
- have_counter = FALSE;
-
- glXSwapBuffers (xlib_renderer->xdpy, drawable);
-
- if (have_counter)
- glx_onscreen->last_swap_vsync_counter = _cogl_winsys_get_vsync_counter ();
-}
-
-static guint32
-_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
-{
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- return xlib_onscreen->xwin;
-}
-
-static unsigned int
-_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
- CoglSwapBuffersNotify callback,
- void *user_data)
-{
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- CoglSwapBuffersNotifyEntry *entry = g_slice_new0 (CoglSwapBuffersNotifyEntry);
- static int next_swap_buffers_callback_id = 0;
-
- entry->callback = callback;
- entry->user_data = user_data;
- entry->id = next_swap_buffers_callback_id++;
-
- glx_onscreen->swap_callbacks =
- g_list_prepend (glx_onscreen->swap_callbacks, entry);
-
- return entry->id;
-}
-
-static void
-_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
- unsigned int id)
-{
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- GList *l;
-
- for (l = glx_onscreen->swap_callbacks; l; l = l->next)
- {
- CoglSwapBuffersNotifyEntry *entry = l->data;
- if (entry->id == id)
- {
- g_slice_free (CoglSwapBuffersNotifyEntry, entry);
- glx_onscreen->swap_callbacks =
- g_list_delete_link (glx_onscreen->swap_callbacks, l);
- return;
- }
- }
-}
-
-static void
-_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglContextGLX *glx_context = context->winsys;
- CoglOnscreenGLX *glx_onscreen = onscreen->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
- GLXDrawable drawable =
- glx_onscreen->glxwin ? glx_onscreen->glxwin : xlib_onscreen->xwin;
-
- if (glx_context->current_drawable != drawable)
- return;
-
- glx_context->current_drawable = 0;
- _cogl_winsys_onscreen_bind (onscreen);
-}
-
-static void
-_cogl_winsys_onscreen_set_visibility (CoglOnscreen *onscreen,
- gboolean visibility)
-{
- CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRendererXlib *xlib_renderer = context->display->renderer->winsys;
- CoglOnscreenXlib *xlib_onscreen = onscreen->winsys;
-
- if (visibility)
- XMapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
- else
- XUnmapWindow (xlib_renderer->xdpy, xlib_onscreen->xwin);
-}
-
-/* XXX: This is a particularly hacky _cogl_winsys interface... */
-static XVisualInfo *
-_cogl_winsys_xlib_get_visual_info (void)
-{
- CoglDisplayGLX *glx_display;
- CoglRendererXlib *xlib_renderer;
-
- _COGL_GET_CONTEXT (ctx, NULL);
-
- g_return_val_if_fail (ctx->display->winsys, FALSE);
-
- glx_display = ctx->display->winsys;
- xlib_renderer = ctx->display->renderer->winsys;
-
- if (!glx_display->found_fbconfig)
- return NULL;
-
- return glXGetVisualFromFBConfig (xlib_renderer->xdpy, glx_display->fbconfig);
-}
-
-static gboolean
-get_fbconfig_for_depth (CoglContext *context,
- unsigned int depth,
- GLXFBConfig *fbconfig_ret,
- gboolean *can_mipmap_ret)
-{
- CoglRendererXlib *xlib_renderer;
- CoglDisplayGLX *glx_display;
- Display *dpy;
- GLXFBConfig *fbconfigs;
- int n_elements, i;
- int db, stencil, alpha, mipmap, rgba, value;
- int spare_cache_slot = 0;
- gboolean found = FALSE;
-
- xlib_renderer = context->display->renderer->winsys;
- glx_display = context->display->winsys;
-
- /* Check if we've already got a cached config for this depth */
- for (i = 0; i < COGL_GLX_N_CACHED_CONFIGS; i++)
- if (glx_display->glx_cached_configs[i].depth == -1)
- spare_cache_slot = i;
- else if (glx_display->glx_cached_configs[i].depth == depth)
- {
- *fbconfig_ret = glx_display->glx_cached_configs[i].fb_config;
- *can_mipmap_ret = glx_display->glx_cached_configs[i].can_mipmap;
- return glx_display->glx_cached_configs[i].found;
- }
-
- dpy = xlib_renderer->xdpy;
-
- fbconfigs = glXGetFBConfigs (dpy, DefaultScreen (dpy), &n_elements);
-
- db = G_MAXSHORT;
- stencil = G_MAXSHORT;
- mipmap = 0;
- rgba = 0;
-
- for (i = 0; i < n_elements; i++)
- {
- XVisualInfo *vi;
- int visual_depth;
-
- vi = glXGetVisualFromFBConfig (dpy, fbconfigs[i]);
- if (vi == NULL)
- continue;
-
- visual_depth = vi->depth;
-
- XFree (vi);
-
- if (visual_depth != depth)
- continue;
-
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_ALPHA_SIZE,
- &alpha);
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_BUFFER_SIZE,
- &value);
- if (value != depth && (value - alpha) != depth)
- continue;
-
- value = 0;
- if (depth == 32)
- {
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_BIND_TO_TEXTURE_RGBA_EXT,
- &value);
- if (value)
- rgba = 1;
- }
-
- if (!value)
- {
- if (rgba)
- continue;
-
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_BIND_TO_TEXTURE_RGB_EXT,
- &value);
- if (!value)
- continue;
- }
-
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_DOUBLEBUFFER,
- &value);
- if (value > db)
- continue;
-
- db = value;
-
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_STENCIL_SIZE,
- &value);
- if (value > stencil)
- continue;
-
- stencil = value;
-
- /* glGenerateMipmap is defined in the offscreen extension */
- if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
- {
- glXGetFBConfigAttrib (dpy,
- fbconfigs[i],
- GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
- &value);
-
- if (value < mipmap)
- continue;
-
- mipmap = value;
- }
-
- *fbconfig_ret = fbconfigs[i];
- *can_mipmap_ret = mipmap;
- found = TRUE;
- }
-
- if (n_elements)
- XFree (fbconfigs);
-
- glx_display->glx_cached_configs[spare_cache_slot].depth = depth;
- glx_display->glx_cached_configs[spare_cache_slot].found = found;
- glx_display->glx_cached_configs[spare_cache_slot].fb_config = *fbconfig_ret;
- glx_display->glx_cached_configs[spare_cache_slot].can_mipmap = mipmap;
-
- return found;
-}
-
-static gboolean
-should_use_rectangle (CoglContext *context)
-{
-
- if (context->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_UNKNOWN)
- {
- if (cogl_features_available (COGL_FEATURE_TEXTURE_RECTANGLE))
- {
- const char *rect_env;
-
- /* Use the rectangle only if it is available and either:
-
- the COGL_PIXMAP_TEXTURE_RECTANGLE environment variable is
- set to 'force'
-
- *or*
-
- the env var is set to 'allow' or not set and NPOTs textures
- are not available */
-
- context->rectangle_state =
- cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) ?
- COGL_WINSYS_RECTANGLE_STATE_DISABLE :
- COGL_WINSYS_RECTANGLE_STATE_ENABLE;
-
- if ((rect_env = g_getenv ("COGL_PIXMAP_TEXTURE_RECTANGLE")) ||
- /* For compatibility, we'll also look at the old Clutter
- environment variable */
- (rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
- {
- if (g_ascii_strcasecmp (rect_env, "force") == 0)
- context->rectangle_state =
- COGL_WINSYS_RECTANGLE_STATE_ENABLE;
- else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
- context->rectangle_state =
- COGL_WINSYS_RECTANGLE_STATE_DISABLE;
- else if (g_ascii_strcasecmp (rect_env, "allow"))
- g_warning ("Unknown value for COGL_PIXMAP_TEXTURE_RECTANGLE, "
- "should be 'force' or 'disable'");
- }
- }
- else
- context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_DISABLE;
- }
-
- return context->rectangle_state == COGL_WINSYS_RECTANGLE_STATE_ENABLE;
-}
-
-static gboolean
-try_create_glx_pixmap (CoglContext *context,
- CoglTexturePixmapX11 *tex_pixmap,
- gboolean mipmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
- CoglRenderer *renderer;
- CoglRendererXlib *xlib_renderer;
- Display *dpy;
- /* We have to initialize this *opaque* variable because gcc tries to
- * be too smart for its own good and warns that the variable may be
- * used uninitialized otherwise. */
- GLXFBConfig fb_config = (GLXFBConfig)0;
- int attribs[7];
- int i = 0;
- GLenum target;
- CoglXlibTrapState trap_state;
-
- renderer = context->display->renderer;
- xlib_renderer = renderer->winsys;
- dpy = xlib_renderer->xdpy;
-
- if (!get_fbconfig_for_depth (context,
- tex_pixmap->depth, &fb_config,
- &glx_tex_pixmap->can_mipmap))
- {
- COGL_NOTE (TEXTURE_PIXMAP, "No suitable FBConfig found for depth %i",
- tex_pixmap->depth);
- return FALSE;
- }
-
- if (should_use_rectangle (context))
- {
- target = GLX_TEXTURE_RECTANGLE_EXT;
- glx_tex_pixmap->can_mipmap = FALSE;
- }
- else
- target = GLX_TEXTURE_2D_EXT;
-
- if (!glx_tex_pixmap->can_mipmap)
- mipmap = FALSE;
-
- attribs[i++] = GLX_TEXTURE_FORMAT_EXT;
-
- if (tex_pixmap->depth == 24)
- attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
- else if (tex_pixmap->depth == 32)
- attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
- else
- return FALSE;
-
- attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
- attribs[i++] = mipmap;
-
- attribs[i++] = GLX_TEXTURE_TARGET_EXT;
- attribs[i++] = target;
-
- attribs[i++] = None;
-
- /* We need to trap errors from glXCreatePixmap because it can
- * sometimes fail during normal usage. For example on NVidia it gets
- * upset if you try to create two GLXPixmaps for the same drawable.
- */
-
- _cogl_renderer_xlib_trap_errors (renderer, &trap_state);
-
- glx_tex_pixmap->glx_pixmap = glXCreatePixmap (dpy,
- fb_config,
- tex_pixmap->pixmap,
- attribs);
- glx_tex_pixmap->has_mipmap_space = mipmap;
-
- XSync (dpy, False);
-
- if (_cogl_renderer_xlib_untrap_errors (renderer, &trap_state))
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Failed to create pixmap for %p", tex_pixmap);
- _cogl_renderer_xlib_trap_errors (renderer, &trap_state);
- glXDestroyPixmap (dpy, glx_tex_pixmap->glx_pixmap);
- XSync (dpy, False);
- _cogl_renderer_xlib_untrap_errors (renderer, &trap_state);
-
- glx_tex_pixmap->glx_pixmap = None;
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-_cogl_winsys_texture_pixmap_x11_create (CoglTexturePixmapX11 *tex_pixmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap;
-
- /* FIXME: It should be possible to get to a CoglContext from any
- * CoglTexture pointer. */
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- if (!_cogl_winsys_has_feature (COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP))
- {
- tex_pixmap->winsys = NULL;
- return FALSE;
- }
-
- glx_tex_pixmap = g_new0 (CoglTexturePixmapGLX, 1);
-
- glx_tex_pixmap->glx_pixmap = None;
- glx_tex_pixmap->can_mipmap = FALSE;
- glx_tex_pixmap->has_mipmap_space = FALSE;
-
- glx_tex_pixmap->glx_tex = COGL_INVALID_HANDLE;
-
- glx_tex_pixmap->bind_tex_image_queued = TRUE;
- glx_tex_pixmap->pixmap_bound = FALSE;
-
- tex_pixmap->winsys = glx_tex_pixmap;
-
- if (!try_create_glx_pixmap (ctx, tex_pixmap, FALSE))
- {
- tex_pixmap->winsys = NULL;
- g_free (glx_tex_pixmap);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static void
-free_glx_pixmap (CoglContext *context,
- CoglTexturePixmapGLX *glx_tex_pixmap)
-{
- CoglXlibTrapState trap_state;
- CoglRenderer *renderer;
- CoglRendererXlib *xlib_renderer;
- CoglRendererGLX *glx_renderer;
-
- renderer = context->display->renderer;
- xlib_renderer = renderer->winsys;
- glx_renderer = renderer->winsys;
-
- if (glx_tex_pixmap->pixmap_bound)
- glx_renderer->pf_glXReleaseTexImage (xlib_renderer->xdpy,
- glx_tex_pixmap->glx_pixmap,
- GLX_FRONT_LEFT_EXT);
-
- /* FIXME - we need to trap errors and synchronize here because
- * of ordering issues between the XPixmap destruction and the
- * GLXPixmap destruction.
- *
- * If the X pixmap is destroyed, the GLX pixmap is destroyed as
- * well immediately, and thus, when Cogl calls glXDestroyPixmap()
- * it'll cause a BadDrawable error.
- *
- * this is technically a bug in the X server, which should not
- * destroy either pixmaps until the call to glXDestroyPixmap(); so
- * at some point we should revisit this code and remove the
- * trap+sync after verifying that the destruction is indeed safe.
- *
- * for reference, see:
- * http://bugzilla.clutter-project.org/show_bug.cgi?id=2324
- */
- _cogl_renderer_xlib_trap_errors (renderer, &trap_state);
- glXDestroyPixmap (xlib_renderer->xdpy, glx_tex_pixmap->glx_pixmap);
- XSync (xlib_renderer->xdpy, False);
- _cogl_renderer_xlib_untrap_errors (renderer, &trap_state);
-
- glx_tex_pixmap->glx_pixmap = None;
- glx_tex_pixmap->pixmap_bound = FALSE;
-}
-
-static void
-_cogl_winsys_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap;
-
- /* FIXME: It should be possible to get to a CoglContext from any
- * CoglTexture pointer. */
- _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
- if (!tex_pixmap->winsys)
- return;
-
- glx_tex_pixmap = tex_pixmap->winsys;
-
- free_glx_pixmap (ctx, glx_tex_pixmap);
-
- if (glx_tex_pixmap->glx_tex)
- cogl_handle_unref (glx_tex_pixmap->glx_tex);
-
- tex_pixmap->winsys = NULL;
- g_free (glx_tex_pixmap);
-}
-
-static gboolean
-_cogl_winsys_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
- gboolean needs_mipmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
- CoglRendererGLX *glx_renderer;
-
- /* FIXME: It should be possible to get to a CoglContext from any CoglTexture
- * pointer. */
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- /* If we don't have a GLX pixmap then fallback */
- if (glx_tex_pixmap->glx_pixmap == None)
- return FALSE;
-
- glx_renderer = ctx->display->renderer->winsys;
-
- /* Lazily create a texture to hold the pixmap */
- if (glx_tex_pixmap->glx_tex == COGL_INVALID_HANDLE)
- {
- CoglPixelFormat texture_format;
-
- texture_format = (tex_pixmap->depth >= 32 ?
- COGL_PIXEL_FORMAT_RGBA_8888_PRE :
- COGL_PIXEL_FORMAT_RGB_888);
-
- if (should_use_rectangle (ctx))
- {
- glx_tex_pixmap->glx_tex =
- _cogl_texture_rectangle_new_with_size (tex_pixmap->width,
- tex_pixmap->height,
- COGL_TEXTURE_NO_ATLAS,
- texture_format);
-
- if (glx_tex_pixmap->glx_tex)
- COGL_NOTE (TEXTURE_PIXMAP, "Created a texture rectangle for %p",
- tex_pixmap);
- else
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
- "texture rectangle could not be created",
- tex_pixmap);
- free_glx_pixmap (ctx, glx_tex_pixmap);
- return FALSE;
- }
- }
- else
- {
- glx_tex_pixmap->glx_tex =
- _cogl_texture_2d_new_with_size (tex_pixmap->width,
- tex_pixmap->height,
- COGL_TEXTURE_NO_ATLAS,
- texture_format);
-
- if (glx_tex_pixmap->glx_tex)
- COGL_NOTE (TEXTURE_PIXMAP, "Created a texture 2d for %p",
- tex_pixmap);
- else
- {
- COGL_NOTE (TEXTURE_PIXMAP, "Falling back for %p because a "
- "texture 2d could not be created",
- tex_pixmap);
- free_glx_pixmap (ctx, glx_tex_pixmap);
- return FALSE;
- }
- }
- }
-
- if (needs_mipmap)
- {
- /* If we can't support mipmapping then temporarily fallback */
- if (!glx_tex_pixmap->can_mipmap)
- return FALSE;
-
- /* Recreate the GLXPixmap if it wasn't previously created with a
- * mipmap tree */
- if (!glx_tex_pixmap->has_mipmap_space)
- {
- free_glx_pixmap (ctx, glx_tex_pixmap);
-
- COGL_NOTE (TEXTURE_PIXMAP, "Recreating GLXPixmap with mipmap "
- "support for %p", tex_pixmap);
- if (!try_create_glx_pixmap (ctx, tex_pixmap, TRUE))
-
- {
- /* If the pixmap failed then we'll permanently fallback
- * to using XImage. This shouldn't happen. */
- COGL_NOTE (TEXTURE_PIXMAP, "Falling back to XGetImage "
- "updates for %p because creating the GLXPixmap "
- "with mipmap support failed", tex_pixmap);
-
- if (glx_tex_pixmap->glx_tex)
- cogl_handle_unref (glx_tex_pixmap->glx_tex);
- return FALSE;
- }
-
- glx_tex_pixmap->bind_tex_image_queued = TRUE;
- }
- }
-
- if (glx_tex_pixmap->bind_tex_image_queued)
- {
- GLuint gl_handle, gl_target;
- CoglRendererXlib *xlib_renderer = ctx->display->renderer->winsys;
-
- cogl_texture_get_gl_texture (glx_tex_pixmap->glx_tex,
- &gl_handle, &gl_target);
-
- COGL_NOTE (TEXTURE_PIXMAP, "Rebinding GLXPixmap for %p", tex_pixmap);
-
- GE( _cogl_bind_gl_texture_transient (gl_target, gl_handle, FALSE) );
-
- if (glx_tex_pixmap->pixmap_bound)
- glx_renderer->pf_glXReleaseTexImage (xlib_renderer->xdpy,
- glx_tex_pixmap->glx_pixmap,
- GLX_FRONT_LEFT_EXT);
-
- glx_renderer->pf_glXBindTexImage (xlib_renderer->xdpy,
- glx_tex_pixmap->glx_pixmap,
- GLX_FRONT_LEFT_EXT,
- NULL);
-
- /* According to the recommended usage in the spec for
- * GLX_EXT_texture_pixmap we should release the texture after
- * we've finished drawing with it and it is undefined what
- * happens if you render to a pixmap that is bound to a texture.
- * However that would require the texture backend to know when
- * Cogl has finished painting and it may be more expensive to
- * keep unbinding the texture. Leaving it bound appears to work
- * on Mesa and NVidia drivers and it is also what Compiz does so
- * it is probably ok */
-
- glx_tex_pixmap->bind_tex_image_queued = FALSE;
- glx_tex_pixmap->pixmap_bound = TRUE;
-
- _cogl_texture_2d_externally_modified (glx_tex_pixmap->glx_tex);
- }
-
- return TRUE;
-}
-
-static void
-_cogl_winsys_texture_pixmap_x11_damage_notify (CoglTexturePixmapX11 *tex_pixmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
-
- glx_tex_pixmap->bind_tex_image_queued = TRUE;
-}
-
-static CoglHandle
-_cogl_winsys_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
-{
- CoglTexturePixmapGLX *glx_tex_pixmap = tex_pixmap->winsys;
-
- return glx_tex_pixmap->glx_tex;
-}
-
-
-static CoglWinsysVtable _cogl_winsys_vtable =
- {
- .name = "GLX",
- .get_proc_address = _cogl_winsys_get_proc_address,
- .renderer_connect = _cogl_winsys_renderer_connect,
- .renderer_disconnect = _cogl_winsys_renderer_disconnect,
- .display_setup = _cogl_winsys_display_setup,
- .display_destroy = _cogl_winsys_display_destroy,
- .context_init = _cogl_winsys_context_init,
- .context_deinit = _cogl_winsys_context_deinit,
- .xlib_get_visual_info = _cogl_winsys_xlib_get_visual_info,
- .onscreen_init = _cogl_winsys_onscreen_init,
- .onscreen_deinit = _cogl_winsys_onscreen_deinit,
- .onscreen_bind = _cogl_winsys_onscreen_bind,
- .onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers,
- .onscreen_swap_region = _cogl_winsys_onscreen_swap_region,
- .onscreen_update_swap_throttled =
- _cogl_winsys_onscreen_update_swap_throttled,
- .onscreen_x11_get_window_xid =
- _cogl_winsys_onscreen_x11_get_window_xid,
- .onscreen_add_swap_buffers_callback =
- _cogl_winsys_onscreen_add_swap_buffers_callback,
- .onscreen_remove_swap_buffers_callback =
- _cogl_winsys_onscreen_remove_swap_buffers_callback,
- .onscreen_set_visibility = _cogl_winsys_onscreen_set_visibility,
- .get_vsync_counter = _cogl_winsys_get_vsync_counter,
-
- /* X11 tfp support... */
- /* XXX: instead of having a rather monolithic winsys vtable we could
- * perhaps look for a way to separate these... */
- .texture_pixmap_x11_create =
- _cogl_winsys_texture_pixmap_x11_create,
- .texture_pixmap_x11_free =
- _cogl_winsys_texture_pixmap_x11_free,
- .texture_pixmap_x11_update =
- _cogl_winsys_texture_pixmap_x11_update,
- .texture_pixmap_x11_damage_notify =
- _cogl_winsys_texture_pixmap_x11_damage_notify,
- .texture_pixmap_x11_get_texture =
- _cogl_winsys_texture_pixmap_x11_get_texture,
- };
-
-/* XXX: we use a function because no doubt someone will complain
- * about using c99 member initializers because they aren't portable
- * to windows. We want to avoid having to rigidly follow the real
- * order of members since some members are #ifdefd and we'd have
- * to mirror the #ifdefing to add padding etc. For any winsys that
- * can assume the platform has a sane compiler then we can just use
- * c99 initializers for insane platforms they can initialize
- * the members by name in a function.
- */
-const CoglWinsysVtable *
-_cogl_winsys_glx_get_vtable (void)
-{
- return &_cogl_winsys_vtable;
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifndef __COGL_WINSYS_PRIVATE_H
-#define __COGL_WINSYS_PRIVATE_H
-
-#include "cogl-framebuffer-private.h"
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include "cogl-texture-pixmap-x11-private.h"
-#endif
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-#include <X11/Xutil.h>
-#include "cogl-texture-pixmap-x11-private.h"
-#endif
-
-GQuark
-_cogl_winsys_error_quark (void);
-
-#define COGL_WINSYS_ERROR (_cogl_winsys_error_quark ())
-
-typedef enum { /*< prefix=COGL_WINSYS_ERROR >*/
- COGL_WINSYS_ERROR_INIT,
- COGL_WINSYS_ERROR_CREATE_CONTEXT,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
-} CoglWinsysError;
-
-typedef enum
-{
- COGL_WINSYS_RECTANGLE_STATE_UNKNOWN,
- COGL_WINSYS_RECTANGLE_STATE_DISABLE,
- COGL_WINSYS_RECTANGLE_STATE_ENABLE
-} CoglWinsysRectangleState;
-
-typedef struct _CoglWinsysVtable
-{
- const char *name;
-
- CoglFuncPtr
- (*get_proc_address) (const char *name);
-
- gboolean
- (*renderer_connect) (CoglRenderer *renderer, GError **error);
-
- void
- (*renderer_disconnect) (CoglRenderer *renderer);
-
- gboolean
- (*display_setup) (CoglDisplay *display, GError **error);
-
- void
- (*display_destroy) (CoglDisplay *display);
-
- gboolean
- (*context_init) (CoglContext *context, GError **error);
-
- void
- (*context_deinit) (CoglContext *context);
-
-#ifdef COGL_HAS_EGL_SUPPORT
- EGLDisplay
- (*context_egl_get_egl_display) (CoglContext *context);
-#endif
-
- gboolean
- (*has_feature) (CoglWinsysFeature feature);
-
-#ifdef COGL_HAS_XLIB_SUPPORT
- XVisualInfo *
- (*xlib_get_visual_info) (void);
-#endif
-
- gboolean
- (*onscreen_init) (CoglOnscreen *onscreen, GError **error);
-
- void
- (*onscreen_deinit) (CoglOnscreen *onscreen);
-
- void
- (*onscreen_bind) (CoglOnscreen *onscreen);
-
- void
- (*onscreen_swap_buffers) (CoglOnscreen *onscreen);
-
- void
- (*onscreen_swap_region) (CoglOnscreen *onscreen,
- int *rectangles,
- int n_rectangles);
-
- void
- (*onscreen_update_swap_throttled) (CoglOnscreen *onscreen);
-
- guint32
- (*onscreen_x11_get_window_xid) (CoglOnscreen *onscreen);
-
- unsigned int
- (*onscreen_add_swap_buffers_callback) (CoglOnscreen *onscreen,
- CoglSwapBuffersNotify callback,
- void *user_data);
-
- void
- (*onscreen_remove_swap_buffers_callback) (CoglOnscreen *onscreen,
- unsigned int id);
-
- void
- (*onscreen_set_visibility) (CoglOnscreen *onscreen,
- gboolean visibility);
-
- guint32
- (*get_vsync_counter) (void);
-
-#ifdef COGL_HAS_XLIB_SUPPORT
- gboolean
- (*texture_pixmap_x11_create) (CoglTexturePixmapX11 *tex_pixmap);
- void
- (*texture_pixmap_x11_free) (CoglTexturePixmapX11 *tex_pixmap);
-
- gboolean
- (*texture_pixmap_x11_update) (CoglTexturePixmapX11 *tex_pixmap,
- gboolean needs_mipmap);
-
- void
- (*texture_pixmap_x11_damage_notify) (CoglTexturePixmapX11 *tex_pixmap);
-
- CoglHandle
- (*texture_pixmap_x11_get_texture) (CoglTexturePixmapX11 *tex_pixmap);
-#endif
-
-} CoglWinsysVtable;
-
-gboolean
-_cogl_winsys_has_feature (CoglWinsysFeature feature);
-
-#endif /* __COGL_WINSYS_PRIVATE_H */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-
-CoglFuncPtr
-_cogl_winsys_get_proc_address (const char *name)
-{
- return NULL;
-}
-
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl-framebuffer-private.h"
-
-/* This provides a stub winsys implementation for when Clutter still handles
- * creating an OpenGL context. This is useful so we don't have to guard all
- * calls into the winsys layer with #ifdef COGL_HAS_FULL_WINSYS
- */
-
-CoglFuncPtr
-_cogl_winsys_get_proc_address (const char *name)
-{
- return NULL;
-}
-
-void
-_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
-{
-
-}
-
-void
-_cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
- int *rectangles,
- int n_rectangles)
-{
-
-}
-
-void
-_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
-{
-
-}
-
-unsigned int
-_cogl_winsys_onscreen_add_swap_buffers_callback (CoglOnscreen *onscreen,
- CoglSwapBuffersNotify callback,
- void *user_data)
-{
- g_assert (0);
- return 0;
-}
-
-void
-_cogl_winsys_onscreen_remove_swap_buffers_callback (CoglOnscreen *onscreen,
- unsigned int id)
-{
- g_assert (0);
-}
-
-#ifdef COGL_HAS_XLIB_SUPPORT
-XVisualInfo *
-_cogl_winsys_xlib_get_visual_info (void)
-{
- g_assert (0);
- return NULL;
-}
-#endif
-
-#ifdef COGL_HAS_X11_SUPPORT
-guint32
-_cogl_winsys_onscreen_x11_get_window_xid (CoglOnscreen *onscreen)
-{
- g_assert (0);
- return 0;
-}
-#endif
-
-gboolean
-_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
- GError **error)
-{
- return TRUE;
-}
-
-void
-_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
-{
-
-}
-
-void
-_cogl_winsys_context_deinit (CoglContext *context)
-{
-
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2007,2008,2009,2010 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "cogl.h"
-#include "cogl-context-private.h"
-
-GQuark
-_cogl_winsys_error_quark (void)
-{
- return g_quark_from_static_string ("cogl-winsys-error-quark");
-}
-
-/* FIXME: we should distinguish renderer and context features */
-gboolean
-_cogl_winsys_has_feature (CoglWinsysFeature feature)
-{
- _COGL_GET_CONTEXT (ctx, FALSE);
-
- return COGL_FLAGS_GET (ctx->winsys_features, feature);
-}
+++ /dev/null
-AC_PREREQ(2.59)
-
-dnl ================================================================
-dnl XXX: If you are making a release then you need to check these
-dnl sections:
-dnl » API versions
-dnl (the pretty numbers that the users see)
-dnl
-dnl » Interface version details for libtool
-dnl (the shared library versioning information)
-dnl
-dnl » Source code release status
-dnl (mark the source code as being part of a "release" or from "git")
-dnl ================================================================
-
-dnl ================================================================
-dnl API versions (i.e. the pretty numbers that users see)
-dnl ================================================================
-m4_define([cogl_major_version], [2])
-m4_define([cogl_minor_version], [0])
-m4_define([cogl_micro_version], [0])
-m4_define([cogl_version],
- [cogl_major_version.cogl_minor_version.cogl_micro_version])
-
-dnl Since the core Cogl library has to also maintain support for the
-dnl Cogl 1.x API for Clutter then we track the 1.x version separately.
-m4_define([cogl_1_minor_version], [6])
-m4_define([cogl_1_micro_version], [0])
-m4_define([cogl_1_version], [1.cogl_1_minor_version.cogl_1_micro_version])
-
-dnl ================================================================
-dnl Interface version details for libtool
-dnl ================================================================
-# Note: we don't automatically deduce the libtool version info from
-# the pretty version number that users sees. This is because we want
-# to update the pretty version number before making a release since it
-# can affect the name of our pkg-config file and the naming or
-# location of other installed files which we want to be able to verify
-# as correct well before making a release.
-#
-# For reference on how the various numbers should be updated at
-# release time these rules are adapted from the libtool info pages:
-#
-# 1. Update the version information only immediately before a public
-# release.
-#
-# 2. If the library source code has changed at all since the last
-# update, then increment REVISION (`C:R:A' becomes `C:r+1:A').
-#
-# 3. If any interfaces have been added, removed, or changed since the
-# last update, increment CURRENT, and set REVISION to 0.
-#
-# 4. If any interfaces have been added since the last public release,
-# then increment AGE.
-#
-# 5. If any interfaces have been removed since the last public release,
-# then set AGE to 0.
-m4_define([cogl_lt_current], 0)
-m4_define([cogl_lt_revision], 0)
-m4_define([cogl_lt_age], 0)
-# We do also tell libtool the pretty version:
-m4_define([cogl_lt_release], [cogl_version])
-
-
-dnl ================================================================
-dnl Source code release status
-dnl ================================================================
-# Finally we explicitly track when we are building development source
-# from Git vs building source corresponding to a release. As with the
-# libtool version info we don't automatically derive this from the
-# pretty version number because we want to test the results of
-# updating the version number in advance of a release.
-m4_define([cogl_release_status], [git])
-
-
-dnl ================================================================
-dnl Required versions for dependencies
-dnl ================================================================
-m4_define([glib_req_version], [2.26.0])
-m4_define([pangocairo_req_version], [1.20])
-m4_define([gi_req_version], [0.9.5])
-m4_define([gdk_pixbuf_req_version], [2.0])
-m4_define([uprof_req_version], [0.3])
-m4_define([gtk_doc_req_version], [1.13])
-m4_define([xfixes_req_version], [3])
-m4_define([xcomposite_req_version], [0.4])
-
-
-AC_INIT(cogl, [cogl_version])
-AC_CONFIG_SRCDIR(cogl/cogl.h)
-AC_CONFIG_AUX_DIR([build])
-AC_CONFIG_MACRO_DIR([build/autotools])
-AC_CONFIG_HEADERS(config.h)
-
-# Save this value here, since automake will set cflags later and we
-# want to know if the user specified custom cflags or not.
-cflags_set=${CFLAGS+set}
-
-AM_INIT_AUTOMAKE([1.11 foreign -Wno-portability no-define no-dist-gzip
- dist-bzip2])
-AM_SILENT_RULES([yes])
-
-
-dnl ================================================================
-dnl Export the API versioning
-dnl ================================================================
-AC_SUBST([COGL_MAJOR_VERSION],[cogl_major_version])
-AC_SUBST([COGL_MINOR_VERSION],[cogl_minor_version])
-AC_SUBST([COGL_MICRO_VERSION],[cogl_micro_version])
-AC_SUBST([COGL_VERSION],[cogl_version])
-AC_SUBST([COGL_API_VERSION],[cogl_major_version.0])
-AC_SUBST([COGL_API_VERSION_AM],[$COGL_MAJOR_VERSION\_0])
-
-AC_SUBST([COGL_1_MINOR_VERSION],[cogl_1_minor_version])
-AC_SUBST([COGL_1_MICRO_VERSION],[cogl_1_micro_version])
-AC_SUBST([COGL_1_VERSION],[cogl_1_version])
-
-
-dnl ================================================================
-dnl Export the libtool versioning
-dnl ================================================================
-AC_SUBST([COGL_LT_CURRENT], [cogl_lt_current])
-AC_SUBST([COGL_LT_REVISION], [cogl_lt_revision])
-AC_SUBST([COGL_LT_AGE], [cogl_lt_age])
-AC_SUBST([COGL_LT_RELEASE], [cogl_lt_release])
-
-
-dnl ================================================================
-dnl Export the source code release status
-dnl ================================================================
-AC_SUBST([COGL_RELEASE_STATUS], [cogl_release_status])
-
-
-dnl ================================================================
-dnl See what platform we are building for
-dnl ================================================================
-AC_CANONICAL_HOST
-AC_MSG_CHECKING([if building for some Win32 platform])
-AS_CASE([$host],
- [*-*-mingw*|*-*-cygwin*],
- [
- COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -no-undefined"
- platform_win32=yes
- ],
-
- [platform_win32=no]
-)
-AC_MSG_RESULT([$platform_win32])
-AM_CONDITIONAL(OS_WIN32, [test "$platform_win32" = "yes"])
-
-
-dnl ================================================================
-dnl Handle extra configure options
-dnl ================================================================
-
-dnl ============================================================
-dnl Enable debugging
-dnl ============================================================
-m4_define([default], [m4_if(cogl_release_status, [git], [yes], [no])])
-AC_ARG_ENABLE(
- [debug],
- [AC_HELP_STRING([--enable-debug=@<:@no/yes@:>@], [Control Cogl debugging level @<:@default=]default[@:>@])],
- [],
- enable_debug=default
-)
-
-AS_CASE(
- [$enable_debug],
- [yes],
- [
- test "$cflags_set" = set || CFLAGS="$CFLAGS -g -O0"
- COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_GL_DEBUG -DCOGL_OBJECT_DEBUG -DCOGL_HANDLE_DEBUG -DCOGL_ENABLE_DEBUG"
- ],
- [no],
- [
- COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -DCOGL_ENABLE_DEBUG -DG_DISABLE_CHECKS -DG_DISABLE_CAST_CHECKS"
- ],
- [AC_MSG_ERROR([Unknown argument for --enable-debug])]
-)
-
-AC_SUBST(COGL_DEBUG_CFLAGS)
-
-
-dnl ============================================================
-dnl Enable strict compiler flags
-dnl ============================================================
-
-# use strict compiler flags only when building from git; the rules for
-# distcheck will take care of turning this on when making a release
-m4_define([default], [m4_if(cogl_release_status, [git], [yes], [no])])
-AC_ARG_ENABLE(
- [maintainer-flags],
- [AC_HELP_STRING([--enable-maintainer-flags=@<:@no/yes/error@:>@], [Use strict compiler flags @<:@default=]default[@:>@])],
- [],
- enable_maintainer_flags=default
-)
-
-MAINTAINER_COMPILER_FLAGS="-Wall -Wshadow -Wcast-align -Wuninitialized
- -Wno-strict-aliasing -Wempty-body -Wformat
- -Wformat-security -Winit-self
- -Wdeclaration-after-statement -Wvla
- -Wpointer-arith"
-
-AS_CASE(
- [$enable_maintainer_flags],
- [yes],
- [
- AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS])
- ],
- [no],
- [
- ],
- [error],
- [
- MAINTAINER_COMPILER_FLAGS="$MAINTAINER_COMPILER_FLAGS -Werror"
- AS_COMPILER_FLAGS([MAINTAINER_CFLAGS], [$MAINTAINER_COMPILER_FLAGS])
- ],
- [*],
- [AC_MSG_ERROR([Invalid option for --enable-maintainer-flags])]
-)
-
-# strip leading spaces
-COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS ${MAINTAINER_CFLAGS/# }"
-
-
-dnl ============================================================
-dnl Choose image loading backend
-dnl ============================================================
-AC_ARG_ENABLE(
- [gdk-pixbuf],
- [AC_HELP_STRING([--enable-gdk-pixbuf=@<:@no/yes@:>@], [Enable image loading via gdk-pixbuf @<:@default=yes@:>@])],
- [],
- enable_gdk_pixbuf=yes
-)
-if test "x$enable_gdk_pixbuf" = "xyes"; then
- PKG_CHECK_EXISTS([gdk-pixbuf-2.0], [have_gdk_pixbuf=yes], [have_gdk_pixbuf=no])
-else
- have_gdk_pixbuf=no
-fi
-
-AC_ARG_ENABLE(
- [quartz-image],
- [AC_HELP_STRING([--enable-quartz-image=@<:@no/yes@:>@], [Enable image loading via quartz @<:@default=no@:>@])],
- [],
- enable_quartz_image=no
-)
-
-AS_IF(
- [test "x$have_gdk_pixbuf" = "xyes"],
- [
- AC_DEFINE([USE_GDKPIXBUF], 1, [Use GdkPixbuf for loading image data])
- COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gdk-pixbuf-2.0 >= gdk_pixbuf_req_version"
- COGL_IMAGE_BACKEND="gdk-pixbuf"
- ],
- [test "x$enable_quartz_image" = "xyes"],
- [
- EXPERIMENTAL_CONFIG=yes
- EXPERIMENTAL_OPTIONS="$EXPERIMENTAL_OPTIONS Quartz Core Graphics,"
- AC_DEFINE([USE_QUARTZ], 1,
- [Use Core Graphics (Quartz) for loading image data])
- COGL_IMAGE_BACKEND="quartz"
- ],
- [
- EXPERIMENTAL_CONFIG=yes
- EXPERIMENTAL_OPTIONS="$EXPERIMENTAL_OPTIONS fallback image decoding (stb_image),"
- AC_DEFINE([USE_INTERNAL], 1,
- [Use internal image decoding for loading image data])
- COGL_IMAGE_BACKEND="stb_image"
- ]
-)
-
-
-
-dnl ============================================================
-dnl Determine which drivers and window systems we can support
-dnl ============================================================
-
-dnl ========================================================
-dnl Drivers first...
-dnl ========================================================
-DRIVER_COUNT=0
-EGL_CHECKED=no
-
-AC_ARG_ENABLE(
- [gles1],
- [AC_HELP_STRING([--enable-gles1=@<:@no/yes@:>@], [Enable support for OpenGL-ES 1.1 @<:@default=no@:>@])],
- [],
- enable_gles1=no
-)
-AS_IF([test "x$enable_gles1" = "xyes"],
- [
- AS_IF([test "x$platform_win32" != "xyes"],
- [AC_MSG_ERROR([GLES 1 not available for win32])])
-
- DRIVER_COUNT=$((DRIVER_COUNT + 1))
- COGL_DRIVER=gles
- glesversion=1.1
-
- cogl_gl_headers="GLES/gl.h GLES/glext.h"
-
- AC_DEFINE([HAVE_COGL_GLES], 1, [Have GLES 1.1 for rendering])
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES1"
-
- PKG_CHECK_EXISTS([glesv1_cm],
- [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv1_cm"
- NEED_EGL=yes
- ],
- [
- AC_CHECK_HEADERS([$cogl_gl_headers],
- [],
- [AC_MSG_ERROR([Unable to locate required GLES headers])])
-
- # Check for a GLES 1.x Common Profile library with/without EGL.
- #
- # Note: historically GLES 1 libraries shipped with the
- # EGL and GLES symbols all bundled in one library. Now
- # the Khronos Implementers Guide defines two naming
- # schemes: -lGLES_CM should be used for a library that
- # bundles the GLES and EGL API together and -lGLESv1_CM
- # would be used for a standalone GLES API.
- AC_CHECK_LIB(GLES_CM, [eglInitialize],
- [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLES_CM"],
- [
- AC_CHECK_LIB(GLESv1_CM, [glFlush],
- [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv1_CM"
- NEED_SEPARATE_EGL=yes
- ],
- [AC_MSG_ERROR([Unable to locate required GLES 1.x Common Profile library])])
- ])
-
- EGL_CHECKED=yes
- ])
- ])
-
-AC_ARG_ENABLE(
- [gles2],
- [AC_HELP_STRING([--enable-gles2=@<:@no/yes@:>@], [Enable support for OpenGL-ES 2.0 @<:@default=no@:>@])],
- [],
- enable_gles2=no
-)
-AS_IF([test "x$enable_gles2" = "xyes"],
- [
- AS_IF([test "x$platform_win32" != "xyes"],
- [AC_MSG_ERROR([GLES 1 not available for win32])])
-
- DRIVER_COUNT=$((DRIVER_COUNT + 1))
- COGL_DRIVER=gles
- glesversion=2.0
-
- cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h"
- AC_DEFINE([HAVE_COGL_GLES2], 1, [Have GLES 2.0 for rendering])
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES CLUTTER_COGL_HAS_GLES"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES2"
-
- PKG_CHECK_EXISTS([glesv2],
- [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glesv2"],
- [
- AC_CHECK_HEADERS([$cogl_gl_headers],
- [],
- [AC_MSG_ERROR([Unable to locate required GLES headers])],
- [[#include <GLES2/gl2.h>
- ]])
-
- COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGLESv2"
- ])
-
- NEED_EGL=yes
- ])
-
-AC_ARG_ENABLE(
- [gl],
- [AC_HELP_STRING([--enable-gl=@<:@no/yes@:>@], [Enable support for OpenGL @<:@default=yes@:>@])],
- [],
- [AS_IF([test $DRIVER_COUNT -gt 0], [enable_gl=no], [enable_gl=yes])]
-)
-AS_IF([test "x$enable_gl" = "xyes"],
- [
- DRIVER_COUNT=$((DRIVER_COUNT + 1))
- COGL_DRIVER=gl
- ALLOW_GLX=yes
-
- cogl_gl_headers="GL/gl.h"
-
- AS_IF([test "x$platform_win32" = "xyes"],
- [
- COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lopengl32 -lgdi32 -lwinmm"
- COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -D_WIN32_WINNT=0x0500"
- ],
- [
- PKG_CHECK_EXISTS(
- [gl], [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gl"],
- [AC_CHECK_LIB(GL, [glGetString],
- [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lGL"],
- [AC_MSG_ERROR([Unable to locate required GL library])])
- ])
- ])
-
- AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
-
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GL"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL"
- ])
-
-AS_IF([test $DRIVER_COUNT -gt 1],
- [AC_MSG_ERROR(['The --enable-gl{es1,es2} options are currently mutually exclusive'])])
-
-AC_SUBST([COGL_DRIVER])
-
-AM_CONDITIONAL([COGL_DRIVER_GL], [test "x$COGL_DRIVER" = "xgl"])
-AM_CONDITIONAL([COGL_DRIVER_GLES], [test "x$COGL_DRIVER" = "xgles"])
-
-dnl ========================================================
-dnl Check window system integration libraries...
-dnl ========================================================
-
-dnl The "stub" winsys is a fallback option we use when Cogl doesn't
-dnl yet have support for a window system. It enables a toolkit like
-dnl Clutter to provide external support instead. Currently this is
-dnl not compatible with other window system backends.
-AC_ARG_ENABLE(
- [stub-winsys],
- [AC_HELP_STRING([--enable-stub-winsys=@<:@no/yes@:>@], [Enable support stub winsys @<:@default=no@:>@])],
- [],
- enable_stub_winsys=no
-)
-AS_IF([test "x$enable_stub_winsys" = "xyes"],
- [
- GL_WINSYS_APIS="$GL_WINSYS_APIS stub"
- ALLOW_GLX=no
- ])
-AM_CONDITIONAL(SUPPORT_STUB, [test "x$enable_stub_winsys" = "xyes"])
-
-AC_ARG_ENABLE(
- [glx],
- [AC_HELP_STRING([--enable-glx=@<:@no/yes@:>@], [Enable support GLX @<:@default=auto@:>@])],
- [],
- [AS_IF([test "x$ALLOW_GLX" = "xyes"], [enable_glx=yes], [enable_glx=no])]
-)
-AS_IF([test "x$enable_glx" = "xyes"],
- [
- AS_IF([test "x$enable_stub_winsys" = "xyes"],
- [AC_MSG_ERROR([Stub winsys not currently compatible with others])])
-
- AS_IF([test "x$ALLOW_GLX" != "xyes"],
- [AC_MSG_ERROR([GLX not supported with $COGL_DRIVER driver])])
-
- NEED_XLIB=yes
- SUPPORT_GLX=yes
- GL_WINSYS_APIS="$GL_WINSYS_APIS glx"
-
- AC_DEFINE([COGL_HAS_GLX_SUPPORT], [1], [Cogl supports OpenGL using the GLX API])
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1],
- [Cogl can create its own OpenGL context])
-
- # We might fall back to DRM for sync-to-vblank on GLX
- PKG_CHECK_EXISTS([libdrm],
- [
- AC_DEFINE([HAVE_DRM], [1], [Have libdrm support])
- COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES libdrm"
- ],
- [])
- ])
-AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "xyes"])
-
-
-EGL_PLATFORM_COUNT=0
-
-AC_ARG_ENABLE(
- [null-egl-platform],
- [AC_HELP_STRING([--enable-null-egl-platform=@<:@no/yes@:>@], [Enable support for the NULL egl platform @<:@default=no@:>@])],
- [],
- enable_null_egl_platform=no
-)
-AS_IF([test "x$enable_null_egl_platform" = "xyes"],
- [
- AS_IF([test "x$enable_stub_winsys" = "xyes"],
- [AC_MSG_ERROR([Stub winsys not currently compatible with others])])
-
- EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1))
- NEED_EGL=yes
- EGL_PLATFORMS="$EGL_PLATFORMS null"
-
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT"
- ])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_NULL,
- [test "x$enable_null_egl_platform" = "xyes"])
-
-AC_ARG_ENABLE(
- [gdl-egl-platform],
- [AC_HELP_STRING([--enable-gdl-egl-platform=@<:@no/yes@:>@], [Enable support for the GDL egl platform @<:@default=no@:>@])],
- [],
- enable_gdl_egl_platform=no
-)
-AS_IF([test "x$enable_gdl_egl_platform" == "xyes"],
- [
- AS_IF([test "x$enable_stub_winsys" = "xyes"],
- [AC_MSG_ERROR([Stub winsys not currently compatible with others])])
-
- EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1))
- NEED_EGL=yes
- EGL_PLATFORMS="$EGL_PLATFORMS gdl"
-
- AC_CHECK_HEADERS(
- [libgdl.h],
- [],
- [
- AC_CHECK_HEADERS(
- [CE4100/libgdl.h],
- [COGL_EXTRA_CFLAGS="$COGL_EXTRA_CFLAGS -I/usr/include/CE4100"],
- [AC_MSG_ERROR([libgdl.h not found])])
- ])
-
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_GDL_SUPPORT"
- ])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_GDL,
- [test "x$enable_gdl_egl_platform" = "xyes"])
-
-dnl This should go last, since it's the default fallback and we need
-dnl to check the value of $EGL_PLATFORM_COUNT here.
-AC_ARG_ENABLE(
- [xlib-egl-platform],
- [AC_HELP_STRING([--enable-xlib-egl-platform=@<:@no/yes@:>@], [Enable support for the Xlib egl platform @<:@default=auto@:>@])],
- [],
- AS_IF([test "x$COGL_DRIVER" = "xgles" && test $EGL_PLATFORM_COUNT -eq 0],
- [enable_xlib_egl_platform=yes], [enable_xlib_egl_platform=no])
-)
-AS_IF([test "x$enable_xlib_egl_platform" = "xyes"],
- [
- AS_IF([test "x$enable_stub_winsys" = "xyes"],
- [AC_MSG_ERROR([Stub winsys not currently compatible with others])])
-
- EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1))
- NEED_EGL=yes
- NEED_XLIB=yes
- EGL_PLATFORMS="$EGL_PLATFORMS xlib"
-
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT"
- ])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_X11,
- [test "x$enable_xlib_egl_platform" = "xyes"])
-
-
-
-AS_IF([test $EGL_PLATFORM_COUNT -gt 1],
- [AC_MSG_ERROR(['The --enable-*-egl-platform options are currently mutually exclusive'])])
-
-AS_IF([test "x$NEED_EGL" = "xyes" && test "x$EGL_CHECKED" != "xyes"],
- [
- PKG_CHECK_EXISTS([egl],
- [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES egl"],
- [
- AC_CHECK_HEADERS(
- [EGL/egl.h],
- [],
- [AC_MSG_ERROR([Unable to locate required EGL headers])])
-
- AC_CHECK_LIB(EGL, [eglInitialize],
- [COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL"],
- [AC_MSG_ERROR([Unable to locate required EGL library])])
-
- COGL_EXTRA_LDFLAGS="$COGL_EXTRA_LDFLAGS -lEGL"
- ]
- )
- SUPPORT_EGL=yes
- GL_WINSYS_APIS="$GL_WINSYS_APIS egl"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_SUPPORT"
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1],
- [Cogl can create its own OpenGL context])
- ])
-AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "xyes"])
-
-
-dnl ========================================================
-dnl Check X11 dependencies if required
-dnl ========================================================
-AS_IF([test "x$NEED_XLIB" = "xyes"],
- [
- X11_MODULES="x11 xext xfixes >= xfixes_req_version xdamage xcomposite >= xcomposite_req_version"
- PKG_CHECK_MODULES(DUMMY, [$X11_MODULES],
- [COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES $X11_MODULES"])
- SUPPORT_X11=yes
- SUPPORT_XLIB=yes
-
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11_SUPPORT"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB_SUPPORT"
- ])
-
-AM_CONDITIONAL(X11_TESTS, [test "x$SUPPORT_X11" = "xyes"])
-AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "xyes"])
-AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "xyes"])
-
-
-AM_CONDITIONAL(COGL_STANDALONE_BUILD, [true])
-
-dnl ================================================================
-dnl Compiler stuff.
-dnl ================================================================
-AC_PROG_CC
-AC_PROG_CPP
-AM_PROG_CC_C_O
-AC_ISC_POSIX
-AC_C_CONST
-
-
-dnl ================================================================
-dnl Libtool stuff.
-dnl ================================================================
-dnl AC_PROG_LIBTOOL
-dnl LIBTOOL="$LIBTOOL --preserve-dup-deps"
-LT_PREREQ([2.2.6])
-LT_INIT([disable-static])
-
-dnl ================================================================
-dnl I18n stuff.
-dnl ================================================================
-AM_GNU_GETTEXT_VERSION([0.17])
-AM_GNU_GETTEXT([external])
-
-GETTEXT_PACKAGE="cogl"
-AC_SUBST(GETTEXT_PACKAGE)
-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,
- "$GETTEXT_PACKAGE",
- [The prefix for our gettext translation domains.])
-AS_ALL_LINGUAS
-
-
-dnl ================================================================
-dnl Documentation stuff.
-dnl ================================================================
-GTK_DOC_CHECK([gtk_doc_req_version], [--flavour no-tmpl])
-
-
-dnl ================================================================
-dnl Check for dependency packages.
-dnl ================================================================
-
-dnl ============================================================
-dnl Check glib dependencies
-dnl ============================================================
-AM_PATH_GLIB_2_0([glib_req_version],
- [have_glib=yes], [have_glib=no],
- [gobject gthread gmodule-no-export])
-AS_IF([test "x$have_glib" = "xno"], AC_MSG_ERROR([glib-2.0 is required]))
-
-COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES glib-2.0 pangocairo >= pangocairo_req_version"
-AC_SUBST(COGL_PKG_REQUIRES)
-PKG_CHECK_MODULES(COGL_DEP, [$COGL_PKG_REQUIRES])
-
-
-dnl ================================================================
-dnl Misc program dependencies.
-dnl ================================================================
-AC_PROG_INSTALL
-
-dnl ================================================================
-dnl GObject-Introspection check
-dnl ================================================================
-GOBJECT_INTROSPECTION_CHECK([gi_req_version])
-
-dnl ================================================================
-dnl Checks for header files.
-dnl ================================================================
-AC_PATH_X
-AC_HEADER_STDC
-AC_CHECK_HEADERS(fcntl.h limits.h unistd.h)
-
-
-dnl ================================================================
-dnl Checks for library functions.
-dnl ================================================================
-
-
-dnl ================================================================
-dnl What needs to be substituted in other files
-dnl ================================================================
-COGL_DEFINES=""
-for x in $COGL_DEFINES_SYMBOLS; do
- COGL_DEFINES="$COGL_DEFINES
-#define $x 1"
-done;
-AC_SUBST(COGL_DEFINES)
-
-
-AS_IF([test "x$cogl_gl_headers" = "x"],
- [AC_MSG_ERROR([Internal error: no GL header set])])
-dnl cogl_gl_headers is a space separate list of headers to
-dnl include. We'll now convert them to a single variable with a
-dnl #include line for each header
-COGL_GL_HEADER_INCLUDES=""
-for x in $cogl_gl_headers; do
- COGL_GL_HEADER_INCLUDES="$COGL_GL_HEADER_INCLUDES
-#include <$x>"
-done;
-AC_SUBST(COGL_GL_HEADER_INCLUDES)
-
-AC_DEFINE([COGL_ENABLE_EXPERIMENTAL_2_0_API], [1],
- [Can use Cogl 2.0 API internally])
-
-AC_SUBST(COGL_DEP_CFLAGS)
-AC_SUBST(COGL_DEP_LIBS)
-AC_SUBST(COGL_EXTRA_CFLAGS)
-AC_SUBST(COGL_EXTRA_LDFLAGS)
-
-# just for compatability with the clutter build...
-MAINTAINER_CFLAGS=
-AC_SUBST(MAINTAINER_CFLAGS)
-
-AC_OUTPUT(
-Makefile
-cogl/Makefile
-cogl/cogl-1.0.pc
-cogl/cogl-$COGL_MAJOR_VERSION.0.pc:cogl/cogl.pc.in
-cogl/cogl-defines.h
-pango/Makefile
-examples/Makefile
-po/Makefile.in
-)
-
-dnl ================================================================
-dnl Dah Da!
-dnl ================================================================
-echo ""
-echo "Cogl - $COGL_1_VERSION/$COGL_VERSION (${COGL_RELEASE_STATUS})"
-
-# Global flags
-echo ""
-echo " • Global:"
-echo " Prefix: ${prefix}"
-
-echo ""
-# Features
-echo " • Features:"
-echo " Driver: ${COGL_DRIVER} ${glesversion}"
-echo " GL Window System APIs:${GL_WINSYS_APIS}"
-if test "x$SUPPORT_EGL" = "xyes"; then
-echo " EGL Platforms:${EGL_PLATFORMS}"
-fi
-echo " Image backend: ${COGL_IMAGE_BACKEND}"
-
-# Compiler/Debug related flags
-echo ""
-echo " • Compiler options:"
-echo " Cogl debug: ${enable_debug}"
-echo " Compiler flags: ${CFLAGS} ${COGL_EXTRA_CFLAGS}"
-echo " Linker flags: ${LDFLAGS} ${COGL_EXTRA_LDFLAGS}"
-
-# Miscellaneous
-echo ""
-echo " • Extra:"
-echo " Build introspection data: ${enable_introspection}"
-
-echo ""
-
-# General warning about experimental features
-if test "x$EXPERIMENTAL_CONFIG" = "xyes"; then
-echo ""
-echo "☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠"
-echo " *WARNING*"
-echo ""
-echo " The stability of your build might be affected by one or more"
-echo " experimental configuration options."
-echo
-echo " experimental options: $EXPERIMENTAL_OPTIONS"
-echo "☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠☠"
-echo ""
-fi
+++ /dev/null
-Cogl Coding Style
---------------------
-
-This document is intended to be a short description of the preferred
-coding style to be used for the Cogl source code.
-
-Coding style is a matter of consistency, readability and maintainance;
-coding style is also completely arbitrary and a matter of taste. This
-document will use examples at the very least to provide authoritative
-and consistent answers to common questions regarding the coding style,
-and will also try to identify the allowed exceptions.
-
-The Cogl coding style is currently defined relative to the Clutter
-coding style, so please first read clutter/docs/CODING_STYLE.
-
-Differences to the Clutter coding style:
-
-+ Headers
-
-Cogl headers are not exempt from the 80 characters limit as they are in
-Clutter. Function prototypes should not be arranged into vertical
-columns but should instead follow the "+ Functions" section of the
-Clutter CODING_STYLE like:
-
-void
-my_function (CoglType type,
- CoglType *a_pointer,
- CoglType another_type);
-
-+ Types
-
-Avoid the use of redundant glib typedefs and wherever possible simply
-use ANSI C types.
-
-The following types should not be used:
- gint, guint, gfloat, gdouble, glong, gulong, gchar and guchar
-Instead use:
- int, unsigned int, float, double, long, unsigned long, char, and
- guint8/unsigned char
-
-The glib types that we continue to use for portability are gboolean,
-gint{8,16,32,64}, guint{8,16,32,64} and gsize. When ever you need a
-byte size type for dealing with pixel data then guint8 should be used.
-
-The general intention is that Cogl should look palatable to the widest
-range of C programmers including those outside the Gnome community so
-- especially for the public API - we want to minimize the number of
-foreign looking typedefs.
-
+++ /dev/null
-include $(top_srcdir)/build/autotools/Makefile.am.silent
-
-INCLUDES = \
- -I$(top_srcdir) \
- -I$(top_srcdir)/clutter/cogl \
- -I$(top_builddir)/clutter/cogl
-
-AM_CFLAGS = \
- $(COGL_DEP_CFLAGS) \
- $(COGL_EXTRA_CFLAGS) \
- -DCOGL_ENABLE_EXPERIMENTAL_2_0_API
-
-AM_CPPFLAGS = \
- -DG_DISABLE_SINGLE_INCLUDES \
- -DCOGL_DISABLE_DEPRECATED
-
-
-common_ldadd = \
- $(top_builddir)/cogl/libcogl.la \
- $(top_builddir)/pango/libcoglpango.la
-
-noinst_PROGRAMS = hello
-
-hello_SOURCES = hello.c
-hello_LDADD = $(common_ldadd)
-
-if X11_TESTS
-noinst_PROGRAMS += x11-foreign
-x11_foreign_SOURCES = x11-foreign.c
-x11_foreign_LDADD = $(common_ldadd)
-endif
+++ /dev/null
-#include <cogl/cogl.h>
-#include <glib.h>
-#include <stdio.h>
-
-int
-main (int argc, char **argv)
-{
- CoglContext *ctx;
- CoglOnscreen *onscreen;
- CoglFramebuffer *fb;
- GError *error = NULL;
- CoglVertexP2C4 triangle_vertices[] = {
- {0, 0.7, 0xff, 0x00, 0x00, 0x80},
- {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
- {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
- };
- CoglPrimitive *triangle;
-
- ctx = cogl_context_new (NULL, &error);
- if (!ctx) {
- fprintf (stderr, "Failed to create context: %s\n", error->message);
- return 1;
- }
- /* Eventually we want to get rid of any "default context" but for now it's
- * needed... */
- cogl_set_default_context (ctx);
-
- onscreen = cogl_onscreen_new (ctx, 640, 480);
- /* Eventually there will be an implicit allocate on first use so this
- * will become optional... */
- fb = COGL_FRAMEBUFFER (onscreen);
- if (!cogl_framebuffer_allocate (fb, &error)) {
- fprintf (stderr, "Failed to allocate framebuffer: %s\n", error->message);
- return 1;
- }
-
- cogl_onscreen_show (onscreen);
-
- cogl_push_framebuffer (fb);
-
- triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,
- 3, triangle_vertices);
- for (;;) {
- cogl_primitive_draw (triangle);
- cogl_framebuffer_swap_buffers (fb);
- }
-
- return 0;
-}
+++ /dev/null
-#include <cogl/cogl.h>
-#include <glib.h>
-#include <stdio.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-static void
-update_cogl_x11_event_mask (CoglOnscreen *onscreen,
- guint32 event_mask,
- void *user_data)
-{
- XDisplay *xdpy = user_data;
- XSetWindowAttributes attrs;
- guint32 xwin;
-
- attrs.event_mask = event_mask;
- xwin = cogl_onscreen_x11_get_window_xid (onscreen);
-
- XChangeWindowAttributes (xdpy,
- (Window)xwin,
- CWEventMask,
- &attrs);
-}
-
-int
-main (int argc, char **argv)
-{
- Display *xdpy;
- CoglRenderer *renderer;
- CoglSwapChain *chain;
- CoglOnscreenTemplate *onscreen_template;
- CoglDisplay *display;
- CoglContext *ctx;
- CoglOnscreen *onscreen;
- CoglFramebuffer *fb;
- GError *error = NULL;
- guint32 visual;
- XVisualInfo template, *xvisinfo;
- int visinfos_count;
- XSetWindowAttributes xattr;
- unsigned long mask;
- Window xwin;
-
- /* Since we want to test external ownership of the X display,
- * connect to X manually... */
- xdpy = XOpenDisplay (NULL);
- if (!xdpy)
- {
- fprintf (stderr, "Failed to open X Display\n");
- return 1;
- }
-
- /* Conceptually choose a GPU... */
- renderer = cogl_renderer_new ();
- /* FIXME: This should conceptually be part of the configuration of
- * a renderer. */
- cogl_renderer_xlib_set_foreign_display (renderer, xdpy);
- if (!cogl_renderer_connect (renderer, &error))
- {
- fprintf (stderr, "Failed to connect to a renderer: %s\n",
- error->message);
- }
-
- chain = cogl_swap_chain_new ();
- cogl_swap_chain_set_has_alpha (chain, TRUE);
-
- /* Conceptually declare upfront the kinds of windows we anticipate
- * creating so that when we configure the display pipeline we can avoid
- * having an impedance miss-match between the format of windows and the
- * format the display pipeline expects. */
- onscreen_template = cogl_onscreen_template_new (chain);
- cogl_object_unref (chain);
-
- /* Conceptually setup a display pipeline */
- display = cogl_display_new (renderer, onscreen_template);
- cogl_object_unref (renderer);
- if (!cogl_display_setup (display, &error))
- {
- fprintf (stderr, "Failed to setup a display pipeline: %s\n",
- error->message);
- return 1;
- }
-
- ctx = cogl_context_new (display, &error);
- if (!ctx)
- {
- fprintf (stderr, "Failed to create context: %s\n", error->message);
- return 1;
- }
- /* Eventually we want to get rid of any "default context" but for now it's
- * needed... */
- cogl_set_default_context (ctx);
-
- onscreen = cogl_onscreen_new (ctx, 640, 480);
-
- /* We want to test that Cogl can handle foreign X windows... */
-
- visual = cogl_onscreen_x11_get_visual_xid (onscreen);
- if (!visual)
- {
- fprintf (stderr, "Failed to query an X visual suitable for the "
- "configured CoglOnscreen framebuffer\n");
- return 1;
- }
-
- template.visualid = visual;
- xvisinfo = XGetVisualInfo (xdpy, VisualIDMask, &template, &visinfos_count);
-
- /* window attributes */
- xattr.background_pixel = WhitePixel (xdpy, DefaultScreen (xdpy));
- xattr.border_pixel = 0;
- xattr.colormap = XCreateColormap (xdpy,
- DefaultRootWindow (xdpy),
- xvisinfo->visual,
- AllocNone);
- mask = CWBorderPixel | CWColormap;
-
- xwin = XCreateWindow (xdpy,
- DefaultRootWindow (xdpy),
- 0, 0,
- 800, 600,
- 0,
- xvisinfo->depth,
- InputOutput,
- xvisinfo->visual,
- mask, &xattr);
-
- XFree (xvisinfo);
-
- cogl_onscreen_x11_set_foreign_window_xid (onscreen, xwin,
- update_cogl_x11_event_mask,
- xdpy);
-
- fb = COGL_FRAMEBUFFER (onscreen);
- /* Eventually there will be an implicit allocate on first use so this
- * will become optional... */
- if (!cogl_framebuffer_allocate (fb, &error))
- {
- fprintf (stderr, "Failed to allocate framebuffer: %s\n", error->message);
- return 1;
- }
-
- XMapWindow (xdpy, xwin);
-
- cogl_push_framebuffer (fb);
-
- cogl_set_source_color4f (1, 0, 0, 1);
- for (;;)
- {
- cogl_rectangle (-1, 1, 1, -1);
- cogl_framebuffer_swap_buffers (fb);
- }
-
- return 0;
-}
+++ /dev/null
-include $(top_srcdir)/build/autotools/Makefile.am.silent
-
-source_c = \
- cogl-pango-display-list.c \
- cogl-pango-fontmap.c \
- cogl-pango-render.c \
- cogl-pango-glyph-cache.c \
- cogl-pango-pipeline-cache.c
-
-source_h = cogl-pango.h
-
-source_h_priv = \
- cogl-pango-display-list.h \
- cogl-pango-private.h \
- cogl-pango-glyph-cache.h \
- cogl-pango-pipeline-cache.h
-
-if COGL_STANDALONE_BUILD
-lib_LTLIBRARIES = libcoglpango.la
-else
-noinst_LTLIBRARIES = libcoglpango.la
-endif
-
-libcoglpango_la_SOURCES = $(source_c) $(source_h) $(source_h_priv)
-libcoglpango_la_CFLAGS = $(COGL_DEP_CFLAGS) $(COGL_EXTRA_CFLAGS) $(MAINTAINER_CFLAGS)
-libcoglpango_la_LIBADD = $(COGL_DEP_LIBS) $(COGL_EXTRA_LDFLAGS)
-if COGL_STANDALONE_BUILD
-libcoglpango_la_LIBADD += $(top_builddir)/cogl/libcogl.la
-libcoglpango_la_LDFLAGS = \
- -export-dynamic \
- -export-symbols-regex "^cogl.*"
- -no-undefined \
- -version-info @COGL_LT_CURRENT@:@COGL_LT_REVISION@:@COGL_LT_AGE@
-endif
-
-INCLUDES = \
- -DG_DISABLE_SINGLE_INCLUDES \
- -DCLUTTER_COMPILATION \
- -DG_LOG_DOMAIN=\"CoglPango\" \
- -I$(top_srcdir)
-if !COGL_STANDALONE_BUILD
-INCLUDES += \
- -I$(top_srcdir)/clutter \
- -I$(top_srcdir)/clutter/cogl \
- -I$(top_builddir)/clutter \
- -I$(top_builddir)/clutter/cogl
-endif
-
-if COGL_STANDALONE_BUILD
-coglpangoheadersdir = $(includedir)/cogl/cogl
-coglpangoheaders_HEADERS = $(source_h)
-else
-coglpangoheadersdir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
-coglpangoheaders_HEADERS = $(source_h)
-endif
-
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Neil Roberts <neil@linux.intel.com>
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <cogl/cogl.h>
-#include <string.h>
-
-#include "cogl-pango-display-list.h"
-
-typedef enum
-{
- COGL_PANGO_DISPLAY_LIST_TEXTURE,
- COGL_PANGO_DISPLAY_LIST_RECTANGLE,
- COGL_PANGO_DISPLAY_LIST_TRAPEZOID
-} CoglPangoDisplayListNodeType;
-
-typedef struct _CoglPangoDisplayListNode CoglPangoDisplayListNode;
-typedef struct _CoglPangoDisplayListVertex CoglPangoDisplayListVertex;
-
-struct _CoglPangoDisplayList
-{
- gboolean color_override;
- CoglColor color;
- GSList *nodes;
- GSList *last_node;
- CoglPangoPipelineCache *pipeline_cache;
-};
-
-struct _CoglPangoDisplayListNode
-{
- CoglPangoDisplayListNodeType type;
-
- gboolean color_override;
- CoglColor color;
-
- CoglPipeline *pipeline;
-
- union
- {
- struct
- {
- /* The texture to render these coords from */
- CoglHandle texture;
- /* Array of vertex data to render out of this texture */
- GArray *verts;
- /* A VBO representing those vertices */
- CoglHandle vertex_buffer;
- } texture;
-
- struct
- {
- float x_1, y_1;
- float x_2, y_2;
- } rectangle;
-
- struct
- {
- float y_1;
- float x_11;
- float x_21;
- float y_2;
- float x_12;
- float x_22;
- } trapezoid;
- } d;
-};
-
-struct _CoglPangoDisplayListVertex
-{
- float x, y, t_x, t_y;
-};
-
-CoglPangoDisplayList *
-_cogl_pango_display_list_new (CoglPangoPipelineCache *pipeline_cache)
-{
- CoglPangoDisplayList *dl = g_slice_new0 (CoglPangoDisplayList);
-
- dl->pipeline_cache = pipeline_cache;
-
- return dl;
-}
-
-static void
-_cogl_pango_display_list_append_node (CoglPangoDisplayList *dl,
- CoglPangoDisplayListNode *node)
-{
- if (dl->last_node)
- dl->last_node = dl->last_node->next = g_slist_prepend (NULL, node);
- else
- dl->last_node = dl->nodes = g_slist_prepend (NULL, node);
-}
-
-void
-_cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
- const CoglColor *color)
-{
- dl->color_override = TRUE;
- dl->color = *color;
-}
-
-void
-_cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl)
-{
- dl->color_override = FALSE;
-}
-
-void
-_cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
- CoglHandle texture,
- float x_1, float y_1,
- float x_2, float y_2,
- float tx_1, float ty_1,
- float tx_2, float ty_2)
-{
- CoglPangoDisplayListNode *node;
- CoglPangoDisplayListVertex *verts;
-
- /* Add to the last node if it is a texture node with the same
- target texture */
- if (dl->last_node
- && (node = dl->last_node->data)->type == COGL_PANGO_DISPLAY_LIST_TEXTURE
- && node->d.texture.texture == texture
- && (dl->color_override
- ? (node->color_override && cogl_color_equal (&dl->color, &node->color))
- : !node->color_override))
- {
- /* Get rid of the vertex buffer so that it will be recreated */
- if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
- {
- cogl_handle_unref (node->d.texture.vertex_buffer);
- node->d.texture.vertex_buffer = COGL_INVALID_HANDLE;
- }
- }
- else
- {
- /* Otherwise create a new node */
- node = g_slice_new (CoglPangoDisplayListNode);
-
- node->type = COGL_PANGO_DISPLAY_LIST_TEXTURE;
- node->color_override = dl->color_override;
- node->color = dl->color;
- node->pipeline = NULL;
- node->d.texture.texture = cogl_handle_ref (texture);
- node->d.texture.verts
- = g_array_new (FALSE, FALSE, sizeof (CoglPangoDisplayListVertex));
- node->d.texture.vertex_buffer = COGL_INVALID_HANDLE;
-
- _cogl_pango_display_list_append_node (dl, node);
- }
-
- g_array_set_size (node->d.texture.verts,
- node->d.texture.verts->len + 4);
- verts = &g_array_index (node->d.texture.verts,
- CoglPangoDisplayListVertex,
- node->d.texture.verts->len - 4);
-
- verts->x = x_1;
- verts->y = y_1;
- verts->t_x = tx_1;
- verts->t_y = ty_1;
- verts++;
- verts->x = x_1;
- verts->y = y_2;
- verts->t_x = tx_1;
- verts->t_y = ty_2;
- verts++;
- verts->x = x_2;
- verts->y = y_2;
- verts->t_x = tx_2;
- verts->t_y = ty_2;
- verts++;
- verts->x = x_2;
- verts->y = y_1;
- verts->t_x = tx_2;
- verts->t_y = ty_1;
-}
-
-void
-_cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
- float x_1, float y_1,
- float x_2, float y_2)
-{
- CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode);
-
- node->type = COGL_PANGO_DISPLAY_LIST_RECTANGLE;
- node->color_override = dl->color_override;
- node->color = dl->color;
- node->d.rectangle.x_1 = x_1;
- node->d.rectangle.y_1 = y_1;
- node->d.rectangle.x_2 = x_2;
- node->d.rectangle.y_2 = y_2;
- node->pipeline = NULL;
-
- _cogl_pango_display_list_append_node (dl, node);
-}
-
-void
-_cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
- float y_1,
- float x_11,
- float x_21,
- float y_2,
- float x_12,
- float x_22)
-{
- CoglPangoDisplayListNode *node = g_slice_new (CoglPangoDisplayListNode);
-
- node->type = COGL_PANGO_DISPLAY_LIST_TRAPEZOID;
- node->color_override = dl->color_override;
- node->color = dl->color;
- node->d.trapezoid.y_1 = y_1;
- node->d.trapezoid.x_11 = x_11;
- node->d.trapezoid.x_21 = x_21;
- node->d.trapezoid.y_2 = y_2;
- node->d.trapezoid.x_12 = x_12;
- node->d.trapezoid.x_22 = x_22;
- node->pipeline = NULL;
-
- _cogl_pango_display_list_append_node (dl, node);
-}
-
-static void
-emit_rectangles_through_journal (CoglPangoDisplayListNode *node)
-{
- int i;
-
- for (i = 0; i < node->d.texture.verts->len; i += 4)
- {
- CoglPangoDisplayListVertex *v0 =
- &g_array_index (node->d.texture.verts,
- CoglPangoDisplayListVertex, i);
- CoglPangoDisplayListVertex *v1 =
- &g_array_index (node->d.texture.verts,
- CoglPangoDisplayListVertex, i + 2);
- cogl_rectangle_with_texture_coords (v0->x, v0->y, v1->x, v1->y,
- v0->t_x, v0->t_y,
- v1->t_x, v1->t_y);
- }
-}
-
-static void
-emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
-{
- /* It's expensive to go through the Cogl journal for large runs
- * of text in part because the journal transforms the quads in software
- * to avoid changing the modelview matrix. So for larger runs of text
- * we load the vertices into a VBO, and this has the added advantage
- * that if the text doesn't change from frame to frame the VBO can
- * be re-used avoiding the repeated cost of validating the data and
- * mapping it into the GPU... */
-
- if (node->d.texture.vertex_buffer == COGL_INVALID_HANDLE)
- {
- CoglHandle vb = cogl_vertex_buffer_new (node->d.texture.verts->len);
-
- cogl_vertex_buffer_add (vb, "gl_Vertex", 2,
- COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
- sizeof (CoglPangoDisplayListVertex),
- &g_array_index (node->d.texture.verts,
- CoglPangoDisplayListVertex, 0).x);
- cogl_vertex_buffer_add (vb, "gl_MultiTexCoord0", 2,
- COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
- sizeof (CoglPangoDisplayListVertex),
- &g_array_index (node->d.texture.verts,
- CoglPangoDisplayListVertex,
- 0).t_x);
- cogl_vertex_buffer_submit (vb);
-
- node->d.texture.vertex_buffer = vb;
- }
-
-
-#ifdef CLUTTER_COGL_HAS_GL
-
- cogl_vertex_buffer_draw (node->d.texture.vertex_buffer,
- GL_QUADS,
- 0, node->d.texture.verts->len);
-
-#else /* CLUTTER_COGL_HAS_GL */
- {
- /* GLES doesn't support GL_QUADS so instead we use a VBO with
- indexed vertices to generate GL_TRIANGLES from the quads */
-
- int n_indices = node->d.texture.verts->len / 4 * 6;
- CoglHandle indices_vbo
- = cogl_vertex_buffer_indices_get_for_quads (n_indices);
-
- cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer,
- COGL_VERTICES_MODE_TRIANGLES,
- indices_vbo,
- 0, node->d.texture.verts->len - 1,
- 0, n_indices);
- }
-#endif /* CLUTTER_COGL_HAS_GL */
-}
-
-static void
-_cogl_pango_display_list_render_texture (CoglPangoDisplayListNode *node)
-{
- /* For small runs of text like icon labels, we can get better performance
- * going through the Cogl journal since text may then be batched together
- * with other geometry. */
- /* FIXME: 100 is a number I plucked out of thin air; it would be good
- * to determine this empirically! */
- if (node->d.texture.verts->len < 100)
- emit_rectangles_through_journal (node);
- else
- emit_vertex_buffer_geometry (node);
-}
-
-void
-_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
- const CoglColor *color)
-{
- GSList *l;
-
- for (l = dl->nodes; l; l = l->next)
- {
- CoglPangoDisplayListNode *node = l->data;
- CoglColor draw_color;
-
- if (node->pipeline == NULL)
- {
- if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
- node->pipeline =
- _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
- node->d.texture.texture);
- else
- node->pipeline =
- _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
- NULL);
- }
-
- if (node->color_override)
- /* Use the override color but preserve the alpha from the
- draw color */
- cogl_color_init_from_4ub (&draw_color,
- cogl_color_get_red_byte (&node->color),
- cogl_color_get_green_byte (&node->color),
- cogl_color_get_blue_byte (&node->color),
- cogl_color_get_alpha_byte (color));
- else
- draw_color = *color;
- cogl_color_premultiply (&draw_color);
-
- cogl_pipeline_set_color (node->pipeline, &draw_color);
- cogl_push_source (node->pipeline);
-
- switch (node->type)
- {
- case COGL_PANGO_DISPLAY_LIST_TEXTURE:
- _cogl_pango_display_list_render_texture (node);
- break;
-
- case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
- cogl_rectangle (node->d.rectangle.x_1,
- node->d.rectangle.y_1,
- node->d.rectangle.x_2,
- node->d.rectangle.y_2);
- break;
-
- case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
- {
- float points[8];
- CoglPath *path;
-
- points[0] = node->d.trapezoid.x_11;
- points[1] = node->d.trapezoid.y_1;
- points[2] = node->d.trapezoid.x_12;
- points[3] = node->d.trapezoid.y_2;
- points[4] = node->d.trapezoid.x_22;
- points[5] = node->d.trapezoid.y_2;
- points[6] = node->d.trapezoid.x_21;
- points[7] = node->d.trapezoid.y_1;
-
- path = cogl_path_new ();
- cogl_path_polygon (path, points, 4);
- cogl_path_fill (path);
- cogl_object_unref (path);
- }
- break;
- }
-
- cogl_pop_source ();
- }
-}
-
-static void
-_cogl_pango_display_list_node_free (CoglPangoDisplayListNode *node)
-{
- if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
- {
- g_array_free (node->d.texture.verts, TRUE);
- if (node->d.texture.texture != COGL_INVALID_HANDLE)
- cogl_handle_unref (node->d.texture.texture);
- if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
- cogl_handle_unref (node->d.texture.vertex_buffer);
- }
-
- if (node->pipeline)
- cogl_object_unref (node->pipeline);
-
- g_slice_free (CoglPangoDisplayListNode, node);
-}
-
-void
-_cogl_pango_display_list_clear (CoglPangoDisplayList *dl)
-{
- g_slist_foreach (dl->nodes, (GFunc) _cogl_pango_display_list_node_free, NULL);
- g_slist_free (dl->nodes);
- dl->nodes = NULL;
- dl->last_node = NULL;
-}
-
-void
-_cogl_pango_display_list_free (CoglPangoDisplayList *dl)
-{
- _cogl_pango_display_list_clear (dl);
- g_slice_free (CoglPangoDisplayList, dl);
-}
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Neil Roberts <neil@linux.intel.com>
- *
- * Copyright (C) 2009 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __COGL_PANGO_DISPLAY_LIST_H__
-#define __COGL_PANGO_DISPLAY_LIST_H__
-
-#include <glib.h>
-#include <cogl/cogl.h>
-#include "cogl-pango-pipeline-cache.h"
-
-G_BEGIN_DECLS
-
-typedef struct _CoglPangoDisplayList CoglPangoDisplayList;
-
-CoglPangoDisplayList *_cogl_pango_display_list_new (CoglPangoPipelineCache *);
-
-void _cogl_pango_display_list_set_color_override (CoglPangoDisplayList *dl,
- const CoglColor *color);
-void _cogl_pango_display_list_remove_color_override (CoglPangoDisplayList *dl);
-
-void _cogl_pango_display_list_add_texture (CoglPangoDisplayList *dl,
- CoglHandle texture,
- float x_1, float y_1,
- float x_2, float y_2,
- float tx_1, float ty_1,
- float tx_2, float ty_2);
-
-void _cogl_pango_display_list_add_rectangle (CoglPangoDisplayList *dl,
- float x_1, float y_1,
- float x_2, float y_2);
-
-void _cogl_pango_display_list_add_trapezoid (CoglPangoDisplayList *dl,
- float y_1,
- float x_11,
- float x_21,
- float y_2,
- float x_12,
- float x_22);
-
-void _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
- const CoglColor *color);
-
-void _cogl_pango_display_list_clear (CoglPangoDisplayList *dl);
-
-void _cogl_pango_display_list_free (CoglPangoDisplayList *dl);
-
-G_END_DECLS
-
-#endif /* __COGL_PANGO_DISPLAY_LIST_H__ */
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * SECTION:cogl-pango
- * @short_description: COGL-based text rendering using Pango
- *
- * FIXME
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-/* This is needed to get the Pango headers to export stuff needed to
- subclass */
-#ifndef PANGO_ENABLE_BACKEND
-#define PANGO_ENABLE_BACKEND 1
-#endif
-
-#include <pango/pango-fontmap.h>
-#include <pango/pangocairo.h>
-#include <pango/pango-renderer.h>
-
-#include "cogl-pango.h"
-#include "cogl-pango-private.h"
-
-static GQuark cogl_pango_font_map_get_renderer_key (void) G_GNUC_CONST;
-
-/**
- * cogl_pango_font_map_new:
- *
- * Creates a new font map.
- *
- * Return value: the newly created #PangoFontMap
- *
- * Since: 1.0
- */
-PangoFontMap *
-cogl_pango_font_map_new (void)
-{
- return pango_cairo_font_map_new ();
-}
-
-/**
- * cogl_pango_font_map_create_context:
- * @fm: a #CoglPangoFontMap
- *
- * Creates a new #PangoContext from the passed font map.
- *
- * Return value: the newly created #PangoContext
- *
- * Since: 1.0
- */
-PangoContext *
-cogl_pango_font_map_create_context (CoglPangoFontMap *fm)
-{
- g_return_val_if_fail (COGL_PANGO_IS_FONT_MAP (fm), NULL);
-
- /* We can just directly use the pango context from the Cairo font
- map */
- return pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fm));
-}
-
-/**
- * cogl_pango_font_map_get_renderer:
- * @fm: a #CoglPangoFontMap
- *
- * Retrieves the #CoglPangoRenderer for the passed font map.
- *
- * Return value: a #PangoRenderer
- *
- * Since: 1.0
- */
-PangoRenderer *
-cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm)
-{
- PangoRenderer *renderer;
-
- g_return_val_if_fail (COGL_PANGO_IS_FONT_MAP (fm), NULL);
-
- /* We want to keep a cached pointer to the renderer from the font
- map instance but as we don't have a proper subclass we have to
- store it in the object data instead */
-
- renderer = g_object_get_qdata (G_OBJECT (fm),
- cogl_pango_font_map_get_renderer_key ());
-
- if (G_UNLIKELY (renderer == NULL))
- {
- renderer = g_object_new (COGL_PANGO_TYPE_RENDERER, NULL);
- g_object_set_qdata_full (G_OBJECT (fm),
- cogl_pango_font_map_get_renderer_key (),
- renderer,
- g_object_unref);
- }
-
- return renderer;
-}
-
-/**
- * cogl_pango_font_map_set_resolution:
- * @font_map: a #CoglPangoFontMap
- * @dpi: DPI to set
- *
- * Sets the resolution to be used by @font_map at @dpi.
- *
- * Since: 1.0
- */
-void
-cogl_pango_font_map_set_resolution (CoglPangoFontMap *font_map,
- double dpi)
-{
- g_return_if_fail (COGL_PANGO_IS_FONT_MAP (font_map));
-
- pango_cairo_font_map_set_resolution (PANGO_CAIRO_FONT_MAP (font_map), dpi);
-}
-
-/**
- * cogl_pango_font_map_clear_glyph_cache:
- * @fm: a #CoglPangoFontMap
- *
- * Clears the glyph cache for @fm.
- *
- * Since: 1.0
- */
-void
-cogl_pango_font_map_clear_glyph_cache (CoglPangoFontMap *fm)
-{
- PangoRenderer *renderer;
-
- renderer = cogl_pango_font_map_get_renderer (fm);
-
- _cogl_pango_renderer_clear_glyph_cache (COGL_PANGO_RENDERER (renderer));
-}
-
-/**
- * cogl_pango_font_map_set_use_mipmapping:
- * @fm: a #CoglPangoFontMap
- * @value: %TRUE to enable the use of mipmapping
- *
- * Sets whether the renderer for the passed font map should use
- * mipmapping when rendering a #PangoLayout.
- *
- * Since: 1.0
- */
-void
-cogl_pango_font_map_set_use_mipmapping (CoglPangoFontMap *fm,
- gboolean value)
-{
- CoglPangoRenderer *renderer;
-
- renderer = COGL_PANGO_RENDERER (cogl_pango_font_map_get_renderer (fm));
-
- _cogl_pango_renderer_set_use_mipmapping (renderer, value);
-}
-
-/**
- * cogl_pango_font_map_get_use_mipmapping:
- * @fm: a #CoglPangoFontMap
- *
- * Retrieves whether the #CoglPangoRenderer used by @fm will
- * use mipmapping when rendering the glyphs.
- *
- * Return value: %TRUE if mipmapping is used, %FALSE otherwise.
- *
- * Since: 1.0
- */
-gboolean
-cogl_pango_font_map_get_use_mipmapping (CoglPangoFontMap *fm)
-{
- CoglPangoRenderer *renderer;
-
- renderer = COGL_PANGO_RENDERER (cogl_pango_font_map_get_renderer (fm));
-
- return _cogl_pango_renderer_get_use_mipmapping (renderer);
-}
-
-static GQuark
-cogl_pango_font_map_get_renderer_key (void)
-{
- static GQuark renderer_key = 0;
-
- if (G_UNLIKELY (renderer_key == 0))
- renderer_key = g_quark_from_static_string ("CoglPangoFontMap");
-
- return renderer_key;
-}
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-
-#include "cogl-pango-glyph-cache.h"
-#include "cogl-pango-private.h"
-#include "cogl/cogl-atlas.h"
-#include "cogl/cogl-atlas-texture-private.h"
-
-typedef struct _CoglPangoGlyphCacheKey CoglPangoGlyphCacheKey;
-
-struct _CoglPangoGlyphCache
-{
- /* Hash table to quickly check whether a particular glyph in a
- particular font is already cached */
- GHashTable *hash_table;
-
- /* List of CoglAtlases */
- GSList *atlases;
-
- /* List of callbacks to invoke when an atlas is reorganized */
- GHookList reorganize_callbacks;
-
- /* TRUE if we've ever stored a texture in the global atlas. This is
- used to make sure we only register one callback to listen for
- global atlas reorganizations */
- gboolean using_global_atlas;
-
- /* True if some of the glyphs are dirty. This is used as an
- optimization in _cogl_pango_glyph_cache_set_dirty_glyphs to avoid
- iterating the hash table if we know none of them are dirty */
- gboolean has_dirty_glyphs;
-
- /* Whether mipmapping is being used for this cache. This only
- affects whether we decide to put the glyph in the global atlas */
- gboolean use_mipmapping;
-};
-
-struct _CoglPangoGlyphCacheKey
-{
- PangoFont *font;
- PangoGlyph glyph;
-};
-
-static void
-cogl_pango_glyph_cache_value_free (CoglPangoGlyphCacheValue *value)
-{
- if (value->texture)
- cogl_handle_unref (value->texture);
- g_slice_free (CoglPangoGlyphCacheValue, value);
-}
-
-static void
-cogl_pango_glyph_cache_key_free (CoglPangoGlyphCacheKey *key)
-{
- g_object_unref (key->font);
- g_slice_free (CoglPangoGlyphCacheKey, key);
-}
-
-static guint
-cogl_pango_glyph_cache_hash_func (gconstpointer key)
-{
- const CoglPangoGlyphCacheKey *cache_key
- = (const CoglPangoGlyphCacheKey *) key;
-
- /* Generate a number affected by both the font and the glyph
- number. We can safely directly compare the pointers because the
- key holds a reference to the font so it is not possible that a
- different font will have the same memory address */
- return GPOINTER_TO_UINT (cache_key->font) ^ cache_key->glyph;
-}
-
-static gboolean
-cogl_pango_glyph_cache_equal_func (gconstpointer a,
- gconstpointer b)
-{
- const CoglPangoGlyphCacheKey *key_a
- = (const CoglPangoGlyphCacheKey *) a;
- const CoglPangoGlyphCacheKey *key_b
- = (const CoglPangoGlyphCacheKey *) b;
-
- /* We can safely directly compare the pointers for the fonts because
- the key holds a reference to the font so it is not possible that
- a different font will have the same memory address */
- return key_a->font == key_b->font
- && key_a->glyph == key_b->glyph;
-}
-
-CoglPangoGlyphCache *
-cogl_pango_glyph_cache_new (gboolean use_mipmapping)
-{
- CoglPangoGlyphCache *cache;
-
- cache = g_malloc (sizeof (CoglPangoGlyphCache));
-
- cache->hash_table = g_hash_table_new_full
- (cogl_pango_glyph_cache_hash_func,
- cogl_pango_glyph_cache_equal_func,
- (GDestroyNotify) cogl_pango_glyph_cache_key_free,
- (GDestroyNotify) cogl_pango_glyph_cache_value_free);
-
- cache->atlases = NULL;
- g_hook_list_init (&cache->reorganize_callbacks, sizeof (GHook));
-
- cache->has_dirty_glyphs = FALSE;
-
- cache->use_mipmapping = use_mipmapping;
-
- return cache;
-}
-
-static void
-cogl_pango_glyph_cache_reorganize_cb (void *user_data)
-{
- CoglPangoGlyphCache *cache = user_data;
-
- g_hook_list_invoke (&cache->reorganize_callbacks, FALSE);
-}
-
-void
-cogl_pango_glyph_cache_clear (CoglPangoGlyphCache *cache)
-{
- g_slist_foreach (cache->atlases, (GFunc) cogl_object_unref, NULL);
- g_slist_free (cache->atlases);
- cache->atlases = NULL;
- cache->has_dirty_glyphs = FALSE;
-
- g_hash_table_remove_all (cache->hash_table);
-}
-
-void
-cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache)
-{
- if (cache->using_global_atlas)
- _cogl_atlas_texture_remove_reorganize_callback
- (cogl_pango_glyph_cache_reorganize_cb, cache);
-
- cogl_pango_glyph_cache_clear (cache);
-
- g_hash_table_unref (cache->hash_table);
-
- g_hook_list_clear (&cache->reorganize_callbacks);
-
- g_free (cache);
-}
-
-static void
-cogl_pango_glyph_cache_update_position_cb (void *user_data,
- CoglHandle new_texture,
- const CoglRectangleMapEntry *rect)
-{
- CoglPangoGlyphCacheValue *value = user_data;
- float tex_width, tex_height;
-
- if (value->texture)
- cogl_handle_unref (value->texture);
- value->texture = cogl_handle_ref (new_texture);
-
- tex_width = cogl_texture_get_width (new_texture);
- tex_height = cogl_texture_get_height (new_texture);
-
- value->tx1 = rect->x / tex_width;
- value->ty1 = rect->y / tex_height;
- value->tx2 = (rect->x + value->draw_width) / tex_width;
- value->ty2 = (rect->y + value->draw_height) / tex_height;
-
- value->tx_pixel = rect->x;
- value->ty_pixel = rect->y;
-
- /* The glyph has changed position so it will need to be redrawn */
- value->dirty = TRUE;
-}
-
-static gboolean
-cogl_pango_glyph_cache_add_to_global_atlas (CoglPangoGlyphCache *cache,
- PangoFont *font,
- PangoGlyph glyph,
- CoglPangoGlyphCacheValue *value)
-{
- CoglHandle texture;
-
- if (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_SHARED_ATLAS))
- return FALSE;
-
- /* If the cache is using mipmapping then we can't use the global
- atlas because it would just get migrated back out */
- if (cache->use_mipmapping)
- return FALSE;
-
- texture = _cogl_atlas_texture_new_with_size (value->draw_width,
- value->draw_height,
- COGL_TEXTURE_NONE,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE);
-
- if (texture == COGL_INVALID_HANDLE)
- return FALSE;
-
- value->texture = texture;
- value->tx1 = 0;
- value->ty1 = 0;
- value->tx2 = 1;
- value->ty2 = 1;
- value->tx_pixel = 0;
- value->ty_pixel = 0;
-
- /* The first time we store a texture in the global atlas we'll
- register for notifications when the global atlas is reorganized
- so we can forward the notification on as a glyph
- reorganization */
- if (!cache->using_global_atlas)
- {
- _cogl_atlas_texture_add_reorganize_callback
- (cogl_pango_glyph_cache_reorganize_cb, cache);
- cache->using_global_atlas = TRUE;
- }
-
- return TRUE;
-}
-
-static gboolean
-cogl_pango_glyph_cache_add_to_local_atlas (CoglPangoGlyphCache *cache,
- PangoFont *font,
- PangoGlyph glyph,
- CoglPangoGlyphCacheValue *value)
-{
- CoglAtlas *atlas = NULL;
- GSList *l;
-
- /* Look for an atlas that can reserve the space */
- for (l = cache->atlases; l; l = l->next)
- if (_cogl_atlas_reserve_space (l->data,
- value->draw_width + 1,
- value->draw_height + 1,
- value))
- {
- atlas = l->data;
- break;
- }
-
- /* If we couldn't find one then start a new atlas */
- if (atlas == NULL)
- {
- atlas = _cogl_atlas_new (COGL_PIXEL_FORMAT_A_8,
- COGL_ATLAS_CLEAR_TEXTURE |
- COGL_ATLAS_DISABLE_MIGRATION,
- cogl_pango_glyph_cache_update_position_cb);
- COGL_NOTE (ATLAS, "Created new atlas for glyphs: %p", atlas);
- /* If we still can't reserve space then something has gone
- seriously wrong so we'll just give up */
- if (!_cogl_atlas_reserve_space (atlas,
- value->draw_width + 1,
- value->draw_height + 1,
- value))
- {
- cogl_object_unref (atlas);
- return FALSE;
- }
-
- _cogl_atlas_add_reorganize_callback
- (atlas, cogl_pango_glyph_cache_reorganize_cb, NULL, cache);
-
- cache->atlases = g_slist_prepend (cache->atlases, atlas);
- }
-
- return TRUE;
-}
-
-CoglPangoGlyphCacheValue *
-cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
- gboolean create,
- PangoFont *font,
- PangoGlyph glyph)
-{
- CoglPangoGlyphCacheKey lookup_key;
- CoglPangoGlyphCacheValue *value;
-
- lookup_key.font = font;
- lookup_key.glyph = glyph;
-
- value = g_hash_table_lookup (cache->hash_table, &lookup_key);
-
- if (create && value == NULL)
- {
- CoglPangoGlyphCacheKey *key;
- PangoRectangle ink_rect;
-
- value = g_slice_new (CoglPangoGlyphCacheValue);
- value->texture = COGL_INVALID_HANDLE;
-
- pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL);
- pango_extents_to_pixels (&ink_rect, NULL);
-
- value->draw_x = ink_rect.x;
- value->draw_y = ink_rect.y;
- value->draw_width = ink_rect.width;
- value->draw_height = ink_rect.height;
-
- /* If the glyph is zero-sized then we don't need to reserve any
- space for it and we can just avoid painting anything */
- if (ink_rect.width < 1 || ink_rect.height < 1)
- value->dirty = FALSE;
- else
- {
- /* Try adding the glyph to the global atlas... */
- if (!cogl_pango_glyph_cache_add_to_global_atlas (cache,
- font,
- glyph,
- value) &&
- /* If it fails try the local atlas */
- !cogl_pango_glyph_cache_add_to_local_atlas (cache,
- font,
- glyph,
- value))
- {
- cogl_pango_glyph_cache_value_free (value);
- return NULL;
- }
-
- value->dirty = TRUE;
- cache->has_dirty_glyphs = TRUE;
- }
-
- key = g_slice_new (CoglPangoGlyphCacheKey);
- key->font = g_object_ref (font);
- key->glyph = glyph;
-
- g_hash_table_insert (cache->hash_table, key, value);
- }
-
- return value;
-}
-
-static void
-_cogl_pango_glyph_cache_set_dirty_glyphs_cb (gpointer key_ptr,
- gpointer value_ptr,
- gpointer user_data)
-{
- CoglPangoGlyphCacheKey *key = key_ptr;
- CoglPangoGlyphCacheValue *value = value_ptr;
- CoglPangoGlyphCacheDirtyFunc func = user_data;
-
- if (value->dirty)
- {
- func (key->font, key->glyph, value);
-
- value->dirty = FALSE;
- }
-}
-
-void
-_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache,
- CoglPangoGlyphCacheDirtyFunc func)
-{
- /* If we know that there are no dirty glyphs then we can shortcut
- out early */
- if (!cache->has_dirty_glyphs)
- return;
-
- g_hash_table_foreach (cache->hash_table,
- _cogl_pango_glyph_cache_set_dirty_glyphs_cb,
- func);
-
- cache->has_dirty_glyphs = FALSE;
-}
-
-void
-_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
- GHookFunc func,
- void *user_data)
-{
- GHook *hook = g_hook_alloc (&cache->reorganize_callbacks);
- hook->func = func;
- hook->data = user_data;
- g_hook_prepend (&cache->reorganize_callbacks, hook);
-}
-
-void
-_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
- GHookFunc func,
- void *user_data)
-{
- GHook *hook = g_hook_find_func_data (&cache->reorganize_callbacks,
- FALSE,
- func,
- user_data);
-
- if (hook)
- g_hook_destroy_link (&cache->reorganize_callbacks, hook);
-}
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __COGL_PANGO_GLYPH_CACHE_H__
-#define __COGL_PANGO_GLYPH_CACHE_H__
-
-#include <glib.h>
-#include <cogl/cogl.h>
-#include <pango/pango-font.h>
-
-G_BEGIN_DECLS
-
-typedef struct _CoglPangoGlyphCache CoglPangoGlyphCache;
-typedef struct _CoglPangoGlyphCacheValue CoglPangoGlyphCacheValue;
-
-struct _CoglPangoGlyphCacheValue
-{
- CoglHandle texture;
-
- float tx1;
- float ty1;
- float tx2;
- float ty2;
-
- int tx_pixel;
- int ty_pixel;
-
- int draw_x;
- int draw_y;
- int draw_width;
- int draw_height;
-
- /* This will be set to TRUE when the glyph atlas is reorganized
- which means the glyph will need to be redrawn */
- gboolean dirty;
-};
-
-typedef void (* CoglPangoGlyphCacheDirtyFunc) (PangoFont *font,
- PangoGlyph glyph,
- CoglPangoGlyphCacheValue *value);
-
-CoglPangoGlyphCache *
-cogl_pango_glyph_cache_new (gboolean use_mipmapping);
-
-void
-cogl_pango_glyph_cache_free (CoglPangoGlyphCache *cache);
-
-CoglPangoGlyphCacheValue *
-cogl_pango_glyph_cache_lookup (CoglPangoGlyphCache *cache,
- gboolean create,
- PangoFont *font,
- PangoGlyph glyph);
-
-void
-cogl_pango_glyph_cache_clear (CoglPangoGlyphCache *cache);
-
-void
-_cogl_pango_glyph_cache_add_reorganize_callback (CoglPangoGlyphCache *cache,
- GHookFunc func,
- void *user_data);
-
-void
-_cogl_pango_glyph_cache_remove_reorganize_callback (CoglPangoGlyphCache *cache,
- GHookFunc func,
- void *user_data);
-
-void
-_cogl_pango_glyph_cache_set_dirty_glyphs (CoglPangoGlyphCache *cache,
- CoglPangoGlyphCacheDirtyFunc func);
-
-G_END_DECLS
-
-#endif /* __COGL_PANGO_GLYPH_CACHE_H__ */
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib.h>
-#include <cogl/cogl.h>
-#include "cogl-pango-pipeline-cache.h"
-
-typedef struct _CoglPangoPipelineCacheEntry CoglPangoPipelineCacheEntry;
-
-struct _CoglPangoPipelineCache
-{
- GHashTable *hash_table;
-
- CoglPipeline *base_texture_alpha_pipeline;
- CoglPipeline *base_texture_rgba_pipeline;
-
- gboolean use_mipmapping;
-};
-
-struct _CoglPangoPipelineCacheEntry
-{
- /* This will take a reference or it can be NULL to represent the
- pipeline used to render colors */
- CoglHandle texture;
-
- /* This will only take a weak reference */
- CoglHandle pipeline;
-};
-
-static void
-_cogl_pango_pipeline_cache_key_destroy (gpointer data)
-{
- if (data)
- cogl_object_unref (data);
-}
-
-static void
-_cogl_pango_pipeline_cache_value_destroy (gpointer data)
-{
- CoglPangoPipelineCacheEntry *cache_entry = data;
-
- if (cache_entry->texture)
- cogl_object_unref (cache_entry->texture);
-
- /* We don't need to unref the pipeline because it only takes a weak
- reference */
-
- g_slice_free (CoglPangoPipelineCacheEntry, cache_entry);
-}
-
-CoglPangoPipelineCache *
-_cogl_pango_pipeline_cache_new (gboolean use_mipmapping)
-{
- CoglPangoPipelineCache *cache = g_new (CoglPangoPipelineCache, 1);
-
- /* The key is the pipeline pointer. A reference is taken when the
- pipeline is used as a key so we should unref it again in the
- destroy function */
- cache->hash_table =
- g_hash_table_new_full (g_direct_hash,
- g_direct_equal,
- _cogl_pango_pipeline_cache_key_destroy,
- _cogl_pango_pipeline_cache_value_destroy);
-
- cache->base_texture_rgba_pipeline = NULL;
- cache->base_texture_alpha_pipeline = NULL;
-
- cache->use_mipmapping = use_mipmapping;
-
- return cache;
-}
-
-static CoglPipeline *
-get_base_texture_rgba_pipeline (CoglPangoPipelineCache *cache)
-{
- if (cache->base_texture_rgba_pipeline == NULL)
- {
- CoglPipeline *pipeline;
-
- pipeline = cache->base_texture_rgba_pipeline = cogl_pipeline_new ();
-
- cogl_pipeline_set_layer_wrap_mode (pipeline, 0,
- COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);
-
- if (cache->use_mipmapping)
- cogl_pipeline_set_layer_filters
- (pipeline, 0,
- COGL_PIPELINE_FILTER_LINEAR_MIPMAP_LINEAR,
- COGL_PIPELINE_FILTER_LINEAR);
- }
-
- return cache->base_texture_rgba_pipeline;
-}
-
-static CoglPipeline *
-get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
-{
- if (cache->base_texture_alpha_pipeline == NULL)
- {
- CoglPipeline *pipeline;
-
- pipeline = cogl_pipeline_copy (get_base_texture_rgba_pipeline (cache));
- cache->base_texture_alpha_pipeline = pipeline;
-
- /* The default combine mode of materials is to modulate (A x B)
- * the texture RGBA channels with the RGBA channels of the
- * previous layer (which in our case is just the font color)
- *
- * Since the RGB for an alpha texture is defined as 0, this gives us:
- *
- * result.rgb = color.rgb * 0
- * result.a = color.a * texture.a
- *
- * What we want is premultiplied rgba values:
- *
- * result.rgba = color.rgb * texture.a
- * result.a = color.a * texture.a
- */
- cogl_pipeline_set_layer_combine (pipeline, 0, /* layer */
- "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
- NULL);
- }
-
- return cache->base_texture_alpha_pipeline;
-}
-
-typedef struct
-{
- CoglPangoPipelineCache *cache;
- CoglHandle texture;
-} PipelineDestroyNotifyData;
-
-static void
-pipeline_destroy_notify_cb (void *user_data)
-{
- PipelineDestroyNotifyData *data = user_data;
-
- g_hash_table_remove (data->cache->hash_table, data->texture);
- g_slice_free (PipelineDestroyNotifyData, data);
-}
-
-CoglPipeline *
-_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
- CoglHandle texture)
-{
- CoglPangoPipelineCacheEntry *entry;
- PipelineDestroyNotifyData *destroy_data;
- static CoglUserDataKey pipeline_destroy_notify_key;
-
- /* Look for an existing entry */
- entry = g_hash_table_lookup (cache->hash_table, texture);
-
- if (entry)
- return cogl_object_ref (entry->pipeline);
-
- /* No existing pipeline was found so let's create another */
- entry = g_slice_new (CoglPangoPipelineCacheEntry);
-
- if (texture)
- {
- CoglPipeline *base;
-
- entry->texture = cogl_handle_ref (texture);
-
- if (cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8)
- base = get_base_texture_alpha_pipeline (cache);
- else
- base = get_base_texture_rgba_pipeline (cache);
-
- entry->pipeline = cogl_pipeline_copy (base);
-
- cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture);
- }
- else
- {
- entry->texture = NULL;
- entry->pipeline = cogl_pipeline_new ();
- }
-
- /* Add a weak reference to the pipeline so we can remove it from the
- hash table when it is destroyed */
- destroy_data = g_slice_new (PipelineDestroyNotifyData);
- destroy_data->cache = cache;
- destroy_data->texture = texture;
- cogl_object_set_user_data (entry->pipeline,
- &pipeline_destroy_notify_key,
- destroy_data,
- pipeline_destroy_notify_cb);
-
- g_hash_table_insert (cache->hash_table,
- texture ? cogl_handle_ref (texture) : NULL,
- entry);
-
- /* This doesn't take a reference on the pipeline so that it will use
- the newly created reference */
- return entry->pipeline;
-}
-
-void
-_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache)
-{
- if (cache->base_texture_rgba_pipeline)
- cogl_object_unref (cache->base_texture_rgba_pipeline);
- if (cache->base_texture_alpha_pipeline)
- cogl_object_unref (cache->base_texture_alpha_pipeline);
-
- g_hash_table_destroy (cache->hash_table);
-
- g_free (cache);
-}
+++ /dev/null
-/*
- * Cogl
- *
- * An object oriented GL/GLES Abstraction/Utility Layer
- *
- * Copyright (C) 2011 Intel Corporation.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see
- * <http://www.gnu.org/licenses/>.
- *
- *
- *
- * Authors:
- * Neil Roberts <neil@linux.intel.com>
- */
-
-#ifndef __COGL_PANGO_PIPELINE_CACHE_H__
-#define __COGL_PANGO_PIPELINE_CACHE_H__
-
-#include <glib.h>
-#include <cogl/cogl.h>
-
-G_BEGIN_DECLS
-
-typedef struct _CoglPangoPipelineCache CoglPangoPipelineCache;
-
-CoglPangoPipelineCache *
-_cogl_pango_pipeline_cache_new (gboolean use_mipmapping);
-
-/* Returns a pipeline that can be used to render glyphs in the given
- texture. The pipeline has a new reference so it is up to the caller
- to unref it */
-CoglPipeline *
-_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
- CoglHandle texture);
-
-void
-_cogl_pango_pipeline_cache_free (CoglPangoPipelineCache *cache);
-
-G_END_DECLS
-
-#endif /* __COGL_PANGO_PIPELINE_CACHE_H__ */
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __COGL_PANGO_PRIVATE_H__
-#define __COGL_PANGO_PRIVATE_H__
-
-#include "cogl-pango.h"
-
-G_BEGIN_DECLS
-
-void _cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer);
-void _cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer,
- gboolean value);
-gboolean _cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer);
-
-G_END_DECLS
-
-#endif /* __COGL_PANGO_PRIVATE_H__ */
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifndef PANGO_ENABLE_BACKEND
-#define PANGO_ENABLE_BACKEND 1
-#endif
-
-#include <pango/pango-fontmap.h>
-#include <pango/pangocairo.h>
-#include <pango/pango-renderer.h>
-#include <cairo.h>
-
-#include "cogl/cogl-debug.h"
-#include "cogl/cogl-texture-private.h"
-#include "cogl-pango-private.h"
-#include "cogl-pango-glyph-cache.h"
-#include "cogl-pango-display-list.h"
-
-struct _CoglPangoRenderer
-{
- PangoRenderer parent_instance;
-
- /* Two caches of glyphs as textures, one with mipmapped textures and
- one without */
- CoglPangoGlyphCache *glyph_cache;
- CoglPangoGlyphCache *mipmapped_glyph_cache;
-
- CoglPangoPipelineCache *pipeline_cache;
- CoglPangoPipelineCache *mipmapped_pipeline_cache;
-
- gboolean use_mipmapping;
-
- /* The current display list that is being built */
- CoglPangoDisplayList *display_list;
-};
-
-struct _CoglPangoRendererClass
-{
- PangoRendererClass class_instance;
-};
-
-typedef struct _CoglPangoRendererQdata CoglPangoRendererQdata;
-
-/* An instance of this struct gets attached to each PangoLayout to
- cache the VBO and to detect changes to the layout */
-struct _CoglPangoRendererQdata
-{
- CoglPangoRenderer *renderer;
- /* The cache of the geometry for the layout */
- CoglPangoDisplayList *display_list;
- /* A reference to the first line of the layout. This is just used to
- detect changes */
- PangoLayoutLine *first_line;
- /* Whether mipmapping was previously used to render this layout. We
- need to regenerate the display list if the mipmapping value is
- changed because it will be using a different set of textures */
- gboolean mipmapping_used;
-};
-
-static void
-_cogl_pango_ensure_glyph_cache_for_layout_line (PangoLayoutLine *line);
-
-typedef struct
-{
- CoglPangoDisplayList *display_list;
- float x1, y1, x2, y2;
-} CoglPangoRendererSliceCbData;
-
-void
-cogl_pango_renderer_slice_cb (CoglHandle handle,
- const float *slice_coords,
- const float *virtual_coords,
- void *user_data)
-{
- CoglPangoRendererSliceCbData *data = user_data;
-
- /* Note: this assumes that there is only one slice containing the
- whole texture and it doesn't attempt to split up the vertex
- coordinates based on the virtual_coords */
-
- _cogl_pango_display_list_add_texture (data->display_list,
- handle,
- data->x1,
- data->y1,
- data->x2,
- data->y2,
- slice_coords[0],
- slice_coords[1],
- slice_coords[2],
- slice_coords[3]);
-}
-
-static void
-cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
- CoglPangoGlyphCacheValue *cache_value,
- float x1,
- float y1)
-{
- CoglPangoRendererSliceCbData data;
-
- g_return_if_fail (priv->display_list != NULL);
-
- data.display_list = priv->display_list;
- data.x1 = x1;
- data.y1 = y1;
- data.x2 = x1 + (float) cache_value->draw_width;
- data.y2 = y1 + (float) cache_value->draw_height;
-
- /* We iterate the internal sub textures of the texture so that we
- can get a pointer to the base texture even if the texture is in
- the global atlas. That way the display list can recognise that
- the neighbouring glyphs are coming from the same atlas and bundle
- them together into a single VBO */
-
- _cogl_texture_foreach_sub_texture_in_region (cache_value->texture,
- cache_value->tx1,
- cache_value->ty1,
- cache_value->tx2,
- cache_value->ty2,
- cogl_pango_renderer_slice_cb,
- &data);
-}
-
-static void cogl_pango_renderer_finalize (GObject *object);
-static void cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
- PangoFont *font,
- PangoGlyphString *glyphs,
- int x,
- int y);
-static void cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer,
- PangoRenderPart part,
- int x,
- int y,
- int width,
- int height);
-static void cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
- PangoRenderPart part,
- double y1,
- double x11,
- double x21,
- double y2,
- double x12,
- double x22);
-
-G_DEFINE_TYPE (CoglPangoRenderer, cogl_pango_renderer, PANGO_TYPE_RENDERER);
-
-static void
-cogl_pango_renderer_init (CoglPangoRenderer *priv)
-{
- priv->pipeline_cache = _cogl_pango_pipeline_cache_new (FALSE);
- priv->mipmapped_pipeline_cache = _cogl_pango_pipeline_cache_new (TRUE);
- priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
- priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
- priv->use_mipmapping = TRUE;
- _cogl_pango_renderer_set_use_mipmapping (priv, FALSE);
-}
-
-static void
-cogl_pango_renderer_class_init (CoglPangoRendererClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
-
- object_class->finalize = cogl_pango_renderer_finalize;
-
- renderer_class->draw_glyphs = cogl_pango_renderer_draw_glyphs;
- renderer_class->draw_rectangle = cogl_pango_renderer_draw_rectangle;
- renderer_class->draw_trapezoid = cogl_pango_renderer_draw_trapezoid;
-}
-
-static void
-cogl_pango_renderer_finalize (GObject *object)
-{
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (object);
-
- cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
- cogl_pango_glyph_cache_free (priv->glyph_cache);
-
- _cogl_pango_pipeline_cache_free (priv->pipeline_cache);
- _cogl_pango_pipeline_cache_free (priv->mipmapped_pipeline_cache);
-
- G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
-}
-
-static CoglPangoRenderer *
-cogl_pango_get_renderer_from_context (PangoContext *context)
-{
- PangoFontMap *font_map;
- PangoRenderer *renderer;
- CoglPangoFontMap *font_map_priv;
-
- font_map = pango_context_get_font_map (context);
- g_return_val_if_fail (COGL_PANGO_IS_FONT_MAP (font_map), NULL);
-
- font_map_priv = COGL_PANGO_FONT_MAP (font_map);
- renderer = cogl_pango_font_map_get_renderer (font_map_priv);
- g_return_val_if_fail (COGL_PANGO_IS_RENDERER (renderer), NULL);
-
- return COGL_PANGO_RENDERER (renderer);
-}
-
-static GQuark
-cogl_pango_render_get_qdata_key (void)
-{
- static GQuark key = 0;
-
- if (G_UNLIKELY (key == 0))
- key = g_quark_from_static_string ("CoglPangoDisplayList");
-
- return key;
-}
-
-static void
-cogl_pango_render_qdata_forget_display_list (CoglPangoRendererQdata *qdata)
-{
- if (qdata->display_list)
- {
- _cogl_pango_glyph_cache_remove_reorganize_callback
- (qdata->renderer->glyph_cache,
- (GHookFunc) cogl_pango_render_qdata_forget_display_list,
- qdata);
-
- _cogl_pango_display_list_free (qdata->display_list);
-
- qdata->display_list = NULL;
- }
-}
-
-static void
-cogl_pango_render_qdata_destroy (CoglPangoRendererQdata *qdata)
-{
- cogl_pango_render_qdata_forget_display_list (qdata);
- if (qdata->first_line)
- pango_layout_line_unref (qdata->first_line);
- g_slice_free (CoglPangoRendererQdata, qdata);
-}
-
-/**
- * cogl_pango_render_layout_subpixel:
- * @layout: a #PangoLayout
- * @x: FIXME
- * @y: FIXME
- * @color: color to use when rendering the layout
- * @flags: flags to pass to the renderer
- *
- * FIXME
- *
- * Since: 1.0
- */
-void
-cogl_pango_render_layout_subpixel (PangoLayout *layout,
- int x,
- int y,
- const CoglColor *color,
- int flags)
-{
- PangoContext *context;
- CoglPangoRenderer *priv;
- CoglPangoRendererQdata *qdata;
-
- context = pango_layout_get_context (layout);
- priv = cogl_pango_get_renderer_from_context (context);
- if (G_UNLIKELY (!priv))
- return;
-
- qdata = g_object_get_qdata (G_OBJECT (layout),
- cogl_pango_render_get_qdata_key ());
-
- if (qdata == NULL)
- {
- qdata = g_slice_new0 (CoglPangoRendererQdata);
- qdata->renderer = priv;
- g_object_set_qdata_full (G_OBJECT (layout),
- cogl_pango_render_get_qdata_key (),
- qdata,
- (GDestroyNotify)
- cogl_pango_render_qdata_destroy);
- }
-
- /* Check if the layout has changed since the last build of the
- display list. This trick was suggested by Behdad Esfahbod here:
- http://mail.gnome.org/archives/gtk-i18n-list/2009-May/msg00019.html */
- if (qdata->display_list &&
- ((qdata->first_line &&
- qdata->first_line->layout != layout) ||
- qdata->mipmapping_used != priv->use_mipmapping))
- cogl_pango_render_qdata_forget_display_list (qdata);
-
- if (qdata->display_list == NULL)
- {
- CoglPangoPipelineCache *pipeline_cache =
- (priv->use_mipmapping ?
- priv->mipmapped_pipeline_cache : priv->pipeline_cache);
-
- cogl_pango_ensure_glyph_cache_for_layout (layout);
-
- qdata->display_list = _cogl_pango_display_list_new (pipeline_cache);
-
- /* Register for notification of when the glyph cache changes so
- we can rebuild the display list */
- _cogl_pango_glyph_cache_add_reorganize_callback
- (priv->glyph_cache,
- (GHookFunc) cogl_pango_render_qdata_forget_display_list,
- qdata);
-
- priv->display_list = qdata->display_list;
- pango_renderer_draw_layout (PANGO_RENDERER (priv), layout, 0, 0);
- priv->display_list = NULL;
-
- qdata->mipmapping_used = priv->use_mipmapping;
- }
-
- cogl_push_matrix ();
- cogl_translate (x / (gfloat) PANGO_SCALE, y / (gfloat) PANGO_SCALE, 0);
- _cogl_pango_display_list_render (qdata->display_list,
- color);
- cogl_pop_matrix ();
-
- /* Keep a reference to the first line of the layout so we can detect
- changes */
- if (qdata->first_line)
- {
- pango_layout_line_unref (qdata->first_line);
- qdata->first_line = NULL;
- }
- if (pango_layout_get_line_count (layout) > 0)
- {
- qdata->first_line = pango_layout_get_line (layout, 0);
- pango_layout_line_ref (qdata->first_line);
- }
-}
-
-/**
- * cogl_pango_render_layout:
- * @layout: a #PangoLayout
- * @x: X coordinate to render the layout at
- * @y: Y coordinate to render the layout at
- * @color: color to use when rendering the layout
- * @flags: flags to pass to the renderer
- *
- * Renders @layout.
- *
- * Since: 1.0
- */
-void
-cogl_pango_render_layout (PangoLayout *layout,
- int x,
- int y,
- const CoglColor *color,
- int flags)
-{
- cogl_pango_render_layout_subpixel (layout,
- x * PANGO_SCALE,
- y * PANGO_SCALE,
- color,
- flags);
-}
-
-/**
- * cogl_pango_render_layout_line:
- * @line: a #PangoLayoutLine
- * @x: X coordinate to render the line at
- * @y: Y coordinate to render the line at
- * @color: color to use when rendering the line
- *
- * Renders @line at the given coordinates using the given color.
- *
- * Since: 1.0
- */
-void
-cogl_pango_render_layout_line (PangoLayoutLine *line,
- int x,
- int y,
- const CoglColor *color)
-{
- PangoContext *context;
- CoglPangoRenderer *priv;
- CoglPangoPipelineCache *pipeline_cache;
-
- context = pango_layout_get_context (line->layout);
- priv = cogl_pango_get_renderer_from_context (context);
- if (G_UNLIKELY (!priv))
- return;
-
- pipeline_cache = (priv->use_mipmapping ?
- priv->mipmapped_pipeline_cache : priv->pipeline_cache);
-
- priv->display_list = _cogl_pango_display_list_new (pipeline_cache);
-
- _cogl_pango_ensure_glyph_cache_for_layout_line (line);
-
- pango_renderer_draw_layout_line (PANGO_RENDERER (priv), line, x, y);
-
- _cogl_pango_display_list_render (priv->display_list,
- color);
-
- _cogl_pango_display_list_free (priv->display_list);
- priv->display_list = NULL;
-}
-
-void
-_cogl_pango_renderer_clear_glyph_cache (CoglPangoRenderer *renderer)
-{
- cogl_pango_glyph_cache_clear (renderer->glyph_cache);
- cogl_pango_glyph_cache_clear (renderer->mipmapped_glyph_cache);
-}
-
-void
-_cogl_pango_renderer_set_use_mipmapping (CoglPangoRenderer *renderer,
- gboolean value)
-{
- renderer->use_mipmapping = value;
-}
-
-gboolean
-_cogl_pango_renderer_get_use_mipmapping (CoglPangoRenderer *renderer)
-{
- return renderer->use_mipmapping;
-}
-
-static CoglPangoGlyphCacheValue *
-cogl_pango_renderer_get_cached_glyph (PangoRenderer *renderer,
- gboolean create,
- PangoFont *font,
- PangoGlyph glyph)
-{
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
- CoglPangoGlyphCache *glyph_cache;
-
- glyph_cache = (priv->use_mipmapping ?
- priv->mipmapped_glyph_cache :
- priv->glyph_cache);
-
- return cogl_pango_glyph_cache_lookup (glyph_cache, create, font, glyph);
-}
-
-static void
-cogl_pango_renderer_set_dirty_glyph (PangoFont *font,
- PangoGlyph glyph,
- CoglPangoGlyphCacheValue *value)
-{
- cairo_surface_t *surface;
- cairo_t *cr;
- cairo_scaled_font_t *scaled_font;
- cairo_glyph_t cairo_glyph;
- cairo_format_t format_cairo;
- CoglPixelFormat format_cogl;
-
- COGL_NOTE (PANGO, "redrawing glyph %i", glyph);
-
- /* Glyphs that don't take up any space will end up without a
- texture. These should never become dirty so they shouldn't end up
- here */
- g_return_if_fail (value->texture != COGL_INVALID_HANDLE);
-
- if (cogl_texture_get_format (value->texture) == COGL_PIXEL_FORMAT_A_8)
- {
- format_cairo = CAIRO_FORMAT_A8;
- format_cogl = COGL_PIXEL_FORMAT_A_8;
- }
- else
- {
- format_cairo = CAIRO_FORMAT_ARGB32;
-
- /* Cairo stores the data in native byte order as ARGB but Cogl's
- pixel formats specify the actual byte order. Therefore we
- need to use a different format depending on the
- architecture */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- format_cogl = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
-#else
- format_cogl = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
-#endif
- }
-
- surface = cairo_image_surface_create (format_cairo,
- value->draw_width,
- value->draw_height);
- cr = cairo_create (surface);
-
- scaled_font = pango_cairo_font_get_scaled_font (PANGO_CAIRO_FONT (font));
- cairo_set_scaled_font (cr, scaled_font);
-
- cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0);
-
- cairo_glyph.x = -value->draw_x;
- cairo_glyph.y = -value->draw_y;
- /* The PangoCairo glyph numbers directly map to Cairo glyph
- numbers */
- cairo_glyph.index = glyph;
- cairo_show_glyphs (cr, &cairo_glyph, 1);
-
- cairo_destroy (cr);
- cairo_surface_flush (surface);
-
- /* Copy the glyph to the texture */
- cogl_texture_set_region (value->texture,
- 0, /* src_x */
- 0, /* src_y */
- value->tx_pixel, /* dst_x */
- value->ty_pixel, /* dst_y */
- value->draw_width, /* dst_width */
- value->draw_height, /* dst_height */
- value->draw_width, /* width */
- value->draw_height, /* height */
- format_cogl,
- cairo_image_surface_get_stride (surface),
- cairo_image_surface_get_data (surface));
-
- cairo_surface_destroy (surface);
-}
-
-static void
-_cogl_pango_ensure_glyph_cache_for_layout_line_internal (PangoLayoutLine *line)
-{
- PangoContext *context;
- PangoRenderer *renderer;
- GSList *l;
-
- context = pango_layout_get_context (line->layout);
- renderer =
- PANGO_RENDERER (cogl_pango_get_renderer_from_context (context));
-
- for (l = line->runs; l; l = l->next)
- {
- PangoLayoutRun *run = l->data;
- PangoGlyphString *glyphs = run->glyphs;
- int i;
-
- for (i = 0; i < glyphs->num_glyphs; i++)
- {
- PangoGlyphInfo *gi = &glyphs->glyphs[i];
-
- /* If the glyph isn't cached then this will reserve
- space for it now. We won't actually draw the glyph
- yet because reserving space could cause all of the
- other glyphs to be moved so we might as well redraw
- them all later once we know that the position is
- settled */
- cogl_pango_renderer_get_cached_glyph (renderer, TRUE,
- run->item->analysis.font,
- gi->glyph);
- }
- }
-}
-
-static void
-_cogl_pango_set_dirty_glyphs (CoglPangoRenderer *priv)
-{
- _cogl_pango_glyph_cache_set_dirty_glyphs
- (priv->glyph_cache, cogl_pango_renderer_set_dirty_glyph);
- _cogl_pango_glyph_cache_set_dirty_glyphs
- (priv->mipmapped_glyph_cache, cogl_pango_renderer_set_dirty_glyph);
-}
-
-static void
-_cogl_pango_ensure_glyph_cache_for_layout_line (PangoLayoutLine *line)
-{
- PangoContext *context;
- CoglPangoRenderer *priv;
-
- context = pango_layout_get_context (line->layout);
- priv = cogl_pango_get_renderer_from_context (context);
-
- _cogl_pango_ensure_glyph_cache_for_layout_line_internal (line);
-
- /* Now that we know all of the positions are settled we'll fill in
- any dirty glyphs */
- _cogl_pango_set_dirty_glyphs (priv);
-}
-
-void
-cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout)
-{
- PangoContext *context;
- CoglPangoRenderer *priv;
- PangoLayoutIter *iter;
-
- context = pango_layout_get_context (layout);
- priv = cogl_pango_get_renderer_from_context (context);
-
- g_return_if_fail (PANGO_IS_LAYOUT (layout));
-
- if ((iter = pango_layout_get_iter (layout)) == NULL)
- return;
-
- do
- {
- PangoLayoutLine *line;
-
- line = pango_layout_iter_get_line_readonly (iter);
-
- _cogl_pango_ensure_glyph_cache_for_layout_line_internal (line);
- }
- while (pango_layout_iter_next_line (iter));
-
- pango_layout_iter_free (iter);
-
- /* Now that we know all of the positions are settled we'll fill in
- any dirty glyphs */
- _cogl_pango_set_dirty_glyphs (priv);
-}
-
-static void
-cogl_pango_renderer_set_color_for_part (PangoRenderer *renderer,
- PangoRenderPart part)
-{
- PangoColor *pango_color = pango_renderer_get_color (renderer, part);
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
-
- if (pango_color)
- {
- CoglColor color;
-
- cogl_color_init_from_4ub (&color,
- pango_color->red >> 8,
- pango_color->green >> 8,
- pango_color->blue >> 8,
- 0xff);
-
- _cogl_pango_display_list_set_color_override (priv->display_list, &color);
- }
- else
- _cogl_pango_display_list_remove_color_override (priv->display_list);
-}
-
-static void
-cogl_pango_renderer_draw_box (PangoRenderer *renderer,
- int x,
- int y,
- int width,
- int height)
-{
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
-
- g_return_if_fail (priv->display_list != NULL);
-
- _cogl_pango_display_list_add_rectangle (priv->display_list,
- x,
- y - height,
- x + width,
- y);
-}
-
-static void
-cogl_pango_renderer_get_device_units (PangoRenderer *renderer,
- int xin,
- int yin,
- float *xout,
- float *yout)
-{
- const PangoMatrix *matrix;
-
- if ((matrix = pango_renderer_get_matrix (renderer)))
- {
- /* Convert user-space coords to device coords */
- *xout = ((xin * matrix->xx + yin * matrix->xy)
- / PANGO_SCALE + matrix->x0);
- *yout = ((yin * matrix->yy + xin * matrix->yx)
- / PANGO_SCALE + matrix->y0);
- }
- else
- {
- *xout = PANGO_PIXELS (xin);
- *yout = PANGO_PIXELS (yin);
- }
-}
-
-static void
-cogl_pango_renderer_draw_rectangle (PangoRenderer *renderer,
- PangoRenderPart part,
- int x,
- int y,
- int width,
- int height)
-{
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
- float x1, x2, y1, y2;
-
- g_return_if_fail (priv->display_list != NULL);
-
- cogl_pango_renderer_set_color_for_part (renderer, part);
-
- cogl_pango_renderer_get_device_units (renderer,
- x, y,
- &x1, &y1);
- cogl_pango_renderer_get_device_units (renderer,
- x + width, y + height,
- &x2, &y2);
-
- _cogl_pango_display_list_add_rectangle (priv->display_list,
- x1, y1, x2, y2);
-}
-
-static void
-cogl_pango_renderer_draw_trapezoid (PangoRenderer *renderer,
- PangoRenderPart part,
- double y1,
- double x11,
- double x21,
- double y2,
- double x12,
- double x22)
-{
- CoglPangoRenderer *priv = COGL_PANGO_RENDERER (renderer);
- float points[8];
-
- g_return_if_fail (priv->display_list != NULL);
-
- points[0] = (x11);
- points[1] = (y1);
- points[2] = (x12);
- points[3] = (y2);
- points[4] = (x22);
- points[5] = points[3];
- points[6] = (x21);
- points[7] = points[1];
-
- cogl_pango_renderer_set_color_for_part (renderer, part);
-
- _cogl_pango_display_list_add_trapezoid (priv->display_list,
- y1,
- x11,
- x21,
- y2,
- x12,
- x22);
-}
-
-static void
-cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
- PangoFont *font,
- PangoGlyphString *glyphs,
- int xi,
- int yi)
-{
- CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer;
- CoglPangoGlyphCacheValue *cache_value;
- int i;
-
- cogl_pango_renderer_set_color_for_part (renderer,
- PANGO_RENDER_PART_FOREGROUND);
-
- for (i = 0; i < glyphs->num_glyphs; i++)
- {
- PangoGlyphInfo *gi = glyphs->glyphs + i;
- float x, y;
-
- cogl_pango_renderer_get_device_units (renderer,
- xi + gi->geometry.x_offset,
- yi + gi->geometry.y_offset,
- &x, &y);
-
- if ((gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
- {
- PangoFontMetrics *metrics;
-
- if (font == NULL ||
- (metrics = pango_font_get_metrics (font, NULL)) == NULL)
- {
- cogl_pango_renderer_draw_box (renderer,
- x,
- y,
- PANGO_UNKNOWN_GLYPH_WIDTH,
- PANGO_UNKNOWN_GLYPH_HEIGHT);
- }
- else
- {
- cogl_pango_renderer_draw_box (renderer,
- x,
- y,
- metrics->approximate_char_width
- / PANGO_SCALE,
- metrics->ascent / PANGO_SCALE);
-
- pango_font_metrics_unref (metrics);
- }
- }
- else
- {
- /* Get the texture containing the glyph */
- cache_value =
- cogl_pango_renderer_get_cached_glyph (renderer,
- FALSE,
- font,
- gi->glyph);
-
- /* cogl_pango_ensure_glyph_cache_for_layout should always be
- called before rendering a layout so we should never have
- a dirty glyph here */
- g_assert (cache_value == NULL || !cache_value->dirty);
-
- if (cache_value == NULL)
- {
- cogl_pango_renderer_draw_box (renderer,
- x,
- y,
- PANGO_UNKNOWN_GLYPH_WIDTH,
- PANGO_UNKNOWN_GLYPH_HEIGHT);
- }
- else if (cache_value->texture)
- {
- x += (float)(cache_value->draw_x);
- y += (float)(cache_value->draw_y);
-
- cogl_pango_renderer_draw_glyph (priv, cache_value, x, y);
- }
- }
-
- xi += gi->geometry.width;
- }
-}
+++ /dev/null
-/*
- * Clutter.
- *
- * An OpenGL based 'interactive canvas' library.
- *
- * Authored By Matthew Allum <mallum@openedhand.com>
- *
- * Copyright (C) 2008 OpenedHand
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __PANGO_CLUTTER_H__
-#define __PANGO_CLUTTER_H__
-
-#include <glib-object.h>
-#include <pango/pango.h>
-#include <pango/pangocairo.h>
-#include <cogl/cogl.h>
-
-G_BEGIN_DECLS
-
-/* It's too difficult to actually subclass the pango cairo font
- * map. Instead we just make a fake set of macros that actually just
- * directly use the original type
- */
-#define COGL_PANGO_TYPE_FONT_MAP PANGO_TYPE_CAIRO_FONT_MAP
-#define COGL_PANGO_FONT_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_PANGO_TYPE_FONT_MAP, CoglPangoFontMap))
-#define COGL_PANGO_IS_FONT_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COGL_PANGO_TYPE_FONT_MAP))
-
-typedef PangoCairoFontMap CoglPangoFontMap;
-
-PangoFontMap * cogl_pango_font_map_new (void);
-PangoContext * cogl_pango_font_map_create_context (CoglPangoFontMap *fm);
-void cogl_pango_font_map_set_resolution (CoglPangoFontMap *font_map,
- double dpi);
-void cogl_pango_font_map_clear_glyph_cache (CoglPangoFontMap *fm);
-void cogl_pango_ensure_glyph_cache_for_layout (PangoLayout *layout);
-void cogl_pango_font_map_set_use_mipmapping (CoglPangoFontMap *fm,
- gboolean value);
-gboolean cogl_pango_font_map_get_use_mipmapping (CoglPangoFontMap *fm);
-PangoRenderer *cogl_pango_font_map_get_renderer (CoglPangoFontMap *fm);
-
-#define COGL_PANGO_TYPE_RENDERER (cogl_pango_renderer_get_type ())
-#define COGL_PANGO_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COGL_PANGO_TYPE_RENDERER, CoglPangoRenderer))
-#define COGL_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), COGL_PANGO_TYPE_RENDERER, CoglPangoRendererClass))
-#define COGL_PANGO_IS_RENDERER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COGL_PANGO_TYPE_RENDERER))
-#define COGL_PANGO_IS_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), COGL_PANGO_TYPE_RENDERER))
-#define COGL_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), COGL_PANGO_TYPE_RENDERER, CoglPangoRendererClass))
-
-/* opaque types */
-typedef struct _CoglPangoRenderer CoglPangoRenderer;
-typedef struct _CoglPangoRendererClass CoglPangoRendererClass;
-
-GType cogl_pango_renderer_get_type (void) G_GNUC_CONST;
-
-void cogl_pango_render_layout_subpixel (PangoLayout *layout,
- int x,
- int y,
- const CoglColor *color,
- int flags);
-void cogl_pango_render_layout (PangoLayout *layout,
- int x,
- int y,
- const CoglColor *color,
- int flags);
-void cogl_pango_render_layout_line (PangoLayoutLine *line,
- int x,
- int y,
- const CoglColor *color);
-
-G_END_DECLS
-
-#endif /* __PANGO_CLUTTER_H__ */
+++ /dev/null
-2011-02-10 gettextize <bug-gnu-gettext@gnu.org>
-
- * Makefile.in.in: New file, from gettext-0.17.
- * boldquot.sed: New file, from gettext-0.17.
- * en@boldquot.header: New file, from gettext-0.17.
- * en@quot.header: New file, from gettext-0.17.
- * insert-header.sin: New file, from gettext-0.17.
- * quot.sed: New file, from gettext-0.17.
- * remove-potcdate.sin: New file, from gettext-0.17.
- * Rules-quot: New file, from gettext-0.17.
- * POTFILES.in: New file.
-
+++ /dev/null
-# Makefile variables for PO directory in any package using GNU gettext.
-
-# Usually the message domain is the same as the package name.
-DOMAIN = $(PACKAGE)
-
-# These two variables depend on the location of this directory.
-subdir = po
-top_builddir = ..
-
-# These options get passed to xgettext.
-XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
-
-# This is the copyright holder that gets inserted into the header of the
-# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
-# package. (Note that the msgstr strings, extracted from the package's
-# sources, belong to the copyright holder of the package.) Translators are
-# expected to transfer the copyright for their translations to this person
-# or entity, or to disclaim their copyright. The empty string stands for
-# the public domain; in this case the translators are expected to disclaim
-# their copyright.
-COPYRIGHT_HOLDER = Free Software Foundation, Inc.
-
-# This is the email address or URL to which the translators shall report
-# bugs in the untranslated strings:
-# - Strings which are not entire sentences, see the maintainer guidelines
-# in the GNU gettext documentation, section 'Preparing Strings'.
-# - Strings which use unclear terms or require additional context to be
-# understood.
-# - Strings which make invalid assumptions about notation of date, time or
-# money.
-# - Pluralisation problems.
-# - Incorrect English spelling.
-# - Incorrect formatting.
-# It can be your email address, or a mailing list address where translators
-# can write to without being subscribed, or the URL of a web page through
-# which the translators can contact you.
-MSGID_BUGS_ADDRESS =
-
-# This is the list of locale categories, beyond LC_MESSAGES, for which the
-# message catalogs shall be used. It is usually empty.
-EXTRA_LOCALE_CATEGORIES =
+++ /dev/null
-# List of source files which contain translatable strings.
+++ /dev/null
-# Special Makefile rules for English message catalogs with quotation marks.
-
-DISTFILES.common.extra1 = quot.sed boldquot.sed en@quot.header en@boldquot.header insert-header.sin Rules-quot
-
-.SUFFIXES: .insert-header .po-update-en
-
-en@quot.po-create:
- $(MAKE) en@quot.po-update
-en@boldquot.po-create:
- $(MAKE) en@boldquot.po-update
-
-en@quot.po-update: en@quot.po-update-en
-en@boldquot.po-update: en@boldquot.po-update-en
-
-.insert-header.po-update-en:
- @lang=`echo $@ | sed -e 's/\.po-update-en$$//'`; \
- if test "$(PACKAGE)" = "gettext"; then PATH=`pwd`/../src:$$PATH; GETTEXTLIBDIR=`cd $(top_srcdir)/src && pwd`; export GETTEXTLIBDIR; fi; \
- tmpdir=`pwd`; \
- echo "$$lang:"; \
- ll=`echo $$lang | sed -e 's/@.*//'`; \
- LC_ALL=C; export LC_ALL; \
- cd $(srcdir); \
- if $(MSGINIT) -i $(DOMAIN).pot --no-translator -l $$ll -o - 2>/dev/null | sed -f $$tmpdir/$$lang.insert-header | $(MSGCONV) -t UTF-8 | $(MSGFILTER) sed -f `echo $$lang | sed -e 's/.*@//'`.sed 2>/dev/null > $$tmpdir/$$lang.new.po; then \
- if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
- rm -f $$tmpdir/$$lang.new.po; \
- else \
- if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
- :; \
- else \
- echo "creation of $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
- exit 1; \
- fi; \
- fi; \
- else \
- echo "creation of $$lang.po failed!" 1>&2; \
- rm -f $$tmpdir/$$lang.new.po; \
- fi
-
-en@quot.insert-header: insert-header.sin
- sed -e '/^#/d' -e 's/HEADER/en@quot.header/g' $(srcdir)/insert-header.sin > en@quot.insert-header
-
-en@boldquot.insert-header: insert-header.sin
- sed -e '/^#/d' -e 's/HEADER/en@boldquot.header/g' $(srcdir)/insert-header.sin > en@boldquot.insert-header
-
-mostlyclean: mostlyclean-quot
-mostlyclean-quot:
- rm -f *.insert-header
+++ /dev/null
-s/"\([^"]*\)"/“\1”/g
-s/`\([^`']*\)'/‘\1’/g
-s/ '\([^`']*\)' / ‘\1’ /g
-s/ '\([^`']*\)'$/ ‘\1’/g
-s/^'\([^`']*\)' /‘\1’ /g
-s/“”/""/g
-s/“/“\e[1m/g
-s/”/\e[0m”/g
-s/‘/‘\e[1m/g
-s/’/\e[0m’/g
+++ /dev/null
-# All this catalog "translates" are quotation characters.
-# The msgids must be ASCII and therefore cannot contain real quotation
-# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
-# and double quote (0x22). These substitutes look strange; see
-# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
-#
-# This catalog translates grave accent (0x60) and apostrophe (0x27) to
-# left single quotation mark (U+2018) and right single quotation mark (U+2019).
-# It also translates pairs of apostrophe (0x27) to
-# left single quotation mark (U+2018) and right single quotation mark (U+2019)
-# and pairs of quotation mark (0x22) to
-# left double quotation mark (U+201C) and right double quotation mark (U+201D).
-#
-# When output to an UTF-8 terminal, the quotation characters appear perfectly.
-# When output to an ISO-8859-1 terminal, the single quotation marks are
-# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
-# grave/acute accent (by libiconv), and the double quotation marks are
-# transliterated to 0x22.
-# When output to an ASCII terminal, the single quotation marks are
-# transliterated to apostrophes, and the double quotation marks are
-# transliterated to 0x22.
-#
-# This catalog furthermore displays the text between the quotation marks in
-# bold face, assuming the VT100/XTerm escape sequences.
-#
+++ /dev/null
-# All this catalog "translates" are quotation characters.
-# The msgids must be ASCII and therefore cannot contain real quotation
-# characters, only substitutes like grave accent (0x60), apostrophe (0x27)
-# and double quote (0x22). These substitutes look strange; see
-# http://www.cl.cam.ac.uk/~mgk25/ucs/quotes.html
-#
-# This catalog translates grave accent (0x60) and apostrophe (0x27) to
-# left single quotation mark (U+2018) and right single quotation mark (U+2019).
-# It also translates pairs of apostrophe (0x27) to
-# left single quotation mark (U+2018) and right single quotation mark (U+2019)
-# and pairs of quotation mark (0x22) to
-# left double quotation mark (U+201C) and right double quotation mark (U+201D).
-#
-# When output to an UTF-8 terminal, the quotation characters appear perfectly.
-# When output to an ISO-8859-1 terminal, the single quotation marks are
-# transliterated to apostrophes (by iconv in glibc 2.2 or newer) or to
-# grave/acute accent (by libiconv), and the double quotation marks are
-# transliterated to 0x22.
-# When output to an ASCII terminal, the single quotation marks are
-# transliterated to apostrophes, and the double quotation marks are
-# transliterated to 0x22.
-#
+++ /dev/null
-# Sed script that inserts the file called HEADER before the header entry.
-#
-# At each occurrence of a line starting with "msgid ", we execute the following
-# commands. At the first occurrence, insert the file. At the following
-# occurrences, do nothing. The distinction between the first and the following
-# occurrences is achieved by looking at the hold space.
-/^msgid /{
-x
-# Test if the hold space is empty.
-s/m/m/
-ta
-# Yes it was empty. First occurrence. Read the file.
-r HEADER
-# Output the file's contents by reading the next line. But don't lose the
-# current line while doing this.
-g
-N
-bb
-:a
-# The hold space was nonempty. Following occurrences. Do nothing.
-x
-:b
-}
+++ /dev/null
-s/"\([^"]*\)"/“\1”/g
-s/`\([^`']*\)'/‘\1’/g
-s/ '\([^`']*\)' / ‘\1’ /g
-s/ '\([^`']*\)'$/ ‘\1’/g
-s/^'\([^`']*\)' /‘\1’ /g
-s/“”/""/g
+++ /dev/null
-# Sed script that remove the POT-Creation-Date line in the header entry
-# from a POT file.
-#
-# The distinction between the first and the following occurrences of the
-# pattern is achieved by looking at the hold space.
-/^"POT-Creation-Date: .*"$/{
-x
-# Test if the hold space is empty.
-s/P/P/
-ta
-# Yes it was empty. First occurrence. Remove the line.
-g
-d
-bb
-:a
-# The hold space was nonempty. Following occurrences. Do nothing.
-x
-:b
-}
#include "x11/clutter-x11-texture-pixmap.h"
-#ifdef CLUTTER_USING_SYSTEM_COGL
#include <cogl/cogl-texture-pixmap-x11.h>
-#else
-#include "cogl/winsys/cogl-texture-pixmap-x11.h"
-#endif
G_DEFINE_TYPE (ClutterGLXTexturePixmap, \
clutter_glx_texture_pixmap, \
return TRUE;
}
-#if defined(HAVE_COGL_GL)
+#if defined(COGL_HAS_GL)
#define _COGL_RENDERABLE_BIT EGL_OPENGL_BIT
-#elif defined(HAVE_COGL_GLES2)
+#elif defined(COGL_HAS_GLES2)
#define _COGL_GLES_VERSION 2
#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES2_BIT
-#elif defined(HAVE_COGL_GLES)
+#elif defined(COGL_HAS_GLES1)
#define _COGL_GLES_VERSION 1
#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES_BIT
#endif
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
{
-#if defined(HAVE_COGL_GL)
+#if defined(COGL_HAS_GL)
static const EGLint *attribs = NULL;
#else
static const EGLint attribs[] =
}
}
-#if defined(HAVE_COGL_GL)
+#if defined(COGL_HAS_GL)
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_opengl"
-#elif defined(HAVE_COGL_GLES)
+#elif defined(COGL_HAS_GLES1)
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles1"
-#elif defined(HAVE_COGL_GLES2)
+#elif defined(COGL_HAS_GLES2)
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles2"
#endif
if (backend_wayland->egl_context != EGL_NO_CONTEXT)
return TRUE;
-#if defined(HAVE_COGL_GL)
+#if defined(COGL_HAS_GL)
eglBindAPI (EGL_OPENGL_API);
#else
eglBindAPI (EGL_OPENGL_ES_API);
#include "clutter-paint-volume-private.h"
#include "clutter-private.h"
-#include "cogl/cogl.h"
+#include <cogl/cogl.h>
-#ifdef CLUTTER_USING_SYSTEM_COGL
#include <cogl/cogl-texture-pixmap-x11.h>
-#else
-#include "cogl/winsys/cogl-texture-pixmap-x11.h"
-#endif
#include <X11/extensions/Xdamage.h>
AC_SUBST([CLUTTER_API_VERSION_AM], [$CLUTTER_MAJOR_VERSION\_0])
AC_SUBST([CLUTTER_RELEASE_STATUS], [clutter_release_status])
-dnl For Makefile.am compatibility with the standalone build of Cogl:
-AC_SUBST([COGL_1_MINOR_VERSION],[clutter_minor_version])
-AC_SUBST([COGL_1_MICRO_VERSION],[clutter_micro_version])
-AC_SUBST([COGL_1_VERSION],[clutter_version])
-
-AC_SUBST([COGL_MAJOR_VERSION],[2])
-AC_SUBST([COGL_MINOR_VERSION],[0])
-AC_SUBST([COGL_MICRO_VERSION],[0])
-AC_SUBST([COGL_VERSION],[2.0.0])
-AC_SUBST([COGL_API_VERSION],[2.0])
-AC_SUBST([COGL_API_VERSION_AM],[2_0])
-
m4_define([lt_current], [m4_eval(100 * clutter_minor_version + clutter_micro_version - clutter_interface_age)])
m4_define([lt_revision], [clutter_interface_age])
m4_define([lt_age], [m4_eval(clutter_binary_age - clutter_interface_age)])
# required versions for dependencies
m4_define([glib_req_version], [2.26.0])
+m4_define([cogl_req_version], [1.6.0])
m4_define([json_glib_req_version], [0.12.0])
m4_define([atk_req_version], [1.17])
m4_define([cairo_req_version], [1.10])
m4_define([xcomposite_req_version], [0.4])
AC_SUBST([GLIB_REQ_VERSION], [glib_req_version])
+AC_SUBST([COGL_REQ_VERSION], [cogl_req_version])
AC_SUBST([JSON_GLIB_REQ_VERSION], [json_glib_req_version])
AC_SUBST([ATK_REQ_VERSION], [atk_req_version])
AC_SUBST([CAIRO_REQ_VERSION], [cairo_req_version])
CLUTTER_WINSYS_BASE=
CLUTTER_WINSYS_BASE_LIB=
CLUTTER_WINSYS=
-cogl_gl_headers=""
glesversion=1.1
use_gles2_wrapper=no
experimental_backend=no
[Select Clutter GLES version (for EGL backends)])],
[glesversion=$with_gles])
-COGL_REQ=""
-AC_ARG_WITH([system-cogl],
- [AS_HELP_STRING([--with-system-cogl=@<:@yes/no@:>@],
- [Use a system installed Cogl library])],
- [
- if test "x$with_system_cogl" = "xyes"; then
- COGL_REQ="cogl-1.0"
- fi
- ],
- [with_system_cogl=no])
-
-AM_CONDITIONAL(USE_SYSTEM_COGL, [test "x$with_system_cogl" = "xyes"])
-AS_IF([test "x$with_system_cogl" = "xyes"],
- [ AC_DEFINE([CLUTTER_USING_SYSTEM_COGL], [1], [Built against the system Cogl library])])
-
# base dependencies for core
-CLUTTER_BASE_PC_FILES="cairo-gobject >= $CAIRO_REQ_VERSION atk >= $ATK_REQ_VERSION pangocairo >= $PANGO_REQ_VERSION json-glib-1.0 >= $JSON_GLIB_REQ_VERSION $COGL_REQ"
+CLUTTER_BASE_PC_FILES="cogl-1.0 cairo-gobject >= $CAIRO_REQ_VERSION atk >= $ATK_REQ_VERSION pangocairo >= $PANGO_REQ_VERSION json-glib-1.0 >= $JSON_GLIB_REQ_VERSION"
# backend specific pkg-config files
BACKEND_PC_FILES=""
[glx],
[
- cogl_gl_headers="GL/gl.h"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_GLX"
SUPPORT_X11=1
SUPPORT_XLIB=1
SUPPORT_GLX=1
- COGL_DRIVER="gl"
-
CLUTTER_WINSYS=glx
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
[opengl-egl-xlib],
[
- cogl_gl_headers="GL/gl.h"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL"
CLUTTER_EGL_BACKEND="generic"
SUPPORT_EGL=1
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
- COGL_DRIVER="gl"
-
CLUTTER_WINSYS=egl
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
[wayland],
[
experimental_backend="yes"
- cogl_gl_headers="GL/gl.h"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_WAYLAND"
SUPPORT_WAYLAND=1
- COGL_DRIVER="gl"
-
CLUTTER_WINSYS=wayland
CLUTTER_SONAME_INFIX=wayland
[eglx],
[
- # the GL header is defined in the COGL checks above
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL"
CLUTTER_EGL_BACKEND="generic"
SUPPORT_EGL=1
SUPPORT_EGL_PLATFORM_POWERVR_X11=1
- COGL_DRIVER="gles"
-
CLUTTER_WINSYS=egl
CLUTTER_WINSYS_BASE=x11
CLUTTER_WINSYS_BASE_LIB="x11/libclutter-x11.la"
[eglnative],
[
- # the GL header is defined in the COGL checks above
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_EGL"
CLUTTER_EGL_BACKEND="generic"
AS_IF([test "x$have_tslib" = "xyes" -a "x$have_evdev" = "xyes"],
[AC_MSG_ERROR([Can't enable both tslib and evdev events])])
- COGL_DRIVER="gles"
-
FLAVOUR_LIBS="$FLAVOUR_LIBS $TSLIB_LIBS $EVDEV_LIBS"
FLAVOUR_CFLAGS="$FLAVOUR_CFLAGS $TSLIB_CFLAGS $EVDEV_CFLAGS"
SUPPORT_EGL=1
SUPPORT_EGL_PLATFORM_GDL=1
- COGL_DRIVER="gles"
-
# The cex100 is a small specialization of the EGL backend
CLUTTER_WINSYS=egl
CLUTTER_SONAME_INFIX=cex100
[osx],
[
experimental_backend="yes"
- cogl_gl_headers="OpenGL/gl.h"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_OSX"
AC_DEFINE([HAVE_CLUTTER_OSX], [1], [Have the OSX backend])
- AC_DEFINE([COGL_HAS_OSX_SUPPORT], [1], [Cogl supports the OSX window system])
-
- COGL_DRIVER="gl"
- AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
FLAVOUR_LIBS="$FLAVOUR_LIBS -framework Cocoa -framework OpenGL"
[win32],
[
- cogl_gl_headers="GL/gl.h"
CLUTTER_STAGE_TYPE="CLUTTER_TYPE_STAGE_WIN32"
AC_DEFINE([HAVE_CLUTTER_WIN32], [1], [Have the Win32 backend])
- AC_DEFINE([COGL_HAS_WIN32_SUPPORT], [1], [Cogl supports the win32 window system])
- AC_DEFINE([COGL_HAS_WGL_SUPPORT], [1], [Cogl supports OpenGL using the WGL API])
-
- COGL_DRIVER="gl"
- AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
FLAVOUR_LIBS="$FLAVOUR_LIBS -lopengl32 -lgdi32 -lwinmm"
FLAVOUR_CFLAGS="$FLAVOUR_CFLAGS -D_WIN32_WINNT=0x0500"
win32, eglx or eglnative])]
)
-AS_IF([test "x$SUPPORT_X11" = "x1"],
- [ AC_DEFINE([COGL_HAS_X11_SUPPORT], [1], [Cogl supports the X11 window system])])
-AS_IF([test "x$SUPPORT_XLIB" = "x1"],
- [ AC_DEFINE([COGL_HAS_XLIB_SUPPORT], [1], [Cogl supports X11 using the Xlib API])])
-
AS_IF([test "x$SUPPORT_GLX" = "x1"],
[
- AC_DEFINE([COGL_HAS_GLX_SUPPORT], [1], [Cogl supports OpenGL using the GLX API])
-
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
-
AC_DEFINE([HAVE_CLUTTER_GLX], [1], [Have the GLX backend])
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
-
AC_CHECK_HEADERS([GL/glx.h],
[],
[AC_MSG_ERROR([Unable to locate required GLX headers])])
AS_IF([test "x$SUPPORT_EGL" = "x1"],
[
AC_DEFINE([HAVE_CLUTTER_EGL], [1], [Have the EGL backend])
- AC_DEFINE([COGL_HAS_EGL_SUPPORT], [1], [Cogl supports GLES using the EGL API])
])
AS_IF([test "x$CLUTTER_EGL_BACKEND" = "xgeneric"],
AS_IF([test "x$CLUTTER_EGL_BACKEND" = "xcex100"],
AC_DEFINE([CLUTTER_EGL_BACKEND_CEX100], [1], [Use CEX100 EGL backend]))
-AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_X11" = "x1"],
- [
- AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT], [1],
- [Cogl supports OpenGL[ES] using the EGL API with PowerVR X11 platform typedefs])
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
- ])
-
-AS_IF([test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"],
- [
- AC_DEFINE([COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT], [1],
- [Cogl supports OpenGL[ES] using the EGL API with PowerVR NULL platform typedefs])
- AC_DEFINE([COGL_HAS_FULL_WINSYS], [1], [Cogl can create its own OpenGL context])
- ])
-
# winsys conditionals for use in automake files...
AM_CONDITIONAL(SUPPORT_GLX, [test "x$SUPPORT_GLX" = "x1"])
AM_CONDITIONAL(SUPPORT_X11, [test "x$SUPPORT_X11" = "x1"])
AM_CONDITIONAL(SUPPORT_XLIB, [test "x$SUPPORT_XLIB" = "x1"])
AM_CONDITIONAL(SUPPORT_EGL, [test "x$SUPPORT_EGL" = "x1"])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_X11, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_X11" = "x1"])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_POWERVR_NULL, [test "x$SUPPORT_EGL_PLATFORM_POWERVR_NULL" = "x1"])
-AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_GDL, [test "x$SUPPORT_EGL_PLATFORM_GDL" = "x1"])
AM_CONDITIONAL(SUPPORT_OSX, [test "x$CLUTTER_WINSYS" = "xosx"])
AM_CONDITIONAL(SUPPORT_WIN32, [test "x$CLUTTER_WINSYS" = "xwin32"])
AM_CONDITIONAL(SUPPORT_CEX100, [test "x$SUPPORT_EGL_PLATFORM_GDL" = "x1"])
"x$CLUTTER_WINSYS" = "xosx" -o \
"x$CLUTTER_WINSYS" = "xwayland"])
-dnl === COGL driver backend =====================================================
-
-AS_IF([test "x$COGL_DRIVER" = "xgl"],
- [ AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
- NEED_SEPARATE_EGL=yes
- ])
-
-cogl_gles_version_define=""
-
-AS_IF([test "x$COGL_DRIVER" = "xgles"],
-
- [
- AS_CASE([$glesversion],
-
- [1*],
- [
- cogl_gl_headers="GLES/gl.h GLES/glext.h"
-
- AC_DEFINE([HAVE_COGL_GLES], 1, [Have GL/ES for rendering])
- cogl_gles_version_define="COGL_HAS_GLES1"
-
- PKG_CHECK_EXISTS([glesv1_cm],
- [BACKEND_PC_FILES="$BACKEND_PC_FILES glesv1_cm"
- NEED_SEPARATE_EGL=yes
- ],
- [
- AC_CHECK_HEADERS([$cogl_gl_headers],
- [],
- [AC_MSG_ERROR([Unable to locate required GLES headers])])
-
- # Check for a GLES 1.x Common Profile library with/without EGL.
- #
- # Note: historically GLES 1 libraries shipped with the
- # EGL and GLES symbols all bundled in one library. Now
- # the Khronos Implementers Guide defines two naming
- # schemes: -lGLES_CM should be used for a library that
- # bundles the GLES and EGL API together and -lGLESv1_CM
- # would be used for a standalone GLES API.
- AC_CHECK_LIB(GLES_CM, [eglInitialize],
- [FLAVOUR_LIBS="$FLAVOUR_LIBS -lGLES_CM"],
- [
- AC_CHECK_LIB(GLESv1_CM, [glFlush],
- [FLAVOUR_LIBS="$FLAVOUR_LIBS -lGLESv1_CM"
- NEED_SEPARATE_EGL=yes
- ],
- [AC_MSG_ERROR([Unable to locate required GLES 1.x Common Profile library])])
- ])
- ])
-
- AS_IF([test "x$NEED_SEPARATE_EGL" = "xyes"],
- [
- PKG_CHECK_EXISTS([egl],
- [BACKEND_PC_FILES="$BACKEND_PC_FILES egl"
- NEED_SEPARATE_EGL=yes
- ],
- [
- AC_CHECK_HEADERS([GLES/egl.h],
- [],
- [AC_MSG_ERROR([Unable to locate required EGL headers])])
-
- AC_CHECK_LIB(EGL, [eglInitialize],
- [FLAVOUR_LIBS="$FLAVOUR_LIBS -lEGL"],
- [AC_MSG_ERROR([Unable to locate required EGL library])])
- ])
- ])
- ],
-
- [2*],
- [
- cogl_gl_headers="GLES2/gl2.h GLES2/gl2ext.h"
- use_gles2_wrapper=yes
- AC_DEFINE([HAVE_COGL_GLES2], 1, [Have GL/ES for rendering])
- cogl_gles_version_define="COGL_HAS_GLES2"
-
- PKG_CHECK_EXISTS([glesv2],
- [BACKEND_PC_FILES="$BACKEND_PC_FILES glesv2"],
- [
- AC_CHECK_HEADERS([$cogl_gl_headers],
- [],
- [AC_MSG_ERROR([Unable to locate required GLES headers])],
- [[#include <GLES2/gl2.h>
- ]])
-
- FLAVOUR_LIBS="$FLAVOUR_LIBS -lGLESv2"
- ])
-
- PKG_CHECK_EXISTS([egl],
- [BACKEND_PC_FILES="$BACKEND_PC_FILES egl"],
- [
- AC_CHECK_HEADERS([EGL/egl.h],
- [],
- [AC_MSG_ERROR([Unable to locate required EGL headers])])
-
- AC_CHECK_LIB(EGL, [eglInitialize],
- [FLAVOUR_LIBS="$FLAVOUR_LIBS -lEGL"],
- [AC_MSG_ERROR([Unable to locate required EGL library])])
-
- FLAVOUR_LIBS="$FLAVOUR_LIBS -lEGL"
- ]
- )
-
- NEED_SEPARATE_EGL=yes
- ],
-
- [AC_MSG_ERROR([Unknown argument for --with-gles])]
- )
- ]
-)
-
AM_CONDITIONAL(USE_TSLIB, [test "x$have_tslib" = "xyes"])
AM_CONDITIONAL(SUPPORT_EVDEV, [test "x$have_evdev" = "xyes"])
-AM_CONDITIONAL(USE_GLES2_WRAPPER, [test "x$use_gles2_wrapper" = "xyes"])
-
-dnl The value of this variable will directly go in the install
-dnl cogl-defines.h header
-COGL_DEFINES="";
-dnl Space-separated list of symbols that should be defined in
-dnl cogl-defines.h
-COGL_DEFINES_SYMBOLS="";
-
-if test "x$SUPPORT_X11" = "x1"; then
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_X11 COGL_HAS_X11_SUPPORT"
-fi;
-
-if test "x$SUPPORT_XLIB" = "x1"; then
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_XLIB COGL_HAS_XLIB_SUPPORT"
-fi;
-
-if test "x$SUPPORT_GLX" = "x1"; then
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLX_SUPPORT"
-fi;
-
-if test "x$SUPPORT_EGL" = "x1"; then
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_SUPPORT"
-fi;
-
-if test "x$NEED_SEPARATE_EGL" = "xyes"; then
- AC_DEFINE([HAVE_STANDALONE_EGL], 1, [Have standalone EGL library])
-fi
-
-if test "x$SUPPORT_EGL_PLATFORM_GDL" = "xyes"; then
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_GDL_SUPPORT"
-fi
-
-AS_CASE([$COGL_DRIVER],
- [gl],
- [COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GL"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GL"],
- [gles],
- [COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_GLES"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS CLUTTER_COGL_HAS_GLES"
- COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS $cogl_gles_version_define"
- ],
- [AC_MSG_ERROR([Unknown cogl driver $COGL_DRIVER])])
-
-dnl Copy all of the words in COGL_DEFINES_SYMBOLS as separate #define
-dnl lines in COGL_DEFINES
-for x in $COGL_DEFINES_SYMBOLS; do
- COGL_DEFINES="$COGL_DEFINES
-#define $x 1"
-done;
-
-AC_SUBST(COGL_DEFINES)
-
-AS_IF([test "x$cogl_gl_headers" = "x"], [AC_MSG_ERROR([Internal error: no GL header set])])
-
-dnl cogl_gl_headers is a space separate list of headers to
-dnl include. We'll now convert them to a single variable with a
-dnl #include line for each header
-COGL_GL_HEADER_INCLUDES=""
-for x in $cogl_gl_headers; do
- COGL_GL_HEADER_INCLUDES="$COGL_GL_HEADER_INCLUDES
-#include <$x>"
-done;
-AC_SUBST(COGL_GL_HEADER_INCLUDES)
-
-AM_CONDITIONAL([COGL_DRIVER_GLES], [test "x$COGL_DRIVER" = "xgles"])
-AM_CONDITIONAL([COGL_DRIVER_GL], [test "x$COGL_DRIVER" = "xgl"])
-
dnl Instead of using AM_CFLAGS to ensure
dnl COGL_ENABLE_EXPERIMENTAL_2_0_API is defined while compiling clutter
dnl and cogl code we use a define in config.h instead. This helps ensure
AC_DEFINE([COGL_ENABLE_EXPERIMENTAL_2_0_API], [1],
[Can use Cogl 2.0 API internally])
-dnl Cogl can be experimentally be built standalone and there are a few
-dnl tweaks we need to make in the Makefiles when building standalone
-AM_CONDITIONAL(COGL_STANDALONE_BUILD, [false])
-
dnl === Clutter configuration =================================================
CLUTTER_CONFIG_DEFINES=
dnl === Clutter substitutions kept for backwards compatibility ================
AC_SUBST([CLUTTER_FLAVOUR])
-CLUTTER_COGL=$COGL_DRIVER
+CLUTTER_COGL=undefined
AC_SUBST([CLUTTER_COGL])
-dnl === Cogl substitutions ====================================================
-AC_SUBST([COGL_IMAGE_BACKEND])
-COGL_WINSYS=$CLUTTER_WINSYS
-AC_SUBST([COGL_WINSYS])
-AC_SUBST([COGL_DRIVER])
-
dnl === Image loading backend =================================================
IMAGE_PC_FILES=""
-# Peek which winsys the user wants so that we can couple the osx winsys with
-# quartz imageloader.
-AS_IF([test "x$COGL_WINSYS" = "xosx"], [COGL_IMAGE_BACKEND=quartz], [COGL_IMAGE_BACKEND=gdk-pixbuf])
-
-AC_ARG_WITH([imagebackend],
- [AC_HELP_STRING([--with-imagebackend=@<:@gdk-pixbuf/quartz/internal@:>@],
- [Select COGL image loading backend])],
- [COGL_IMAGE_BACKEND=$with_imagebackend])
-
-AS_CASE([$COGL_IMAGE_BACKEND],
-
- [quartz],
- [
- experimental_image=yes
- AC_DEFINE([USE_QUARTZ], 1, [Use Core Graphics (Quartz) for loading image data])
- ],
-
- [gdk-pixbuf],
- [
- AC_DEFINE([USE_GDKPIXBUF], 1, [Use GdkPixbuf for loading image data])
- IMAGE_PC_FILES="gdk-pixbuf-2.0 >= $GDK_PIXBUF_REQ_VERSION"
- ],
-
- [internal],
- [
- experimental_image=yes
- AC_DEFINE([USE_INTERNAL], 1, [Use internal image decoding for loading image data])
- ],
-
- [AC_MSG_ERROR([Unknown argument for --with-imagebackend])]
-)
-
dnl === X11 checks, only for X11-based backends ===============================
X11_PC_FILES=""
x11_tests=no
AC_SUBST(CLUTTER_DEBUG_CFLAGS)
-m4_define([cogl_debug_default], [minimum])
-AC_ARG_ENABLE([cogl-debug],
- [AC_HELP_STRING([--enable-cogl-debug=@<:@no/yes@:>@],
- [Control COGL debugging level @<:@default=cogl_debug_default@:>@])],
- [],
- [enable_cogl_debug=cogl_debug_default])
-
-AS_CASE([$enable_cogl_debug],
-
- [yes],
- [COGL_EXTRA_CFLAGS="-DCOGL_GL_DEBUG -DCOGL_OBJECT_DEBUG -DCOGL_HANDLE_DEBUG -DCOGL_ENABLE_DEBUG"],
-
- [minimum],
- [COGL_EXTRA_CFLAGS="-DCOGL_ENABLE_DEBUG"],
-
- [no],
- [COGL_EXTRA_CFLAGS=""],
-
- [AC_MSG_ERROR([Invalid value for --enable-cogl-debug])]
-)
-
-AC_SUBST(COGL_EXTRA_CFLAGS)
-
dnl === Conformance test suite ================================================
AC_ARG_ENABLE([conformance],
AS_IF([test "x$GCC" = "xyes"],
[
PKG_CHECK_MODULES([PROFILE_DEP], [uprof-0.3])
- CLUTTER_PROFILE_CFLAGS="-DCLUTTER_ENABLE_PROFILE -DCOGL_ENABLE_PROFILE $PROFILE_DEP_CFLAGS"
+ CLUTTER_PROFILE_CFLAGS="-DCLUTTER_ENABLE_PROFILE $PROFILE_DEP_CFLAGS"
CLUTTER_PROFILE_LDFLAGS="$PROFILE_DEP_LIBS"
AS_IF([test "x$enable_debug" = "xyes"], [CLUTTER_PROFILE_CFLAGS+=" -DUPROF_DEBUG"])
AC_SUBST(CLUTTER_CFLAGS)
AC_SUBST(CLUTTER_LIBS)
-dnl For Makefile.am compatibility with the standalone build of Cogl:
-AC_SUBST([COGL_DEP_CFLAGS], [$CLUTTER_CFLAGS])
-AC_SUBST([COGL_DEP_LIBS], [$CLUTTER_LIBS])
-AC_SUBST([COGL_PKG_REQUIRES],[$CLUTTER_REQUIRES])
-
dnl === GObject-Introspection check ===========================================
clutter/cally/cally-$CLUTTER_API_VERSION.pc:clutter/cally/cally.pc.in
- clutter/cogl/Makefile
- clutter/cogl/po/Makefile.in
- clutter/cogl/examples/Makefile
- clutter/cogl/cogl/Makefile
- clutter/cogl/cogl/cogl-defines.h
- clutter/cogl/cogl/cogl-1.0.pc:clutter/cogl/cogl/cogl-1.0-clutter.pc.in
- clutter/cogl/pango/Makefile
-
clutter/egl/clutter-cex100.h
tests/Makefile
doc/reference/Makefile
doc/reference/clutter/Makefile
doc/reference/clutter/clutter-docs.xml
- doc/reference/cogl/Makefile
- doc/reference/cogl/cogl-docs.xml
doc/reference/cally/Makefile
doc/reference/cally/cally-docs.xml
doc/common/Makefile
echo ""
echo " • Global:"
echo " Prefix: ${prefix}"
-echo " Flavour: ${CLUTTER_WINSYS}/${COGL_DRIVER}"
+echo " Flavour: ${CLUTTER_WINSYS}"
echo " Target library: ${CLUTTER_WINSYS_LIB}"
# Compiler/Debug related flags
echo ""
echo " • Compiler options:"
echo " Clutter debug level: ${enable_debug}"
-echo " COGL debug level: ${enable_cogl_debug}"
echo " Compiler flags: ${CFLAGS} ${MAINTAINER_CFLAGS}"
echo " Profiling enabled: ${enable_profile}"
echo " Enable coverage tests: ${enable_gcov}"
echo " Build introspection data: ${enable_introspection}"
echo " Build conformance test suite: ${enable_conformance}"
-# Cogl flags
-echo ""
-echo " • Cogl Backend:"
-echo " Driver: ${COGL_DRIVER}"
-echo " GL header: ${cogl_gl_headers}"
-
-if test "x$COGL_DRIVER" = "xgles"; then
- if test "x$use_gles2_wrapper" = "xyes"; then
-echo " GLES version: 2.0"
- else
-echo " GLES version: 1.1"
- fi
-fi
-
-if test "x$experimental_image" = "xno"; then
-echo " Image backend: ${COGL_IMAGE_BACKEND}"
-else
-echo " Image backend: ${COGL_IMAGE_BACKEND} (WARNING: Experimental)"
-fi
-
# Clutter backend related flags
echo ""
echo " • Clutter Backend:"
-SUBDIRS = cogl clutter cally
+SUBDIRS = clutter cally
-DIST_SUBDIRS = cogl clutter cally
+DIST_SUBDIRS = clutter cally
+++ /dev/null
-## Process this file with automake to produce Makefile.in
-
-# We require automake 1.6 at least.
-AUTOMAKE_OPTIONS = 1.6
-
-# This is a blank Makefile.am for using gtk-doc.
-# Copy this to your project's API docs directory and modify the variables to
-# suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples
-# of using the various options.
-
-# The name of the module, e.g. 'glib'.
-DOC_MODULE=cogl
-
-# The top-level SGML file. You can change this if you want to.
-DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.xml
-
-# The directory containing the source code. Relative to $(srcdir).
-# gtk-doc will search all .c & .h files beneath here for inline comments
-# documenting the functions and macros.
-# e.g. DOC_SOURCE_DIR=../../../gtk
-DOC_SOURCE_DIR=../../../clutter/cogl/cogl
-
-# Extra options to pass to gtkdoc-scangobj. Not normally needed.
-SCANGOBJ_OPTIONS=--type-init-func="g_type_init()"
-
-# Extra options to supply to gtkdoc-scan.
-# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
-SCAN_OPTIONS=--deprecated-guards="COGL_DISABLE_DEPRECATED"
-
-# Extra options to supply to gtkdoc-mkdb.
-# e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml
-MKDB_OPTIONS=--sgml-mode --output-format=xml --name-space=cogl
-
-# Extra options to supply to gtkdoc-mktmpl
-# e.g. MKTMPL_OPTIONS=--only-section-tmpl
-MKTMPL_OPTIONS=
-
-# Extra options to supply to gtkdoc-fixref. Not normally needed.
-# e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html
-FIXXREF_OPTIONS=\
- --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \
- --extra-dir=$(GDPIXBUF_PREFIX)/share/gtk-doc/html/gdk-pixbuf
-
-# Used for dependencies. The docs will be rebuilt if any of these change.
-# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
-# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
-HFILE_GLOB=\
- $(top_srcdir)/clutter/cogl/cogl/*.h \
- $(top_builddir)/clutter/cogl/cogl/*.h
-CFILE_GLOB=$(top_srcdir)/clutter/cogl/cogl/*.c
-
-# Header files to ignore when scanning.
-# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
-IGNORE_HFILES=\
- cogl-atlas.h \
- cogl-atlas-texture-private.h \
- cogl-bitmap-private.h \
- cogl-buffer-private.h \
- cogl-color-private.h \
- cogl-feature-private.h \
- cogl-framebuffer-private.h \
- cogl-gtype-private.h \
- cogl-index-array-private.h \
- cogl-indices-private.h \
- cogl-journal-private.h \
- cogl-matrix-private.h \
- cogl-object-private.h \
- cogl-path-private.h \
- cogl-pipeline-fragend-arbfp-private.h \
- cogl-pipeline-fragend-fixed-private.h \
- cogl-pipeline-fragend-glsl-private.h \
- cogl-pipeline-opengl-private.h \
- cogl-pipeline-private.h \
- cogl-pipeline-progend-glsl-private.h \
- cogl-pipeline-vertend-fixed-private.h \
- cogl-pipeline-vertend-glsl-private.h \
- cogl-pixel-array-private.h \
- cogl-primitive-private.h \
- cogl-primitives-private.h \
- cogl-private.h \
- cogl-program-private.h \
- cogl-shader-private.h \
- cogl-sub-texture-private.h \
- cogl-texture-2d-private.h \
- cogl-texture-2d-sliced-private.h \
- cogl-texture-3d-private.h \
- cogl-texture-private.h \
- cogl-texture-rectangle-private.h \
- cogl-vertex-array-private.h \
- cogl-vertex-attribute-private.h \
- cogl-vertex-buffer-private.h \
- cogl-blend-string.h \
- cogl-clip-stack.h \
- cogl-context.h \
- cogl-debug.h \
- cogl-defines.h \
- cogl-deprecated.h \
- cogl-handle.h \
- cogl-internal.h \
- cogl-matrix-mesa.h \
- cogl-matrix-stack.h \
- cogl-spans.h \
- cogl-profile.h \
- cogl-util.h \
- driver \
- tesselator \
- winsys
-
-EXTRA_HFILES=
-
-# Images to copy into HTML directory.
-# e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png
-HTML_IMAGES = \
- fill-rule-non-zero.png \
- fill-rule-even-odd.png \
- quad-indices-order.png \
- quad-indices-triangles.png \
- cogl_ortho.png
-
-# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
-# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
-content_files = \
- blend-strings.xml
-
-# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
-# These files must be listed here *and* in content_files
-# e.g. expand_content_files=running.sgml
-expand_content_files = \
- blend-strings.xml
-
-# CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library.
-# Only needed if you are using gtkdoc-scangobj to dynamically query widget
-# signals and properties.
-# e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
-# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-
-INCLUDES=-I$(top_srcdir) -I$(top_srcdir)/clutter -I$(top_srcdir)/clutter/cogl -I$(top_builddir)/clutter/cogl -DCOGL_ENABLE_EXPERIMENTAL_API $(CLUTTER_CFLAGS)
-GTKDOC_LIBS=$(top_builddir)/clutter/libclutter-@CLUTTER_WINSYS@-@CLUTTER_API_VERSION@.la $(CLUTTER_LIBS)
-
-# This includes the standard gtk-doc make rules, copied by gtkdocize.
-include $(top_srcdir)/gtk-doc.make
-
-# Other files to distribute
-# e.g. EXTRA_DIST += version.xml.in
-
-EXTRA_DIST += \
- fill-rule-non-zero.png \
- fill-rule-even-odd.png \
- quad-indices-triangles.png \
- quad-indices-order.png \
- cogl_ortho.png
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY version SYSTEM "version.xml">
-]>
-
-<refentry id="cogl-Blend-Strings">
-<refmeta>
-<refentrytitle role="top_of_page" id="cogl-Blend-Strings.top_of_page">Material Blend Strings</refentrytitle>
-<manvolnum>3</manvolnum>
-<refmiscinfo>COGL Library</refmiscinfo>
-</refmeta>
-
-<refnamediv>
-<refname>Material Blend Strings</refname>
-<refpurpose>A simple syntax and grammar for describing blending and texture
-combining functions.</refpurpose>
-</refnamediv>
-
-<refsect1 id="cogl-Blend-Strings.description" role="desc">
-<title>Cogl Blend Strings</title>
-<para>
-Describing GPU blending and texture combining states is rather awkward to do
-in a consise but also readable fashion. Cogl helps by supporting
-string based descriptions using a simple syntax.
-</para>
-
-<section>
-<title>Some examples</title>
-
-<para>Here is an example used for blending:</para>
-<programlisting>
-"RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]), DST_COLOR * (1-SRC_COLOR[A]))"
-</programlisting>
-<para>In OpenGL terms this replaces glBlendFunc[Separate] and
-glBlendEquation[Separate]</para>
-<para>
-Actually in this case it's more verbose than the GL equivalent:
-</para>
-<programlisting>
-glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-</programlisting>
-<para>
-But unless you are familiar with OpenGL or refer to its API documentation
-you wouldn't know that the default function used by OpenGL is GL_FUNC_ADD
-nor would you know that the above arguments determine what the source color
-and destination color will be multiplied by before being adding.
-</para>
-
-<para>Here is an example used for texture combining:</para>
-<programlisting>
-"RGB = REPLACE (PREVIOUS)"
-"A = MODULATE (PREVIOUS, TEXTURE)"
-</programlisting>
-<para>
-In OpenGL terms this replaces glTexEnv, and the above example is equivalent
-to this OpenGL code:
-</para>
-<programlisting>
- glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_RGB, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC0_ALPHA, GL_PREVIOUS);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_COLOR);
- glTexEnvi (GL_TEXTURE_ENV, GL_SRC1_ALPHA, GL_TEXTURE);
- glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_COLOR);
-</programlisting>
-
-</section>
-
-<section id="cogl-Blend-String-syntax">
-<title>Here's the syntax</title>
-
-<programlisting>
-<statement>:
- <channel-mask>=<function-name>(<arg-list>)
-
- You can either use a single statement with an RGBA channel-mask or you can use
- two statements; one with an A channel-mask and the other with an RGB
- channel-mask.
-
-<channel-mask>:
- A or RGB or RGBA
-
-<function-name>:
- [A-Za-z_]*
-
-<arg-list>:
- <arg>,<arg>
- or <arg>
- or ""
-
- I.e. functions may take 0 or more arguments
-
-<arg>:
- <color-source>
- 1 - <color-source> : Only intended for texture combining
- <color-source> * ( <factor> ) : Only intended for blending
- 0 : Only intended for blending
-
- See the blending or texture combining sections for further notes and examples.
-
-<color-source>:
- <source-name>[<channel-mask>]
- <source-name>
-
- See the blending or texture combining sections for the list of source-names
- valid in each context.
-
- If a channel mask is not given then the channel mask of the statement
- is assumed instead.
-
-<factor>:
- 0
- 1
- <color-source>
- 1-<color-source>
- SRC_ALPHA_SATURATE
-</programlisting>
-
-</section>
-
-
-</refsect1>
-
-
-</refentry>
+++ /dev/null
-<?xml version="1.0"?>
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
-<!ENTITY version "@VERSION@">
-]>
-<book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
-
- <bookinfo>
- <title>Cogl Reference Manual</title>
- <releaseinfo>for Cogl &version;</releaseinfo>
-
- <copyright>
- <year>2008</year>
- <holder>OpenedHand LTD</holder>
- </copyright>
-
- <copyright>
- <year>2009</year>
- <year>2010</year>
- <holder>Intel Corporation</holder>
- </copyright>
-
- <legalnotice>
- <para>
- Permission is granted to copy, distribute and/or modify this
- document under the terms of the <citetitle>GNU Free
- Documentation License</citetitle>, Version 1.1 or any later
- version published by the Free Software Foundation with no
- Invariant Sections, no Front-Cover Texts, and no Back-Cover
- Texts. You may obtain a copy of the <citetitle>GNU Free
- Documentation License</citetitle> from the Free Software
- Foundation by visiting <ulink type="http"
- url="http://www.fsf.org">their Web site</ulink> or by writing
- to:
-
- <address>
- The Free Software Foundation, Inc.,
- <street>59 Temple Place</street> - Suite 330,
- <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>,
- <country>USA</country>
- </address>
- </para>
- </legalnotice>
-
- </bookinfo>
-
- <chapter>
- <title>Cogl - a modern 3D graphics API</title>
-
- <section id="cogl-intro">
- <title>About Cogl</title>
-
- <para>Cogl is a modern 3D graphics API with associated utility
- APIs designed to expose the features of 3D graphics hardware
- using a more object oriented design than OpenGL. The library has
- primarily been driven by the practical needs of Clutter but it
- is not tied to any one toolkit or even constrained to developing
- UI toolkits.</para>
-
- </section>
-
- <xi:include href="xml/cogl.xml"/>
- <xi:include href="xml/cogl-color.xml"/>
- <xi:include href="xml/cogl-texture.xml"/>
- <xi:include href="blend-strings.xml"/>
- <xi:include href="xml/cogl-material.xml"/>
- <xi:include href="xml/cogl-primitives.xml"/>
- <xi:include href="xml/cogl-paths.xml"/>
- <xi:include href="xml/cogl-clipping.xml"/>
- <xi:include href="xml/cogl-vertex-buffer.xml"/>
- <xi:include href="xml/cogl-matrix.xml"/>
- <xi:include href="xml/cogl-shaders.xml"/>
- <xi:include href="xml/cogl-offscreen.xml"/>
- <xi:include href="xml/cogl-bitmap.xml"/>
- <xi:include href="xml/cogl-fixed.xml"/>
- <xi:include href="xml/cogl-gtype.xml"/>
-
- </chapter>
-
- <chapter>
- <title>Cogl experimental API</title>
-
- <section id="cogl-experimental">
- <title>About the experimental API</title>
-
- <para>Cogl has some experimental API developers are welcomed to play
- with. The main drawback when using those is that there is no API
- stability guarantee, functions flagged as experimental could be changed
- or removed in future versions of the library. To use this experimental
- API you will need to define
- <literal>COGL_ENABLE_EXPERIMENTAL_API</literal> before including
- <filename class="headerfile"><clutter/clutter.h></filename> or
- <filename class="headerfile"><cogl/cogl.h></filename>.</para>
-
- </section>
-
- <xi:include href="xml/cogl-buffer.xml"/>
- <xi:include href="xml/cogl-vector.xml"/>
- <xi:include href="xml/cogl-texture-3d.xml"/>
-
- </chapter>
-
- <chapter>
- <title>Cogl deprecated API</title>
-
- <section id="cogl-deprecated">
-
- <title>About the deprecated API</title>
-
- <para>Cogl has evolved from once being a thin abstraction over
- OpenGL and GLES where a lot of OpenGL's state machine style APIs
- were simply rebranded as Cogl API into the more distinguished API
- style we have today. The result of this evolution though is that
- some of the APIs are considered deprecated and because we plan to
- remove them at the next opportunity we have to break the API
- developers should aim to avoid these functions to keep their code
- working with future major versions of Cogl.</para>
-
- </section>
-
- <xi:include href="xml/cogl-deprecated.xml"/>
- <xi:include href="xml/cogl-texture-deprecated.xml"/>
- <xi:include href="xml/cogl-material-deprecated.xml"/>
- <xi:include href="xml/cogl-clipping-deprecated.xml"/>
- <xi:include href="xml/cogl-vertex-buffer-deprecated.xml"/>
- <xi:include href="xml/cogl-shaders-deprecated.xml"/>
- <xi:include href="xml/cogl-offscreen-deprecated.xml"/>
-
- </chapter>
-
- <chapter id="coglglossary">
- <title>Glossaries</title>
-
- <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
- </chapter>
-
- <index>
- <title>Index of all symbols</title>
- <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="deprecated">
- <title>Index of deprecated symbols</title>
- <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="0.8">
- <title>Index of new symbols in 0.8</title>
- <xi:include href="xml/api-index-0.8.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="1.0">
- <title>Index of new symbols in 1.0</title>
- <xi:include href="xml/api-index-1.0.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="1.2">
- <title>Index of new symbols in 1.2</title>
- <xi:include href="xml/api-index-1.2.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="1.4">
- <title>Index of new symbols in 1.4</title>
- <xi:include href="xml/api-index-1.4.xml"><xi:fallback /></xi:include>
- </index>
-
- <index role="1.6">
- <title>Index of new symbols in 1.6</title>
- <xi:include href="xml/api-index-1.6.xml"><xi:fallback /></xi:include>
- </index>
-
- <appendix id="license">
- <title>License</title>
-
- <para>
- This library is free software; you can redistribute it and/or
- modify it under the terms of the <citetitle>GNU Library General
- Public License</citetitle> as published by the Free Software
- Foundation; either version 2 of the License, or (at your option)
- any later version.
- </para>
-
- <para>
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- <citetitle>GNU Library General Public License</citetitle> for
- more details.
- </para>
-
- <para>
- You may obtain a copy of the <citetitle>GNU Library General
- Public License</citetitle> from the Free Software Foundation by
- visiting <ulink type="http" url="http://www.fsf.org">their Web
- site</ulink> or by writing to:
-
- <address>
- Free Software Foundation, Inc.
- <street>59 Temple Place</street> - Suite 330
- <city>Boston</city>, <state>MA</state> <postcode>02111-1307</postcode>
- <country>USA</country>
- </address>
- </para>
- </appendix>
-
-</book>
+++ /dev/null
-<SECTION>
-<FILE>cogl</FILE>
-<TITLE>General API</TITLE>
-CoglObject
-cogl_object_ref
-cogl_object_unref
-CoglUserDataKey
-cogl_object_get_user_data
-cogl_object_set_user_data
-COGL_INVALID_HANDLE
-CoglHandle
-cogl_handle_ref
-cogl_handle_unref
-
-<SUBSECTION>
-CoglFuncPtr
-CoglPixelFormat
-CoglBufferTarget
-CoglBufferBit
-CoglAttributeType
-
-<SUBSECTION>
-CoglFeatureFlags
-cogl_get_features
-cogl_features_available
-cogl_get_proc_address
-cogl_get_option_group
-
-<SUBSECTION>
-cogl_push_matrix
-cogl_pop_matrix
-cogl_scale
-cogl_translate
-cogl_rotate
-cogl_transform
-cogl_frustum
-cogl_perspective
-cogl_ortho
-
-<SUBSECTION>
-cogl_get_modelview_matrix
-cogl_set_modelview_matrix
-cogl_get_projection_matrix
-cogl_set_projection_matrix
-cogl_set_viewport
-cogl_get_viewport
-
-<SUBSECTION>
-cogl_clear
-cogl_set_backface_culling_enabled
-cogl_get_backface_culling_enabled
-
-<SUBSECTION>
-CoglFogMode
-cogl_set_fog
-cogl_disable_fog
-
-<SUBSECTION>
-cogl_set_source
-cogl_set_source_color
-cogl_set_source_color4ub
-cogl_set_source_color4f
-cogl_set_source_texture
-cogl_get_source
-cogl_push_source
-cogl_pop_source
-
-<SUBSECTION>
-CoglReadPixelsFlags
-cogl_read_pixels
-
-<SUBSECTION>
-cogl_flush
-cogl_begin_gl
-cogl_end_gl
-
-<SUBSECTION Standard>
-COGL_TYPE_ATTRIBUTE_TYPE
-COGL_TYPE_BLEND_STRING_ERROR
-COGL_TYPE_BUFFER_ACCESS
-COGL_TYPE_BUFFER_BIT
-COGL_TYPE_BUFFER_TARGET
-COGL_TYPE_BUFFER_UPDATE_HINT
-COGL_TYPE_BUFFER_USAGE_HINT
-COGL_TYPE_DEBUG_FLAGS
-COGL_TYPE_DRIVER_ERROR
-COGL_TYPE_FEATURE_FLAGS
-COGL_TYPE_FIXED
-COGL_TYPE_FOG_MODE
-COGL_TYPE_HANDLE
-COGL_TYPE_INDICES_TYPE
-COGL_TYPE_MATERIAL_ALPHA_FUNC
-COGL_TYPE_MATERIAL_FILTER
-COGL_TYPE_MATERIAL_LAYER_TYPE
-COGL_TYPE_PIXEL_FORMAT
-COGL_TYPE_READ_PIXELS_FLAGS
-COGL_TYPE_SHADER_TYPE
-COGL_TYPE_TEXTURE_FLAGS
-COGL_TYPE_VERTICES_MODE
-
-<SUBSECTION Private>
-COGL_DRIVER_ERROR
-CoglDriverError
-cogl_attribute_type_get_type
-cogl_buffer_bit_get_type
-cogl_buffer_target_get_type
-cogl_debug_flags_get_type
-cogl_driver_error_get_type
-cogl_feature_flags_get_type
-cogl_fixed_get_type
-cogl_fog_mode_get_type
-cogl_handle_get_type
-cogl_indices_type_get_type
-cogl_material_alpha_func_get_type
-cogl_material_filter_get_type
-cogl_material_layer_type_get_type
-cogl_pixel_format_get_type
-cogl_read_pixels_flags_get_type
-cogl_shader_type_get_type
-cogl_texture_flags_get_type
-cogl_vertices_mode_get_type
-COGL_AFIRST_BIT
-COGL_A_BIT
-COGL_BGR_BIT
-COGL_PIXEL_FORMAT_24
-COGL_PIXEL_FORMAT_32
-COGL_PREMULT_BIT
-COGL_UNORDERED_MASK
-COGL_UNPREMULT_MASK
-</SECTION>
-
-<SECTION>
-<FILE>cogl-clipping</FILE>
-<TITLE>Clipping</TITLE>
-cogl_clip_push_rectangle
-cogl_clip_push_window_rectangle
-cogl_clip_push_from_path
-cogl_clip_push_from_path_preserve
-cogl_clip_pop
-</SECTION>
-
-<SECTION>
-<FILE>cogl-primitives</FILE>
-<TITLE>Primitives</TITLE>
-cogl_rectangle
-cogl_rectangles
-cogl_rectangle_with_texture_coords
-cogl_rectangles_with_texture_coords
-cogl_rectangle_with_multitexture_coords
-cogl_polygon
-</SECTION>
-
-<SECTION>
-<FILE>cogl-paths</FILE>
-<TITLE>Path Primitives</TITLE>
-cogl_is_path
-cogl_path_new
-cogl_get_path
-cogl_set_path
-cogl_path_copy
-cogl_path_move_to
-cogl_path_close
-cogl_path_line_to
-cogl_path_curve_to
-cogl_path_arc
-cogl_path_rel_move_to
-cogl_path_rel_line_to
-cogl_path_rel_curve_to
-cogl_path_line
-cogl_path_polyline
-cogl_path_polygon
-cogl_path_rectangle
-cogl_path_round_rectangle
-cogl_path_ellipse
-
-<SUBSECTION>
-CoglPathFillRule
-cogl_path_set_fill_rule
-cogl_path_get_fill_rule
-cogl_path_fill
-cogl_path_fill_preserve
-cogl_path_stroke
-cogl_path_stroke_preserve
-</SECTION>
-
-<SECTION>
-<FILE>cogl-bitmap</FILE>
-<TITLE>Bitmaps</TITLE>
-CoglBitmap
-cogl_bitmap_new_from_file
-cogl_bitmap_get_size_from_file
-cogl_is_bitmap
-CoglBitmapError
-COGL_BITMAP_ERROR
-<SUBSECTION Standard>
-cogl_bitmap_error_get_type
-cogl_bitmap_error_quark
-</SECTION>
-
-<SECTION>
-<FILE>cogl-texture</FILE>
-<TITLE>Textures</TITLE>
-CoglTextureVertex
-CoglTextureFlags
-cogl_texture_new_with_size
-cogl_texture_new_from_file
-cogl_texture_new_from_data
-cogl_texture_new_from_foreign
-cogl_texture_new_from_bitmap
-cogl_texture_new_from_sub_texture
-cogl_is_texture
-
-<SUBSECTION>
-cogl_texture_get_width
-cogl_texture_get_height
-cogl_texture_get_format
-cogl_texture_get_rowstride
-cogl_texture_get_max_waste
-cogl_texture_is_sliced
-cogl_texture_get_gl_texture
-cogl_texture_get_data
-cogl_texture_set_region
-
-<SUBSECTION Private>
-COGL_TEXTURE_MAX_WASTE
-</SECTION>
-
-<SECTION>
-<FILE>cogl-texture-3d</FILE>
-<TITLE>3D textures</TITLE>
-cogl_texture_3d_new_with_size
-cogl_texture_3d_new_from_data
-cogl_is_texture_3d
-</SECTION>
-
-<SECTION>
-<FILE>cogl-shaders</FILE>
-<TITLE>Shaders and Programmable Pipeline</TITLE>
-CoglShaderType
-cogl_create_shader
-cogl_is_shader
-cogl_shader_source
-cogl_shader_compile
-cogl_shader_get_info_log
-cogl_shader_get_type
-cogl_shader_is_compiled
-
-<SUBSECTION>
-cogl_create_program
-cogl_is_program
-cogl_program_attach_shader
-cogl_program_link
-cogl_program_get_uniform_location
-cogl_program_set_uniform_1f
-cogl_program_set_uniform_1i
-cogl_program_set_uniform_float
-cogl_program_set_uniform_int
-cogl_program_set_uniform_matrix
-</SECTION>
-
-<SECTION>
-<FILE>cogl-offscreen</FILE>
-<TITLE>Offscreen Buffers</TITLE>
-cogl_offscreen_new_to_texture
-cogl_is_offscreen
-cogl_set_framebuffer
-cogl_push_framebuffer
-cogl_pop_framebuffer
-cogl_set_draw_buffer
-cogl_pop_draw_buffer
-cogl_push_draw_buffer
-</SECTION>
-
-<SECTION>
-<FILE>cogl-fixed</FILE>
-<TITLE>Fixed Point API</TITLE>
-CoglFixed
-COGL_FIXED_BITS
-COGL_FIXED_Q
-COGL_FIXED_MAX
-COGL_FIXED_MIN
-
-<SUBSECTION>
-COGL_FIXED_FROM_FLOAT
-COGL_FIXED_TO_FLOAT
-COGL_FIXED_FROM_INT
-COGL_FIXED_TO_INT
-COGL_FIXED_FROM_DOUBLE
-COGL_FIXED_TO_DOUBLE
-COGL_FLOAT_TO_INT
-COGL_FLOAT_TO_UINT
-
-<SUBSECTION>
-COGL_FIXED_EPSILON
-COGL_FIXED_1
-COGL_FIXED_0_5
-COGL_FIXED_30
-COGL_FIXED_45
-COGL_FIXED_60
-COGL_FIXED_90
-COGL_FIXED_120
-COGL_FIXED_180
-COGL_FIXED_240
-COGL_FIXED_255
-COGL_FIXED_270
-COGL_FIXED_360
-
-<SUBSECTION>
-COGL_FIXED_MUL
-COGL_FIXED_DIV
-COGL_FIXED_MUL_DIV
-COGL_FIXED_FAST_DIV
-COGL_FIXED_FAST_MUL
-COGL_FIXED_FRACTION
-COGL_FIXED_FLOOR
-COGL_FIXED_CEIL
-
-<SUBSECTION>
-COGL_FIXED_2_PI
-COGL_FIXED_PI
-COGL_FIXED_PI_2
-COGL_FIXED_PI_4
-COGL_RADIANS_TO_DEGREES
-
-<SUBSECTION>
-COGL_SQRTI_ARG_10_PERCENT
-COGL_SQRTI_ARG_5_PERCENT
-COGL_SQRTI_ARG_MAX
-cogl_sqrti
-
-<SUBSECTION>
-cogl_fixed_atan2
-cogl_fixed_atan
-cogl_fixed_cos
-cogl_fixed_log2
-cogl_fixed_pow
-cogl_fixed_pow2
-cogl_fixed_sin
-cogl_fixed_sqrt
-cogl_fixed_tan
-cogl_fixed_div
-cogl_fixed_mul
-cogl_fixed_mul_div
-
-<SUBSECTION>
-CoglAngle
-COGL_ANGLE_FROM_DEG
-COGL_ANGLE_FROM_DEGX
-COGL_ANGLE_TO_DEG
-COGL_ANGLE_TO_DEGX
-cogl_angle_cos
-cogl_angle_sin
-cogl_angle_tan
-
-<SUBSECTION Private>
-cogl_double_to_fixed
-cogl_double_to_int
-cogl_double_to_uint
-</SECTION>
-
-<SECTION>
-<FILE>cogl-color</FILE>
-<TITLE>Color Type</TITLE>
-CoglColor
-cogl_color_new
-cogl_color_copy
-cogl_color_free
-cogl_color_init_from_4f
-cogl_color_init_from_4fv
-cogl_color_init_from_4ub
-cogl_color_set_from_4ub
-cogl_color_set_from_4f
-
-<SUBSECTION>
-cogl_color_get_red
-cogl_color_get_green
-cogl_color_get_blue
-cogl_color_get_alpha
-
-<SUBSECTION>
-cogl_color_get_red_byte
-cogl_color_get_green_byte
-cogl_color_get_blue_byte
-cogl_color_get_alpha_byte
-
-<SUBSECTION>
-cogl_color_get_red_float
-cogl_color_get_green_float
-cogl_color_get_blue_float
-cogl_color_get_alpha_float
-
-<SUBSECTION>
-cogl_color_set_red
-cogl_color_set_green
-cogl_color_set_blue
-cogl_color_set_alpha
-
-<SUBSECTION>
-cogl_color_set_red_byte
-cogl_color_set_green_byte
-cogl_color_set_blue_byte
-cogl_color_set_alpha_byte
-
-<SUBSECTION>
-cogl_color_set_red_float
-cogl_color_set_green_float
-cogl_color_set_blue_float
-cogl_color_set_alpha_float
-
-<SUBSECTION>
-cogl_color_premultiply
-cogl_color_unpremultiply
-cogl_color_equal
-</SECTION>
-
-<SECTION>
-<FILE>cogl-vertex-buffer</FILE>
-<TITLE>Vertex Buffers</TITLE>
-cogl_vertex_buffer_new
-cogl_vertex_buffer_get_n_vertices
-cogl_vertex_buffer_add
-cogl_vertex_buffer_delete
-cogl_vertex_buffer_submit
-cogl_vertex_buffer_disable
-cogl_vertex_buffer_enable
-CoglVerticesMode
-cogl_vertex_buffer_draw
-cogl_is_vertex_buffer
-
-<SUBSECTION>
-CoglIndicesType
-cogl_vertex_buffer_indices_new
-cogl_vertex_buffer_draw_elements
-cogl_vertex_buffer_indices_get_for_quads
-cogl_is_vertex_buffer_indices
-
-<SUBSECTION Private>
-cogl_vertex_buffer_indices_get_type
-</SECTION>
-
-<SECTION>
-<FILE>cogl-matrix</FILE>
-<TITLE>Matrices</TITLE>
-CoglMatrix
-cogl_matrix_init_identity
-cogl_matrix_copy
-cogl_matrix_equal
-cogl_matrix_free
-cogl_matrix_frustum
-cogl_matrix_ortho
-cogl_matrix_perspective
-cogl_matrix_multiply
-cogl_matrix_rotate
-cogl_matrix_translate
-cogl_matrix_scale
-cogl_matrix_init_from_array
-cogl_matrix_get_array
-cogl_matrix_get_inverse
-cogl_matrix_transform_point
-cogl_matrix_project_points
-cogl_matrix_transform_points
-</SECTION>
-
-<SECTION>
-<FILE>cogl-material</FILE>
-<TITLE>Materials</TITLE>
-CoglMaterial
-CoglMaterialLayer
-CoglMaterialLayerCallback
-cogl_material_new
-cogl_material_copy
-cogl_is_material
-cogl_material_set_color
-cogl_material_set_color4ub
-cogl_material_set_color4f
-cogl_material_get_color
-cogl_material_set_ambient
-cogl_material_get_ambient
-cogl_material_set_diffuse
-cogl_material_get_diffuse
-cogl_material_set_ambient_and_diffuse
-cogl_material_set_emission
-cogl_material_get_emission
-cogl_material_set_specular
-cogl_material_get_specular
-cogl_material_set_shininess
-cogl_material_get_shininess
-CoglMaterialAlphaFunc
-cogl_material_set_alpha_test_function
-COGL_BLEND_STRING_ERROR
-CoglBlendStringError
-cogl_material_set_blend
-cogl_material_set_blend_constant
-cogl_material_set_point_size
-cogl_material_get_point_size
-cogl_material_set_layer
-cogl_material_remove_layer
-cogl_material_set_layer_combine
-cogl_material_set_layer_combine_constant
-cogl_material_set_layer_matrix
-cogl_material_set_layer_point_sprite_coords_enabled
-cogl_material_get_layer_point_sprite_coords_enabled
-cogl_material_get_n_layers
-CoglMaterialFilter
-cogl_material_set_layer_filters
-CoglMaterialLayerType
-cogl_material_layer_get_type
-cogl_material_layer_get_texture
-cogl_material_layer_get_min_filter
-cogl_material_layer_get_mag_filter
-CoglMaterialWrapMode
-cogl_material_set_layer_wrap_mode
-cogl_material_set_layer_wrap_mode_s
-cogl_material_set_layer_wrap_mode_t
-cogl_material_set_layer_wrap_mode_p
-cogl_material_get_layer_wrap_mode_s
-cogl_material_get_layer_wrap_mode_t
-cogl_material_get_layer_wrap_mode_p
-cogl_material_wrap_mode_get_type
-cogl_material_set_user_program
-cogl_material_get_user_program
-cogl_material_set_depth_range
-cogl_material_get_depth_range
-cogl_material_set_depth_test_enabled
-cogl_material_get_depth_test_enabled
-cogl_material_set_depth_test_function
-cogl_material_get_depth_test_function
-cogl_material_set_depth_writing_enabled
-cogl_material_get_depth_writing_enabled
-cogl_material_foreach_layer
-
-<SUBSECTION Private>
-cogl_blend_string_error_get_type
-cogl_blend_string_error_quark
-</SECTION>
-
-<SECTION>
-<FILE>cogl-buffer</FILE>
-<TITLE>Buffers</TITLE>
-cogl_is_buffer
-cogl_buffer_get_size
-CoglBufferUsageHint
-cogl_buffer_set_usage_hint
-cogl_buffer_get_usage_hint
-CoglBufferUpdateHint
-cogl_buffer_set_update_hint
-cogl_buffer_get_update_hint
-CoglBufferAccess
-cogl_buffer_map
-cogl_buffer_unmap
-cogl_buffer_set_data
-
-<SUBSECTION>
-cogl_pixel_buffer_new
-cogl_pixel_buffer_new_for_size
-cogl_is_pixel_buffer
-
-<SUBSECTION>
-cogl_texture_new_from_buffer
-
-<SUBSECTION Private>
-cogl_buffer_access_get_type
-cogl_buffer_update_hint_get_type
-cogl_buffer_usage_hint_get_type
-</SECTION>
-
-<SECTION>
-<FILE>cogl-vector</FILE>
-<TITLE>Vectors</TITLE>
-cogl_vector3_init
-cogl_vector3_init_zero
-cogl_vector3_equal
-cogl_vector3_equal_with_epsilon
-cogl_vector3_copy
-cogl_vector3_free
-cogl_vector3_invert
-cogl_vector3_add
-cogl_vector3_subtract
-cogl_vector3_multiply_scalar
-cogl_vector3_divide_scalar
-cogl_vector3_normalize
-cogl_vector3_magnitude
-cogl_vector3_cross_product
-cogl_vector3_dot_product
-cogl_vector3_distance
-</SECTION>
-
-<SECTION>
-<FILE>cogl-gtype</FILE>
-<TITLE>GType Integration API</TITLE>
-cogl_gtype_matrix_get_type
-</SECTION>
-
-<SECTION>
-<FILE>cogl-deprecated</FILE>
-<TITLE>General API (Deprecated)</TITLE>
-cogl_check_extension
-cogl_viewport
-
-cogl_get_bitmasks
-
-cogl_set_depth_test_enabled
-cogl_get_depth_test_enabled
-</SECTION>
-
-<SECTION>
-<FILE>cogl-clipping-deprecated</FILE>
-<TITLE>Clipping (Deprecated)</TITLE>
-cogl_clip_push
-cogl_clip_push_window_rect
-cogl_clip_ensure
-cogl_clip_stack_save
-cogl_clip_stack_restore
-</SECTION>
-
-<SECTION>
-<FILE>cogl-texture-deprecated</FILE>
-<TITLE>Textures (Deprecated)</TITLE>
-cogl_texture_ref
-cogl_texture_unref
-</SECTION>
-
-<SECTION>
-<FILE>cogl-material-deprecated</FILE>
-<TITLE>Materials (Deprecated)</TITLE>
-cogl_material_ref
-cogl_material_unref
-cogl_material_get_layers
-</SECTION>
-
-<SECTION>
-<FILE>cogl-vertex-buffer-deprecated</FILE>
-<TITLE>Vertex Buffers (Deprecated)</TITLE>
-cogl_vertex_buffer_ref
-cogl_vertex_buffer_unref
-</SECTION>
-
-<SECTION>
-<FILE>cogl-shaders-deprecated</FILE>
-<TITLE>Shaders and Programmable Pipeline (Deprecated)</TITLE>
-cogl_shader_ref
-cogl_shader_unref
-
-<SUBSECTION>
-cogl_program_ref
-cogl_program_unref
-cogl_program_use
-cogl_program_uniform_1f
-cogl_program_uniform_1i
-cogl_program_uniform_float
-cogl_program_uniform_int
-cogl_program_uniform_matrix
-</SECTION>
-
-<SECTION>
-<FILE>cogl-offscreen-deprecated</FILE>
-<TITLE>Offscreen Buffers (Deprecated)</TITLE>
-cogl_offscreen_ref
-cogl_offscreen_unref
-</SECTION>
#ifdef COGL_HAS_XLIB
#include <clutter/x11/clutter-x11.h>
-/* This gets installed to a different location so a real application
- would use <cogl/cogl-texture-pixmap-x11.h> */
-#include "cogl/winsys/cogl-texture-pixmap-x11.h"
+#include <cogl/cogl-texture-pixmap-x11.h>
#define PIXMAP_WIDTH 512
#define PIXMAP_HEIGHT 256
#include <clutter/clutter.h>
#include <cogl/cogl.h>
-#include "pango/cogl-pango.h"
+#include <cogl/cogl-pango.h>
#define INSTRUCTIONS \
"Press v\t\342\236\236\tSwitch horizontal/vertical\n" \
#include <clutter/clutter.h>
#include <cogl/cogl.h>
-#include "pango/cogl-pango.h"
+#include <cogl/cogl-pango.h>
#define FONT "Sans 12"