mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 19:42:05 +00:00
Merge branch '1.0-integration'
* 1.0-integration: (138 commits) [x11] Disable XInput by default [xinput] Invert the XI extension version check [cogl-primitives] Fix an unused variable warning when building GLES [clutter-stage-egl] Pass -1,-1 to clutter_stage_x11_fix_window_size Update the GLES backend to have the layer filters in the material [gles/cogl-shader] Add a missing semicolon [cogl] Move the texture filters to be a property of the material layer [text] Fix Pango unit to pixels conversion [actor] Force unrealization on destroy only for non-toplevels [x11] Rework map/unmap and resizing [xinput] Check for the XInput entry points [units] Validate units against the ParamSpec [actor] Add the ::allocation-changed signal [actor] Use flags to control allocations [units] Rework Units into logical distance value Remove a stray g_value_get_int() Remove usage of Units and macros [cogl-material] Allow setting a layer with an invalid texture handle [timeline] Remove the concept of frames from timelines [gles/cogl-shader] Fix parameter spec for cogl_shader_get_info_log ... Conflicts: configure.ac
This commit is contained in:
commit
7e33fe3175
18
.gitignore
vendored
18
.gitignore
vendored
@ -19,8 +19,11 @@ clutter/stamp-*
|
||||
/clutter/clutter-json.h
|
||||
/clutter/cogl/cogl-defines-gl.h
|
||||
/clutter/cogl/cogl-defines-gles.h
|
||||
/clutter/cogl/cogl-enum-types.h
|
||||
/clutter/cogl/cogl.h
|
||||
/clutter/cogl/*.pc
|
||||
/clutter/cogl/common/cogl-enum-types.[ch]
|
||||
/clutter/cogl/common/stamp-cogl-enum-types.h
|
||||
/clutter/cogl/gles/cogl-fixed-vertex-shader.[ch]
|
||||
/clutter/cogl/gles/cogl-fixed-fragment-shader.[ch]
|
||||
*.gir
|
||||
@ -36,12 +39,12 @@ doc/reference/clutter/clutter-*.txt
|
||||
doc/reference/clutter/html
|
||||
doc/reference/clutter/tmpl
|
||||
doc/reference/clutter/xml
|
||||
doc/reference/clutter/version.xml
|
||||
doc/reference/clutter/clutter.args
|
||||
doc/reference/clutter/clutter.hierarchy
|
||||
doc/reference/clutter/clutter.interfaces
|
||||
doc/reference/clutter/clutter.prerequisites
|
||||
doc/reference/clutter/clutter.signals
|
||||
doc/reference/clutter/clutter-docs.xml
|
||||
doc/reference/clutter/*.stamp
|
||||
doc/reference/clutter/*.bak
|
||||
doc/reference/cogl/cogl-*.txt
|
||||
@ -49,12 +52,12 @@ doc/reference/cogl/cogl-*.txt
|
||||
doc/reference/cogl/html
|
||||
doc/reference/cogl/tmpl
|
||||
doc/reference/cogl/xml
|
||||
doc/reference/cogl/version.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
|
||||
doltcompile
|
||||
@ -193,7 +196,16 @@ stamp-h1
|
||||
/tests/conform/test-list-model-filter
|
||||
/tests/conform/test-npot-texture
|
||||
/tests/conform/redhand.png
|
||||
/tests/micro-bench/test-glyph-perf
|
||||
/tests/conform/test-map-recursive
|
||||
/tests/conform/test-realize-not-recursive
|
||||
/tests/conform/test-shown-not-parented
|
||||
/tests/conform/test-blend-strings
|
||||
/tests/conform/test-color-from-string
|
||||
/tests/conform/test-color-to-string
|
||||
/tests/conform/test-units-constructors
|
||||
/tests/conform/test-units-string
|
||||
/tests/conform/test-conformance-result.xml
|
||||
/tests/micro-bench/test-text-perf
|
||||
/tests/micro-bench/test-text
|
||||
/tests/micro-bench/test-picking
|
||||
/tests/tools/disable-npots.sh
|
||||
|
3
README
3
README
@ -333,6 +333,9 @@ Release Notes for Clutter 1.0
|
||||
* cogl_shader_get_parameteriv has been replaced by cogl_shader_get_type and
|
||||
cogl_shader_is_compiled. More getters can be added later if desired.
|
||||
|
||||
* cogl_enable_depth_test has been renamed to cogl_set_depth_test_enabled and
|
||||
a corresponding cogl_get_depth_test_enabled function has been added.
|
||||
|
||||
Release Notes for Clutter 0.8
|
||||
-------------------------------
|
||||
|
||||
|
61
clutter.doap
61
clutter.doap
@ -1,29 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Project xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
|
||||
xmlns:foaf="http://xmlns.com/foaf/0.1/"
|
||||
xmlns:gnome="http://api.gnome.org/doap-extensions#"
|
||||
xmlns="http://usefulinc.com/ns/doap#">
|
||||
|
||||
<name>Clutter</name>
|
||||
<shortname>clutter</shortname>
|
||||
<created>2006-11-18</created>
|
||||
|
||||
<shortdesc xml:lang="en">
|
||||
Clutter is an OpenGL based interface library
|
||||
</shortdesc>
|
||||
<shortdesc xml:lang="en">Clutter is an OpenGL based interface library</shortdesc>
|
||||
|
||||
<description xml:lang="en">
|
||||
Clutter is an open source software library for creating fast, visually
|
||||
rich and animated graphical user interfaces. Clutter uses OpenGL (and
|
||||
optionally OpenGL ES for use on Mobile and embedded platforms) for
|
||||
rendering, but with an API which hides the underlying GL complexity
|
||||
from the developer. The Clutter API is intended to be easy to use,
|
||||
efficient and flexible.
|
||||
</description>
|
||||
<description xml:lang="en">Clutter is an open source software library for creating
|
||||
fast, visually rich, portable and animated graphical user interfaces. Clutter uses
|
||||
OpenGL (and optionally OpenGL|ES for use on Mobile and embedded platforms) for
|
||||
rendering, but with an API which hides the underlying GL complexity from the
|
||||
developer. The Clutter API is intended to be easy to use, efficient and
|
||||
flexible.</description>
|
||||
|
||||
<homepage rdf:resource="http://www.clutter-project.org" />
|
||||
<download-page rdf:resource="http://www.clutter-project.org/sources" />
|
||||
<license rdf:resource="http://usefulinc.com/doap/licenses/lgpl" />
|
||||
<bug-database rdf:resource="http://bugzilla.o-hand.com/enter_bug.cgi?product=Clutter"/>
|
||||
<download-page rdf:resource="http://www.clutter-project.org/sources" />
|
||||
<mailing-list rdf:resource="mailto:clutter+subscribe@o-hand.com" />
|
||||
|
||||
<programming-language>C</programming-language>
|
||||
@ -32,6 +30,7 @@
|
||||
<category rdf:resource="http://labs.o-hand.com/doap/category/graphics"/>
|
||||
<category rdf:resource="http://labs.o-hand.com/doap/category/embedded"/>
|
||||
<category rdf:resource="http://labs.o-hand.com/doap/category/clutter"/>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Matthew Allum</foaf:name>
|
||||
@ -39,6 +38,13 @@
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<maintainer>
|
||||
<foaf:Person>
|
||||
<foaf:name>Emmanuele Bassi</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:ebassi@linux.intel.com"/>
|
||||
</foaf:Person>
|
||||
</maintainer>
|
||||
|
||||
<author>
|
||||
<foaf:Person>
|
||||
<foaf:name>Matthew Allum</foaf:name>
|
||||
@ -49,15 +55,36 @@
|
||||
<author>
|
||||
<foaf:Person>
|
||||
<foaf:name>Emmanuele Bassi</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:ebassi@o-hand.com"/>
|
||||
<foaf:mbox rdf:resource="mailto:ebassi@linux.intel.com"/>
|
||||
</foaf:Person>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<foaf:Person>
|
||||
<foaf:name>Neil Roberts</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:neil@linux.intel.com"/>
|
||||
</foaf:Person>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<foaf:Person>
|
||||
<foaf:name>Robert Bragg</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:robert@linux.intel.com"/>
|
||||
</foaf:Person>
|
||||
</author>
|
||||
|
||||
<author>
|
||||
<foaf:Person>
|
||||
<foaf:name>Øyvind Kolås</foaf:name>
|
||||
<foaf:mbox rdf:resource="mailto:pippin@linux.intel.com"/>
|
||||
</foaf:Person>
|
||||
</author>
|
||||
|
||||
<repository>
|
||||
<SVNRepository>
|
||||
<browse rdf:resource="http://svn.o-hand.com/view/clutter"/>
|
||||
<location rdf:resource="https://svn.o-hand.com/repos/clutter"/>
|
||||
</SVNRepository>
|
||||
<GitRepository>
|
||||
<browse rdf:resource="http://git.clutter-project.org/?r=clutter"/>
|
||||
<location rdf:resource="git://git.clutter-project.org/clutter"/>
|
||||
</GitRepository>
|
||||
</repository>
|
||||
|
||||
<release>
|
||||
|
@ -169,6 +169,7 @@ source_c = \
|
||||
$(srcdir)/clutter-list-model.c \
|
||||
$(srcdir)/clutter-main.c \
|
||||
clutter-marshal.c \
|
||||
$(srcdir)/clutter-master-clock.c \
|
||||
$(srcdir)/clutter-media.c \
|
||||
$(srcdir)/clutter-model.c \
|
||||
$(srcdir)/clutter-path.c \
|
||||
@ -195,6 +196,7 @@ source_h_priv = \
|
||||
$(srcdir)/clutter-bezier.h \
|
||||
$(srcdir)/clutter-debug.h \
|
||||
$(srcdir)/clutter-keysyms-table.h \
|
||||
$(srcdir)/clutter-master-clock.h \
|
||||
$(srcdir)/clutter-model-private.h \
|
||||
$(srcdir)/clutter-private.h \
|
||||
$(srcdir)/clutter-id-pool.h \
|
||||
@ -234,7 +236,6 @@ clutter_HEADERS = \
|
||||
$(source_h) \
|
||||
$(top_builddir)/clutter/clutter-json.h \
|
||||
$(top_builddir)/clutter/clutter-enum-types.h \
|
||||
$(top_builddir)/clutter/clutter-version.h \
|
||||
$(top_srcdir)/clutter/clutter.h
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
@ -248,11 +249,6 @@ endif
|
||||
# subdir Makefile.am, so just extract them from cogl.h instead. The doc
|
||||
# comments for COGL are in the headers, so we don't need the source files.
|
||||
Clutter-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_API_VERSION@.la
|
||||
headers=`sed -n "s/#include <cogl\/\([^>]*\)>/\1/p" < $(top_srcdir)/clutter/cogl/cogl.h` ; \
|
||||
cogl_headers="" ; \
|
||||
for header in $$headers; do \
|
||||
cogl_headers="$$cogl_headers $(top_srcdir)/clutter/cogl/$$header " ; \
|
||||
done ; \
|
||||
$(INTROSPECTION_SCANNER) -v --namespace Clutter --nsversion=@CLUTTER_API_VERSION@ \
|
||||
$(INCLUDES) \
|
||||
$(json_gir_include_path) \
|
||||
@ -260,6 +256,7 @@ Clutter-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-@CLUTTER_
|
||||
--include=GObject-2.0 \
|
||||
--include=Pango-1.0 \
|
||||
--include=PangoCairo-1.0 \
|
||||
--include=Cogl-@CLUTTER_API_VERSION@ \
|
||||
--include=ClutterJson-@CLUTTER_API_VERSION@ \
|
||||
--library=clutter-@CLUTTER_FLAVOUR@-@CLUTTER_API_VERSION@ \
|
||||
--libtool="$(top_builddir)/doltlibtool" \
|
||||
@ -268,8 +265,6 @@ Clutter-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-@CLUTTER_
|
||||
--pkg pangocairo \
|
||||
--output $@ \
|
||||
$(clutter_HEADERS) \
|
||||
$$cogl_headers \
|
||||
$(top_builddir)/clutter/cogl/cogl-defines-$(CLUTTER_COGL).h \
|
||||
$(source_c)
|
||||
|
||||
BUILT_GIRSOURCES += Clutter-@CLUTTER_API_VERSION@.gir
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -74,10 +74,10 @@ G_BEGIN_DECLS
|
||||
*/
|
||||
#define CLUTTER_ACTOR_UNSET_FLAGS(a,f) (((ClutterActor*)(a))->flags &= ~(f))
|
||||
|
||||
#define CLUTTER_ACTOR_IS_MAPPED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_MAPPED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_REALIZED(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REALIZED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_VISIBLE(e) (CLUTTER_ACTOR_IS_MAPPED (e) && CLUTTER_ACTOR_IS_REALIZED (e))
|
||||
#define CLUTTER_ACTOR_IS_REACTIVE(e) ((((ClutterActor*)(e))->flags & CLUTTER_ACTOR_REACTIVE) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_MAPPED(a) ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_MAPPED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_REALIZED(a) ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_REALIZED) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_VISIBLE(a) ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_VISIBLE) != FALSE)
|
||||
#define CLUTTER_ACTOR_IS_REACTIVE(a) ((((ClutterActor*)(a))->flags & CLUTTER_ACTOR_REACTIVE) != FALSE)
|
||||
|
||||
typedef struct _ClutterActorClass ClutterActorClass;
|
||||
typedef struct _ClutterActorBox ClutterActorBox;
|
||||
@ -90,7 +90,8 @@ typedef struct _ClutterActorPrivate ClutterActorPrivate;
|
||||
*
|
||||
* Generic callback
|
||||
*/
|
||||
typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data);
|
||||
typedef void (*ClutterCallback) (ClutterActor *actor,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* CLUTTER_CALLBACK
|
||||
@ -102,11 +103,12 @@ typedef void (*ClutterCallback) (ClutterActor *actor, gpointer data);
|
||||
|
||||
/**
|
||||
* ClutterActorFlags:
|
||||
* @CLUTTER_ACTOR_MAPPED: the actor has been painted
|
||||
* @CLUTTER_ACTOR_MAPPED: the actor will be painted (is visible, and inside a toplevel, and all parents visible)
|
||||
* @CLUTTER_ACTOR_REALIZED: the resources associated to the actor have been
|
||||
* allocated
|
||||
* @CLUTTER_ACTOR_REACTIVE: the actor 'reacts' to mouse events emmitting event
|
||||
* signals
|
||||
* @CLUTTER_ACTOR_VISIBLE: the actor has been shown by the application program
|
||||
*
|
||||
* Flags used to signal the state of an actor.
|
||||
*/
|
||||
@ -114,9 +116,28 @@ typedef enum
|
||||
{
|
||||
CLUTTER_ACTOR_MAPPED = 1 << 1,
|
||||
CLUTTER_ACTOR_REALIZED = 1 << 2,
|
||||
CLUTTER_ACTOR_REACTIVE = 1 << 3
|
||||
CLUTTER_ACTOR_REACTIVE = 1 << 3,
|
||||
CLUTTER_ACTOR_VISIBLE = 1 << 4
|
||||
} ClutterActorFlags;
|
||||
|
||||
/**
|
||||
* ClutterAllocationFlags:
|
||||
* @CLUTTER_ALLOCATION_NONE: No flag set
|
||||
* @CLUTTER_ABSOLUTE_ORIGIN_CHANGED: Whether the absolute origin of the
|
||||
* actor has changed; this implies that any ancestor of the actor has
|
||||
* been moved
|
||||
*
|
||||
* Flags passed to the #ClutterActor::allocate() virtual function and
|
||||
* to the clutter_actor_allocate() function
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
CLUTTER_ALLOCATION_NONE = 0,
|
||||
CLUTTER_ABSOLUTE_ORIGIN_CHANGED = 1 << 1
|
||||
} ClutterAllocationFlags;
|
||||
|
||||
/**
|
||||
* ClutterActorBox:
|
||||
* @x1: X coordinate of the top left corner
|
||||
@ -126,15 +147,15 @@ typedef enum
|
||||
*
|
||||
* Bounding box of an actor. The coordinates of the top left and right bottom
|
||||
* corners of an actor. The coordinates of the two points are expressed in
|
||||
* #ClutterUnit<!-- -->s, that is are device-independent. If you want to obtain
|
||||
* the box dimensions in pixels, use clutter_actor_get_geometry().
|
||||
* pixels with sub-pixel precision
|
||||
*/
|
||||
struct _ClutterActorBox
|
||||
{
|
||||
ClutterUnit x1;
|
||||
ClutterUnit y1;
|
||||
ClutterUnit x2;
|
||||
ClutterUnit y2;
|
||||
gfloat x1;
|
||||
gfloat y1;
|
||||
|
||||
gfloat x2;
|
||||
gfloat y2;
|
||||
};
|
||||
|
||||
GType clutter_actor_box_get_type (void) G_GNUC_CONST;
|
||||
@ -177,6 +198,10 @@ struct _ClutterActor
|
||||
* it should chain up to the parent's implementation
|
||||
* @unrealize: virtual function, used to deallocate resources allocated
|
||||
* in ::realize; it should chain up to the parent's implementation
|
||||
* @map: virtual function for containers and composite actors, to
|
||||
* map their children; it must chain up to the parent's implementation
|
||||
* @unmap: virtual function for containers and composite actors, to
|
||||
* unmap their children; it must chain up to the parent's implementation
|
||||
* @paint: virtual function, used to paint the actor
|
||||
* @get_preferred_width: virtual function, used when querying the minimum
|
||||
* and natural widths of an actor for a given height; it is used by
|
||||
@ -203,8 +228,8 @@ struct _ClutterActor
|
||||
* @enter_event: signal class closure for #ClutterActor::enter-event
|
||||
* @leave_event: signal class closure for #ClutterActor::leave-event
|
||||
* @captured_event: signal class closure for #ClutterActor::captured-event
|
||||
* @focus_in: signal class closure for #ClutterActor::focus-in
|
||||
* @focus_out: signal class closure for #ClutterActor::focus-out
|
||||
* @key_focus_in: signal class closure for #ClutterActor::focus-in
|
||||
* @key_focus_out: signal class closure for #ClutterActor::focus-out
|
||||
*
|
||||
* Base class for actors.
|
||||
*/
|
||||
@ -220,6 +245,8 @@ struct _ClutterActorClass
|
||||
void (* hide_all) (ClutterActor *actor);
|
||||
void (* realize) (ClutterActor *actor);
|
||||
void (* unrealize) (ClutterActor *actor);
|
||||
void (* map) (ClutterActor *actor);
|
||||
void (* unmap) (ClutterActor *actor);
|
||||
void (* paint) (ClutterActor *actor);
|
||||
void (* parent_set) (ClutterActor *actor,
|
||||
ClutterActor *old_parent);
|
||||
@ -232,17 +259,17 @@ struct _ClutterActorClass
|
||||
ClutterActor *leaf_that_queued);
|
||||
|
||||
/* size negotiation */
|
||||
void (* get_preferred_width) (ClutterActor *actor,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p);
|
||||
void (* get_preferred_height) (ClutterActor *actor,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p);
|
||||
void (* allocate) (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
gboolean absolute_origin_changed);
|
||||
void (* get_preferred_width) (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p);
|
||||
void (* get_preferred_height) (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p);
|
||||
void (* allocate) (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags);
|
||||
/* event signals */
|
||||
gboolean (* event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
@ -264,8 +291,8 @@ struct _ClutterActorClass
|
||||
ClutterCrossingEvent *event);
|
||||
gboolean (* captured_event) (ClutterActor *actor,
|
||||
ClutterEvent *event);
|
||||
void (* focus_in) (ClutterActor *actor);
|
||||
void (* focus_out) (ClutterActor *actor);
|
||||
void (* key_focus_in) (ClutterActor *actor);
|
||||
void (* key_focus_out) (ClutterActor *actor);
|
||||
|
||||
/*< private >*/
|
||||
/* padding for future expansion */
|
||||
@ -274,12 +301,20 @@ struct _ClutterActorClass
|
||||
|
||||
GType clutter_actor_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void clutter_actor_set_flags (ClutterActor *self,
|
||||
ClutterActorFlags flags);
|
||||
void clutter_actor_unset_flags (ClutterActor *self,
|
||||
ClutterActorFlags flags);
|
||||
ClutterActorFlags clutter_actor_get_flags (ClutterActor *self);
|
||||
|
||||
void clutter_actor_show (ClutterActor *self);
|
||||
void clutter_actor_show_all (ClutterActor *self);
|
||||
void clutter_actor_hide (ClutterActor *self);
|
||||
void clutter_actor_hide_all (ClutterActor *self);
|
||||
void clutter_actor_realize (ClutterActor *self);
|
||||
void clutter_actor_unrealize (ClutterActor *self);
|
||||
void clutter_actor_map (ClutterActor *self);
|
||||
void clutter_actor_unmap (ClutterActor *self);
|
||||
void clutter_actor_paint (ClutterActor *self);
|
||||
void clutter_actor_pick (ClutterActor *self,
|
||||
const ClutterColor *color);
|
||||
@ -289,23 +324,29 @@ void clutter_actor_destroy (ClutterActor
|
||||
|
||||
/* size negotiation */
|
||||
void clutter_actor_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p);
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p);
|
||||
void clutter_actor_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p);
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p);
|
||||
void clutter_actor_get_preferred_size (ClutterActor *self,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_width_p,
|
||||
ClutterUnit *natural_height_p);
|
||||
gfloat *min_width_p,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_width_p,
|
||||
gfloat *natural_height_p);
|
||||
void clutter_actor_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean absolute_origin_changed);
|
||||
ClutterAllocationFlags flags);
|
||||
void clutter_actor_allocate_preferred_size (ClutterActor *self,
|
||||
gboolean absolute_origin_changed);
|
||||
ClutterAllocationFlags flags);
|
||||
void clutter_actor_allocate_available_size (ClutterActor *self,
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat available_width,
|
||||
gfloat available_height,
|
||||
ClutterAllocationFlags flags);
|
||||
void clutter_actor_get_allocation_coords (ClutterActor *self,
|
||||
gint *x_1,
|
||||
gint *y_1,
|
||||
@ -324,100 +365,60 @@ void clutter_actor_set_geometry (ClutterActor
|
||||
void clutter_actor_get_geometry (ClutterActor *self,
|
||||
ClutterGeometry *geometry);
|
||||
void clutter_actor_set_size (ClutterActor *self,
|
||||
gint width,
|
||||
gint height);
|
||||
void clutter_actor_set_sizeu (ClutterActor *self,
|
||||
ClutterUnit width,
|
||||
ClutterUnit height);
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
void clutter_actor_get_size (ClutterActor *self,
|
||||
guint *width,
|
||||
guint *height);
|
||||
void clutter_actor_get_sizeu (ClutterActor *self,
|
||||
ClutterUnit *width,
|
||||
ClutterUnit *height);
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
void clutter_actor_get_transformed_size (ClutterActor *self,
|
||||
guint *width,
|
||||
guint *height);
|
||||
void clutter_actor_get_transformed_sizeu (ClutterActor *self,
|
||||
ClutterUnit *width,
|
||||
ClutterUnit *height);
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
void clutter_actor_set_position (ClutterActor *self,
|
||||
gint x,
|
||||
gint y);
|
||||
void clutter_actor_set_positionu (ClutterActor *self,
|
||||
ClutterUnit x,
|
||||
ClutterUnit y);
|
||||
gfloat x,
|
||||
gfloat y);
|
||||
void clutter_actor_get_position (ClutterActor *self,
|
||||
gint *x,
|
||||
gint *y);
|
||||
void clutter_actor_get_positionu (ClutterActor *self,
|
||||
ClutterUnit *x,
|
||||
ClutterUnit *y);
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
void clutter_actor_get_transformed_position (ClutterActor *self,
|
||||
gint *x,
|
||||
gint *y);
|
||||
void clutter_actor_get_transformed_positionu (ClutterActor *self,
|
||||
ClutterUnit *x,
|
||||
ClutterUnit *y);
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
|
||||
gboolean clutter_actor_get_fixed_position_set (ClutterActor *self);
|
||||
void clutter_actor_set_fixed_position_set (ClutterActor *self,
|
||||
gboolean is_set);
|
||||
|
||||
guint clutter_actor_get_width (ClutterActor *self);
|
||||
ClutterUnit clutter_actor_get_widthu (ClutterActor *self);
|
||||
guint clutter_actor_get_height (ClutterActor *self);
|
||||
ClutterUnit clutter_actor_get_heightu (ClutterActor *self);
|
||||
gfloat clutter_actor_get_width (ClutterActor *self);
|
||||
gfloat clutter_actor_get_height (ClutterActor *self);
|
||||
void clutter_actor_set_width (ClutterActor *self,
|
||||
guint width);
|
||||
void clutter_actor_set_widthu (ClutterActor *self,
|
||||
ClutterUnit width);
|
||||
gfloat width);
|
||||
void clutter_actor_set_height (ClutterActor *self,
|
||||
guint height);
|
||||
void clutter_actor_set_heightu (ClutterActor *self,
|
||||
ClutterUnit height);
|
||||
gint clutter_actor_get_x (ClutterActor *self);
|
||||
ClutterUnit clutter_actor_get_xu (ClutterActor *self);
|
||||
gint clutter_actor_get_y (ClutterActor *self);
|
||||
ClutterUnit clutter_actor_get_yu (ClutterActor *self);
|
||||
gfloat height);
|
||||
gfloat clutter_actor_get_x (ClutterActor *self);
|
||||
gfloat clutter_actor_get_y (ClutterActor *self);
|
||||
void clutter_actor_set_x (ClutterActor *self,
|
||||
gint x);
|
||||
void clutter_actor_set_xu (ClutterActor *self,
|
||||
ClutterUnit x);
|
||||
gfloat x);
|
||||
void clutter_actor_set_y (ClutterActor *self,
|
||||
gint y);
|
||||
void clutter_actor_set_yu (ClutterActor *self,
|
||||
ClutterUnit y);
|
||||
gfloat y);
|
||||
void clutter_actor_set_rotation (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gdouble angle,
|
||||
gint x,
|
||||
gint y,
|
||||
gint z);
|
||||
void clutter_actor_set_rotationu (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gdouble angle,
|
||||
ClutterUnit x,
|
||||
ClutterUnit y,
|
||||
ClutterUnit z);
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat z);
|
||||
void clutter_actor_set_z_rotation_from_gravity (ClutterActor *self,
|
||||
gdouble angle,
|
||||
ClutterGravity gravity);
|
||||
gdouble clutter_actor_get_rotation (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
gint *x,
|
||||
gint *y,
|
||||
gint *z);
|
||||
gdouble clutter_actor_get_rotationu (ClutterActor *self,
|
||||
ClutterRotateAxis axis,
|
||||
ClutterUnit *x,
|
||||
ClutterUnit *y,
|
||||
ClutterUnit *z);
|
||||
gfloat *x,
|
||||
gfloat *y,
|
||||
gfloat *z);
|
||||
ClutterGravity clutter_actor_get_z_rotation_gravity (ClutterActor *self);
|
||||
|
||||
void clutter_actor_set_opacity (ClutterActor *self,
|
||||
guint8 opacity);
|
||||
guint8 clutter_actor_get_opacity (ClutterActor *self);
|
||||
|
||||
guint8 clutter_actor_get_paint_opacity (ClutterActor *self);
|
||||
gboolean clutter_actor_get_paint_visibility (ClutterActor *self);
|
||||
|
||||
@ -428,27 +429,17 @@ G_CONST_RETURN gchar *clutter_actor_get_name (ClutterActor
|
||||
|
||||
guint32 clutter_actor_get_gid (ClutterActor *self);
|
||||
void clutter_actor_set_clip (ClutterActor *self,
|
||||
gint xoff,
|
||||
gint yoff,
|
||||
gint width,
|
||||
gint height);
|
||||
void clutter_actor_set_clipu (ClutterActor *self,
|
||||
ClutterUnit xoff,
|
||||
ClutterUnit yoff,
|
||||
ClutterUnit width,
|
||||
ClutterUnit height);
|
||||
gfloat xoff,
|
||||
gfloat yoff,
|
||||
gfloat width,
|
||||
gfloat height);
|
||||
void clutter_actor_remove_clip (ClutterActor *self);
|
||||
gboolean clutter_actor_has_clip (ClutterActor *self);
|
||||
void clutter_actor_get_clip (ClutterActor *self,
|
||||
gint *xoff,
|
||||
gint *yoff,
|
||||
gint *width,
|
||||
gint *height);
|
||||
void clutter_actor_get_clipu (ClutterActor *self,
|
||||
ClutterUnit *xoff,
|
||||
ClutterUnit *yoff,
|
||||
ClutterUnit *width,
|
||||
ClutterUnit *height);
|
||||
gfloat *xoff,
|
||||
gfloat *yoff,
|
||||
gfloat *width,
|
||||
gfloat *height);
|
||||
|
||||
void clutter_actor_set_parent (ClutterActor *self,
|
||||
ClutterActor *parent);
|
||||
@ -465,11 +456,8 @@ void clutter_actor_lower (ClutterActor
|
||||
void clutter_actor_raise_top (ClutterActor *self);
|
||||
void clutter_actor_lower_bottom (ClutterActor *self);
|
||||
void clutter_actor_set_depth (ClutterActor *self,
|
||||
gint depth);
|
||||
gint clutter_actor_get_depth (ClutterActor *self);
|
||||
void clutter_actor_set_depthu (ClutterActor *self,
|
||||
ClutterUnit depth);
|
||||
ClutterUnit clutter_actor_get_depthu (ClutterActor *self);
|
||||
gfloat depth);
|
||||
gfloat clutter_actor_get_depth (ClutterActor *self);
|
||||
|
||||
void clutter_actor_set_scale (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
@ -477,13 +465,8 @@ void clutter_actor_set_scale (ClutterActor
|
||||
void clutter_actor_set_scale_full (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y,
|
||||
int center_x,
|
||||
int center_y);
|
||||
void clutter_actor_set_scale_fullu (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y,
|
||||
ClutterUnit center_x,
|
||||
ClutterUnit center_y);
|
||||
gfloat center_x,
|
||||
gfloat center_y);
|
||||
void clutter_actor_set_scale_with_gravity (ClutterActor *self,
|
||||
gdouble scale_x,
|
||||
gdouble scale_y,
|
||||
@ -492,19 +475,13 @@ void clutter_actor_get_scale (ClutterActor
|
||||
gdouble *scale_x,
|
||||
gdouble *scale_y);
|
||||
void clutter_actor_get_scale_center (ClutterActor *self,
|
||||
gint *center_x,
|
||||
gint *center_y);
|
||||
void clutter_actor_get_scale_centeru (ClutterActor *self,
|
||||
ClutterUnit *center_x,
|
||||
ClutterUnit *center_y);
|
||||
gfloat *center_x,
|
||||
gfloat *center_y);
|
||||
ClutterGravity clutter_actor_get_scale_gravity (ClutterActor *self);
|
||||
|
||||
void clutter_actor_move_by (ClutterActor *self,
|
||||
gint dx,
|
||||
gint dy);
|
||||
void clutter_actor_move_byu (ClutterActor *self,
|
||||
ClutterUnit dx,
|
||||
ClutterUnit dy);
|
||||
gfloat dx,
|
||||
gfloat dy);
|
||||
|
||||
void clutter_actor_set_reactive (ClutterActor *actor,
|
||||
gboolean reactive);
|
||||
@ -530,34 +507,25 @@ void clutter_actor_set_shader_param_float (ClutterActor
|
||||
gfloat value);
|
||||
|
||||
void clutter_actor_set_anchor_point (ClutterActor *self,
|
||||
gint anchor_x,
|
||||
gint anchor_y);
|
||||
gfloat anchor_x,
|
||||
gfloat anchor_y);
|
||||
void clutter_actor_move_anchor_point (ClutterActor *self,
|
||||
gint anchor_x,
|
||||
gint anchor_y);
|
||||
gfloat anchor_x,
|
||||
gfloat anchor_y);
|
||||
void clutter_actor_get_anchor_point (ClutterActor *self,
|
||||
gint *anchor_x,
|
||||
gint *anchor_y);
|
||||
gfloat *anchor_x,
|
||||
gfloat *anchor_y);
|
||||
ClutterGravity clutter_actor_get_anchor_point_gravity (ClutterActor *self);
|
||||
void clutter_actor_set_anchor_pointu (ClutterActor *self,
|
||||
ClutterUnit anchor_x,
|
||||
ClutterUnit anchor_y);
|
||||
void clutter_actor_move_anchor_pointu (ClutterActor *self,
|
||||
ClutterUnit anchor_x,
|
||||
ClutterUnit anchor_y);
|
||||
void clutter_actor_get_anchor_pointu (ClutterActor *self,
|
||||
ClutterUnit *anchor_x,
|
||||
ClutterUnit *anchor_y);
|
||||
void clutter_actor_set_anchor_point_from_gravity (ClutterActor *self,
|
||||
ClutterGravity gravity);
|
||||
void clutter_actor_move_anchor_point_from_gravity (ClutterActor *self,
|
||||
ClutterGravity gravity);
|
||||
|
||||
gboolean clutter_actor_transform_stage_point (ClutterActor *self,
|
||||
ClutterUnit x,
|
||||
ClutterUnit y,
|
||||
ClutterUnit *x_out,
|
||||
ClutterUnit *y_out);
|
||||
gfloat x,
|
||||
gfloat y,
|
||||
gfloat *x_out,
|
||||
gfloat *y_out);
|
||||
gboolean clutter_actor_is_rotated (ClutterActor *self);
|
||||
gboolean clutter_actor_is_scaled (ClutterActor *self);
|
||||
gboolean clutter_actor_should_pick_paint (ClutterActor *self);
|
||||
|
@ -603,9 +603,7 @@ clutter_ease_out_quad (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return -1.0 * p * (p - 2);
|
||||
}
|
||||
@ -615,8 +613,8 @@ clutter_ease_in_out_quad (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
@ -632,9 +630,7 @@ clutter_ease_in_cubic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return p * p * p;
|
||||
}
|
||||
@ -644,8 +640,8 @@ clutter_ease_out_cubic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / d - 1;
|
||||
|
||||
return p * p * p + 1;
|
||||
@ -656,8 +652,8 @@ clutter_ease_in_out_cubic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
@ -673,9 +669,7 @@ clutter_ease_in_quart (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return p * p * p * p;
|
||||
}
|
||||
@ -685,8 +679,8 @@ clutter_ease_out_quart (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / d - 1;
|
||||
|
||||
return -1.0 * (p * p * p * p - 1);
|
||||
@ -697,8 +691,8 @@ clutter_ease_in_out_quart (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
@ -714,9 +708,7 @@ clutter_ease_in_quint (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return p * p * p * p * p;
|
||||
}
|
||||
@ -726,8 +718,8 @@ clutter_ease_out_quint (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / d - 1;
|
||||
|
||||
return p * p * p * p * p + 1;
|
||||
@ -738,8 +730,8 @@ clutter_ease_in_out_quint (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
@ -755,8 +747,8 @@ clutter_ease_in_sine (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return -1.0 * cos (t / d * G_PI_2) + 1.0;
|
||||
}
|
||||
@ -766,8 +758,8 @@ clutter_ease_out_sine (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return sin (t / d * G_PI_2);
|
||||
}
|
||||
@ -777,8 +769,8 @@ clutter_ease_in_out_sine (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return -0.5 * (cos (G_PI * t / d) - 1);
|
||||
}
|
||||
@ -788,8 +780,8 @@ clutter_ease_in_expo (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return (t == 0) ? 0.0 : pow (2, 10 * (t / d - 1));
|
||||
}
|
||||
@ -799,8 +791,8 @@ clutter_ease_out_expo (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return (t == d) ? 1.0 : -pow (2, -10 * t / d) + 1;
|
||||
}
|
||||
@ -810,8 +802,8 @@ clutter_ease_in_out_expo (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p;
|
||||
|
||||
if (t == 0)
|
||||
@ -835,9 +827,7 @@ clutter_ease_in_circ (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return -1.0 * (sqrt (1 - p * p) - 1);
|
||||
}
|
||||
@ -847,8 +837,8 @@ clutter_ease_out_circ (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / d - 1;
|
||||
|
||||
return sqrt (1 - p * p);
|
||||
@ -859,8 +849,8 @@ clutter_ease_in_out_circ (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
|
||||
if (p < 1)
|
||||
@ -876,8 +866,8 @@ clutter_ease_in_elastic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = d * .3;
|
||||
gdouble s = p / 4;
|
||||
gdouble q = t / d;
|
||||
@ -895,8 +885,8 @@ clutter_ease_out_elastic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = d * .3;
|
||||
gdouble s = p / 4;
|
||||
gdouble q = t / d;
|
||||
@ -912,8 +902,8 @@ clutter_ease_in_out_elastic (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = d * (.3 * 1.5);
|
||||
gdouble s = p / 4;
|
||||
gdouble q = t / (d / 2);
|
||||
@ -942,9 +932,7 @@ clutter_ease_in_back (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble p = t / d;
|
||||
gdouble p = clutter_timeline_get_progress (timeline);
|
||||
|
||||
return p * p * ((1.70158 + 1) * p - 1.70158);
|
||||
}
|
||||
@ -954,8 +942,8 @@ clutter_ease_out_back (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / d - 1;
|
||||
|
||||
return p * p * ((1.70158 + 1) * p + 1.70158) + 1;
|
||||
@ -966,8 +954,8 @@ clutter_ease_in_out_back (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
gdouble p = t / (d / 2);
|
||||
gdouble s = 1.70158 * 1.525;
|
||||
|
||||
@ -1019,8 +1007,8 @@ clutter_ease_in_bounce (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return ease_in_bounce_internal (t, d);
|
||||
}
|
||||
@ -1030,8 +1018,8 @@ clutter_ease_out_bounce (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
return ease_out_bounce_internal (t, d);
|
||||
}
|
||||
@ -1041,8 +1029,8 @@ clutter_ease_in_out_bounce (ClutterAlpha *alpha,
|
||||
gpointer dummy G_GNUC_UNUSED)
|
||||
{
|
||||
ClutterTimeline *timeline = alpha->priv->timeline;
|
||||
gdouble t = clutter_timeline_get_current_frame (timeline);
|
||||
gdouble d = clutter_timeline_get_n_frames (timeline);
|
||||
gdouble t = clutter_timeline_get_elapsed_time (timeline);
|
||||
gdouble d = clutter_timeline_get_duration (timeline);
|
||||
|
||||
if (t < d / 2)
|
||||
return ease_in_bounce_internal (t * 2, d) * 0.5;
|
||||
|
@ -86,9 +86,12 @@ clutter_animatable_get_type (void)
|
||||
* All implementation of the #ClutterAnimatable interface must
|
||||
* implement this function.
|
||||
*
|
||||
* Return value: %TRUE if the value has been validated and can
|
||||
* be applied to the #ClutterAnimatable, and %FALSE otherwise
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
gboolean
|
||||
clutter_animatable_animate_property (ClutterAnimatable *animatable,
|
||||
ClutterAnimation *animation,
|
||||
const gchar *property_name,
|
||||
@ -97,21 +100,27 @@ clutter_animatable_animate_property (ClutterAnimatable *animatable,
|
||||
gdouble progress,
|
||||
GValue *value)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable));
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
g_return_if_fail (initial_value != NULL && final_value != NULL);
|
||||
g_return_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID);
|
||||
g_return_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID);
|
||||
g_return_if_fail (value != NULL);
|
||||
g_return_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) &&
|
||||
G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value));
|
||||
gboolean res;
|
||||
|
||||
CLUTTER_ANIMATABLE_GET_IFACE (animatable)->animate_property (animatable,
|
||||
animation,
|
||||
property_name,
|
||||
initial_value,
|
||||
final_value,
|
||||
progress,
|
||||
value);
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), FALSE);
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
|
||||
g_return_val_if_fail (property_name != NULL, FALSE);
|
||||
g_return_val_if_fail (initial_value != NULL && final_value != NULL, FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (initial_value) != G_TYPE_INVALID, FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (final_value) != G_TYPE_INVALID, FALSE);
|
||||
g_return_val_if_fail (value != NULL, FALSE);
|
||||
g_return_val_if_fail (G_VALUE_TYPE (value) == G_VALUE_TYPE (initial_value) &&
|
||||
G_VALUE_TYPE (value) == G_VALUE_TYPE (final_value),
|
||||
FALSE);
|
||||
|
||||
res =
|
||||
CLUTTER_ANIMATABLE_GET_IFACE (animatable)->animate_property (animatable,
|
||||
animation,
|
||||
property_name,
|
||||
initial_value,
|
||||
final_value,
|
||||
progress,
|
||||
value);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -56,24 +56,24 @@ struct _ClutterAnimatableIface
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
/*< public >*/
|
||||
void (* animate_property) (ClutterAnimatable *animatable,
|
||||
ClutterAnimation *animation,
|
||||
const gchar *property_name,
|
||||
const GValue *initial_value,
|
||||
const GValue *final_value,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
gboolean (* animate_property) (ClutterAnimatable *animatable,
|
||||
ClutterAnimation *animation,
|
||||
const gchar *property_name,
|
||||
const GValue *initial_value,
|
||||
const GValue *final_value,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
};
|
||||
|
||||
GType clutter_animatable_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void clutter_animatable_animate_property (ClutterAnimatable *animatable,
|
||||
ClutterAnimation *animation,
|
||||
const gchar *property_name,
|
||||
const GValue *initial_value,
|
||||
const GValue *final_value,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
gboolean clutter_animatable_animate_property (ClutterAnimatable *animatable,
|
||||
ClutterAnimation *animation,
|
||||
const gchar *property_name,
|
||||
const GValue *initial_value,
|
||||
const GValue *final_value,
|
||||
gdouble progress,
|
||||
GValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -25,14 +25,43 @@
|
||||
/**
|
||||
* SECTION:clutter-animation
|
||||
* @short_description: Simple implicit animations
|
||||
* @See_Also: #ClutterAnimatable, #ClutterInterval, #ClutterAlpha,
|
||||
* #ClutterTimeline
|
||||
*
|
||||
* #ClutterAnimation is an object providing simple, implicit animations
|
||||
* for #GObject<!-- -->s.
|
||||
*
|
||||
* #ClutterAnimation instances will bind a #GObject property belonging
|
||||
* to a #GObject to a #ClutterInterval, and will then use a #ClutterTimeline
|
||||
* to interpolate the property between the initial and final values of the
|
||||
* interval.
|
||||
* #ClutterAnimation instances will bind one or more #GObject properties
|
||||
* belonging to a #GObject to a #ClutterInterval, and will then use a
|
||||
* #ClutterAlpha to interpolate the property between the initial and final
|
||||
* values of the interval.
|
||||
*
|
||||
* The duration of the animation is set using clutter_animation_set_duration().
|
||||
* The easing mode of the animation is set using clutter_animation_set_mode().
|
||||
*
|
||||
* If you want to control the animation you should retrieve the
|
||||
* #ClutterTimeline using clutter_animation_get_timeline() and then
|
||||
* use #ClutterTimeline functions like clutter_timeline_start(),
|
||||
* clutter_timeline_pause() or clutter_timeline_stop().
|
||||
*
|
||||
* A #ClutterAnimation will emit the #ClutterAnimation::completed signal
|
||||
* when the #ClutterTimeline used by the animation is completed; unlike
|
||||
* #ClutterTimeline, though, the #ClutterAnimation::completed will not be
|
||||
* emitted if #ClutterAnimation:loop is set to %TRUE - that is, a looping
|
||||
* animation never completes.
|
||||
*
|
||||
* If your animation depends on user control you can force its completion
|
||||
* using clutter_animation_completed().
|
||||
*
|
||||
* If the #GObject instance bound to a #ClutterAnimation implements the
|
||||
* #ClutterAnimatable interface it is possible for that instance to
|
||||
* control the way the initial and final states are interpolated.
|
||||
*
|
||||
* #ClutterAnimation<!-- -->s are distinguished from #ClutterBehaviour<!-- -->s
|
||||
* because the former can only control #GObject properties of a single
|
||||
* #GObject instance, while the latter can control multiple properties
|
||||
* using accessor functions inside the #ClutterBehaviour::alpha_notify
|
||||
* virtual function, and can control multiple #ClutterActor<!-- -->s as well.
|
||||
*
|
||||
* For convenience, it is possible to use the clutter_actor_animate()
|
||||
* function call which will take care of setting up and tearing down
|
||||
@ -85,16 +114,10 @@ struct _ClutterAnimationPrivate
|
||||
|
||||
GHashTable *properties;
|
||||
|
||||
gulong mode;
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
guint loop : 1;
|
||||
guint duration;
|
||||
|
||||
ClutterTimeline *timeline;
|
||||
guint timeline_started_id;
|
||||
guint timeline_completed_id;
|
||||
|
||||
ClutterAlpha *alpha;
|
||||
guint alpha_notify_id;
|
||||
};
|
||||
|
||||
@ -122,48 +145,43 @@ static void
|
||||
clutter_animation_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
if (priv->object)
|
||||
if (priv->alpha != NULL)
|
||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||
else
|
||||
timeline = NULL;
|
||||
|
||||
if (timeline != NULL && priv->timeline_started_id != 0)
|
||||
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
||||
|
||||
if (timeline != NULL && priv->timeline_completed_id != 0)
|
||||
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
||||
|
||||
priv->timeline_started_id = 0;
|
||||
priv->timeline_completed_id = 0;
|
||||
|
||||
if (priv->alpha != NULL)
|
||||
{
|
||||
if (priv->alpha_notify_id != 0)
|
||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||
|
||||
g_object_unref (priv->alpha);
|
||||
}
|
||||
|
||||
priv->alpha_notify_id = 0;
|
||||
priv->alpha = NULL;
|
||||
|
||||
if (priv->object != NULL)
|
||||
{
|
||||
g_object_weak_unref (G_OBJECT (gobject),
|
||||
on_animation_weak_notify,
|
||||
priv->object);
|
||||
g_object_set_qdata (priv->object, quark_object_animation, NULL);
|
||||
g_object_unref (priv->object);
|
||||
priv->object = NULL;
|
||||
}
|
||||
|
||||
if (priv->timeline)
|
||||
{
|
||||
if (priv->timeline_started_id)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->timeline,
|
||||
priv->timeline_started_id);
|
||||
priv->timeline_started_id = 0;
|
||||
}
|
||||
|
||||
if (priv->timeline_completed_id)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->timeline,
|
||||
priv->timeline_completed_id);
|
||||
priv->timeline_completed_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (priv->timeline);
|
||||
priv->timeline = NULL;
|
||||
}
|
||||
|
||||
if (priv->alpha)
|
||||
{
|
||||
if (priv->alpha_notify_id)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||
priv->alpha_notify_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (priv->alpha);
|
||||
priv->alpha = NULL;
|
||||
}
|
||||
priv->object = NULL;
|
||||
|
||||
G_OBJECT_CLASS (clutter_animation_parent_class)->dispose (gobject);
|
||||
}
|
||||
@ -214,7 +232,8 @@ clutter_animation_get_property (GObject *gobject,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = CLUTTER_ANIMATION (gobject)->priv;
|
||||
ClutterAnimation *animation = CLUTTER_ANIMATION (gobject);
|
||||
ClutterAnimationPrivate *priv = animation->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
@ -223,23 +242,23 @@ clutter_animation_get_property (GObject *gobject,
|
||||
break;
|
||||
|
||||
case PROP_MODE:
|
||||
g_value_set_ulong (value, priv->mode);
|
||||
g_value_set_ulong (value, clutter_animation_get_mode (animation));
|
||||
break;
|
||||
|
||||
case PROP_DURATION:
|
||||
g_value_set_uint (value, priv->duration);
|
||||
g_value_set_uint (value, clutter_animation_get_duration (animation));
|
||||
break;
|
||||
|
||||
case PROP_LOOP:
|
||||
g_value_set_boolean (value, priv->loop);
|
||||
g_value_set_boolean (value, clutter_animation_get_loop (animation));
|
||||
break;
|
||||
|
||||
case PROP_TIMELINE:
|
||||
g_value_set_object (value, priv->timeline);
|
||||
g_value_set_object (value, clutter_animation_get_timeline (animation));
|
||||
break;
|
||||
|
||||
case PROP_ALPHA:
|
||||
g_value_set_object (value, priv->alpha);
|
||||
g_value_set_object (value, clutter_animation_get_alpha (animation));
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -370,7 +389,7 @@ clutter_animation_class_init (ClutterAnimationClass *klass)
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
/**
|
||||
* ClutterAniamtion::completed:
|
||||
* ClutterAnimation::completed:
|
||||
* @animation: the animation that emitted the signal
|
||||
*
|
||||
* The ::completed signal is emitted once the animation has
|
||||
@ -396,7 +415,6 @@ clutter_animation_init (ClutterAnimation *self)
|
||||
{
|
||||
self->priv = CLUTTER_ANIMATION_GET_PRIVATE (self);
|
||||
|
||||
self->priv->mode = CLUTTER_LINEAR;
|
||||
self->priv->properties =
|
||||
g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
@ -750,7 +768,7 @@ on_timeline_completed (ClutterTimeline *timeline,
|
||||
{
|
||||
CLUTTER_NOTE (ANIMATION, "Timeline [%p] complete", timeline);
|
||||
|
||||
if (!animation->priv->loop)
|
||||
if (!clutter_animation_get_loop (animation))
|
||||
g_signal_emit (animation, animation_signals[COMPLETED], 0);
|
||||
}
|
||||
|
||||
@ -781,6 +799,7 @@ on_alpha_notify (GObject *gobject,
|
||||
const gchar *p_name = p->data;
|
||||
ClutterInterval *interval;
|
||||
GValue value = { 0, };
|
||||
gboolean apply;
|
||||
|
||||
interval = g_hash_table_lookup (priv->properties, p_name);
|
||||
g_assert (CLUTTER_IS_INTERVAL (interval));
|
||||
@ -794,23 +813,22 @@ on_alpha_notify (GObject *gobject,
|
||||
initial = clutter_interval_peek_initial_value (interval);
|
||||
final = clutter_interval_peek_final_value (interval);
|
||||
|
||||
CLUTTER_NOTE (ANIMATION, "Animatable property '%s'", p_name);
|
||||
clutter_animatable_animate_property (animatable, animation,
|
||||
p_name,
|
||||
initial, final,
|
||||
alpha_value,
|
||||
&value);
|
||||
|
||||
g_object_set_property (priv->object, p_name, &value);
|
||||
apply = clutter_animatable_animate_property (animatable, animation,
|
||||
p_name,
|
||||
initial, final,
|
||||
alpha_value,
|
||||
&value);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLUTTER_NOTE (ANIMATION, "Standard property '%s'", p_name);
|
||||
|
||||
if (clutter_interval_compute_value (interval, alpha_value, &value))
|
||||
g_object_set_property (priv->object, p_name, &value);
|
||||
apply = clutter_interval_compute_value (interval,
|
||||
alpha_value,
|
||||
&value);
|
||||
}
|
||||
|
||||
if (apply)
|
||||
g_object_set_property (priv->object, p_name, &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
}
|
||||
|
||||
@ -819,6 +837,65 @@ on_alpha_notify (GObject *gobject,
|
||||
g_object_thaw_notify (priv->object);
|
||||
}
|
||||
|
||||
static ClutterAlpha *
|
||||
clutter_animation_get_alpha_internal (ClutterAnimation *animation)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = animation->priv;
|
||||
|
||||
if (priv->alpha == NULL)
|
||||
{
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
alpha = clutter_alpha_new ();
|
||||
clutter_alpha_set_mode (alpha, CLUTTER_LINEAR);
|
||||
|
||||
priv->alpha_notify_id =
|
||||
g_signal_connect (alpha, "notify::alpha",
|
||||
G_CALLBACK (on_alpha_notify),
|
||||
animation);
|
||||
|
||||
priv->alpha = g_object_ref_sink (alpha);
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "alpha");
|
||||
}
|
||||
|
||||
return priv->alpha;
|
||||
}
|
||||
|
||||
static ClutterTimeline *
|
||||
clutter_animation_get_timeline_internal (ClutterAnimation *animation)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = animation->priv;
|
||||
ClutterTimeline *timeline;
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
alpha = clutter_animation_get_alpha_internal (animation);
|
||||
timeline = clutter_alpha_get_timeline (alpha);
|
||||
if (timeline != NULL)
|
||||
return timeline;
|
||||
|
||||
timeline = g_object_new (CLUTTER_TYPE_TIMELINE, NULL);
|
||||
|
||||
priv->timeline_started_id =
|
||||
g_signal_connect (timeline, "started",
|
||||
G_CALLBACK (on_timeline_started),
|
||||
animation);
|
||||
|
||||
priv->timeline_completed_id =
|
||||
g_signal_connect (timeline, "completed",
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
animation);
|
||||
|
||||
clutter_alpha_set_timeline (alpha, timeline);
|
||||
|
||||
/* the alpha owns the timeline now */
|
||||
g_object_unref (timeline);
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "timeline");
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes the animation pointer from the qdata section of the
|
||||
* actor attached to the animation
|
||||
@ -924,16 +1001,6 @@ clutter_animation_get_object (ClutterAnimation *animation)
|
||||
return animation->priv->object;
|
||||
}
|
||||
|
||||
static inline void
|
||||
clutter_animation_set_mode_internal (ClutterAnimation *animation,
|
||||
ClutterAlpha *alpha)
|
||||
{
|
||||
ClutterAnimationPrivate *priv = animation->priv;
|
||||
|
||||
if (alpha)
|
||||
clutter_alpha_set_mode (alpha, priv->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animation_set_mode:
|
||||
* @animation: a #ClutterAnimation
|
||||
@ -943,22 +1010,26 @@ clutter_animation_set_mode_internal (ClutterAnimation *animation,
|
||||
* a logical id, either coming from the #ClutterAnimationMode enumeration
|
||||
* or the return value of clutter_alpha_register_func().
|
||||
*
|
||||
* This function will also set #ClutterAnimation:alpha if needed.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_animation_set_mode (ClutterAnimation *animation,
|
||||
gulong mode)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
|
||||
priv = animation->priv;
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
priv->mode = mode;
|
||||
clutter_animation_set_mode_internal (animation, priv->alpha);
|
||||
alpha = clutter_animation_get_alpha_internal (animation);
|
||||
clutter_alpha_set_mode (alpha, mode);
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "mode");
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (animation));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -975,9 +1046,13 @@ clutter_animation_set_mode (ClutterAnimation *animation,
|
||||
gulong
|
||||
clutter_animation_get_mode (ClutterAnimation *animation)
|
||||
{
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), CLUTTER_LINEAR);
|
||||
|
||||
return animation->priv->mode;
|
||||
alpha = clutter_animation_get_alpha_internal (animation);
|
||||
|
||||
return clutter_alpha_get_mode (alpha);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -987,35 +1062,28 @@ clutter_animation_get_mode (ClutterAnimation *animation)
|
||||
*
|
||||
* Sets the duration of @animation in milliseconds.
|
||||
*
|
||||
* This function will set #ClutterAnimation:alpha and
|
||||
* #ClutterAnimation:timeline if needed.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_animation_set_duration (ClutterAnimation *animation,
|
||||
gint msecs)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
|
||||
priv = animation->priv;
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
priv->duration = msecs;
|
||||
|
||||
if (priv->timeline)
|
||||
{
|
||||
gboolean was_playing;
|
||||
|
||||
was_playing = clutter_timeline_is_playing (priv->timeline);
|
||||
if (was_playing)
|
||||
clutter_timeline_stop (priv->timeline);
|
||||
|
||||
clutter_timeline_set_duration (priv->timeline, msecs);
|
||||
|
||||
if (was_playing)
|
||||
clutter_timeline_start (priv->timeline);
|
||||
}
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
clutter_timeline_set_duration (timeline, msecs);
|
||||
clutter_timeline_rewind (timeline);
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "duration");
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (animation));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1028,27 +1096,27 @@ clutter_animation_set_duration (ClutterAnimation *animation,
|
||||
* A looping #ClutterAnimation will not emit the #ClutterAnimation::completed
|
||||
* signal when finished.
|
||||
*
|
||||
* This function will set #ClutterAnimation:alpha and
|
||||
* #ClutterAnimation:timeline if needed.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_animation_set_loop (ClutterAnimation *animation,
|
||||
gboolean loop)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
|
||||
priv = animation->priv;
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
if (priv->loop != loop)
|
||||
{
|
||||
priv->loop = loop;
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
clutter_timeline_set_loop (timeline, loop);
|
||||
|
||||
if (priv->timeline)
|
||||
clutter_timeline_set_loop (priv->timeline, priv->loop);
|
||||
g_object_notify (G_OBJECT (animation), "loop");
|
||||
|
||||
g_object_notify (G_OBJECT (animation), "loop");
|
||||
}
|
||||
g_object_thaw_notify (G_OBJECT (animation));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1064,9 +1132,13 @@ clutter_animation_set_loop (ClutterAnimation *animation,
|
||||
gboolean
|
||||
clutter_animation_get_loop (ClutterAnimation *animation)
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), FALSE);
|
||||
|
||||
return animation->priv->loop;
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
|
||||
return clutter_timeline_get_loop (timeline);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1082,26 +1154,23 @@ clutter_animation_get_loop (ClutterAnimation *animation)
|
||||
guint
|
||||
clutter_animation_get_duration (ClutterAnimation *animation)
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), 0);
|
||||
|
||||
return animation->priv->duration;
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
|
||||
return clutter_timeline_get_duration (timeline);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animation_set_timeline:
|
||||
* @animation: a #ClutterAnimation
|
||||
* @timeline: a #ClutterTimeline or %NULL
|
||||
* @timeline: a #ClutterTimeline, or %NULL to unset the
|
||||
* current #ClutterTimeline
|
||||
*
|
||||
* Sets the #ClutterTimeline used by @animation.
|
||||
*
|
||||
* The #ClutterAnimation:duration and #ClutterAnimation:loop properties
|
||||
* will be set using the corresponding #ClutterTimeline properties as a
|
||||
* side effect.
|
||||
*
|
||||
* If @timeline is %NULL a new #ClutterTimeline will be constructed
|
||||
* using the current values of the #ClutterAnimation:duration and
|
||||
* #ClutterAnimation:loop properties.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
@ -1109,62 +1178,50 @@ clutter_animation_set_timeline (ClutterAnimation *animation,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterTimeline *cur_timeline;
|
||||
ClutterAlpha *alpha;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
g_return_if_fail (timeline == NULL || CLUTTER_IS_TIMELINE (timeline));
|
||||
|
||||
priv = animation->priv;
|
||||
|
||||
if (timeline != NULL && priv->timeline == timeline)
|
||||
if (priv->alpha != NULL)
|
||||
cur_timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||
else
|
||||
cur_timeline = NULL;
|
||||
|
||||
if (cur_timeline == timeline)
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
if (priv->timeline != NULL)
|
||||
{
|
||||
if (priv->timeline_started_id)
|
||||
g_signal_handler_disconnect (priv->timeline,
|
||||
priv->timeline_started_id);
|
||||
if (cur_timeline != NULL && priv->timeline_started_id != 0)
|
||||
g_signal_handler_disconnect (cur_timeline, priv->timeline_started_id);
|
||||
|
||||
if (priv->timeline_completed_id)
|
||||
g_signal_handler_disconnect (priv->timeline,
|
||||
priv->timeline_completed_id);
|
||||
if (cur_timeline != NULL && priv->timeline_completed_id != 0)
|
||||
g_signal_handler_disconnect (cur_timeline, priv->timeline_completed_id);
|
||||
|
||||
g_object_unref (priv->timeline);
|
||||
priv->timeline_started_id = 0;
|
||||
priv->timeline_completed_id = 0;
|
||||
priv->timeline = 0;
|
||||
}
|
||||
priv->timeline_started_id = 0;
|
||||
priv->timeline_completed_id = 0;
|
||||
|
||||
if (timeline == NULL)
|
||||
{
|
||||
timeline = g_object_new (CLUTTER_TYPE_TIMELINE,
|
||||
"duration", priv->duration,
|
||||
"loop", priv->loop,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_object_ref (timeline);
|
||||
|
||||
priv->duration = clutter_timeline_get_duration (timeline);
|
||||
g_object_notify (G_OBJECT (animation), "duration");
|
||||
|
||||
priv->loop = clutter_timeline_get_loop (timeline);
|
||||
g_object_notify (G_OBJECT (animation), "loop");
|
||||
}
|
||||
|
||||
priv->timeline = timeline;
|
||||
alpha = clutter_animation_get_alpha_internal (animation);
|
||||
clutter_alpha_set_timeline (alpha, timeline);
|
||||
g_object_notify (G_OBJECT (animation), "timeline");
|
||||
g_object_notify (G_OBJECT (animation), "duration");
|
||||
g_object_notify (G_OBJECT (animation), "loop");
|
||||
|
||||
priv->timeline_started_id =
|
||||
g_signal_connect (timeline, "started",
|
||||
G_CALLBACK (on_timeline_started),
|
||||
animation);
|
||||
priv->timeline_completed_id =
|
||||
g_signal_connect (timeline, "completed",
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
animation);
|
||||
if (timeline)
|
||||
{
|
||||
priv->timeline_started_id =
|
||||
g_signal_connect (timeline, "started",
|
||||
G_CALLBACK (on_timeline_started),
|
||||
animation);
|
||||
priv->timeline_completed_id =
|
||||
g_signal_connect (timeline, "completed",
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
animation);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (animation));
|
||||
}
|
||||
@ -1184,19 +1241,18 @@ clutter_animation_get_timeline (ClutterAnimation *animation)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||
|
||||
return animation->priv->timeline;
|
||||
return clutter_animation_get_timeline_internal (animation);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_animation_set_alpha:
|
||||
* @animation: a #ClutterAnimation
|
||||
* @alpha: a #ClutterAlpha, or %NULL
|
||||
* @alpha: a #ClutterAlpha, or %NULL to unset the current #ClutterAlpha
|
||||
*
|
||||
* Sets @alpha as the #ClutterAlpha used by @animation.
|
||||
*
|
||||
* If @alpha is %NULL, a new #ClutterAlpha will be constructed from
|
||||
* the current values of the #ClutterAnimation:mode and
|
||||
* #ClutterAnimation:timeline properties.
|
||||
* If @alpha is not %NULL, the #ClutterAnimation will take ownership
|
||||
* of the #ClutterAlpha instance.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
@ -1205,41 +1261,84 @@ clutter_animation_set_alpha (ClutterAnimation *animation,
|
||||
ClutterAlpha *alpha)
|
||||
{
|
||||
ClutterAnimationPrivate *priv;
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ANIMATION (animation));
|
||||
g_return_if_fail (alpha == NULL || CLUTTER_IS_ALPHA (alpha));
|
||||
|
||||
priv = animation->priv;
|
||||
|
||||
if (!alpha)
|
||||
if (priv->alpha == alpha)
|
||||
return;
|
||||
|
||||
g_object_freeze_notify (G_OBJECT (animation));
|
||||
|
||||
if (priv->alpha != NULL)
|
||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||
else
|
||||
timeline = NULL;
|
||||
|
||||
/* disconnect the old timeline first */
|
||||
if (timeline != NULL && priv->timeline_started_id != 0)
|
||||
{
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
timeline = clutter_animation_get_timeline (animation);
|
||||
|
||||
alpha = clutter_alpha_new ();
|
||||
clutter_alpha_set_timeline (alpha, timeline);
|
||||
clutter_animation_set_mode_internal (animation, alpha);
|
||||
g_signal_handler_disconnect (timeline, priv->timeline_started_id);
|
||||
priv->timeline_started_id = 0;
|
||||
}
|
||||
|
||||
g_object_ref_sink (alpha);
|
||||
|
||||
if (priv->alpha)
|
||||
if (timeline != NULL && priv->timeline_completed_id != 0)
|
||||
{
|
||||
if (priv->alpha_notify_id)
|
||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||
g_signal_handler_disconnect (timeline, priv->timeline_completed_id);
|
||||
priv->timeline_completed_id = 0;
|
||||
}
|
||||
|
||||
g_object_unref (priv->alpha);
|
||||
/* then we need to disconnect the signal handler from the old alpha */
|
||||
if (priv->alpha_notify_id != 0)
|
||||
{
|
||||
g_signal_handler_disconnect (priv->alpha, priv->alpha_notify_id);
|
||||
priv->alpha_notify_id = 0;
|
||||
}
|
||||
|
||||
if (priv->alpha != NULL)
|
||||
{
|
||||
/* this will take care of any reference we hold on the timeline */
|
||||
g_object_unref (priv->alpha);
|
||||
priv->alpha = NULL;
|
||||
}
|
||||
|
||||
priv->alpha = alpha;
|
||||
if (alpha == NULL)
|
||||
goto out;
|
||||
|
||||
priv->alpha = g_object_ref_sink (alpha);
|
||||
priv->alpha_notify_id =
|
||||
g_signal_connect (alpha, "notify::alpha",
|
||||
g_signal_connect (priv->alpha, "notify::value",
|
||||
G_CALLBACK (on_alpha_notify),
|
||||
animation);
|
||||
|
||||
/* if the alpha has a timeline then we use it, otherwise we create one */
|
||||
timeline = clutter_alpha_get_timeline (priv->alpha);
|
||||
if (timeline != NULL)
|
||||
{
|
||||
priv->timeline_started_id =
|
||||
g_signal_connect (timeline, "started",
|
||||
G_CALLBACK (on_timeline_started),
|
||||
animation);
|
||||
priv->timeline_completed_id =
|
||||
g_signal_connect (timeline, "completed",
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
animation);
|
||||
}
|
||||
else
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
|
||||
out:
|
||||
/* emit all relevant notifications */
|
||||
g_object_notify (G_OBJECT (animation), "mode");
|
||||
g_object_notify (G_OBJECT (animation), "duration");
|
||||
g_object_notify (G_OBJECT (animation), "loop");
|
||||
g_object_notify (G_OBJECT (animation), "alpha");
|
||||
g_object_notify (G_OBJECT (animation), "timeline");
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (animation));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1257,7 +1356,7 @@ clutter_animation_get_alpha (ClutterAnimation *animation)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL);
|
||||
|
||||
return animation->priv->alpha;
|
||||
return clutter_animation_get_alpha_internal (animation);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1298,8 +1397,12 @@ on_animation_completed (ClutterAnimation *animation)
|
||||
static void
|
||||
clutter_animation_start (ClutterAnimation *animation)
|
||||
{
|
||||
if (G_LIKELY (animation->priv->timeline))
|
||||
clutter_timeline_start (animation->priv->timeline);
|
||||
ClutterTimeline *timeline;
|
||||
|
||||
timeline = clutter_animation_get_timeline_internal (animation);
|
||||
|
||||
if (G_LIKELY (timeline != NULL))
|
||||
clutter_timeline_start (timeline);
|
||||
else
|
||||
{
|
||||
/* sanity check */
|
||||
@ -1545,7 +1648,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
||||
g_return_val_if_fail (first_property_name != NULL, NULL);
|
||||
|
||||
timeline = clutter_alpha_get_timeline (alpha);
|
||||
if (G_UNLIKELY (!timeline))
|
||||
if (timeline == NULL)
|
||||
{
|
||||
g_warning ("The passed ClutterAlpha does not have an "
|
||||
"associated ClutterTimeline.");
|
||||
@ -1553,9 +1656,10 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
||||
}
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
G_CALLBACK (on_animation_completed),
|
||||
@ -1566,9 +1670,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor,
|
||||
else
|
||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_set_alpha (animation, alpha);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
va_start (args, first_property_name);
|
||||
clutter_animation_setup_valist (animation, first_property_name, args);
|
||||
@ -1618,9 +1720,10 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
|
||||
g_return_val_if_fail (first_property_name != NULL, NULL);
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
G_CALLBACK (on_animation_completed),
|
||||
@ -1631,10 +1734,8 @@ clutter_actor_animate_with_timeline (ClutterActor *actor,
|
||||
else
|
||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_set_alpha (animation, NULL);
|
||||
clutter_animation_set_mode (animation, mode);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
|
||||
va_start (args, first_property_name);
|
||||
clutter_animation_setup_valist (animation, first_property_name, args);
|
||||
@ -1809,15 +1910,13 @@ clutter_actor_animate (ClutterActor *actor,
|
||||
g_return_val_if_fail (first_property_name != NULL, NULL);
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
/* if there is no animation already attached to the actor,
|
||||
* create one and set up the timeline and alpha using the
|
||||
* current values for duration, mode and loop
|
||||
*/
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_timeline (animation, NULL);
|
||||
clutter_animation_set_alpha (animation, NULL);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
@ -1832,8 +1931,8 @@ clutter_actor_animate (ClutterActor *actor,
|
||||
/* force the update of duration and mode using the new
|
||||
* values coming from the parameters of this function
|
||||
*/
|
||||
clutter_animation_set_duration (animation, duration);
|
||||
clutter_animation_set_mode (animation, mode);
|
||||
clutter_animation_set_duration (animation, duration);
|
||||
|
||||
va_start (args, first_property_name);
|
||||
clutter_animation_setup_valist (animation, first_property_name, args);
|
||||
@ -1888,15 +1987,13 @@ clutter_actor_animatev (ClutterActor *actor,
|
||||
g_return_val_if_fail (values != NULL, NULL);
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
/* if there is no animation already attached to the actor,
|
||||
* create one and set up the timeline and alpha using the
|
||||
* current values for duration, mode and loop
|
||||
*/
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_timeline (animation, NULL);
|
||||
clutter_animation_set_alpha (animation, NULL);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
@ -1911,8 +2008,8 @@ clutter_actor_animatev (ClutterActor *actor,
|
||||
/* force the update of duration and mode using the new
|
||||
* values coming from the parameters of this function
|
||||
*/
|
||||
clutter_animation_set_duration (animation, duration);
|
||||
clutter_animation_set_mode (animation, mode);
|
||||
clutter_animation_set_duration (animation, duration);
|
||||
clutter_animation_setupv (animation, n_properties, properties, values);
|
||||
clutter_animation_start (animation);
|
||||
|
||||
@ -1967,9 +2064,10 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor,
|
||||
g_return_val_if_fail (values != NULL, NULL);
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
G_CALLBACK (on_animation_completed),
|
||||
@ -1980,10 +2078,8 @@ clutter_actor_animate_with_timelinev (ClutterActor *actor,
|
||||
else
|
||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_set_alpha (animation, NULL);
|
||||
clutter_animation_set_mode (animation, mode);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_setupv (animation, n_properties, properties, values);
|
||||
clutter_animation_start (animation);
|
||||
|
||||
@ -2036,7 +2132,7 @@ clutter_actor_animate_with_alphav (ClutterActor *actor,
|
||||
g_return_val_if_fail (values != NULL, NULL);
|
||||
|
||||
timeline = clutter_alpha_get_timeline (alpha);
|
||||
if (G_UNLIKELY (!timeline))
|
||||
if (timeline == NULL)
|
||||
{
|
||||
g_warning ("The passed ClutterAlpha does not have an "
|
||||
"associated ClutterTimeline.");
|
||||
@ -2044,9 +2140,10 @@ clutter_actor_animate_with_alphav (ClutterActor *actor,
|
||||
}
|
||||
|
||||
animation = g_object_get_qdata (G_OBJECT (actor), quark_object_animation);
|
||||
if (G_LIKELY (!animation))
|
||||
if (animation == NULL)
|
||||
{
|
||||
animation = clutter_animation_new ();
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
|
||||
g_signal_connect (animation, "completed",
|
||||
G_CALLBACK (on_animation_completed),
|
||||
@ -2057,9 +2154,7 @@ clutter_actor_animate_with_alphav (ClutterActor *actor,
|
||||
else
|
||||
CLUTTER_NOTE (ANIMATION, "Reusing Animation [%p]", animation);
|
||||
|
||||
clutter_animation_set_timeline (animation, timeline);
|
||||
clutter_animation_set_alpha (animation, alpha);
|
||||
clutter_animation_set_object (animation, G_OBJECT (actor));
|
||||
clutter_animation_setupv (animation, n_properties, properties, values);
|
||||
clutter_animation_start (animation);
|
||||
|
||||
|
@ -61,7 +61,8 @@ struct _ClutterBackendPrivate
|
||||
guint double_click_distance;
|
||||
|
||||
gdouble resolution;
|
||||
gdouble units_per_em;
|
||||
|
||||
gfloat units_per_em;
|
||||
|
||||
cairo_font_options_t *font_options;
|
||||
|
||||
@ -102,55 +103,74 @@ clutter_backend_dispose (GObject *gobject)
|
||||
G_OBJECT_CLASS (clutter_backend_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static inline void
|
||||
update_units_per_em (ClutterBackend *backend)
|
||||
static gfloat
|
||||
get_units_per_em (ClutterBackend *backend,
|
||||
PangoFontDescription *font_desc)
|
||||
{
|
||||
ClutterBackendPrivate *priv = backend->priv;
|
||||
const gchar *font_name;
|
||||
gfloat units_per_em = -1.0;
|
||||
gboolean free_font_desc = FALSE;
|
||||
gdouble dpi;
|
||||
|
||||
font_name = clutter_backend_get_font_name (backend);
|
||||
dpi = clutter_backend_get_resolution (backend);
|
||||
|
||||
if (G_LIKELY (font_name != NULL && *font_name != '\0'))
|
||||
if (font_desc == NULL)
|
||||
{
|
||||
PangoFontDescription *font_desc;
|
||||
gdouble font_size = 0;
|
||||
const gchar *font_name = clutter_backend_get_font_name (backend);
|
||||
|
||||
font_desc = pango_font_description_from_string (font_name);
|
||||
if (G_LIKELY (font_desc != NULL))
|
||||
if (G_LIKELY (font_name != NULL && *font_name != '\0'))
|
||||
{
|
||||
gint pango_size;
|
||||
gboolean is_absolute;
|
||||
|
||||
pango_size = pango_font_description_get_size (font_desc);
|
||||
is_absolute =
|
||||
pango_font_description_get_size_is_absolute (font_desc);
|
||||
if (!is_absolute)
|
||||
font_size = ((gdouble) font_size) / PANGO_SCALE;
|
||||
|
||||
pango_font_description_free (font_desc);
|
||||
font_desc = pango_font_description_from_string (font_name);
|
||||
free_font_desc = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* 10 points at 96 DPI is 12 pixels */
|
||||
priv->units_per_em = 1.2 * font_size
|
||||
* dpi
|
||||
/ 96.0;
|
||||
if (font_desc != NULL)
|
||||
{
|
||||
gdouble font_size = 0;
|
||||
gint pango_size;
|
||||
gboolean is_absolute;
|
||||
|
||||
pango_size = pango_font_description_get_size (font_desc);
|
||||
is_absolute = pango_font_description_get_size_is_absolute (font_desc);
|
||||
|
||||
/* "absolute" means "device units" (usually, pixels); otherwise,
|
||||
* it means logical units (points)
|
||||
*/
|
||||
if (is_absolute)
|
||||
font_size = (gdouble) pango_size / PANGO_SCALE;
|
||||
else
|
||||
font_size = (gdouble) pango_size / PANGO_SCALE
|
||||
* dpi
|
||||
/ 96.0f;
|
||||
|
||||
/* 10 points at 96 DPI is 13.3 pixels */
|
||||
units_per_em = (1.2f * font_size)
|
||||
* dpi
|
||||
/ 96.0f;
|
||||
}
|
||||
else
|
||||
priv->units_per_em = -1.0;
|
||||
units_per_em = -1.0f;
|
||||
|
||||
if (free_font_desc)
|
||||
pango_font_description_free (font_desc);
|
||||
|
||||
return units_per_em;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_real_resolution_changed (ClutterBackend *backend)
|
||||
{
|
||||
update_units_per_em (backend);
|
||||
backend->priv->units_per_em = get_units_per_em (backend, NULL);
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_real_font_changed (ClutterBackend *backend)
|
||||
{
|
||||
update_units_per_em (backend);
|
||||
backend->priv->units_per_em = get_units_per_em (backend, NULL);
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Units per em: %.2f", backend->priv->units_per_em);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -280,36 +300,63 @@ _clutter_backend_redraw (ClutterBackend *backend,
|
||||
klass->redraw (backend, stage);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_backend_create_context (ClutterBackend *backend,
|
||||
gboolean is_offscreen,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE);
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (klass->create_context)
|
||||
return klass->create_context (backend, is_offscreen, error);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
static ClutterStage *current_context_stage = NULL;
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
if (current_context_stage != stage || !CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
ClutterStage *new_stage = NULL;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
CLUTTER_NOTE (MULTISTAGE, "Stage is not realized, unsetting");
|
||||
stage = NULL;
|
||||
new_stage = NULL;
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE,
|
||||
"Stage [%p] is not realized, unsetting the stage",
|
||||
stage);
|
||||
}
|
||||
else
|
||||
CLUTTER_NOTE (MULTISTAGE, "Setting the new stage [%p]", stage);
|
||||
|
||||
{
|
||||
new_stage = stage;
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE,
|
||||
"Setting the new stage [%p]",
|
||||
new_stage);
|
||||
}
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (G_LIKELY (klass->ensure_context))
|
||||
klass->ensure_context (backend, stage);
|
||||
klass->ensure_context (backend, new_stage);
|
||||
|
||||
/* FIXME: With a NULL stage and thus no active context it may make more
|
||||
* sense to clean the context but then re call with the default stage
|
||||
* so at least there is some kind of context in place (as to avoid
|
||||
* potential issue of GL calls with no context)
|
||||
*/
|
||||
current_context_stage = stage;
|
||||
current_context_stage = new_stage;
|
||||
|
||||
/* if the new stage has a different size than the previous one
|
||||
* we need to update the viewport; we do it by simply setting the
|
||||
@ -359,8 +406,9 @@ _clutter_backend_init_events (ClutterBackend *backend)
|
||||
klass->init_events (backend);
|
||||
}
|
||||
|
||||
ClutterUnit
|
||||
_clutter_backend_get_units_per_em (ClutterBackend *backend)
|
||||
gfloat
|
||||
_clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
PangoFontDescription *font_desc)
|
||||
{
|
||||
ClutterBackendPrivate *priv;
|
||||
|
||||
@ -368,8 +416,12 @@ _clutter_backend_get_units_per_em (ClutterBackend *backend)
|
||||
|
||||
priv = backend->priv;
|
||||
|
||||
if (G_UNLIKELY (priv->units_per_em < 0))
|
||||
update_units_per_em (backend);
|
||||
/* recompute for the font description, but do not cache the result */
|
||||
if (font_desc != NULL)
|
||||
return get_units_per_em (backend, font_desc);
|
||||
|
||||
if (priv->units_per_em < 0)
|
||||
priv->units_per_em = get_units_per_em (backend, NULL);
|
||||
|
||||
return priv->units_per_em;
|
||||
}
|
||||
@ -602,6 +654,8 @@ clutter_backend_get_font_options (ClutterBackend *backend)
|
||||
cairo_font_options_set_antialias (priv->font_options,
|
||||
CAIRO_ANTIALIAS_DEFAULT);
|
||||
|
||||
g_signal_emit (backend, backend_signals[FONT_CHANGED], 0);
|
||||
|
||||
return priv->font_options;
|
||||
}
|
||||
|
||||
@ -661,7 +715,12 @@ clutter_backend_get_font_name (ClutterBackend *backend)
|
||||
if (G_LIKELY (priv->font_name))
|
||||
return priv->font_name;
|
||||
|
||||
/* if we have never been called then we need to set the
|
||||
* default font and update everything that relies on the
|
||||
* ::font-changed signal
|
||||
*/
|
||||
priv->font_name = g_strdup (DEFAULT_FONT_NAME);
|
||||
g_signal_emit (backend, backend_signals[FONT_CHANGED], 0);
|
||||
|
||||
return priv->font_name;
|
||||
}
|
||||
|
@ -77,6 +77,9 @@ struct _ClutterBackendClass
|
||||
ClutterFeatureFlags (* get_features) (ClutterBackend *backend);
|
||||
void (* redraw) (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
gboolean (* create_context) (ClutterBackend *backend,
|
||||
gboolean is_offscreen,
|
||||
GError **error);
|
||||
void (* ensure_context) (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
|
@ -552,13 +552,16 @@ notify_cb (GObject *object,
|
||||
* @behave: a #ClutterBehaviour
|
||||
* @alpha: a #ClutterAlpha or %NULL to unset a previously set alpha
|
||||
*
|
||||
* Binds @alpha to a #ClutterBehaviour. The #ClutterAlpha object
|
||||
* Binds @alpha to a #ClutterBehaviour. The #ClutterAlpha object
|
||||
* is what makes a behaviour work: for each tick of the timeline
|
||||
* used by #ClutterAlpha a new value of the alpha parameter is
|
||||
* computed by the alpha function; the value should be used by
|
||||
* the #ClutterBehaviour to update one or more properties of the
|
||||
* actors to which the behaviour applies.
|
||||
*
|
||||
* If @alpha is not %NULL, the #ClutterBehaviour will take ownership
|
||||
* of the #ClutterAlpha instance.
|
||||
*
|
||||
* Since: 0.2
|
||||
*/
|
||||
void
|
||||
|
@ -325,9 +325,9 @@ clutter_cairo_texture_notify (GObject *object,
|
||||
|
||||
static void
|
||||
clutter_cairo_texture_get_preferred_width (ClutterActor *actor,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width,
|
||||
ClutterUnit *natural_width)
|
||||
gfloat for_height,
|
||||
gfloat *min_width,
|
||||
gfloat *natural_width)
|
||||
{
|
||||
ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (actor)->priv;
|
||||
|
||||
@ -335,14 +335,14 @@ clutter_cairo_texture_get_preferred_width (ClutterActor *actor,
|
||||
*min_width = 0;
|
||||
|
||||
if (natural_width)
|
||||
*natural_width = CLUTTER_UNITS_FROM_DEVICE (priv->width);
|
||||
*natural_width = (gfloat) priv->width;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cairo_texture_get_preferred_height (ClutterActor *actor,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height,
|
||||
ClutterUnit *natural_height)
|
||||
gfloat for_width,
|
||||
gfloat *min_height,
|
||||
gfloat *natural_height)
|
||||
{
|
||||
ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (actor)->priv;
|
||||
|
||||
@ -350,7 +350,7 @@ clutter_cairo_texture_get_preferred_height (ClutterActor *actor,
|
||||
*min_height = 0;
|
||||
|
||||
if (natural_height)
|
||||
*natural_height = CLUTTER_UNITS_FROM_DEVICE (priv->height);
|
||||
*natural_height = (gfloat) priv->height;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -65,16 +65,18 @@ struct _ClutterClonePrivate
|
||||
ClutterActor *clone_source;
|
||||
};
|
||||
|
||||
static void clutter_clone_set_source_internal (ClutterClone *clone,
|
||||
ClutterActor *source);
|
||||
static void
|
||||
clutter_clone_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
|
||||
ClutterActor *clone_source = priv->clone_source;
|
||||
|
||||
if (G_UNLIKELY (clone_source == NULL))
|
||||
if (clone_source == NULL)
|
||||
{
|
||||
if (min_width_p)
|
||||
*min_width_p = 0;
|
||||
@ -91,14 +93,14 @@ clutter_clone_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_clone_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
|
||||
ClutterActor *clone_source = priv->clone_source;
|
||||
|
||||
if (G_UNLIKELY (clone_source == NULL))
|
||||
if (clone_source == NULL)
|
||||
{
|
||||
if (min_height_p)
|
||||
*min_height_p = 0;
|
||||
@ -120,6 +122,7 @@ clutter_clone_paint (ClutterActor *self)
|
||||
ClutterClonePrivate *priv = clone->priv;
|
||||
ClutterGeometry geom, clone_geom;
|
||||
gfloat x_scale, y_scale;
|
||||
gboolean was_unmapped = FALSE;
|
||||
|
||||
if (G_UNLIKELY (priv->clone_source == NULL))
|
||||
return;
|
||||
@ -153,23 +156,32 @@ clutter_clone_paint (ClutterActor *self)
|
||||
_clutter_actor_set_opacity_parent (priv->clone_source, self);
|
||||
_clutter_actor_set_enable_model_view_transform (priv->clone_source, FALSE);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_MAPPED (priv->clone_source))
|
||||
{
|
||||
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, TRUE);
|
||||
was_unmapped = TRUE;
|
||||
}
|
||||
|
||||
clutter_actor_paint (priv->clone_source);
|
||||
|
||||
if (was_unmapped)
|
||||
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, FALSE);
|
||||
|
||||
_clutter_actor_set_enable_model_view_transform (priv->clone_source, TRUE);
|
||||
_clutter_actor_set_opacity_parent (priv->clone_source, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_clone_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (self)->priv;
|
||||
ClutterActorClass *parent_class;
|
||||
|
||||
/* chain up */
|
||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_clone_parent_class);
|
||||
parent_class->allocate (self, box, origin_changed);
|
||||
parent_class->allocate (self, box, flags);
|
||||
|
||||
if (G_UNLIKELY (priv->clone_source == NULL))
|
||||
return;
|
||||
@ -182,10 +194,7 @@ clutter_clone_allocate (ClutterActor *self,
|
||||
* paint cycle, we can safely give it as much size as it requires
|
||||
*/
|
||||
if (clutter_actor_get_parent (priv->clone_source) == NULL)
|
||||
{
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source,
|
||||
origin_changed);
|
||||
}
|
||||
clutter_actor_allocate_preferred_size (priv->clone_source, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -231,13 +240,7 @@ clutter_clone_get_property (GObject *gobject,
|
||||
static void
|
||||
clutter_clone_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterClonePrivate *priv = CLUTTER_CLONE (gobject)->priv;
|
||||
|
||||
if (priv->clone_source)
|
||||
{
|
||||
g_object_unref (priv->clone_source);
|
||||
priv->clone_source = NULL;
|
||||
}
|
||||
clutter_clone_set_source_internal (CLUTTER_CLONE (gobject), NULL);
|
||||
|
||||
G_OBJECT_CLASS (clutter_clone_parent_class)->dispose (gobject);
|
||||
}
|
||||
@ -302,6 +305,46 @@ clutter_clone_new (ClutterActor *source)
|
||||
return g_object_new (CLUTTER_TYPE_CLONE, "source", source, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clone_source_queue_redraw_cb (ClutterActor *source,
|
||||
ClutterActor *origin,
|
||||
ClutterClone *clone)
|
||||
{
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (clone));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_clone_set_source_internal (ClutterClone *clone,
|
||||
ClutterActor *source)
|
||||
{
|
||||
ClutterClonePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CLONE (clone));
|
||||
g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
|
||||
|
||||
priv = clone->priv;
|
||||
|
||||
if (priv->clone_source)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (priv->clone_source,
|
||||
(void *) clone_source_queue_redraw_cb,
|
||||
clone);
|
||||
g_object_unref (priv->clone_source);
|
||||
priv->clone_source = NULL;
|
||||
}
|
||||
|
||||
if (source)
|
||||
{
|
||||
priv->clone_source = g_object_ref (source);
|
||||
g_signal_connect (priv->clone_source, "queue-redraw",
|
||||
G_CALLBACK (clone_source_queue_redraw_cb), clone);
|
||||
}
|
||||
|
||||
g_object_notify (G_OBJECT (clone), "source");
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (clone));
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_clone_set_source:
|
||||
* @clone: a #ClutterClone
|
||||
@ -315,24 +358,10 @@ void
|
||||
clutter_clone_set_source (ClutterClone *clone,
|
||||
ClutterActor *source)
|
||||
{
|
||||
ClutterClonePrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CLONE (clone));
|
||||
g_return_if_fail (source == NULL || CLUTTER_IS_ACTOR (source));
|
||||
|
||||
priv = clone->priv;
|
||||
|
||||
if (priv->clone_source)
|
||||
{
|
||||
g_object_unref (priv->clone_source);
|
||||
priv->clone_source = NULL;
|
||||
}
|
||||
|
||||
if (source)
|
||||
priv->clone_source = g_object_ref (source);
|
||||
|
||||
g_object_notify (G_OBJECT (clone), "source");
|
||||
|
||||
clutter_clone_set_source_internal (clone, source);
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (clone));
|
||||
}
|
||||
|
||||
|
@ -398,7 +398,7 @@ clutter_color_from_string (ClutterColor *color,
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
/* if the string contains a color encoded using the hexadecimal
|
||||
* notations (#rrggbbaa or #rrggbb) we attempt a rough pass at
|
||||
* notations (#rrggbbaa or #rgba) we attempt a rough pass at
|
||||
* parsing the color ourselves, as we need the alpha channel that
|
||||
* Pango can't retrieve.
|
||||
*/
|
||||
@ -407,36 +407,34 @@ clutter_color_from_string (ClutterColor *color,
|
||||
gint32 result;
|
||||
|
||||
if (sscanf (str + 1, "%x", &result))
|
||||
{
|
||||
if (strlen (str) == 9)
|
||||
{
|
||||
{
|
||||
if (strlen (str) == 9)
|
||||
{
|
||||
/* #rrggbbaa */
|
||||
color->red = (result >> 24) & 0xff;
|
||||
color->green = (result >> 16) & 0xff;
|
||||
color->blue = (result >> 8) & 0xff;
|
||||
color->red = (result >> 24) & 0xff;
|
||||
color->green = (result >> 16) & 0xff;
|
||||
color->blue = (result >> 8) & 0xff;
|
||||
|
||||
color->alpha = result & 0xff;
|
||||
color->alpha = result & 0xff;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (strlen (str) == 7)
|
||||
{
|
||||
/* #rrggbb */
|
||||
color->red = (result >> 16) & 0xff;
|
||||
color->green = (result >> 8) & 0xff;
|
||||
color->blue = result & 0xff;
|
||||
return TRUE;
|
||||
}
|
||||
else if (strlen (str) == 5)
|
||||
{
|
||||
/* #rgba */
|
||||
color->red = ((result >> 12) & 0xf);
|
||||
color->green = ((result >> 8) & 0xf);
|
||||
color->blue = ((result >> 4) & 0xf);
|
||||
color->alpha = result & 0xf;
|
||||
|
||||
color->alpha = 0xff;
|
||||
color->red = (color->red << 4) | color->red;
|
||||
color->green = (color->green << 4) | color->green;
|
||||
color->blue = (color->blue << 4) | color->blue;
|
||||
color->alpha = (color->alpha << 4) | color->alpha;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX - should we return FALSE here? it's not like
|
||||
* Pango is endowed with mystical parsing powers and
|
||||
* will be able to do better than the code above.
|
||||
* still, it doesn't hurt
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Fall back to pango for named colors */
|
||||
|
@ -449,7 +449,10 @@ clutter_container_get_children (ClutterContainer *container)
|
||||
* @callback: a function to be called for each child
|
||||
* @user_data: data to be passed to the function, or %NULL
|
||||
*
|
||||
* Calls @callback for each child of @container.
|
||||
* Calls @callback for each child of @container that was added
|
||||
* by the application (with clutter_container_add_actor()). Does
|
||||
* not iterate over "internal" children that are part of the
|
||||
* container's own implementation, if any.
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
@ -473,6 +476,41 @@ clutter_container_foreach (ClutterContainer *container,
|
||||
iface->foreach (container, callback, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_container_foreach_with_internals:
|
||||
* @container: a #ClutterContainer
|
||||
* @callback: a function to be called for each child
|
||||
* @user_data: data to be passed to the function, or %NULL
|
||||
*
|
||||
* Calls @callback for each child of @container, including "internal"
|
||||
* children built in to the container itself that were never added
|
||||
* by the application.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_container_foreach_with_internals (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterContainerIface *iface;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
iface = CLUTTER_CONTAINER_GET_IFACE (container);
|
||||
if (!iface->foreach)
|
||||
{
|
||||
CLUTTER_CONTAINER_WARN_NOT_IMPLEMENTED (container, "foreach");
|
||||
return;
|
||||
}
|
||||
|
||||
if (iface->foreach_with_internals != NULL)
|
||||
iface->foreach_with_internals (container, callback, user_data);
|
||||
else
|
||||
iface->foreach (container, callback, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_container_raise_child:
|
||||
* @container: a #ClutterContainer
|
||||
|
@ -52,6 +52,11 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
|
||||
* implementation of this virtual function is required.
|
||||
* @foreach: virtual function for iterating over the container's children.
|
||||
* The implementation of this virtual function is required.
|
||||
* @foreach_with_internals: virtual functions for iterating over the
|
||||
* container's children, both added using the #ClutterContainer API
|
||||
* and internal children. The implementation of this virtual function
|
||||
* is required only if the #ClutterContainer implementation has
|
||||
* internal children.
|
||||
* @raise: virtual function for raising a child
|
||||
* @lower: virtual function for lowering a child
|
||||
* @sort_depth_order: virtual function for sorting the children of a
|
||||
@ -90,6 +95,10 @@ struct _ClutterContainerIface
|
||||
ClutterCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
void (* foreach_with_internals) (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/* child stacking */
|
||||
void (* raise) (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
@ -137,20 +146,22 @@ void clutter_container_remove_actor (ClutterContainer *container,
|
||||
void clutter_container_remove_valist (ClutterContainer *container,
|
||||
ClutterActor *first_actor,
|
||||
va_list var_args);
|
||||
GList * clutter_container_get_children (ClutterContainer *container);
|
||||
void clutter_container_foreach (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data);
|
||||
ClutterActor *clutter_container_find_child_by_name (ClutterContainer *container,
|
||||
const gchar *child_name);
|
||||
void clutter_container_raise_child (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling);
|
||||
void clutter_container_lower_child (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling);
|
||||
void clutter_container_sort_depth_order (ClutterContainer *container);
|
||||
|
||||
GList * clutter_container_get_children (ClutterContainer *container);
|
||||
void clutter_container_foreach (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data);
|
||||
void clutter_container_foreach_with_internals (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data);
|
||||
ClutterActor *clutter_container_find_child_by_name (ClutterContainer *container,
|
||||
const gchar *child_name);
|
||||
void clutter_container_raise_child (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling);
|
||||
void clutter_container_lower_child (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling);
|
||||
void clutter_container_sort_depth_order (ClutterContainer *container);
|
||||
|
||||
|
||||
GParamSpec * clutter_container_class_find_child_property (GObjectClass *klass,
|
||||
|
@ -148,4 +148,24 @@
|
||||
|
||||
#define clutter_shader_set_uniform_1f clutter_shader_set_uniform_1f_REPLACED_BY_clutter_shader_set_uniform
|
||||
|
||||
#define clutter_actor_set_xu clutter_actor_set_xu_DEPRECATED_BY_clutter_actor_set_x
|
||||
#define clutter_actor_set_yu clutter_actor_set_yu_DEPRECATED_BY_clutter_actor_set_y
|
||||
#define clutter_actor_set_widthu clutter_actor_set_widthu_DEPRECATED_BY_clutter_actor_set_width
|
||||
#define clutter_actor_set_heightu clutter_actor_set_heightu_DEPRECATED_BY_clutter_actor_set_height
|
||||
#define clutter_actor_set_depthu clutter_actor_set_depthu_DEPRECATED_BY_clutter_actor_set_depth
|
||||
#define clutter_actor_set_positionu clutter_actor_set_positionu_DEPRECATED_BY_clutter_actor_set_position
|
||||
#define clutter_actor_set_sizeu clutter_actor_set_sizeu_DEPRECATED_BY_clutter_actor_set_size
|
||||
|
||||
#define clutter_actor_set_anchor_pointu clutter_actor_set_anchor_pointu_DEPRECATED_BY_clutter_actor_set_anchor_point
|
||||
#define clutter_actor_get_anchor_pointu clutter_actor_get_anchor_pointu_DEPRECATED_BY_clutter_actor_get_anchor_point
|
||||
#define clutter_actor_move_byu clutter_actor_move_byu_DEPRECATED_BY_clutter_actor_move_by
|
||||
|
||||
#define clutter_actor_get_xu clutter_actor_get_xu_DEPRECATED_BY_clutter_actor_get_x
|
||||
#define clutter_actor_get_yu clutter_actor_get_yu_DEPRECATED_BY_clutter_actor_get_y
|
||||
#define clutter_actor_get_widthu clutter_actor_get_widthu_DEPRECATED_BY_clutter_actor_get_width
|
||||
#define clutter_actor_get_heightu clutter_actor_get_heightu_DEPRECATED_BY_clutter_actor_get_height
|
||||
#define clutter_actor_get_depthu clutter_actor_get_depthu_DEPRECATED_BY_clutter_actor_get_depth
|
||||
#define clutter_actor_get_positionu clutter_actor_get_positionu_DEPRECATED_BY_clutter_actor_get_position
|
||||
#define clutter_actor_get_sizeu clutter_actor_get_sizeu_DEPRECATED_BY_clutter_actor_get_size
|
||||
|
||||
#endif /* CLUTTER_DEPRECATED_H */
|
||||
|
@ -3,15 +3,19 @@
|
||||
/*** END file-header ***/
|
||||
|
||||
/*** BEGIN file-production ***/
|
||||
|
||||
/* enumerations from "@filename@" */
|
||||
#include "@filename@"
|
||||
|
||||
/*** END file-production ***/
|
||||
|
||||
/*** BEGIN value-header ***/
|
||||
GType
|
||||
@enum_name@_get_type(void) {
|
||||
static GType etype = 0;
|
||||
if (G_UNLIKELY (!etype))
|
||||
@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 ***/
|
||||
@ -23,8 +27,14 @@ GType
|
||||
/*** BEGIN value-tail ***/
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
|
||||
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 etype;
|
||||
|
||||
return g_enum_type_id__volatile;
|
||||
}
|
||||
/*** END value-tail ***/
|
||||
|
@ -120,10 +120,10 @@ clutter_event_get_state (ClutterEvent *event)
|
||||
*/
|
||||
void
|
||||
clutter_event_get_coords (ClutterEvent *event,
|
||||
gint *x,
|
||||
gint *y)
|
||||
gfloat *x,
|
||||
gfloat *y)
|
||||
{
|
||||
gint event_x, event_y;
|
||||
gfloat event_x, event_y;
|
||||
|
||||
g_return_if_fail (event != NULL);
|
||||
|
||||
@ -141,15 +141,18 @@ clutter_event_get_coords (ClutterEvent *event,
|
||||
case CLUTTER_ENTER:
|
||||
case CLUTTER_LEAVE:
|
||||
break;
|
||||
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
event_x = event->button.x;
|
||||
event_y = event->button.y;
|
||||
break;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
event_x = event->motion.x;
|
||||
event_y = event->motion.y;
|
||||
break;
|
||||
|
||||
case CLUTTER_SCROLL:
|
||||
event_x = event->scroll.x;
|
||||
event_y = event->scroll.y;
|
||||
|
@ -221,8 +221,8 @@ typedef struct _ClutterInputDevice ClutterInputDevice;
|
||||
*/
|
||||
struct _ClutterAnyEvent
|
||||
{
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
@ -290,8 +290,8 @@ struct _ClutterButtonEvent
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
ClutterModifierType modifier_state;
|
||||
guint32 button;
|
||||
guint click_count;
|
||||
@ -322,8 +322,8 @@ struct _ClutterCrossingEvent
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
ClutterInputDevice *device; /* future use */
|
||||
ClutterActor *related;
|
||||
};
|
||||
@ -352,8 +352,8 @@ struct _ClutterMotionEvent
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
ClutterModifierType modifier_state;
|
||||
gdouble *axes; /* Future use */
|
||||
ClutterInputDevice *device; /* Future use */
|
||||
@ -384,8 +384,8 @@ struct _ClutterScrollEvent
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
ClutterScrollDirection direction;
|
||||
ClutterModifierType modifier_state;
|
||||
gdouble *axes; /* future use */
|
||||
@ -451,8 +451,8 @@ ClutterEventType clutter_event_type (ClutterEvent *event);
|
||||
guint32 clutter_event_get_time (ClutterEvent *event);
|
||||
ClutterModifierType clutter_event_get_state (ClutterEvent *event);
|
||||
void clutter_event_get_coords (ClutterEvent *event,
|
||||
gint *x,
|
||||
gint *y);
|
||||
gfloat *x,
|
||||
gfloat *y);
|
||||
gint clutter_event_get_device_id (ClutterEvent *event);
|
||||
ClutterActor* clutter_event_get_source (ClutterEvent *event);
|
||||
|
||||
|
@ -96,8 +96,7 @@ clutter_group_paint (ClutterActor *actor)
|
||||
|
||||
g_assert (child != NULL);
|
||||
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
clutter_actor_paint (child);
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (PAINT, "ClutterGroup paint leave '%s'",
|
||||
@ -105,44 +104,36 @@ clutter_group_paint (ClutterActor *actor)
|
||||
: "unknown");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_realize (ClutterActor *actor)
|
||||
{
|
||||
clutter_container_foreach (CLUTTER_CONTAINER (actor),
|
||||
CLUTTER_CALLBACK (clutter_actor_realize),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_unrealize (ClutterActor *actor)
|
||||
{
|
||||
clutter_container_foreach (CLUTTER_CONTAINER (actor),
|
||||
CLUTTER_CALLBACK (clutter_actor_unrealize),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_pick (ClutterActor *actor,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
|
||||
GList *child_item;
|
||||
|
||||
/* Chain up so we get a bounding box pained (if we are reactive) */
|
||||
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, color);
|
||||
|
||||
/* Just forward to the paint call which in turn will trigger
|
||||
* the child actors also getting 'picked'.
|
||||
*/
|
||||
if (CLUTTER_ACTOR_IS_VISIBLE (actor))
|
||||
clutter_group_paint (actor);
|
||||
for (child_item = priv->children;
|
||||
child_item != NULL;
|
||||
child_item = child_item->next)
|
||||
{
|
||||
ClutterActor *child = child_item->data;
|
||||
|
||||
g_assert (child != NULL);
|
||||
|
||||
clutter_actor_paint (child);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_width (GList *children,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
clutter_fixed_layout_get_preferred_width (GList *children,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
GList *l;
|
||||
ClutterUnit min_left, min_right;
|
||||
ClutterUnit natural_left, natural_right;
|
||||
gfloat min_left, min_right;
|
||||
gfloat natural_left, natural_right;
|
||||
|
||||
min_left = 0;
|
||||
min_right = 0;
|
||||
@ -152,9 +143,9 @@ clutter_fixed_layout_get_preferred_width (GList *children,
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
ClutterUnit child_x, child_min, child_natural;
|
||||
gfloat child_x, child_min, child_natural;
|
||||
|
||||
child_x = clutter_actor_get_xu (child);
|
||||
child_x = clutter_actor_get_x (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
&child_min, NULL,
|
||||
@ -212,13 +203,13 @@ clutter_fixed_layout_get_preferred_width (GList *children,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_height (GList *children,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
clutter_fixed_layout_get_preferred_height (GList *children,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
GList *l;
|
||||
ClutterUnit min_top, min_bottom;
|
||||
ClutterUnit natural_top, natural_bottom;
|
||||
gfloat min_top, min_bottom;
|
||||
gfloat natural_top, natural_bottom;
|
||||
|
||||
min_top = 0;
|
||||
min_bottom = 0;
|
||||
@ -228,9 +219,9 @@ clutter_fixed_layout_get_preferred_height (GList *children,
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
ClutterUnit child_y, child_min, child_natural;
|
||||
gfloat child_y, child_min, child_natural;
|
||||
|
||||
child_y = clutter_actor_get_yu (child);
|
||||
child_y = clutter_actor_get_y (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
NULL, &child_min,
|
||||
@ -288,23 +279,23 @@ clutter_fixed_layout_get_preferred_height (GList *children,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_allocate (GList *children,
|
||||
gboolean absolute_origin_changed)
|
||||
clutter_fixed_layout_allocate (GList *children,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
clutter_actor_allocate_preferred_size (child, absolute_origin_changed);
|
||||
clutter_actor_allocate_preferred_size (child, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
@ -316,9 +307,9 @@ clutter_group_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_group_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
@ -329,22 +320,21 @@ clutter_group_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_group_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
/* chain up to set actor->allocation */
|
||||
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->allocate (self, box,
|
||||
origin_changed);
|
||||
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->allocate (self, box, flags);
|
||||
|
||||
/* Note that fixed-layout allocation of children does not care what
|
||||
* allocation the container received, so "box" is not passed in
|
||||
* here. We do not require that children's allocations are completely
|
||||
* contained by our own.
|
||||
*/
|
||||
clutter_fixed_layout_allocate (priv->children, origin_changed);
|
||||
clutter_fixed_layout_allocate (priv->children, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -587,8 +577,6 @@ clutter_group_class_init (ClutterGroupClass *klass)
|
||||
actor_class->pick = clutter_group_pick;
|
||||
actor_class->show_all = clutter_group_real_show_all;
|
||||
actor_class->hide_all = clutter_group_real_hide_all;
|
||||
actor_class->realize = clutter_group_realize;
|
||||
actor_class->unrealize = clutter_group_unrealize;
|
||||
|
||||
actor_class->get_preferred_width = clutter_group_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_group_get_preferred_height;
|
||||
|
@ -95,20 +95,7 @@ clutter_interval_real_validate (ClutterInterval *interval,
|
||||
GType pspec_gtype = G_PARAM_SPEC_VALUE_TYPE (pspec);
|
||||
|
||||
/* check the GTypes we provide first */
|
||||
if (pspec_gtype == CLUTTER_TYPE_UNIT)
|
||||
{
|
||||
ClutterParamSpecUnit *pspec_unit = CLUTTER_PARAM_SPEC_UNIT (pspec);
|
||||
ClutterUnit a, b;
|
||||
|
||||
a = b = 0;
|
||||
clutter_interval_get_interval (interval, &a, &b);
|
||||
if ((a >= pspec_unit->minimum && a <= pspec_unit->maximum) &&
|
||||
(b >= pspec_unit->minimum && b <= pspec_unit->maximum))
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
else if (pspec_gtype == COGL_TYPE_FIXED)
|
||||
if (pspec_gtype == COGL_TYPE_FIXED)
|
||||
{
|
||||
ClutterParamSpecFixed *pspec_fixed = CLUTTER_PARAM_SPEC_FIXED (pspec);
|
||||
CoglFixed a, b;
|
||||
@ -265,8 +252,16 @@ clutter_interval_real_compute_value (ClutterInterval *interval,
|
||||
{
|
||||
gdouble ia, ib, res;
|
||||
|
||||
ia = g_value_get_double (initial);
|
||||
ib = g_value_get_double (final);
|
||||
if (value_type == G_TYPE_DOUBLE)
|
||||
{
|
||||
ia = g_value_get_double (initial);
|
||||
ib = g_value_get_double (final);
|
||||
}
|
||||
else
|
||||
{
|
||||
ia = g_value_get_float (initial);
|
||||
ib = g_value_get_float (final);
|
||||
}
|
||||
|
||||
res = (factor * (ib - ia)) + ia;
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-actor.h"
|
||||
#include "clutter-stage.h"
|
||||
@ -118,7 +119,7 @@ clutter_get_show_fps (void)
|
||||
void
|
||||
_clutter_stage_maybe_relayout (ClutterActor *stage)
|
||||
{
|
||||
ClutterUnit natural_width, natural_height;
|
||||
gfloat natural_width, natural_height;
|
||||
ClutterActorBox box = { 0, };
|
||||
|
||||
/* avoid reentrancy */
|
||||
@ -139,10 +140,10 @@ _clutter_stage_maybe_relayout (ClutterActor *stage)
|
||||
box.y2 = natural_height;
|
||||
|
||||
CLUTTER_NOTE (ACTOR, "Allocating (0, 0 - %d, %d) for the stage",
|
||||
CLUTTER_UNITS_TO_DEVICE (natural_width),
|
||||
CLUTTER_UNITS_TO_DEVICE (natural_height));
|
||||
(int) natural_width,
|
||||
(int) natural_height);
|
||||
|
||||
clutter_actor_allocate (stage, &box, FALSE);
|
||||
clutter_actor_allocate (stage, &box, CLUTTER_ALLOCATION_NONE);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_IN_RELAYOUT);
|
||||
}
|
||||
@ -154,18 +155,20 @@ _clutter_stage_maybe_setup_viewport (ClutterStage *stage)
|
||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
||||
{
|
||||
ClutterPerspective perspective;
|
||||
guint width, height;
|
||||
gfloat width, height;
|
||||
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height);
|
||||
clutter_stage_get_perspective (stage, &perspective);
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Setting up the viewport");
|
||||
CLUTTER_NOTE (PAINT,
|
||||
"Setting up the viewport { w:%.2f, h:%.2f }",
|
||||
width, height);
|
||||
|
||||
cogl_setup_viewport (width, height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
_cogl_setup_viewport (width, height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
@ -181,14 +184,12 @@ void
|
||||
clutter_redraw (ClutterStage *stage)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
static GTimer *timer = NULL;
|
||||
static guint timer_n_frames = 0;
|
||||
ClutterMasterClock *master_clock;
|
||||
static GTimer *timer = NULL;
|
||||
static guint timer_n_frames = 0;
|
||||
|
||||
ctx = clutter_context_get_default ();
|
||||
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw start for stage:%p", stage);
|
||||
CLUTTER_NOTE (PAINT, " Redraw enter for stage:%p", stage);
|
||||
CLUTTER_NOTE (MULTISTAGE, "Redraw called for stage:%p", stage);
|
||||
master_clock = _clutter_master_clock_get_default ();
|
||||
|
||||
/* Before we can paint, we have to be sure we have the latest layout */
|
||||
_clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
|
||||
@ -209,10 +210,15 @@ clutter_redraw (ClutterStage *stage)
|
||||
|
||||
/* Call through to the actual backend to do the painting down from
|
||||
* the stage. It will likely need to swap buffers, vblank sync etc
|
||||
* which will be windowing system dependant.
|
||||
* which will be windowing system dependent
|
||||
*/
|
||||
_clutter_backend_redraw (ctx->backend, stage);
|
||||
|
||||
/* prepare for the next frame; if anything queues a redraw as the
|
||||
* result of a timeline, this will end up redrawing the scene
|
||||
*/
|
||||
_clutter_master_clock_advance (master_clock);
|
||||
|
||||
/* Complete FPS info */
|
||||
if (G_UNLIKELY (clutter_get_show_fps ()))
|
||||
{
|
||||
@ -226,7 +232,6 @@ clutter_redraw (ClutterStage *stage)
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (PAINT, " Redraw leave for stage:%p", stage);
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw finish for stage:%p", stage);
|
||||
}
|
||||
|
||||
@ -1053,6 +1058,8 @@ clutter_context_get_default (void)
|
||||
ctx->is_initialized = FALSE;
|
||||
ctx->motion_events_per_actor = TRUE;
|
||||
|
||||
ctx->master_clock = _clutter_master_clock_get_default ();
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
ctx->timer = g_timer_new ();
|
||||
g_timer_start (ctx->timer);
|
||||
@ -1932,8 +1939,8 @@ generate_enter_leave_events (ClutterEvent *event)
|
||||
{
|
||||
if (motion_current_actor)
|
||||
{
|
||||
gint x, y;
|
||||
ClutterEvent cev;
|
||||
gfloat x, y;
|
||||
|
||||
cev.crossing.device = device;
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
@ -2154,7 +2161,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
case CLUTTER_SCROLL:
|
||||
{
|
||||
ClutterActor *actor;
|
||||
gint x,y;
|
||||
gfloat x, y;
|
||||
|
||||
clutter_event_get_coords (event, &x, &y);
|
||||
|
||||
@ -2171,7 +2178,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
if (event->type == CLUTTER_BUTTON_RELEASE)
|
||||
{
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Release off stage received at %i, %i",
|
||||
"Release off stage received at %.2f, %.2f",
|
||||
x, y);
|
||||
|
||||
event->button.source = stage;
|
||||
@ -2197,12 +2204,14 @@ clutter_do_event (ClutterEvent *event)
|
||||
|
||||
|
||||
/* FIXME: for an optimisation should check if there are
|
||||
* actually any reactive actors and avoid the pick all togeather
|
||||
* actually any reactive actors and avoid the pick all together
|
||||
* (signalling just the stage). Should be big help for gles.
|
||||
*/
|
||||
|
||||
CLUTTER_NOTE (EVENT, "Reactive event received at %i, %i - actor: %p",
|
||||
x, y, actor);
|
||||
CLUTTER_NOTE (EVENT,
|
||||
"Reactive event received at %.2f, %.2f - actor: %p",
|
||||
x, y,
|
||||
actor);
|
||||
|
||||
/* Create, enter/leave events if needed */
|
||||
generate_enter_leave_events (event);
|
||||
@ -2809,3 +2818,162 @@ clutter_get_font_map (void)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
typedef struct _ClutterRepaintFunction
|
||||
{
|
||||
guint id;
|
||||
GSourceFunc func;
|
||||
gpointer data;
|
||||
GDestroyNotify notify;
|
||||
} ClutterRepaintFunction;
|
||||
|
||||
/**
|
||||
* clutter_threads_remove_repaint_func:
|
||||
* @handle_id: an unsigned integer greater than zero
|
||||
*
|
||||
* Removes the repaint function with @handle_id as its id
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_threads_remove_repaint_func (guint handle_id)
|
||||
{
|
||||
ClutterRepaintFunction *repaint_func;
|
||||
ClutterMainContext *context;
|
||||
GList *l;
|
||||
|
||||
g_return_if_fail (handle_id > 0);
|
||||
|
||||
context = CLUTTER_CONTEXT ();
|
||||
l = context->repaint_funcs;
|
||||
while (l != NULL)
|
||||
{
|
||||
repaint_func = l->data;
|
||||
|
||||
if (repaint_func->id == handle_id)
|
||||
{
|
||||
context->repaint_funcs =
|
||||
g_list_remove_link (context->repaint_funcs, l);
|
||||
|
||||
g_list_free (l);
|
||||
|
||||
if (repaint_func->notify)
|
||||
repaint_func->notify (repaint_func->data);
|
||||
|
||||
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_threads_add_repaint_func:
|
||||
* @func: the function to be called within the paint cycle
|
||||
* @data: data to be passed to the function, or %NULL
|
||||
* @notify: function to be called when removing the repaint
|
||||
* function, or %NULL
|
||||
*
|
||||
* Adds a function to be called whenever Clutter is repainting a Stage.
|
||||
* If the function returns %FALSE it is automatically removed from the
|
||||
* list of repaint functions and will not be called again.
|
||||
*
|
||||
* This function is guaranteed to be called from within the same thread
|
||||
* that called clutter_main(), and while the Clutter lock is being held.
|
||||
*
|
||||
* A repaint function is useful to ensure that an update of the scenegraph
|
||||
* is performed before the scenegraph is repainted; for instance, uploading
|
||||
* a frame from a video into a #ClutterTexture.
|
||||
*
|
||||
* When the repaint function is removed (either because it returned %FALSE
|
||||
* or because clutter_threads_remove_repaint_func() has been called) the
|
||||
* @notify function will be called, if any is set.
|
||||
*
|
||||
* Return value: the ID (greater than 0) of the repaint function. You
|
||||
* can use the returned integer to remove the repaint function by
|
||||
* calling clutter_threads_remove_repaint_func().
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
guint
|
||||
clutter_threads_add_repaint_func (GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify)
|
||||
{
|
||||
static guint repaint_id = 1;
|
||||
ClutterMainContext *context;
|
||||
ClutterRepaintFunction *repaint_func;
|
||||
|
||||
g_return_val_if_fail (func != NULL, 0);
|
||||
|
||||
context = CLUTTER_CONTEXT ();
|
||||
|
||||
/* XXX lock the context */
|
||||
|
||||
repaint_func = g_slice_new (ClutterRepaintFunction);
|
||||
|
||||
repaint_func->id = repaint_id++;
|
||||
repaint_func->func = func;
|
||||
repaint_func->data = data;
|
||||
repaint_func->notify = notify;
|
||||
|
||||
context->repaint_funcs = g_list_prepend (context->repaint_funcs,
|
||||
repaint_func);
|
||||
|
||||
/* XXX unlock the context */
|
||||
|
||||
return repaint_func->id;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_run_repaint_functions:
|
||||
*
|
||||
* Executes the repaint functions added using the
|
||||
* clutter_threads_add_repaint_func() function.
|
||||
*
|
||||
* Must be called before calling clutter_redraw() and
|
||||
* with the Clutter thread lock held.
|
||||
*/
|
||||
void
|
||||
_clutter_run_repaint_functions (void)
|
||||
{
|
||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||
ClutterRepaintFunction *repaint_func;
|
||||
GList *reinvoke_list, *l;
|
||||
|
||||
if (context->repaint_funcs == NULL)
|
||||
return;
|
||||
|
||||
reinvoke_list = NULL;
|
||||
|
||||
/* consume the whole list while we execute the functions */
|
||||
while (context->repaint_funcs)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
|
||||
repaint_func = context->repaint_funcs->data;
|
||||
|
||||
l = context->repaint_funcs;
|
||||
context->repaint_funcs =
|
||||
g_list_remove_link (context->repaint_funcs, context->repaint_funcs);
|
||||
|
||||
g_list_free (l);
|
||||
|
||||
res = repaint_func->func (repaint_func->data);
|
||||
|
||||
if (res)
|
||||
reinvoke_list = g_list_prepend (reinvoke_list, repaint_func);
|
||||
else
|
||||
{
|
||||
if (repaint_func->notify)
|
||||
repaint_func->notify (repaint_func->data);
|
||||
|
||||
g_slice_free (ClutterRepaintFunction, repaint_func);
|
||||
}
|
||||
}
|
||||
|
||||
if (reinvoke_list)
|
||||
context->repaint_funcs = reinvoke_list;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ GQuark clutter_init_error_quark (void);
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
#define CLUTTER_PRIORITY_REDRAW (G_PRIORITY_DEFAULT + 10)
|
||||
#define CLUTTER_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 20)
|
||||
|
||||
/**
|
||||
* CLUTTER_PRIORITY_TIMELINE:
|
||||
@ -109,34 +109,38 @@ gboolean clutter_get_show_fps (void);
|
||||
gulong clutter_get_timestamp (void);
|
||||
|
||||
/* Threading functions */
|
||||
void clutter_threads_init (void);
|
||||
void clutter_threads_enter (void);
|
||||
void clutter_threads_leave (void);
|
||||
void clutter_threads_set_lock_functions (GCallback enter_fn,
|
||||
GCallback leave_fn);
|
||||
guint clutter_threads_add_idle (GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_idle_full (gint priority,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint clutter_threads_add_timeout (guint interval,
|
||||
GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_timeout_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint clutter_threads_add_frame_source (guint fps,
|
||||
GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_frame_source_full
|
||||
(gint priority,
|
||||
guint fps,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void clutter_threads_init (void);
|
||||
void clutter_threads_enter (void);
|
||||
void clutter_threads_leave (void);
|
||||
void clutter_threads_set_lock_functions (GCallback enter_fn,
|
||||
GCallback leave_fn);
|
||||
guint clutter_threads_add_idle (GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_idle_full (gint priority,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint clutter_threads_add_timeout (guint interval,
|
||||
GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_timeout_full (gint priority,
|
||||
guint interval,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
guint clutter_threads_add_frame_source (guint fps,
|
||||
GSourceFunc func,
|
||||
gpointer data);
|
||||
guint clutter_threads_add_frame_source_full (gint priority,
|
||||
guint fps,
|
||||
GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
|
||||
guint clutter_threads_add_repaint_func (GSourceFunc func,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void clutter_threads_remove_repaint_func (guint handle_id);
|
||||
|
||||
void clutter_set_motion_events_enabled (gboolean enable);
|
||||
gboolean clutter_get_motion_events_enabled (void);
|
||||
@ -158,7 +162,7 @@ void clutter_clear_glyph_cache (void);
|
||||
void clutter_set_font_flags (ClutterFontFlags flags);
|
||||
ClutterFontFlags clutter_get_font_flags (void);
|
||||
|
||||
ClutterInputDevice* clutter_get_input_device_for_id (gint id);
|
||||
ClutterInputDevice *clutter_get_input_device_for_id (gint id);
|
||||
|
||||
void clutter_grab_pointer_for_device (ClutterActor *actor,
|
||||
gint id);
|
||||
|
@ -3,9 +3,11 @@ BOOLEAN:STRING,UINT,ENUM
|
||||
DOUBLE:VOID
|
||||
UINT:VOID
|
||||
VOID:BOXED
|
||||
VOID:BOXED,FLAGS
|
||||
VOID:INT
|
||||
VOID:INT64,INT64,FLOAT,BOOLEAN
|
||||
VOID:INT,INT
|
||||
VOID:FLOAT,FLOAT
|
||||
VOID:INT,INT,INT,INT
|
||||
VOID:OBJECT
|
||||
VOID:OBJECT,OBJECT,PARAM
|
||||
|
477
clutter/clutter-master-clock.c
Normal file
477
clutter/clutter-master-clock.c
Normal file
@ -0,0 +1,477 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* SECTION:clutter-master-clock
|
||||
* @short_description: The master clock for all animations
|
||||
*
|
||||
* The #ClutterMasterClock class is responsible for advancing all
|
||||
* #ClutterTimelines when a stage is being redrawn. The master clock
|
||||
* makes sure that the scenegraph is always integrally updated before
|
||||
* painting it.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define CLUTTER_MASTER_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClockClass))
|
||||
#define CLUTTER_IS_MASTER_CLOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_MASTER_CLOCK))
|
||||
#define CLUTTER_MASTER_CLASS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClockClass))
|
||||
|
||||
typedef struct _ClutterClockSource ClutterClockSource;
|
||||
typedef struct _ClutterMasterClockClass ClutterMasterClockClass;
|
||||
|
||||
struct _ClutterMasterClock
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
/* the list of timelines handled by the clock */
|
||||
GSList *timelines;
|
||||
|
||||
/* the previous state of the clock, used to compute
|
||||
* the delta
|
||||
*/
|
||||
GTimeVal prev_tick;
|
||||
gulong msecs_delta;
|
||||
|
||||
/* an idle source, used by the Master Clock to queue
|
||||
* a redraw on the stage and drive the animations
|
||||
*/
|
||||
GSource *source;
|
||||
|
||||
/* a guard, so that we dispatch the last redraw even
|
||||
* after the last timeline has been completed
|
||||
*/
|
||||
guint last_advance : 1;
|
||||
};
|
||||
|
||||
struct _ClutterMasterClockClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
struct _ClutterClockSource
|
||||
{
|
||||
GSource source;
|
||||
|
||||
ClutterMasterClock *master_clock;
|
||||
};
|
||||
|
||||
static void on_timeline_started (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock);
|
||||
static void on_timeline_completed (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock);
|
||||
static void on_timeline_paused (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock);
|
||||
|
||||
static gboolean clutter_clock_prepare (GSource *source,
|
||||
gint *timeout);
|
||||
static gboolean clutter_clock_check (GSource *source);
|
||||
static gboolean clutter_clock_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data);
|
||||
|
||||
static ClutterMasterClock *default_clock = NULL;
|
||||
|
||||
static GSourceFuncs clock_funcs = {
|
||||
clutter_clock_prepare,
|
||||
clutter_clock_check,
|
||||
clutter_clock_dispatch,
|
||||
NULL
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterMasterClock, clutter_master_clock, G_TYPE_OBJECT);
|
||||
|
||||
/*
|
||||
* has_running_timeline:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
* @filter: a #ClutterTimeline or %NULL
|
||||
*
|
||||
* Checks if @master_clock has any running timeline; if @filter
|
||||
* is not %NULL then the timeline will be filtered from the
|
||||
* list of timelines held by @master_clock
|
||||
*
|
||||
* Return value: %TRUE if the #ClutterMasterClock has at least
|
||||
* one running timeline
|
||||
*/
|
||||
static gboolean
|
||||
has_running_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *filter)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
if (master_clock->last_advance)
|
||||
return TRUE;
|
||||
|
||||
if (master_clock->timelines == NULL)
|
||||
return FALSE;
|
||||
|
||||
for (l = master_clock->timelines; l != NULL; l = l->next)
|
||||
{
|
||||
/* if we get a timeline then we should filter it
|
||||
* from the list of timelines we want to check
|
||||
*/
|
||||
if (filter != NULL && filter == l->data)
|
||||
continue;
|
||||
|
||||
if (clutter_timeline_is_playing (l->data))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* clutter_clock_source_new:
|
||||
* @master_clock: a #ClutterMasterClock for the source
|
||||
*
|
||||
* The #ClutterClockSource is an idle GSource that will queue a redraw
|
||||
* if @master_clock has at least a running #ClutterTimeline. The redraw
|
||||
* will cause @master_clock to advance all timelines, thus advancing all
|
||||
* animations as well.
|
||||
*
|
||||
* Return value: the newly created #GSource
|
||||
*/
|
||||
static GSource *
|
||||
clutter_clock_source_new (ClutterMasterClock *master_clock)
|
||||
{
|
||||
GSource *source = g_source_new (&clock_funcs, sizeof (ClutterClockSource));
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
|
||||
clock_source->master_clock = master_clock;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_prepare (GSource *source,
|
||||
gint *timeout)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClock *master_clock = clock_source->master_clock;
|
||||
gboolean retval;
|
||||
|
||||
/* just like an idle source, we are ready if nothing else is */
|
||||
*timeout = -1;
|
||||
|
||||
retval = has_running_timeline (master_clock, NULL);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_check (GSource *source)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClock *master_clock = clock_source->master_clock;
|
||||
gboolean retval;
|
||||
|
||||
retval = has_running_timeline (master_clock, NULL);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_clock_dispatch (GSource *source,
|
||||
GSourceFunc callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterClockSource *clock_source = (ClutterClockSource *) source;
|
||||
ClutterMasterClock *master_clock = clock_source->master_clock;
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
const GSList *stages, *l;
|
||||
|
||||
CLUTTER_NOTE (SCHEDULER, "Master clock [tick]");
|
||||
|
||||
stages = clutter_stage_manager_peek_stages (stage_manager);
|
||||
|
||||
/* queue a redraw for each stage; this will advance each timeline
|
||||
* held by the master clock of the amount of milliseconds elapsed
|
||||
* since the last redraw
|
||||
*/
|
||||
for (l = stages; l != NULL; l = l->next)
|
||||
clutter_actor_queue_redraw (l->data);
|
||||
|
||||
/* if this is the remainder of an advancement, needed for the last
|
||||
* timeline to finish its run, then we need to reset the prev_tick
|
||||
*/
|
||||
if (master_clock->last_advance)
|
||||
{
|
||||
master_clock->prev_tick.tv_sec = 0;
|
||||
master_clock->last_advance = FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
timeline_weak_ref (gpointer data,
|
||||
GObject *object_pointer)
|
||||
{
|
||||
ClutterMasterClock *master_clock = data;
|
||||
|
||||
master_clock->timelines =
|
||||
g_slist_remove (master_clock->timelines, object_pointer);
|
||||
|
||||
if (master_clock->timelines == NULL)
|
||||
master_clock->prev_tick.tv_sec = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_finalize (GObject *gobject)
|
||||
{
|
||||
ClutterMasterClock *master_clock = CLUTTER_MASTER_CLOCK (gobject);
|
||||
GSList *l;
|
||||
|
||||
for (l = master_clock->timelines; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterTimeline *timeline = l->data;
|
||||
|
||||
g_object_weak_unref (G_OBJECT (timeline),
|
||||
timeline_weak_ref,
|
||||
master_clock);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_started),
|
||||
master_clock);
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
master_clock);
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_paused),
|
||||
master_clock);
|
||||
}
|
||||
|
||||
g_slist_free (master_clock->timelines);
|
||||
|
||||
G_OBJECT_CLASS (clutter_master_clock_parent_class)->finalize (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_class_init (ClutterMasterClockClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize = clutter_master_clock_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_master_clock_init (ClutterMasterClock *self)
|
||||
{
|
||||
GSource *source;
|
||||
|
||||
source = clutter_clock_source_new (self);
|
||||
self->source = source;
|
||||
|
||||
g_source_set_priority (source, CLUTTER_PRIORITY_REDRAW);
|
||||
g_source_set_can_recurse (source, FALSE);
|
||||
g_source_attach (source, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_get_default:
|
||||
*
|
||||
* Retrieves the default master clock. If this function has never
|
||||
* been called before, the default master clock is created.
|
||||
*
|
||||
* Return value: the default master clock. The returned object is
|
||||
* owned by Clutter and should not be modified or freed
|
||||
*/
|
||||
ClutterMasterClock *
|
||||
_clutter_master_clock_get_default (void)
|
||||
{
|
||||
if (G_LIKELY (default_clock != NULL))
|
||||
return default_clock;
|
||||
|
||||
default_clock = g_object_new (CLUTTER_TYPE_MASTER_CLOCK, NULL);
|
||||
|
||||
return default_clock;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timeline_started (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock)
|
||||
{
|
||||
/* we want to reset the prev_tick if this is the first
|
||||
* timeline; since timeline is playing we need to filter
|
||||
* it out, otherwise has_running_timeline() will return
|
||||
* TRUE and prev_tick will not be unset
|
||||
*/
|
||||
if (!has_running_timeline (master_clock, timeline))
|
||||
master_clock->prev_tick.tv_sec = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timeline_completed (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock)
|
||||
{
|
||||
/* if this is the last timeline we need to turn :last-advance
|
||||
* on in order to queue the redraw of the scene for the last
|
||||
* frame; otherwise the ClockSource will fail the prepare and
|
||||
* check phases and the last frame will not be painted
|
||||
*/
|
||||
if (!has_running_timeline (master_clock, NULL))
|
||||
master_clock->last_advance = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_timeline_paused (ClutterTimeline *timeline,
|
||||
ClutterMasterClock *master_clock)
|
||||
{
|
||||
/* see the comment in on_timeline_completed */
|
||||
if (!has_running_timeline (master_clock, NULL))
|
||||
master_clock->last_advance = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_add_timeline:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
* @timeline: a #ClutterTimeline
|
||||
*
|
||||
* Adds @timeline to the list of timelines held by the master
|
||||
* clock. This function should be called during the instance
|
||||
* creation phase of the timeline.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
gboolean is_first = FALSE;
|
||||
|
||||
if (g_slist_find (master_clock->timelines, timeline))
|
||||
return;
|
||||
|
||||
is_first = (master_clock->timelines == NULL) ? TRUE : FALSE;
|
||||
|
||||
master_clock->timelines = g_slist_prepend (master_clock->timelines,
|
||||
timeline);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (timeline),
|
||||
timeline_weak_ref,
|
||||
master_clock);
|
||||
|
||||
g_signal_connect (timeline, "started",
|
||||
G_CALLBACK (on_timeline_started),
|
||||
master_clock);
|
||||
g_signal_connect (timeline, "completed",
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
master_clock);
|
||||
g_signal_connect (timeline, "paused",
|
||||
G_CALLBACK (on_timeline_paused),
|
||||
master_clock);
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_remove_timeline:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
* @timeline: a #ClutterTimeline
|
||||
*
|
||||
* Removes @timeline from the list of timelines held by the
|
||||
* master clock. This function should be called during the
|
||||
* #ClutterTimeline finalization.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline)
|
||||
{
|
||||
if (!g_slist_find (master_clock->timelines, timeline))
|
||||
return;
|
||||
|
||||
master_clock->timelines = g_slist_remove (master_clock->timelines,
|
||||
timeline);
|
||||
|
||||
g_object_weak_unref (G_OBJECT (timeline),
|
||||
timeline_weak_ref,
|
||||
master_clock);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_started),
|
||||
master_clock);
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_completed),
|
||||
master_clock);
|
||||
g_signal_handlers_disconnect_by_func (timeline,
|
||||
G_CALLBACK (on_timeline_paused),
|
||||
master_clock);
|
||||
|
||||
/* last timeline: unset the prev_tick so that we can start
|
||||
* from scratch when we add a new timeline
|
||||
*/
|
||||
if (master_clock->timelines == NULL)
|
||||
master_clock->prev_tick.tv_sec = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* _clutter_master_clock_advance:
|
||||
* @master_clock: a #ClutterMasterClock
|
||||
*
|
||||
* Advances all the timelines held by the master clock. This function
|
||||
* should be called before calling clutter_redraw() to make sure that
|
||||
* all the timelines are advanced and the scene is updated.
|
||||
*/
|
||||
void
|
||||
_clutter_master_clock_advance (ClutterMasterClock *master_clock)
|
||||
{
|
||||
GTimeVal cur_tick = { 0, };
|
||||
gulong msecs;
|
||||
GSList *l;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_MASTER_CLOCK (master_clock));
|
||||
|
||||
if (master_clock->timelines == NULL)
|
||||
return;
|
||||
|
||||
g_get_current_time (&cur_tick);
|
||||
|
||||
if (master_clock->prev_tick.tv_sec == 0)
|
||||
master_clock->prev_tick = cur_tick;
|
||||
|
||||
msecs = (cur_tick.tv_sec - master_clock->prev_tick.tv_sec) * 1000
|
||||
+ (cur_tick.tv_usec - master_clock->prev_tick.tv_usec) / 1000;
|
||||
|
||||
if (msecs == 0)
|
||||
return;
|
||||
|
||||
CLUTTER_NOTE (SCHEDULER, "Advancing %d timelines by %lu milliseconds",
|
||||
g_slist_length (master_clock->timelines),
|
||||
msecs);
|
||||
|
||||
for (l = master_clock->timelines; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterTimeline *timeline = l->data;
|
||||
|
||||
if (clutter_timeline_is_playing (timeline))
|
||||
clutter_timeline_advance_delta (timeline, msecs);
|
||||
}
|
||||
|
||||
/* store the previous state so that we can use
|
||||
* it for the next advancement
|
||||
*/
|
||||
master_clock->msecs_delta = msecs;
|
||||
master_clock->prev_tick = cur_tick;
|
||||
}
|
48
clutter/clutter-master-clock.h
Normal file
48
clutter/clutter-master-clock.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By: Emmanuele Bassi <ebassi@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 __CLUTTER_MASTER_CLOCK_H__
|
||||
#define __CLUTTER_MASTER_CLOCK_H__
|
||||
|
||||
#include <clutter/clutter-timeline.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_MASTER_CLOCK (clutter_master_clock_get_type ())
|
||||
#define CLUTTER_MASTER_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_MASTER_CLOCK, ClutterMasterClock))
|
||||
#define CLUTTER_IS_MASTER_CLOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_MASTER_CLOCK))
|
||||
|
||||
typedef struct _ClutterMasterClock ClutterMasterClock;
|
||||
|
||||
GType clutter_master_clock_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterMasterClock *_clutter_master_clock_get_default (void);
|
||||
void _clutter_master_clock_add_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void _clutter_master_clock_remove_timeline (ClutterMasterClock *master_clock,
|
||||
ClutterTimeline *timeline);
|
||||
void _clutter_master_clock_advance (ClutterMasterClock *master_clock);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_MASTER_CLOCK_H__ */
|
@ -44,9 +44,11 @@
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-id-pool.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-stage-window.h"
|
||||
#include "clutter-stage.h"
|
||||
#include "clutter-timeline.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -65,12 +67,6 @@ typedef enum {
|
||||
CLUTTER_TEXTURE_IN_CLONE_PAINT = 1 << 6 /* Used for safety in clones */
|
||||
} ClutterPrivateFlags;
|
||||
|
||||
typedef enum {
|
||||
CLUTTER_PICK_NONE = 0,
|
||||
CLUTTER_PICK_REACTIVE,
|
||||
CLUTTER_PICK_ALL
|
||||
} ClutterPickMode;
|
||||
|
||||
struct _ClutterInputDevice
|
||||
{
|
||||
gint id;
|
||||
@ -133,6 +129,11 @@ struct _ClutterMainContext
|
||||
MultiTouch */
|
||||
|
||||
guint32 last_event_time;
|
||||
|
||||
ClutterMasterClock *master_clock;
|
||||
gulong redraw_count;
|
||||
|
||||
GList *repaint_funcs;
|
||||
};
|
||||
|
||||
#define CLUTTER_CONTEXT() (clutter_context_get_default ())
|
||||
@ -185,6 +186,9 @@ ClutterActor *_clutter_backend_create_stage (ClutterBackend *backend,
|
||||
GError **error);
|
||||
void _clutter_backend_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
gboolean _clutter_backend_create_context (ClutterBackend *backend,
|
||||
gboolean is_offscreen,
|
||||
GError **error);
|
||||
|
||||
void _clutter_backend_add_options (ClutterBackend *backend,
|
||||
GOptionGroup *group);
|
||||
@ -196,21 +200,21 @@ void _clutter_backend_init_events (ClutterBackend *backend);
|
||||
|
||||
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
|
||||
|
||||
ClutterUnit _clutter_backend_get_units_per_em (ClutterBackend *backend);
|
||||
gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend,
|
||||
PangoFontDescription *font_desc);
|
||||
|
||||
void _clutter_feature_init (void);
|
||||
|
||||
/* Picking code */
|
||||
ClutterActor *_clutter_do_pick (ClutterStage *stage,
|
||||
gint x,
|
||||
gint y,
|
||||
ClutterPickMode mode);
|
||||
ClutterActor *_clutter_do_pick (ClutterStage *stage,
|
||||
gint x,
|
||||
gint y,
|
||||
ClutterPickMode mode);
|
||||
|
||||
guint _clutter_pixel_to_id (guchar pixel[4]);
|
||||
|
||||
void _clutter_id_to_color (guint id, ClutterColor *col);
|
||||
|
||||
|
||||
/* use this function as the accumulator if you have a signal with
|
||||
* a G_TYPE_BOOLEAN return value; this will stop the emission as
|
||||
* soon as one handler returns TRUE
|
||||
@ -223,12 +227,21 @@ gboolean _clutter_boolean_handled_accumulator (GSignalInvocationHint *ihint,
|
||||
void _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor);
|
||||
|
||||
void _clutter_actor_rerealize (ClutterActor *self,
|
||||
ClutterCallback callback,
|
||||
void *data);
|
||||
|
||||
void _clutter_actor_set_opacity_parent (ClutterActor *self,
|
||||
ClutterActor *parent);
|
||||
|
||||
void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
|
||||
gboolean enable);
|
||||
|
||||
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
|
||||
gboolean enable);
|
||||
|
||||
void _clutter_run_repaint_functions (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _HAVE_CLUTTER_PRIVATE_H */
|
||||
|
@ -451,16 +451,22 @@ clutter_shader_glsl_bind (ClutterShader *self,
|
||||
cogl_shader_compile (shader);
|
||||
if (!cogl_shader_is_compiled (shader))
|
||||
{
|
||||
gchar error_buf[512];
|
||||
gchar *log_buf;
|
||||
|
||||
cogl_shader_get_info_log (shader, 512, error_buf);
|
||||
log_buf = cogl_shader_get_info_log (shader);
|
||||
|
||||
/* translators: the first %s is the type of the shader, either
|
||||
* Vertex shader or Fragment shader; the second %s is the actual
|
||||
* error as reported by COGL
|
||||
*/
|
||||
g_set_error (error, CLUTTER_SHADER_ERROR,
|
||||
CLUTTER_SHADER_ERROR_COMPILE,
|
||||
_("%s compilation failed: %s"),
|
||||
shader_type == CLUTTER_VERTEX_SHADER ? _("Vertex shader")
|
||||
: _("Fragment shader"),
|
||||
error_buf);
|
||||
log_buf);
|
||||
|
||||
g_free (log_buf);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -224,8 +224,9 @@ clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager)
|
||||
*
|
||||
* Lists all currently used stages.
|
||||
*
|
||||
* Return value: (transfer container) (element-type ClutterStage): a newly allocated list
|
||||
* of #ClutterStage objects. Use g_slist_free() to deallocate it when done.
|
||||
* Return value: (transfer container) (element-type ClutterStage): a newly
|
||||
* allocated list of #ClutterStage objects. Use g_slist_free() to
|
||||
* deallocate it when done.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
@ -235,6 +236,25 @@ clutter_stage_manager_list_stages (ClutterStageManager *stage_manager)
|
||||
return g_slist_copy (stage_manager->stages);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_manager_list_stage:
|
||||
* @stage_manager: a #ClutterStageManager
|
||||
*
|
||||
* Lists all currently used stages.
|
||||
*
|
||||
* Return value: (transfer none) (element-type ClutterStage): a pointer
|
||||
* to the internal list of #ClutterStage objects. The returned list
|
||||
* is owned by the #ClutterStageManager and should never be modified
|
||||
* or freed
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
const GSList *
|
||||
clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager)
|
||||
{
|
||||
return stage_manager->stages;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage)
|
||||
|
@ -61,6 +61,7 @@ void clutter_stage_manager_set_default_stage (ClutterStageManage
|
||||
ClutterStage *stage);
|
||||
ClutterStage * clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager);
|
||||
GSList * clutter_stage_manager_list_stages (ClutterStageManager *stage_manager);
|
||||
const GSList * clutter_stage_manager_peek_stages (ClutterStageManager *stage_manager);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -27,6 +27,10 @@ struct _ClutterStageWindowIface
|
||||
gboolean cursor_visible);
|
||||
void (* set_user_resizable) (ClutterStageWindow *stage_window,
|
||||
gboolean is_resizable);
|
||||
|
||||
void (* show) (ClutterStageWindow *stage_window,
|
||||
gboolean do_raise);
|
||||
void (* hide) (ClutterStageWindow *stage_window);
|
||||
};
|
||||
|
||||
GType clutter_stage_window_get_type (void) G_GNUC_CONST;
|
||||
|
@ -59,6 +59,7 @@
|
||||
#include "clutter-color.h"
|
||||
#include "clutter-util.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-master-clock.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
@ -86,7 +87,7 @@ struct _ClutterStagePrivate
|
||||
gchar *title;
|
||||
ClutterActor *key_focused_actor;
|
||||
|
||||
guint update_idle; /* repaint idler id */
|
||||
guint update_idle; /* repaint idler id */
|
||||
|
||||
guint is_fullscreen : 1;
|
||||
guint is_offscreen : 1;
|
||||
@ -126,9 +127,9 @@ static const ClutterColor default_stage_color = { 255, 255, 255, 255 };
|
||||
|
||||
static void
|
||||
clutter_stage_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
@ -142,9 +143,9 @@ clutter_stage_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_stage_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
@ -156,11 +157,14 @@ clutter_stage_get_preferred_height (ClutterActor *self,
|
||||
natural_height_p);
|
||||
}
|
||||
static void
|
||||
clutter_stage_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_stage_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
gboolean origin_changed;
|
||||
|
||||
origin_changed = (flags & CLUTTER_ABSOLUTE_ORIGIN_CHANGED) ? TRUE : FALSE;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
|
||||
@ -168,30 +172,31 @@ clutter_stage_allocate (ClutterActor *self,
|
||||
* then we simply ignore any allocation request and override the
|
||||
* allocation chain.
|
||||
*/
|
||||
if (G_LIKELY (!clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)))
|
||||
if ((!clutter_feature_available (CLUTTER_FEATURE_STAGE_STATIC)))
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
|
||||
CLUTTER_NOTE (ACTOR, "Following allocation to %dx%d (origin %s)",
|
||||
CLUTTER_UNITS_TO_DEVICE (box->x2 - box->x1),
|
||||
CLUTTER_UNITS_TO_DEVICE (box->y2 - box->y1),
|
||||
CLUTTER_NOTE (LAYOUT,
|
||||
"Following allocation to %dx%d (origin %s)",
|
||||
(int) (box->x2 - box->x1),
|
||||
(int) (box->y2 - box->y1),
|
||||
origin_changed ? "changed" : "not changed");
|
||||
|
||||
klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
||||
klass->allocate (self, box, origin_changed);
|
||||
klass->allocate (self, box, flags);
|
||||
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->impl);
|
||||
klass->allocate (priv->impl, box, origin_changed);
|
||||
klass->allocate (priv->impl, box, flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
ClutterActorBox override = { 0, };
|
||||
ClutterActorClass *klass;
|
||||
ClutterUnit natural_width, natural_height;
|
||||
gfloat natural_width, natural_height;
|
||||
|
||||
/* propagate the allocation */
|
||||
klass = CLUTTER_ACTOR_GET_CLASS (priv->impl);
|
||||
klass->allocate (self, box, origin_changed);
|
||||
klass->allocate (self, box, flags);
|
||||
|
||||
/* get the preferred size from the backend */
|
||||
clutter_actor_get_preferred_size (priv->impl,
|
||||
@ -203,9 +208,18 @@ clutter_stage_allocate (ClutterActor *self,
|
||||
override.x2 = natural_width;
|
||||
override.y2 = natural_height;
|
||||
|
||||
CLUTTER_NOTE (LAYOUT,
|
||||
"Overrigin original allocation of %dx%d "
|
||||
"with %dx%d (origin %s)",
|
||||
(int) (box->x2 - box->x1),
|
||||
(int) (box->y2 - box->y1),
|
||||
(int) (override.x2),
|
||||
(int) (override.y2),
|
||||
origin_changed ? "changed" : "not changed");
|
||||
|
||||
/* and store the overridden allocation */
|
||||
klass = CLUTTER_ACTOR_CLASS (clutter_stage_parent_class);
|
||||
klass->allocate (self, &override, origin_changed);
|
||||
klass->allocate (self, &override, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,7 +271,7 @@ clutter_stage_pick (ClutterActor *self,
|
||||
* Chain up to the groups paint howerer so our children get picked
|
||||
* - clutter_group_pick
|
||||
*/
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->paint (self);
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->pick (self, color);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -265,21 +279,23 @@ clutter_stage_realize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* Make sure the viewport and projection matrix are valid for the
|
||||
first paint (which will likely occur before the ConfigureNotify
|
||||
is received) */
|
||||
* first paint (which will likely occur before the ConfigureNotify
|
||||
* is received)
|
||||
*/
|
||||
CLUTTER_SET_PRIVATE_FLAGS (self, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->realize (priv->impl);
|
||||
clutter_actor_realize (priv->impl);
|
||||
|
||||
/* ensure that the stage is using the context if the
|
||||
* realization sequence was successful
|
||||
*/
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
{
|
||||
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
}
|
||||
else
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
}
|
||||
@ -289,12 +305,9 @@ clutter_stage_unrealize (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
/* unset the flag */
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
/* and then unrealize the implementation */
|
||||
g_assert (priv->impl != NULL);
|
||||
CLUTTER_ACTOR_GET_CLASS (priv->impl)->unrealize (priv->impl);
|
||||
clutter_actor_unrealize (priv->impl);
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE (self));
|
||||
}
|
||||
@ -303,33 +316,60 @@ static void
|
||||
clutter_stage_show (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (priv->impl))
|
||||
clutter_actor_realize (priv->impl);
|
||||
|
||||
clutter_actor_show (priv->impl);
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->show (self);
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->show (impl, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_hide (ClutterActor *self)
|
||||
{
|
||||
ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
g_assert (priv->impl != NULL);
|
||||
clutter_actor_hide (priv->impl);
|
||||
impl = CLUTTER_STAGE_WINDOW (priv->impl);
|
||||
CLUTTER_STAGE_WINDOW_GET_IFACE (impl)->hide (impl);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_parent_class)->hide (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_emit_key_focus_event (ClutterStage *stage,
|
||||
gboolean focus_in)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
|
||||
if (priv->key_focused_actor == NULL)
|
||||
return;
|
||||
|
||||
if (focus_in)
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
|
||||
else
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_real_activate (ClutterStage *stage)
|
||||
{
|
||||
clutter_stage_emit_key_focus_event (stage, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_real_deactivate (ClutterStage *stage)
|
||||
{
|
||||
clutter_stage_emit_key_focus_event (stage, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_real_fullscreen (ClutterStage *stage)
|
||||
{
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterUnit natural_width, natural_height;
|
||||
gfloat natural_width, natural_height;
|
||||
ClutterActorBox box;
|
||||
|
||||
/* we need to force an allocation here because the size
|
||||
@ -348,7 +388,9 @@ clutter_stage_real_fullscreen (ClutterStage *stage)
|
||||
box.x2 = natural_width;
|
||||
box.y2 = natural_height;
|
||||
|
||||
clutter_actor_allocate (CLUTTER_ACTOR (stage), &box, FALSE);
|
||||
clutter_actor_allocate (CLUTTER_ACTOR (stage),
|
||||
&box,
|
||||
CLUTTER_ALLOCATION_NONE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -356,23 +398,48 @@ redraw_update_idle (gpointer user_data)
|
||||
{
|
||||
ClutterStage *stage = user_data;
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterMasterClock *master_clock;
|
||||
|
||||
/* clutter_redraw() will also call maybe_relayout(), but since a relayout can
|
||||
* queue a redraw, we want to do the relayout before we clear the update_idle
|
||||
* to avoid painting the stage twice. Calling maybe_relayout() twice in a row
|
||||
* is cheap because of caching of requested and allocated size.
|
||||
/* before we redraw we advance the master clock of one tick; this means
|
||||
* that all the timelines that need advancing will be advanced by one
|
||||
* frame. this will cause multiple redraw requests, so we do this before
|
||||
* we ask for a relayout and before we do the actual redraw. this ensures
|
||||
* that we paint the most updated scenegraph state and that all animations
|
||||
* are in sync with the paint process.
|
||||
*/
|
||||
CLUTTER_NOTE (PAINT, "Avdancing master clock");
|
||||
master_clock = _clutter_master_clock_get_default ();
|
||||
_clutter_master_clock_advance (master_clock);
|
||||
|
||||
/* run the (eventual) repaint functions; since those might end up queuing
|
||||
* a relayout or a redraw we need to execute them before maybe_relayout()
|
||||
*/
|
||||
CLUTTER_NOTE (PAINT, "Repaint functions");
|
||||
_clutter_run_repaint_functions ();
|
||||
|
||||
/* clutter_redraw() will also call maybe_relayout(), but since a relayout
|
||||
* can queue a redraw, we want to do the relayout before we clear the
|
||||
* update_idle to avoid painting the stage twice. Calling maybe_relayout()
|
||||
* twice in a row is cheap because of caching of requested and allocated
|
||||
* size.
|
||||
*/
|
||||
_clutter_stage_maybe_relayout (CLUTTER_ACTOR (stage));
|
||||
|
||||
if (priv->update_idle)
|
||||
{
|
||||
g_source_remove (priv->update_idle);
|
||||
priv->update_idle = 0;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "redrawing via idle for stage:%p", stage);
|
||||
/* redrawing will advance the master clock */
|
||||
CLUTTER_NOTE (PAINT, "redrawing via idle for stage[%p]", stage);
|
||||
clutter_redraw (stage);
|
||||
|
||||
/* reset the guard, so that new redraws are possible */
|
||||
priv->update_idle = 0;
|
||||
|
||||
if (CLUTTER_CONTEXT ()->redraw_count > 0)
|
||||
{
|
||||
CLUTTER_NOTE (SCHEDULER, "Queued %lu redraws during the last cycle",
|
||||
CLUTTER_CONTEXT ()->redraw_count);
|
||||
|
||||
CLUTTER_CONTEXT ()->redraw_count = 0;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -383,17 +450,28 @@ clutter_stage_real_queue_redraw (ClutterActor *actor,
|
||||
ClutterStage *stage = CLUTTER_STAGE (actor);
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
|
||||
CLUTTER_NOTE (PAINT, "Redraw request number %lu",
|
||||
CLUTTER_CONTEXT ()->redraw_count + 1);
|
||||
|
||||
if (priv->update_idle == 0)
|
||||
{
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for stage: %p", stage);
|
||||
CLUTTER_NOTE (PAINT, "Adding idle source for stage: %p", stage);
|
||||
|
||||
/* FIXME: weak_ref self in case we dissapear before paint? */
|
||||
priv->update_idle =
|
||||
clutter_threads_add_idle_full (CLUTTER_PRIORITY_REDRAW,
|
||||
redraw_update_idle,
|
||||
stage,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
CLUTTER_CONTEXT ()->redraw_count += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
set_offscreen_while_unrealized (ClutterActor *actor,
|
||||
void *data)
|
||||
{
|
||||
CLUTTER_STAGE (actor)->priv->is_offscreen = GPOINTER_TO_INT (data);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -417,24 +495,26 @@ clutter_stage_set_property (GObject *object,
|
||||
break;
|
||||
|
||||
case PROP_OFFSCREEN:
|
||||
if (priv->is_offscreen == g_value_get_boolean (value))
|
||||
return;
|
||||
{
|
||||
gboolean was_showing;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
{
|
||||
/* Backend needs to check this prop and handle accordingly
|
||||
* in realise.
|
||||
* FIXME: More 'obvious' implementation needed?
|
||||
*/
|
||||
clutter_actor_unrealize (actor);
|
||||
priv->is_offscreen = g_value_get_boolean (value);
|
||||
clutter_actor_realize (actor);
|
||||
if (priv->is_offscreen == g_value_get_boolean (value))
|
||||
return;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
priv->is_offscreen = ~g_value_get_boolean (value);
|
||||
}
|
||||
else
|
||||
priv->is_offscreen = g_value_get_boolean (value);
|
||||
was_showing = CLUTTER_ACTOR_IS_VISIBLE (actor);
|
||||
|
||||
/* Backend needs to check this prop and handle accordingly
|
||||
* in realise.
|
||||
* FIXME: More 'obvious' implementation needed?
|
||||
*/
|
||||
_clutter_actor_rerealize (actor,
|
||||
set_offscreen_while_unrealized,
|
||||
GINT_TO_POINTER (g_value_get_boolean (value)));
|
||||
|
||||
if (was_showing &&
|
||||
!CLUTTER_ACTOR_IS_REALIZED (actor))
|
||||
priv->is_offscreen = ~g_value_get_boolean (value);
|
||||
}
|
||||
break;
|
||||
|
||||
case PROP_FULLSCREEN:
|
||||
@ -536,7 +616,7 @@ clutter_stage_dispose (GObject *object)
|
||||
ClutterStagePrivate *priv = stage->priv;
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (object));
|
||||
clutter_actor_hide (CLUTTER_ACTOR (object));
|
||||
|
||||
if (priv->update_idle)
|
||||
{
|
||||
@ -548,8 +628,9 @@ clutter_stage_dispose (GObject *object)
|
||||
|
||||
if (priv->impl)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "Disposing of the stage implementation");
|
||||
g_object_unref (priv->impl);
|
||||
CLUTTER_NOTE (BACKEND, "Disposing of the stage implementation");
|
||||
clutter_actor_hide (priv->impl);
|
||||
clutter_actor_destroy (priv->impl);
|
||||
priv->impl = NULL;
|
||||
}
|
||||
|
||||
@ -783,6 +864,8 @@ clutter_stage_class_init (ClutterStageClass *klass)
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
klass->fullscreen = clutter_stage_real_fullscreen;
|
||||
klass->activate = clutter_stage_real_activate;
|
||||
klass->deactivate = clutter_stage_real_deactivate;
|
||||
|
||||
g_type_class_add_private (gobject_class, sizeof (ClutterStagePrivate));
|
||||
}
|
||||
@ -813,6 +896,9 @@ clutter_stage_init (ClutterStage *self)
|
||||
else
|
||||
g_object_ref_sink (priv->impl);
|
||||
|
||||
/* make sure that the implementation is considered a top level */
|
||||
CLUTTER_SET_PRIVATE_FLAGS (priv->impl, CLUTTER_ACTOR_IS_TOPLEVEL);
|
||||
|
||||
priv->is_offscreen = FALSE;
|
||||
priv->is_fullscreen = FALSE;
|
||||
priv->is_user_resizable = FALSE;
|
||||
@ -1244,20 +1330,26 @@ clutter_stage_read_pixels (ClutterStage *stage,
|
||||
/**
|
||||
* clutter_stage_get_actor_at_pos:
|
||||
* @stage: a #ClutterStage
|
||||
* @pick_mode: how the scene graph should be painted
|
||||
* @x: X coordinate to check
|
||||
* @y: Y coordinate to check
|
||||
*
|
||||
* Checks the scene at the coordinates @x and @y and returns a pointer
|
||||
* to the #ClutterActor at those coordinates.
|
||||
*
|
||||
* Return value: (transfer none): the actor at the specified coordinates, if any
|
||||
* By using @pick_mode it is possible to control which actors will be
|
||||
* painted and thus available.
|
||||
*
|
||||
* Return value: (transfer none): the actor at the specified coordinates,
|
||||
* if any
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_stage_get_actor_at_pos (ClutterStage *stage,
|
||||
gint x,
|
||||
gint y)
|
||||
clutter_stage_get_actor_at_pos (ClutterStage *stage,
|
||||
ClutterPickMode pick_mode,
|
||||
gint x,
|
||||
gint y)
|
||||
{
|
||||
return _clutter_do_pick (stage, x, y, CLUTTER_PICK_ALL);
|
||||
return _clutter_do_pick (stage, x, y, pick_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1428,12 +1520,12 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
g_object_weak_unref (G_OBJECT (priv->key_focused_actor),
|
||||
on_key_focused_weak_notify,
|
||||
stage);
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "focus-out");
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-out");
|
||||
|
||||
priv->key_focused_actor = NULL;
|
||||
}
|
||||
else
|
||||
g_signal_emit_by_name (stage, "focus-out");
|
||||
g_signal_emit_by_name (stage, "key-focus-out");
|
||||
|
||||
if (actor)
|
||||
{
|
||||
@ -1442,10 +1534,10 @@ clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
g_object_weak_ref (G_OBJECT (actor),
|
||||
on_key_focused_weak_notify,
|
||||
stage);
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "focus-in");
|
||||
g_signal_emit_by_name (priv->key_focused_actor, "key-focus-in");
|
||||
}
|
||||
else
|
||||
g_signal_emit_by_name (stage, "focus-in");
|
||||
g_signal_emit_by_name (stage, "key-focus-in");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -79,6 +79,22 @@ G_BEGIN_DECLS
|
||||
#define CLUTTER_STAGE_HEIGHT() \
|
||||
(clutter_actor_get_height (clutter_stage_get_default ()))
|
||||
|
||||
/**
|
||||
* ClutterPickMode:
|
||||
* @CLUTTER_PICK_NONE: Do not paint any actor
|
||||
* @CLUTTER_PICK_REACTIVE: Paint only the reactive actors
|
||||
* @CLUTTER_PICK_ALL: Paint all actors
|
||||
*
|
||||
* Controls the paint cycle of the scene graph when in pick mode
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum {
|
||||
CLUTTER_PICK_NONE = 0,
|
||||
CLUTTER_PICK_REACTIVE,
|
||||
CLUTTER_PICK_ALL
|
||||
} ClutterPickMode;
|
||||
|
||||
typedef struct _ClutterPerspective ClutterPerspective;
|
||||
typedef struct _ClutterFog ClutterFog;
|
||||
|
||||
@ -192,6 +208,7 @@ void clutter_stage_show_cursor (ClutterStage *stage);
|
||||
void clutter_stage_hide_cursor (ClutterStage *stage);
|
||||
|
||||
ClutterActor *clutter_stage_get_actor_at_pos (ClutterStage *stage,
|
||||
ClutterPickMode pick_mode,
|
||||
gint x,
|
||||
gint y);
|
||||
guchar * clutter_stage_read_pixels (ClutterStage *stage,
|
||||
|
@ -87,10 +87,10 @@ struct _LayoutCache
|
||||
PangoLayout *layout;
|
||||
|
||||
/* The width that was used to generate this layout */
|
||||
ClutterUnit width;
|
||||
gfloat width;
|
||||
|
||||
/* The height that was used to generate this layout */
|
||||
ClutterUnit height;
|
||||
gfloat height;
|
||||
|
||||
/* A number representing the age of this cache (so that when a
|
||||
* new layout is needed the last used cache is replaced)
|
||||
@ -240,8 +240,8 @@ clutter_text_clear_selection (ClutterText *self)
|
||||
|
||||
static PangoLayout *
|
||||
clutter_text_create_layout_no_cache (ClutterText *text,
|
||||
ClutterUnit allocation_width,
|
||||
ClutterUnit allocation_height)
|
||||
gfloat allocation_width,
|
||||
gfloat allocation_height)
|
||||
{
|
||||
ClutterTextPrivate *priv = text->priv;
|
||||
PangoLayout *layout;
|
||||
@ -322,7 +322,7 @@ clutter_text_create_layout_no_cache (ClutterText *text,
|
||||
gint width;
|
||||
|
||||
width = allocation_width > 0
|
||||
? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_width)
|
||||
? (allocation_width * 1024)
|
||||
: -1;
|
||||
|
||||
pango_layout_set_width (layout, width);
|
||||
@ -345,7 +345,7 @@ clutter_text_create_layout_no_cache (ClutterText *text,
|
||||
gint height;
|
||||
|
||||
height = allocation_height > 0
|
||||
? CLUTTER_UNITS_TO_PANGO_UNIT (allocation_height)
|
||||
? (allocation_height * 1024)
|
||||
: -1;
|
||||
|
||||
pango_layout_set_height (layout, height);
|
||||
@ -390,8 +390,8 @@ clutter_text_font_changed_cb (ClutterText *text)
|
||||
*/
|
||||
static PangoLayout *
|
||||
clutter_text_create_layout (ClutterText *text,
|
||||
ClutterUnit allocation_width,
|
||||
ClutterUnit allocation_height)
|
||||
gfloat allocation_width,
|
||||
gfloat allocation_height)
|
||||
{
|
||||
ClutterTextPrivate *priv = text->priv;
|
||||
LayoutCache *oldest_cache = priv->cached_layouts;
|
||||
@ -456,16 +456,17 @@ clutter_text_create_layout (ClutterText *text,
|
||||
|
||||
static gint
|
||||
clutter_text_coords_to_position (ClutterText *text,
|
||||
gint x,
|
||||
gint y)
|
||||
gfloat x,
|
||||
gfloat y)
|
||||
{
|
||||
ClutterTextPrivate *priv = text->priv;
|
||||
gint index_;
|
||||
gint px, py;
|
||||
gint trailing;
|
||||
|
||||
/* Take any offset due to scrolling into account */
|
||||
if (text->priv->single_line_mode)
|
||||
x += text->priv->text_x * -1;
|
||||
if (priv->single_line_mode)
|
||||
x += priv->text_x * -1;
|
||||
|
||||
px = x * PANGO_SCALE;
|
||||
py = y * PANGO_SCALE;
|
||||
@ -494,9 +495,9 @@ clutter_text_coords_to_position (ClutterText *text,
|
||||
gboolean
|
||||
clutter_text_position_to_coords (ClutterText *self,
|
||||
gint position,
|
||||
ClutterUnit *x,
|
||||
ClutterUnit *y,
|
||||
ClutterUnit *line_height)
|
||||
gfloat *x,
|
||||
gfloat *y,
|
||||
gfloat *line_height)
|
||||
{
|
||||
ClutterTextPrivate *priv;
|
||||
PangoRectangle rect;
|
||||
@ -537,7 +538,7 @@ clutter_text_position_to_coords (ClutterText *self,
|
||||
|
||||
if (x)
|
||||
{
|
||||
*x = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.x);
|
||||
*x = (gfloat) rect.x / 1024.0f;
|
||||
|
||||
/* Take any offset due to scrolling into account */
|
||||
if (priv->single_line_mode)
|
||||
@ -545,10 +546,10 @@ clutter_text_position_to_coords (ClutterText *self,
|
||||
}
|
||||
|
||||
if (y)
|
||||
*y = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.y);
|
||||
*y = (gfloat) rect.y / 1024.0f;
|
||||
|
||||
if (line_height)
|
||||
*line_height = CLUTTER_UNITS_FROM_PANGO_UNIT (rect.height);
|
||||
*line_height = (gfloat) rect.height / 1024.0f;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -557,7 +558,7 @@ static inline void
|
||||
clutter_text_ensure_cursor_position (ClutterText *self)
|
||||
{
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
ClutterUnit x, y, cursor_height;
|
||||
gfloat x, y, cursor_height;
|
||||
ClutterGeometry cursor_pos = { 0, };
|
||||
gboolean x_changed, y_changed;
|
||||
gboolean width_changed, height_changed;
|
||||
@ -961,7 +962,7 @@ cursor_paint (ClutterText *self)
|
||||
gint i;
|
||||
gint index_;
|
||||
gint maxindex;
|
||||
ClutterUnit y, height;
|
||||
gfloat y, height;
|
||||
|
||||
line = pango_layout_get_line_readonly (layout, line_no);
|
||||
pango_layout_line_x_to_index (line, G_MAXINT, &maxindex, NULL);
|
||||
@ -982,22 +983,20 @@ cursor_paint (ClutterText *self)
|
||||
gint range_x;
|
||||
gint range_width;
|
||||
|
||||
range_x = ranges[i * 2]
|
||||
/ PANGO_SCALE;
|
||||
range_x = ranges[i * 2] / PANGO_SCALE;
|
||||
|
||||
/* Account for any scrolling in single line mode */
|
||||
if (priv->single_line_mode)
|
||||
range_x += priv->text_x;
|
||||
range_x += priv->text_x;
|
||||
|
||||
|
||||
range_width = (ranges[i * 2 + 1] - ranges[i * 2])
|
||||
/ PANGO_SCALE;
|
||||
|
||||
cogl_rectangle (range_x,
|
||||
CLUTTER_UNITS_TO_DEVICE (y),
|
||||
y,
|
||||
range_x + range_width,
|
||||
CLUTTER_UNITS_TO_DEVICE (y)
|
||||
+ CLUTTER_UNITS_TO_DEVICE (height));
|
||||
y + height);
|
||||
}
|
||||
|
||||
g_free (ranges);
|
||||
@ -1164,7 +1163,7 @@ clutter_text_button_press (ClutterActor *actor,
|
||||
ClutterText *self = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
gboolean res = FALSE;
|
||||
ClutterUnit x, y;
|
||||
gfloat x, y;
|
||||
gint index_;
|
||||
|
||||
/* we'll steal keyfocus if we do not have it */
|
||||
@ -1182,18 +1181,15 @@ clutter_text_button_press (ClutterActor *actor,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
x = CLUTTER_UNITS_FROM_INT (event->x);
|
||||
y = CLUTTER_UNITS_FROM_INT (event->y);
|
||||
|
||||
res = clutter_actor_transform_stage_point (actor, x, y, &x, &y);
|
||||
res = clutter_actor_transform_stage_point (actor,
|
||||
event->x,
|
||||
event->y,
|
||||
&x, &y);
|
||||
if (res)
|
||||
{
|
||||
gint offset;
|
||||
|
||||
index_ = clutter_text_coords_to_position (self,
|
||||
CLUTTER_UNITS_TO_INT (x),
|
||||
CLUTTER_UNITS_TO_INT (y));
|
||||
|
||||
index_ = clutter_text_coords_to_position (self, x, y);
|
||||
offset = bytes_to_offset (priv->text, index_);
|
||||
|
||||
/* what we select depends on the number of button clicks we
|
||||
@ -1229,32 +1225,30 @@ static gboolean
|
||||
clutter_text_motion (ClutterActor *actor,
|
||||
ClutterMotionEvent *mev)
|
||||
{
|
||||
ClutterText *ttext = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = ttext->priv;
|
||||
ClutterUnit x, y;
|
||||
gint index_;
|
||||
const gchar *text;
|
||||
ClutterText *self = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
gfloat x, y;
|
||||
gint index_, offset;
|
||||
gboolean res;
|
||||
|
||||
if (!priv->in_select_drag)
|
||||
return FALSE;
|
||||
|
||||
text = clutter_text_get_text (ttext);
|
||||
res = clutter_actor_transform_stage_point (actor,
|
||||
mev->x, mev->y,
|
||||
&x, &y);
|
||||
if (!res)
|
||||
return FALSE;
|
||||
|
||||
x = CLUTTER_UNITS_FROM_INT (mev->x);
|
||||
y = CLUTTER_UNITS_FROM_INT (mev->y);
|
||||
|
||||
clutter_actor_transform_stage_point (actor, x, y, &x, &y);
|
||||
|
||||
index_ = clutter_text_coords_to_position (ttext,
|
||||
CLUTTER_UNITS_TO_INT (x),
|
||||
CLUTTER_UNITS_TO_INT (y));
|
||||
index_ = clutter_text_coords_to_position (self, x, y);
|
||||
offset = bytes_to_offset (priv->text, index_);
|
||||
|
||||
if (priv->selectable)
|
||||
clutter_text_set_cursor_position (ttext, bytes_to_offset (text, index_));
|
||||
clutter_text_set_cursor_position (self, offset);
|
||||
else
|
||||
{
|
||||
clutter_text_set_cursor_position (ttext, bytes_to_offset (text, index_));
|
||||
clutter_text_set_selection_bound (ttext, bytes_to_offset (text, index_));
|
||||
clutter_text_set_cursor_position (self, offset);
|
||||
clutter_text_set_selection_bound (self, offset);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@ -1264,8 +1258,8 @@ static gboolean
|
||||
clutter_text_button_release (ClutterActor *actor,
|
||||
ClutterButtonEvent *bev)
|
||||
{
|
||||
ClutterText *ttext = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = ttext->priv;
|
||||
ClutterText *self = CLUTTER_TEXT (actor);
|
||||
ClutterTextPrivate *priv = self->priv;
|
||||
|
||||
if (priv->in_select_drag)
|
||||
{
|
||||
@ -1380,11 +1374,11 @@ clutter_text_paint (ClutterActor *self)
|
||||
pango_layout_get_extents (layout, NULL, &logical_rect);
|
||||
|
||||
cogl_clip_push (0, 0,
|
||||
CLUTTER_UNITS_TO_FLOAT (alloc.x2 - alloc.x1),
|
||||
CLUTTER_UNITS_TO_FLOAT (alloc.y2 - alloc.y1));
|
||||
(alloc.x2 - alloc.x1),
|
||||
(alloc.y2 - alloc.y1));
|
||||
clip_set = TRUE;
|
||||
|
||||
actor_width = (CLUTTER_UNITS_TO_DEVICE (alloc.x2 - alloc.x1))
|
||||
actor_width = (alloc.x2 - alloc.x1)
|
||||
- 2 * TEXT_PADDING;
|
||||
text_width = logical_rect.width / PANGO_SCALE;
|
||||
|
||||
@ -1449,16 +1443,16 @@ clutter_text_paint (ClutterActor *self)
|
||||
|
||||
static void
|
||||
clutter_text_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (self);
|
||||
ClutterTextPrivate *priv = text->priv;
|
||||
PangoRectangle logical_rect = { 0, };
|
||||
PangoLayout *layout;
|
||||
gint logical_width;
|
||||
ClutterUnit layout_width;
|
||||
gfloat layout_width;
|
||||
|
||||
layout = clutter_text_create_layout (text, -1, -1);
|
||||
|
||||
@ -1471,7 +1465,7 @@ clutter_text_get_preferred_width (ClutterActor *self,
|
||||
logical_width = logical_rect.x + logical_rect.width;
|
||||
|
||||
layout_width = logical_width > 0
|
||||
? CLUTTER_UNITS_FROM_PANGO_UNIT (logical_width)
|
||||
? (logical_width / 1024.0f)
|
||||
: 1;
|
||||
|
||||
if (min_width_p)
|
||||
@ -1493,9 +1487,9 @@ clutter_text_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_text_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterTextPrivate *priv = CLUTTER_TEXT (self)->priv;
|
||||
|
||||
@ -1512,7 +1506,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
PangoLayout *layout;
|
||||
PangoRectangle logical_rect = { 0, };
|
||||
gint logical_height;
|
||||
ClutterUnit layout_height;
|
||||
gfloat layout_height;
|
||||
|
||||
layout = clutter_text_create_layout (CLUTTER_TEXT (self),
|
||||
for_width, -1);
|
||||
@ -1524,7 +1518,7 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
* the height accordingly
|
||||
*/
|
||||
logical_height = logical_rect.y + logical_rect.height;
|
||||
layout_height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_height);
|
||||
layout_height = (gfloat) logical_height / 1024.0f;
|
||||
|
||||
if (min_height_p)
|
||||
{
|
||||
@ -1534,13 +1528,13 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
if (priv->ellipsize && priv->wrap)
|
||||
{
|
||||
PangoLayoutLine *line;
|
||||
ClutterUnit line_height;
|
||||
gfloat line_height;
|
||||
|
||||
line = pango_layout_get_line_readonly (layout, 0);
|
||||
pango_layout_line_get_extents (line, NULL, &logical_rect);
|
||||
|
||||
logical_height = logical_rect.y + logical_rect.height;
|
||||
line_height = CLUTTER_UNITS_FROM_PANGO_UNIT (logical_height);
|
||||
line_height = (gfloat) logical_height / 1024.0f;
|
||||
|
||||
*min_height_p = line_height;
|
||||
}
|
||||
@ -1554,9 +1548,9 @@ clutter_text_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_text_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_text_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterText *text = CLUTTER_TEXT (self);
|
||||
ClutterActorClass *parent_class;
|
||||
@ -1569,7 +1563,7 @@ clutter_text_allocate (ClutterActor *self,
|
||||
box->y2 - box->y1);
|
||||
|
||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_text_parent_class);
|
||||
parent_class->allocate (self, box, origin_changed);
|
||||
parent_class->allocate (self, box, flags);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -3362,11 +3356,11 @@ clutter_text_set_markup (ClutterText *self,
|
||||
PangoLayout *
|
||||
clutter_text_get_layout (ClutterText *self)
|
||||
{
|
||||
ClutterUnit width, height;
|
||||
gfloat width, height;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXT (self), NULL);
|
||||
|
||||
clutter_actor_get_sizeu (CLUTTER_ACTOR (self), &width, &height);
|
||||
clutter_actor_get_size (CLUTTER_ACTOR (self), &width, &height);
|
||||
|
||||
return clutter_text_create_layout (self, width, height);
|
||||
}
|
||||
|
@ -77,10 +77,8 @@ typedef struct _ClutterTextureAsyncData ClutterTextureAsyncData;
|
||||
|
||||
struct _ClutterTexturePrivate
|
||||
{
|
||||
gint width;
|
||||
gint height;
|
||||
gint max_tile_waste;
|
||||
ClutterTextureQuality filter_quality;
|
||||
gfloat width;
|
||||
gfloat height;
|
||||
CoglHandle material;
|
||||
gboolean no_slice;
|
||||
|
||||
@ -136,7 +134,7 @@ enum
|
||||
PROP_0,
|
||||
PROP_NO_SLICE,
|
||||
PROP_MAX_TILE_WASTE,
|
||||
PROP_PIXEL_FORMAT, /* Texture format */
|
||||
PROP_PIXEL_FORMAT,
|
||||
PROP_SYNC_SIZE,
|
||||
PROP_REPEAT_Y,
|
||||
PROP_REPEAT_X,
|
||||
@ -177,36 +175,35 @@ clutter_texture_error_quark (void)
|
||||
return g_quark_from_static_string ("clutter-texture-error-quark");
|
||||
}
|
||||
|
||||
static const struct
|
||||
{
|
||||
gint min_filter;
|
||||
gint mag_filter;
|
||||
}
|
||||
clutter_texture_quality_filters[] =
|
||||
{
|
||||
/* CLUTTER_TEXTURE_QUALITY_LOW */
|
||||
{ COGL_MATERIAL_FILTER_NEAREST, COGL_MATERIAL_FILTER_NEAREST },
|
||||
|
||||
/* CLUTTER_TEXTURE_QUALITY_MEDIUM */
|
||||
{ COGL_MATERIAL_FILTER_LINEAR, COGL_MATERIAL_FILTER_LINEAR },
|
||||
|
||||
/* CLUTTER_TEXTURE_QUALITY_HIGH */
|
||||
{ COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR, COGL_MATERIAL_FILTER_LINEAR }
|
||||
};
|
||||
|
||||
static inline void
|
||||
clutter_texture_quality_to_filters (ClutterTextureQuality quality,
|
||||
gint *min_filter_p,
|
||||
gint *mag_filter_p)
|
||||
{
|
||||
gint min_filter, mag_filter;
|
||||
|
||||
switch (quality)
|
||||
{
|
||||
case CLUTTER_TEXTURE_QUALITY_LOW:
|
||||
min_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
mag_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
break;
|
||||
|
||||
case CLUTTER_TEXTURE_QUALITY_MEDIUM:
|
||||
min_filter = COGL_TEXTURE_FILTER_LINEAR;
|
||||
mag_filter = COGL_TEXTURE_FILTER_LINEAR;
|
||||
break;
|
||||
|
||||
case CLUTTER_TEXTURE_QUALITY_HIGH:
|
||||
min_filter = COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR;
|
||||
mag_filter = COGL_TEXTURE_FILTER_LINEAR;
|
||||
break;
|
||||
}
|
||||
g_return_if_fail (quality < G_N_ELEMENTS (clutter_texture_quality_filters));
|
||||
|
||||
if (min_filter_p)
|
||||
*min_filter_p = min_filter;
|
||||
*min_filter_p = clutter_texture_quality_filters[quality].min_filter;
|
||||
|
||||
if (mag_filter_p)
|
||||
*mag_filter_p = mag_filter;
|
||||
*mag_filter_p = clutter_texture_quality_filters[quality].mag_filter;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -217,7 +214,10 @@ texture_free_gl_resources (ClutterTexture *texture)
|
||||
CLUTTER_MARK();
|
||||
|
||||
if (priv->material != COGL_INVALID_HANDLE)
|
||||
cogl_material_remove_layer (priv->material, 0);
|
||||
/* We want to keep the layer so that the filter settings will
|
||||
remain but we want to free its resources so we clear the
|
||||
texture handle */
|
||||
cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -286,31 +286,20 @@ clutter_texture_realize (ClutterActor *actor)
|
||||
if (priv->fbo_source)
|
||||
{
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE;
|
||||
gint min_filter, mag_filter;
|
||||
gint max_waste = -1;
|
||||
CoglHandle tex;
|
||||
|
||||
/* Handle FBO's */
|
||||
|
||||
if (!priv->no_slice)
|
||||
max_waste = priv->max_tile_waste;
|
||||
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
if (priv->no_slice)
|
||||
flags |= COGL_TEXTURE_NO_SLICING;
|
||||
|
||||
tex = cogl_texture_new_with_size (priv->width,
|
||||
priv->height,
|
||||
max_waste, flags,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888);
|
||||
|
||||
cogl_material_set_layer (priv->material, 0, tex);
|
||||
|
||||
clutter_texture_quality_to_filters (priv->filter_quality,
|
||||
&min_filter,
|
||||
&mag_filter);
|
||||
|
||||
cogl_texture_set_filters (tex, min_filter, mag_filter);
|
||||
|
||||
priv->fbo_handle = cogl_offscreen_new_to_texture (tex);
|
||||
|
||||
/* The material now has a reference to the texture so it will
|
||||
@ -337,19 +326,15 @@ clutter_texture_realize (ClutterActor *actor)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_READ_PIXELS))
|
||||
{
|
||||
/* Dont allow realization with no data - note set_data
|
||||
* will set realize flags.
|
||||
*/
|
||||
CLUTTER_NOTE (TEXTURE,
|
||||
"Texture has no image data cannot realize");
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
CLUTTER_NOTE (TEXTURE, "flags %i", actor->flags);
|
||||
return;
|
||||
}
|
||||
/* If we have no data, then realization is a no-op but
|
||||
* we still want to be in REALIZED state to maintain
|
||||
* invariants. We may have already created the texture
|
||||
* if someone set some data earlier, or we may create it
|
||||
* later if someone sets some data later. The fact that
|
||||
* we may have created it earlier is really a bug, since
|
||||
* it means ClutterTexture can have GL resources without
|
||||
* being realized.
|
||||
*/
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "Texture realized");
|
||||
@ -357,9 +342,9 @@ clutter_texture_realize (ClutterActor *actor)
|
||||
|
||||
static void
|
||||
clutter_texture_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
||||
ClutterTexturePrivate *priv = texture->priv;
|
||||
@ -376,19 +361,14 @@ clutter_texture_get_preferred_width (ClutterActor *self,
|
||||
for_height < 0 ||
|
||||
priv->height <= 0)
|
||||
{
|
||||
*natural_width_p = CLUTTER_UNITS_FROM_DEVICE (priv->width);
|
||||
*natural_width_p = priv->width;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the natural width so as to preserve the aspect ratio */
|
||||
gfloat ratio, height;
|
||||
gfloat ratio = priv->width / priv->height;
|
||||
|
||||
ratio = (float)(priv->width) / (float)(priv->height);
|
||||
|
||||
height = CLUTTER_UNITS_TO_FLOAT (for_height);
|
||||
|
||||
*natural_width_p =
|
||||
CLUTTER_UNITS_FROM_FLOAT (ratio * height);
|
||||
*natural_width_p = ratio * for_height;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,9 +381,9 @@ clutter_texture_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_texture_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
||||
ClutterTexturePrivate *priv = texture->priv;
|
||||
@ -420,19 +400,14 @@ clutter_texture_get_preferred_height (ClutterActor *self,
|
||||
for_width < 0 ||
|
||||
priv->width <= 0)
|
||||
{
|
||||
*natural_height_p = CLUTTER_UNITS_FROM_DEVICE (priv->height);
|
||||
*natural_height_p = priv->height;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the natural height so as to preserve the aspect ratio */
|
||||
gfloat ratio, width;
|
||||
gfloat ratio = priv->height / priv->width;
|
||||
|
||||
ratio = (float)(priv->height) / (float)(priv->width);
|
||||
|
||||
width = CLUTTER_UNITS_TO_FLOAT (for_width);
|
||||
|
||||
*natural_height_p =
|
||||
CLUTTER_UNITS_FROM_FLOAT (ratio * width);
|
||||
*natural_height_p = ratio * for_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -444,20 +419,21 @@ clutter_texture_get_preferred_height (ClutterActor *self,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_texture_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_texture_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterTexturePrivate *priv = CLUTTER_TEXTURE (self)->priv;
|
||||
|
||||
/* chain up to set actor->allocation */
|
||||
CLUTTER_ACTOR_CLASS (clutter_texture_parent_class)->allocate (self, box,
|
||||
origin_changed);
|
||||
CLUTTER_ACTOR_CLASS (clutter_texture_parent_class)->allocate (self,
|
||||
box,
|
||||
flags);
|
||||
|
||||
/* If we adopted the source fbo then allocate that at its preferred
|
||||
size */
|
||||
if (priv->fbo_source && clutter_actor_get_parent (priv->fbo_source) == self)
|
||||
clutter_actor_allocate_preferred_size (priv->fbo_source, origin_changed);
|
||||
clutter_actor_allocate_preferred_size (priv->fbo_source, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -466,7 +442,7 @@ clutter_texture_set_fbo_projection (ClutterActor *self)
|
||||
ClutterTexturePrivate *priv = CLUTTER_TEXTURE (self)->priv;
|
||||
ClutterVertex verts[4];
|
||||
gfloat viewport[4];
|
||||
ClutterUnit x_min, x_max, y_min, y_max;
|
||||
gfloat x_min, x_max, y_min, y_max;
|
||||
gfloat tx_min, tx_max, ty_min, ty_max;
|
||||
gfloat tan_angle, near_size;
|
||||
ClutterPerspective perspective;
|
||||
@ -501,13 +477,13 @@ clutter_texture_set_fbo_projection (ClutterActor *self)
|
||||
/* Convert the coordinates back to [-1,1] range */
|
||||
cogl_get_viewport (viewport);
|
||||
|
||||
tx_min = (CLUTTER_UNITS_TO_FLOAT (x_min) / viewport[2])
|
||||
tx_min = (x_min / viewport[2])
|
||||
* 2 - 1.0;
|
||||
tx_max = (CLUTTER_UNITS_TO_FLOAT (x_max) / viewport[2])
|
||||
tx_max = (x_max / viewport[2])
|
||||
* 2 - 1.0;
|
||||
ty_min = (CLUTTER_UNITS_TO_FLOAT (y_min) / viewport[3])
|
||||
ty_min = (y_min / viewport[3])
|
||||
* 2 - 1.0;
|
||||
ty_max = (CLUTTER_UNITS_TO_FLOAT (y_max) / viewport[3])
|
||||
ty_max = (y_max / viewport[3])
|
||||
* 2 - 1.0;
|
||||
|
||||
/* Set up a projection matrix so that the actor will be projected as
|
||||
@ -528,7 +504,7 @@ clutter_texture_paint (ClutterActor *self)
|
||||
{
|
||||
ClutterTexture *texture = CLUTTER_TEXTURE (self);
|
||||
ClutterTexturePrivate *priv = texture->priv;
|
||||
gint x_1, y_1, x_2, y_2;
|
||||
ClutterActorBox box = { 0, };
|
||||
CoglColor transparent_col;
|
||||
gfloat t_w, t_h;
|
||||
guint8 paint_opacity = clutter_actor_get_paint_opacity (self);
|
||||
@ -541,9 +517,6 @@ clutter_texture_paint (ClutterActor *self)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR(texture)))
|
||||
clutter_actor_realize (CLUTTER_ACTOR(texture));
|
||||
|
||||
if (priv->fbo_handle != COGL_INVALID_HANDLE)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
@ -567,19 +540,20 @@ clutter_texture_paint (ClutterActor *self)
|
||||
|
||||
if ((stage = clutter_actor_get_stage (self)))
|
||||
{
|
||||
guint stage_width, stage_height;
|
||||
ClutterActor *source_parent;
|
||||
gfloat stage_width, stage_height;
|
||||
ClutterActor *source_parent;
|
||||
|
||||
clutter_stage_get_perspective (CLUTTER_STAGE (stage), &perspective);
|
||||
clutter_actor_get_size (stage, &stage_width, &stage_height);
|
||||
|
||||
/* Use below to set the modelview matrix as if the viewport
|
||||
was still the same size as the stage */
|
||||
cogl_setup_viewport (stage_width, stage_height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
_cogl_setup_viewport (stage_width, stage_height,
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
|
||||
/* Use a projection matrix that makes the actor appear as it
|
||||
would if it was rendered at its normal screen location */
|
||||
clutter_texture_set_fbo_projection (self);
|
||||
@ -636,28 +610,28 @@ clutter_texture_paint (ClutterActor *self)
|
||||
|
||||
cogl_material_set_color4ub (priv->material, 0xff, 0xff, 0xff, paint_opacity);
|
||||
|
||||
clutter_actor_get_allocation_coords (self, &x_1, &y_1, &x_2, &y_2);
|
||||
clutter_actor_get_allocation_box (self, &box);
|
||||
|
||||
CLUTTER_NOTE (PAINT, "paint to x1: %i, y1: %i x2: %i, y2: %i "
|
||||
CLUTTER_NOTE (PAINT, "paint to x1: %f, y1: %f x2: %f, y2: %f "
|
||||
"opacity: %i",
|
||||
x_1, y_1, x_2, y_2,
|
||||
box.x1, box.y1, box.x2, box.y2,
|
||||
clutter_actor_get_opacity (self));
|
||||
|
||||
if (priv->repeat_x && priv->width > 0)
|
||||
t_w = (float) (x_2 - x_1) / (float) (priv->width);
|
||||
t_w = (box.x2 - box.x1) / priv->width;
|
||||
else
|
||||
t_w = 1.0;
|
||||
|
||||
if (priv->repeat_y && priv->height > 0)
|
||||
t_h = (float) (y_2 - y_1) / (float) (priv->height);
|
||||
t_h = (box.y2 - box.y1) / priv->height;
|
||||
else
|
||||
t_h = 1.0;
|
||||
|
||||
/* Paint will have translated us */
|
||||
cogl_set_source (priv->material);
|
||||
cogl_rectangle_with_texture_coords (0, 0,
|
||||
(float) (x_2 - x_1),
|
||||
(float) (y_2 - y_1),
|
||||
box.x2 - box.x1,
|
||||
box.y2 - box.y1,
|
||||
0, 0, t_w, t_h);
|
||||
}
|
||||
|
||||
@ -791,10 +765,6 @@ clutter_texture_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MAX_TILE_WASTE:
|
||||
clutter_texture_set_max_tile_waste (texture, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
case PROP_SYNC_SIZE:
|
||||
clutter_texture_set_sync_size (texture, g_value_get_boolean (value));
|
||||
break;
|
||||
@ -876,14 +846,14 @@ clutter_texture_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MAX_TILE_WASTE:
|
||||
g_value_set_int (value, clutter_texture_get_max_tile_waste (texture));
|
||||
break;
|
||||
|
||||
case PROP_PIXEL_FORMAT:
|
||||
g_value_set_enum (value, clutter_texture_get_pixel_format (texture));
|
||||
break;
|
||||
|
||||
case PROP_MAX_TILE_WASTE:
|
||||
g_value_set_int (value, clutter_texture_get_max_tile_waste (texture));
|
||||
break;
|
||||
|
||||
case PROP_SYNC_SIZE:
|
||||
g_value_set_boolean (value, priv->sync_actor_size);
|
||||
break;
|
||||
@ -962,6 +932,14 @@ clutter_texture_class_init (ClutterTextureClass *klass)
|
||||
FALSE,
|
||||
G_PARAM_CONSTRUCT_ONLY | CLUTTER_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class, PROP_MAX_TILE_WASTE,
|
||||
g_param_spec_int ("tile-waste",
|
||||
"Tile Waste",
|
||||
"Maximum waste area of a sliced texture",
|
||||
-1, G_MAXINT,
|
||||
COGL_TEXTURE_MAX_WASTE,
|
||||
CLUTTER_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class, PROP_REPEAT_X,
|
||||
@ -990,19 +968,6 @@ clutter_texture_class_init (ClutterTextureClass *klass)
|
||||
CLUTTER_TEXTURE_QUALITY_MEDIUM,
|
||||
G_PARAM_CONSTRUCT | CLUTTER_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class, PROP_MAX_TILE_WASTE,
|
||||
g_param_spec_int ("tile-waste",
|
||||
"Tile dimension to waste",
|
||||
"Max wastage dimension of a texture when using "
|
||||
"sliced textures or -1 to disable slicing. "
|
||||
"Bigger values use less textures, "
|
||||
"smaller values less texture memory.",
|
||||
-1,
|
||||
G_MAXINT,
|
||||
63,
|
||||
G_PARAM_CONSTRUCT_ONLY | CLUTTER_PARAM_READWRITE));
|
||||
|
||||
g_object_class_install_property
|
||||
(gobject_class, PROP_PIXEL_FORMAT,
|
||||
g_param_spec_enum ("pixel-format",
|
||||
@ -1112,9 +1077,9 @@ clutter_texture_class_init (ClutterTextureClass *klass)
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterTextureClass, size_change),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__INT_INT,
|
||||
clutter_marshal_VOID__FLOAT_FLOAT,
|
||||
G_TYPE_NONE,
|
||||
2, G_TYPE_INT, G_TYPE_INT);
|
||||
2, G_TYPE_FLOAT, G_TYPE_FLOAT);
|
||||
/**
|
||||
* ClutterTexture::pixbuf-change:
|
||||
* @texture: the texture which received the signal
|
||||
@ -1215,8 +1180,6 @@ clutter_texture_init (ClutterTexture *self)
|
||||
|
||||
self->priv = priv = CLUTTER_TEXTURE_GET_PRIVATE (self);
|
||||
|
||||
priv->max_tile_waste = 63;
|
||||
priv->filter_quality = CLUTTER_TEXTURE_QUALITY_MEDIUM;
|
||||
priv->repeat_x = FALSE;
|
||||
priv->repeat_y = FALSE;
|
||||
priv->sync_actor_size = TRUE;
|
||||
@ -1256,12 +1219,6 @@ clutter_texture_save_to_local_data (ClutterTexture *texture)
|
||||
/* Align to 4 bytes */
|
||||
priv->local_data_rowstride = (priv->local_data_width * bpp + 3) & ~3;
|
||||
|
||||
/* Store the filter quality and max_tile_waste from the texture
|
||||
properties so that they will be restored the data is loaded
|
||||
again */
|
||||
priv->max_tile_waste = clutter_texture_get_max_tile_waste (texture);
|
||||
priv->filter_quality = clutter_texture_get_filter_quality (texture);
|
||||
|
||||
priv->local_data = g_malloc (priv->local_data_rowstride
|
||||
* priv->local_data_height);
|
||||
|
||||
@ -1396,6 +1353,12 @@ clutter_texture_get_cogl_texture (ClutterTexture *texture)
|
||||
* @cogl_tex. A reference to the texture is taken so if the handle is
|
||||
* no longer needed it should be deref'd with cogl_handle_unref.
|
||||
*
|
||||
* This should not be called on an unrealizable texture (one that
|
||||
* isn't inside a stage). (Currently the ClutterTexture
|
||||
* implementation relies on being able to have a GL texture while
|
||||
* unrealized, which means you can get away with it, but it's
|
||||
* not correct and may change in the future.)
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
@ -1409,6 +1372,12 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
g_return_if_fail (CLUTTER_IS_TEXTURE (texture));
|
||||
g_return_if_fail (cogl_is_texture (cogl_tex));
|
||||
|
||||
/* FIXME this implementation should realize the actor if it's in a
|
||||
* stage, and warn and return if not in a stage yet. However, right
|
||||
* now everything would break if we did that, so we just fudge it
|
||||
* and we're broken: we can have a texture without being realized.
|
||||
*/
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
width = cogl_texture_get_width (cogl_tex);
|
||||
@ -1424,6 +1393,14 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
|
||||
/* Remove old texture */
|
||||
texture_free_gl_resources (texture);
|
||||
|
||||
/* Free any saved data so realization doesn't resend it to GL */
|
||||
if (priv->local_data)
|
||||
{
|
||||
g_free (priv->local_data);
|
||||
priv->local_data = NULL;
|
||||
}
|
||||
|
||||
/* Use the new texture */
|
||||
|
||||
cogl_material_set_layer (priv->material, 0, cogl_tex);
|
||||
@ -1436,12 +1413,10 @@ clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
priv->width = width;
|
||||
priv->height = height;
|
||||
|
||||
CLUTTER_NOTE (TEXTURE, "set size %ix%i\n",
|
||||
CLUTTER_NOTE (TEXTURE, "set size %.2fx%.2f\n",
|
||||
priv->width,
|
||||
priv->height);
|
||||
|
||||
CLUTTER_ACTOR_SET_FLAGS (CLUTTER_ACTOR (texture), CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
if (size_change)
|
||||
{
|
||||
g_signal_emit (texture, texture_signals[SIZE_CHANGE], 0,
|
||||
@ -1475,17 +1450,16 @@ clutter_texture_set_from_data (ClutterTexture *texture,
|
||||
ClutterTexturePrivate *priv = texture->priv;
|
||||
CoglHandle new_texture = COGL_INVALID_HANDLE;
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE;
|
||||
gint min_filter, mag_filter;
|
||||
gint max_waste = -1;
|
||||
|
||||
if (!priv->no_slice)
|
||||
max_waste = priv->max_tile_waste;
|
||||
if (priv->no_slice)
|
||||
flags |= COGL_TEXTURE_NO_SLICING;
|
||||
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
/* FIXME if we are not realized, we should store the data
|
||||
* for future use, instead of creating the texture.
|
||||
*/
|
||||
|
||||
new_texture = cogl_texture_new_from_data (width, height,
|
||||
max_waste, flags,
|
||||
flags,
|
||||
source_format,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
rowstride,
|
||||
@ -1500,12 +1474,6 @@ clutter_texture_set_from_data (ClutterTexture *texture,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clutter_texture_quality_to_filters (priv->filter_quality,
|
||||
&min_filter,
|
||||
&mag_filter);
|
||||
|
||||
cogl_texture_set_filters (new_texture, min_filter, mag_filter);
|
||||
|
||||
clutter_texture_set_cogl_texture (texture, new_texture);
|
||||
|
||||
cogl_handle_unref (new_texture);
|
||||
@ -1530,25 +1498,23 @@ clutter_texture_set_from_data (ClutterTexture *texture,
|
||||
*
|
||||
* Sets #ClutterTexture image data.
|
||||
*
|
||||
* Note: This function is likely to change in future versions.
|
||||
*
|
||||
* Return value: %TRUE on success, %FALSE on failure.
|
||||
*
|
||||
* Since: 0.4.
|
||||
**/
|
||||
*/
|
||||
gboolean
|
||||
clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
||||
const guchar *data,
|
||||
gboolean has_alpha,
|
||||
gint width,
|
||||
gint height,
|
||||
gint rowstride,
|
||||
gint bpp,
|
||||
ClutterTextureFlags flags,
|
||||
GError **error)
|
||||
clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
||||
const guchar *data,
|
||||
gboolean has_alpha,
|
||||
gint width,
|
||||
gint height,
|
||||
gint rowstride,
|
||||
gint bpp,
|
||||
ClutterTextureFlags flags,
|
||||
GError **error)
|
||||
{
|
||||
ClutterTexturePrivate *priv;
|
||||
CoglPixelFormat source_format;
|
||||
CoglPixelFormat source_format;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), FALSE);
|
||||
|
||||
@ -1561,9 +1527,13 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
||||
{
|
||||
g_set_error (error, CLUTTER_TEXTURE_ERROR,
|
||||
CLUTTER_TEXTURE_ERROR_BAD_FORMAT,
|
||||
"Unsupported BPP");
|
||||
"Unsupported bits per pixel value '%d': "
|
||||
"Clutter supports only a BPP value of 4 "
|
||||
"for RGBA data",
|
||||
bpp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
source_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
}
|
||||
else
|
||||
@ -1572,11 +1542,16 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
||||
{
|
||||
g_set_error (error, CLUTTER_TEXTURE_ERROR,
|
||||
CLUTTER_TEXTURE_ERROR_BAD_FORMAT,
|
||||
"Unsupported BPP");
|
||||
"Unsupported bits per pixel value '%d': "
|
||||
"Clutter supports only a BPP value of 3 "
|
||||
"for RGB data",
|
||||
bpp);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
source_format = COGL_PIXEL_FORMAT_RGB_888;
|
||||
}
|
||||
|
||||
if ((flags & CLUTTER_TEXTURE_RGB_FLAG_BGR))
|
||||
source_format |= COGL_BGR_BIT;
|
||||
if ((flags & CLUTTER_TEXTURE_RGB_FLAG_PREMULT))
|
||||
@ -1601,8 +1576,6 @@ clutter_texture_set_from_rgb_data (ClutterTexture *texture,
|
||||
* Sets a #ClutterTexture from YUV image data. If an error occurred,
|
||||
* %FALSE is returned and @error is set.
|
||||
*
|
||||
* This function is likely to change in future versions.
|
||||
*
|
||||
* Return value: %TRUE if the texture was successfully updated
|
||||
*
|
||||
* Since: 0.4
|
||||
@ -1634,7 +1607,7 @@ clutter_texture_set_from_yuv_data (ClutterTexture *texture,
|
||||
{
|
||||
g_set_error (error, CLUTTER_TEXTURE_ERROR,
|
||||
CLUTTER_TEXTURE_ERROR_BAD_FORMAT,
|
||||
"YUV2 not supported");
|
||||
"YUV2 textues are not supported");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -1663,20 +1636,16 @@ clutter_texture_async_load_complete (ClutterTexture *self,
|
||||
ClutterTexturePrivate *priv = self->priv;
|
||||
CoglHandle handle;
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE;
|
||||
gint waste = -1;
|
||||
|
||||
priv->async_data = NULL;
|
||||
|
||||
if (error == NULL)
|
||||
{
|
||||
if (!priv->no_slice)
|
||||
waste = priv->max_tile_waste;
|
||||
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
if (priv->no_slice)
|
||||
flags |= COGL_TEXTURE_NO_SLICING;
|
||||
|
||||
handle = cogl_texture_new_from_bitmap (bitmap,
|
||||
waste, flags,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_ANY);
|
||||
clutter_texture_set_cogl_texture (self, handle);
|
||||
if (priv->load_size_async)
|
||||
@ -1908,8 +1877,6 @@ clutter_texture_set_from_file (ClutterTexture *texture,
|
||||
CoglHandle new_texture = COGL_INVALID_HANDLE;
|
||||
GError *internal_error = NULL;
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE;
|
||||
gint min_filter, mag_filter;
|
||||
gint max_waste = -1;
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
@ -1918,14 +1885,11 @@ clutter_texture_set_from_file (ClutterTexture *texture,
|
||||
if (priv->load_data_async)
|
||||
return clutter_texture_async_load (texture, filename, error);
|
||||
|
||||
if (!priv->no_slice)
|
||||
max_waste = priv->max_tile_waste;
|
||||
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
if (priv->no_slice)
|
||||
flags |= COGL_TEXTURE_NO_SLICING;
|
||||
|
||||
new_texture = cogl_texture_new_from_file (filename,
|
||||
max_waste, flags,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
&internal_error);
|
||||
if (new_texture == COGL_INVALID_HANDLE)
|
||||
@ -1945,12 +1909,6 @@ clutter_texture_set_from_file (ClutterTexture *texture,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
clutter_texture_quality_to_filters (priv->filter_quality,
|
||||
&min_filter,
|
||||
&mag_filter);
|
||||
|
||||
cogl_texture_set_filters (new_texture, min_filter, mag_filter);
|
||||
|
||||
clutter_texture_set_cogl_texture (texture, new_texture);
|
||||
|
||||
cogl_handle_unref (new_texture);
|
||||
@ -1991,33 +1949,14 @@ clutter_texture_set_filter_quality (ClutterTexture *texture,
|
||||
|
||||
if (filter_quality != old_quality)
|
||||
{
|
||||
CoglHandle cogl_texture = clutter_texture_get_cogl_texture (texture);
|
||||
gint min_filter, mag_filter;
|
||||
|
||||
priv->filter_quality = filter_quality;
|
||||
|
||||
clutter_texture_quality_to_filters (priv->filter_quality,
|
||||
clutter_texture_quality_to_filters (filter_quality,
|
||||
&min_filter,
|
||||
&mag_filter);
|
||||
|
||||
/* Is this actually needed - causes problems with TFP mipmaps */
|
||||
if (cogl_texture != COGL_INVALID_HANDLE)
|
||||
cogl_texture_set_filters (cogl_texture, min_filter, mag_filter);
|
||||
|
||||
if ((old_quality == CLUTTER_TEXTURE_QUALITY_HIGH ||
|
||||
filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH) &&
|
||||
CLUTTER_ACTOR_IS_REALIZED (texture))
|
||||
{
|
||||
gboolean was_visible;
|
||||
|
||||
was_visible = CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (texture));
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (texture));
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
|
||||
if (was_visible)
|
||||
clutter_actor_show (CLUTTER_ACTOR (texture));
|
||||
}
|
||||
cogl_material_set_layer_filters (priv->material, 0,
|
||||
min_filter, mag_filter);
|
||||
|
||||
g_object_notify (G_OBJECT (texture), "filter-quality");
|
||||
|
||||
@ -2040,46 +1979,28 @@ ClutterTextureQuality
|
||||
clutter_texture_get_filter_quality (ClutterTexture *texture)
|
||||
{
|
||||
ClutterTexturePrivate *priv;
|
||||
const GList *layers;
|
||||
CoglMaterialFilter min_filter, mag_filter;
|
||||
int i;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), 0);
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
return priv->filter_quality;
|
||||
}
|
||||
layers = cogl_material_get_layers (priv->material);
|
||||
if (layers == NULL)
|
||||
return CLUTTER_TEXTURE_QUALITY_MEDIUM;
|
||||
|
||||
/**
|
||||
* clutter_texture_set_max_tile_waste
|
||||
* @texture: A #ClutterTexture
|
||||
* @max_tile_waste: Maximum amount of waste in pixels or -1
|
||||
*
|
||||
* Sets the maximum number of pixels in either axis that can be wasted
|
||||
* for an individual texture slice. If -1 is specified then the
|
||||
* texture is forced not to be sliced and the texture creation will
|
||||
* fail if the hardware can't create a texture large enough.
|
||||
*
|
||||
* The value is only used when first creating a texture so changing it
|
||||
* after the texture data has been set has no effect.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
clutter_texture_set_max_tile_waste (ClutterTexture *texture,
|
||||
gint max_tile_waste)
|
||||
{
|
||||
ClutterTexturePrivate *priv;
|
||||
CoglHandle cogl_texture;
|
||||
min_filter = cogl_material_layer_get_min_filter (layers->data);
|
||||
mag_filter = cogl_material_layer_get_mag_filter (layers->data);
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_TEXTURE (texture));
|
||||
for (i = 0; i < G_N_ELEMENTS (clutter_texture_quality_filters); i++)
|
||||
if (clutter_texture_quality_filters[i].min_filter == min_filter
|
||||
&& clutter_texture_quality_filters[i].mag_filter == mag_filter)
|
||||
return i;
|
||||
|
||||
priv = texture->priv;
|
||||
cogl_texture = clutter_texture_get_cogl_texture (texture);
|
||||
|
||||
/* There's no point in changing the max_tile_waste if the texture
|
||||
has already been created because it will be overridden with the
|
||||
value from the texture handle */
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
priv->max_tile_waste = max_tile_waste;
|
||||
/* Unknown filter combination */
|
||||
return CLUTTER_TEXTURE_QUALITY_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2090,7 +2011,7 @@ clutter_texture_set_max_tile_waste (ClutterTexture *texture,
|
||||
* -1 if slicing is disabled.
|
||||
*
|
||||
* Return value: The maximum waste or -1 if the texture waste is
|
||||
* unlimited.
|
||||
* unlimited.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
@ -2103,13 +2024,12 @@ clutter_texture_get_max_tile_waste (ClutterTexture *texture)
|
||||
g_return_val_if_fail (CLUTTER_IS_TEXTURE (texture), 0);
|
||||
|
||||
priv = texture->priv;
|
||||
|
||||
cogl_texture = clutter_texture_get_cogl_texture (texture);
|
||||
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
return texture->priv->max_tile_waste;
|
||||
return priv->no_slice ? -1 : COGL_TEXTURE_MAX_WASTE;
|
||||
else
|
||||
/* If we have a valid texture handle then use the value from that
|
||||
instead */
|
||||
return cogl_texture_get_max_waste (cogl_texture);
|
||||
}
|
||||
|
||||
@ -2247,8 +2167,15 @@ clutter_texture_set_area_from_rgb_data (ClutterTexture *texture,
|
||||
if ((flags & CLUTTER_TEXTURE_RGB_FLAG_PREMULT))
|
||||
source_format |= COGL_PREMULT_BIT;
|
||||
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
/* attempt to realize ... */
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture) &&
|
||||
clutter_actor_get_stage (CLUTTER_ACTOR (texture)) != NULL)
|
||||
clutter_actor_realize (CLUTTER_ACTOR (texture));
|
||||
|
||||
/* due to the fudging of clutter_texture_set_cogl_texture()
|
||||
* which allows setting a texture pre-realize, we may end
|
||||
* up having a texture even if we couldn't realize yet.
|
||||
*/
|
||||
cogl_texture = clutter_texture_get_cogl_texture (texture);
|
||||
if (cogl_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
@ -2287,14 +2214,13 @@ on_fbo_source_size_change (GObject *object,
|
||||
ClutterTexture *texture)
|
||||
{
|
||||
ClutterTexturePrivate *priv = texture->priv;
|
||||
guint w, h;
|
||||
gfloat w, h;
|
||||
|
||||
clutter_actor_get_transformed_size (priv->fbo_source, &w, &h);
|
||||
|
||||
if (w != priv->width || h != priv->height)
|
||||
{
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE;
|
||||
gint min_filter, mag_filter;
|
||||
CoglHandle tex;
|
||||
|
||||
/* tear down the FBO */
|
||||
@ -2306,23 +2232,15 @@ on_fbo_source_size_change (GObject *object,
|
||||
priv->width = w;
|
||||
priv->height = h;
|
||||
|
||||
if (priv->filter_quality == CLUTTER_TEXTURE_QUALITY_HIGH)
|
||||
flags |= COGL_TEXTURE_AUTO_MIPMAP;
|
||||
flags |= COGL_TEXTURE_NO_SLICING;
|
||||
|
||||
tex = cogl_texture_new_with_size (MAX (priv->width, 1),
|
||||
MAX (priv->height, 1),
|
||||
-1,
|
||||
flags,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888);
|
||||
|
||||
cogl_material_set_layer (priv->material, 0, tex);
|
||||
|
||||
clutter_texture_quality_to_filters (priv->filter_quality,
|
||||
&min_filter,
|
||||
&mag_filter);
|
||||
|
||||
cogl_texture_set_filters (tex, min_filter, mag_filter);
|
||||
|
||||
priv->fbo_handle = cogl_offscreen_new_to_texture (tex);
|
||||
|
||||
/* The material now has a reference to the texture so it will
|
||||
@ -2332,8 +2250,6 @@ on_fbo_source_size_change (GObject *object,
|
||||
if (priv->fbo_handle == COGL_INVALID_HANDLE)
|
||||
{
|
||||
g_warning ("%s: Offscreen texture creation failed", G_STRLOC);
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (CLUTTER_ACTOR (texture),
|
||||
CLUTTER_ACTOR_REALIZED);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2439,7 +2355,7 @@ clutter_texture_new_from_actor (ClutterActor *actor)
|
||||
{
|
||||
ClutterTexture *texture;
|
||||
ClutterTexturePrivate *priv;
|
||||
guint w, h;
|
||||
gfloat w, h;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
|
||||
|
||||
@ -2509,8 +2425,8 @@ clutter_texture_new_from_actor (ClutterActor *actor)
|
||||
G_CALLBACK(on_fbo_parent_change),
|
||||
texture);
|
||||
|
||||
priv->width = w;
|
||||
priv->height = h;
|
||||
priv->width = w;
|
||||
priv->height = h;
|
||||
|
||||
clutter_actor_set_size (CLUTTER_ACTOR (texture), priv->width, priv->height);
|
||||
|
||||
@ -2764,7 +2680,7 @@ clutter_texture_get_keep_aspect_ratio (ClutterTexture *texture)
|
||||
/**
|
||||
* clutter_texture_set_load_async:
|
||||
* @texture: a #ClutterTexture
|
||||
* @load_sync: %TRUE if the texture should asynchronously load data
|
||||
* @load_async: %TRUE if the texture should asynchronously load data
|
||||
* from a filename
|
||||
*
|
||||
* Sets whether @texture should use a worker thread to load the data
|
||||
|
@ -202,9 +202,6 @@ void clutter_texture_get_base_size (ClutterTexture
|
||||
void clutter_texture_set_filter_quality (ClutterTexture *texture,
|
||||
ClutterTextureQuality filter_quality);
|
||||
ClutterTextureQuality clutter_texture_get_filter_quality (ClutterTexture *texture);
|
||||
void clutter_texture_set_max_tile_waste (ClutterTexture *texture,
|
||||
gint max_tile_waste);
|
||||
gint clutter_texture_get_max_tile_waste (ClutterTexture *texture);
|
||||
CoglHandle clutter_texture_get_cogl_texture (ClutterTexture *texture);
|
||||
void clutter_texture_set_cogl_texture (ClutterTexture *texture,
|
||||
CoglHandle cogl_tex);
|
||||
@ -221,6 +218,7 @@ void clutter_texture_get_repeat (ClutterTexture
|
||||
gboolean *repeat_x,
|
||||
gboolean *repeat_y);
|
||||
CoglPixelFormat clutter_texture_get_pixel_format (ClutterTexture *texture);
|
||||
gint clutter_texture_get_max_tile_waste (ClutterTexture *texture);
|
||||
void clutter_texture_set_keep_aspect_ratio (ClutterTexture *texture,
|
||||
gboolean keep_aspect);
|
||||
gboolean clutter_texture_get_keep_aspect_ratio (ClutterTexture *texture);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -112,17 +112,12 @@ struct _ClutterTimelineClass
|
||||
|
||||
GType clutter_timeline_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterTimeline *clutter_timeline_new (guint n_frames,
|
||||
guint fps);
|
||||
ClutterTimeline *clutter_timeline_new_for_duration (guint msecs);
|
||||
ClutterTimeline *clutter_timeline_new (guint msecs);
|
||||
ClutterTimeline *clutter_timeline_clone (ClutterTimeline *timeline);
|
||||
|
||||
guint clutter_timeline_get_duration (ClutterTimeline *timeline);
|
||||
void clutter_timeline_set_duration (ClutterTimeline *timeline,
|
||||
guint msecs);
|
||||
guint clutter_timeline_get_speed (ClutterTimeline *timeline);
|
||||
void clutter_timeline_set_speed (ClutterTimeline *timeline,
|
||||
guint fps);
|
||||
ClutterTimelineDirection clutter_timeline_get_direction (ClutterTimeline *timeline);
|
||||
void clutter_timeline_set_direction (ClutterTimeline *timeline,
|
||||
ClutterTimelineDirection direction);
|
||||
@ -134,38 +129,35 @@ void clutter_timeline_set_loop (ClutterTimeline *timeli
|
||||
gboolean clutter_timeline_get_loop (ClutterTimeline *timeline);
|
||||
void clutter_timeline_rewind (ClutterTimeline *timeline);
|
||||
void clutter_timeline_skip (ClutterTimeline *timeline,
|
||||
guint n_frames);
|
||||
guint msecs);
|
||||
void clutter_timeline_advance (ClutterTimeline *timeline,
|
||||
guint frame_num);
|
||||
gint clutter_timeline_get_current_frame (ClutterTimeline *timeline);
|
||||
guint msecs);
|
||||
guint clutter_timeline_get_elapsed_time (ClutterTimeline *timeline);
|
||||
gdouble clutter_timeline_get_progress (ClutterTimeline *timeline);
|
||||
CoglFixed clutter_timeline_get_progressx (ClutterTimeline *timeline);
|
||||
void clutter_timeline_set_n_frames (ClutterTimeline *timeline,
|
||||
guint n_frames);
|
||||
guint clutter_timeline_get_n_frames (ClutterTimeline *timeline);
|
||||
gboolean clutter_timeline_is_playing (ClutterTimeline *timeline);
|
||||
void clutter_timeline_set_delay (ClutterTimeline *timeline,
|
||||
guint msecs);
|
||||
guint clutter_timeline_get_delay (ClutterTimeline *timeline);
|
||||
guint clutter_timeline_get_delta (ClutterTimeline *timeline,
|
||||
guint *msecs);
|
||||
guint clutter_timeline_get_delta (ClutterTimeline *timeline);
|
||||
|
||||
void clutter_timeline_add_marker_at_frame (ClutterTimeline *timeline,
|
||||
const gchar *marker_name,
|
||||
guint frame_num);
|
||||
void clutter_timeline_add_marker_at_time (ClutterTimeline *timeline,
|
||||
const gchar *marker_name,
|
||||
guint msecs);
|
||||
void clutter_timeline_remove_marker (ClutterTimeline *timeline,
|
||||
const gchar *marker_name);
|
||||
gchar ** clutter_timeline_list_markers (ClutterTimeline *timeline,
|
||||
gint frame_num,
|
||||
gint msecs,
|
||||
gsize *n_markers) G_GNUC_MALLOC;
|
||||
gboolean clutter_timeline_has_marker (ClutterTimeline *timeline,
|
||||
const gchar *marker_name);
|
||||
void clutter_timeline_advance_to_marker (ClutterTimeline *timeline,
|
||||
const gchar *marker_name);
|
||||
|
||||
/*< private >*/
|
||||
void clutter_timeline_advance_delta (ClutterTimeline *timeline,
|
||||
guint msecs);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _CLUTTER_TIMELINE_H__ */
|
||||
|
@ -106,15 +106,15 @@ GType clutter_geometry_get_type (void) G_GNUC_CONST;
|
||||
* @y: Y coordinate of the vertex
|
||||
* @z: Z coordinate of the vertex
|
||||
*
|
||||
* Vertex of an actor in 3D space, expressed in device independent units.
|
||||
* Vertex of an actor in 3D space, expressed in pixels
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
struct _ClutterVertex
|
||||
{
|
||||
ClutterUnit x;
|
||||
ClutterUnit y;
|
||||
ClutterUnit z;
|
||||
gfloat x;
|
||||
gfloat y;
|
||||
gfloat z;
|
||||
};
|
||||
|
||||
GType clutter_vertex_get_type (void) G_GNUC_CONST;
|
||||
|
@ -27,68 +27,39 @@
|
||||
|
||||
/**
|
||||
* SECTION:clutter-units
|
||||
* @short_description: A logical distance unit.
|
||||
* @short_description: A logical distance unit
|
||||
*
|
||||
* Clutter units are logical units with granularity greater than that of the
|
||||
* device units; they are used by #ClutterActorBox and the units-based family
|
||||
* of #ClutterActor functions. To convert between Clutter units and device
|
||||
* units, use %CLUTTER_UNITS_FROM_DEVICE and %CLUTTER_UNITS_TO_DEVICE macros.
|
||||
* #ClutterUnits is a structure holding a logical distance value along with
|
||||
* its type, expressed as a value of the #ClutterUnitType enumeration. It is
|
||||
* possible to use #ClutterUnits to store a position or a size in units
|
||||
* different than pixels, and convert them whenever needed (for instance
|
||||
* inside the #ClutterActor::allocate() virtual function, or inside the
|
||||
* #ClutterActor::get_preferred_width() and #ClutterActor::get_preferred_height()
|
||||
* virtual functions.
|
||||
*
|
||||
* #ClutterUnit<!-- -->s can be converted from other units like millimeters,
|
||||
* typographic points (at the current resolution) and percentages. It is
|
||||
* also possible to convert fixed point values to and from #ClutterUnit
|
||||
* values.
|
||||
*
|
||||
* In order to register a #ClutterUnit property, the #ClutterParamSpecUnit
|
||||
* In order to register a #ClutterUnits property, the #ClutterParamSpecUnits
|
||||
* #GParamSpec sub-class should be used:
|
||||
*
|
||||
* |[
|
||||
* GParamSpec *pspec;
|
||||
*
|
||||
* pspec = clutter_param_spec_unit ("width",
|
||||
* "Width",
|
||||
* "Width of the actor, in units",
|
||||
* 0, CLUTTER_MAXUNIT,
|
||||
* 0,
|
||||
* G_PARAM_READWRITE);
|
||||
* pspec = clutter_param_spec_units ("active-width",
|
||||
* "Width",
|
||||
* "Width of the active area, in millimeters",
|
||||
* CLUTTER_UNIT_MM,
|
||||
* 0.0, 12.0,
|
||||
* 12.0,
|
||||
* G_PARAM_READWRITE);
|
||||
* g_object_class_install_property (gobject_class, PROP_WIDTH, pspec);
|
||||
* ]|
|
||||
*
|
||||
* A #GValue holding units can be manipulated using clutter_value_set_unit()
|
||||
* and clutter_value_get_unit(). #GValue<!-- -->s containing a #ClutterUnit
|
||||
* value can also be transformed to #GValue<!-- -->s containing integer
|
||||
* values - with a loss of precision:
|
||||
* A #GValue holding units can be manipulated using clutter_value_set_units()
|
||||
* and clutter_value_get_units(). #GValue<!-- -->s containing a #ClutterUnits
|
||||
* value can also be transformed to #GValue<!-- -->s initialized with
|
||||
* %G_TYPE_INT, %G_TYPE_FLOAT and %G_TYPE_STRING through implicit conversion
|
||||
* and using g_value_transform().
|
||||
*
|
||||
* |[
|
||||
* static gboolean
|
||||
* units_to_int (const GValue *src,
|
||||
* GValue *dest)
|
||||
* {
|
||||
* g_return_val_if_fail (CLUTTER_VALUE_HOLDS_UNIT (src), FALSE);
|
||||
*
|
||||
* g_value_init (dest, G_TYPE_INT);
|
||||
* return g_value_transform (src, &dest);
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* The code above is equivalent to:
|
||||
*
|
||||
* |[
|
||||
* static gboolean
|
||||
* units_to_int (const GValue *src,
|
||||
* GValue *dest)
|
||||
* {
|
||||
* g_return_val_if_fail (CLUTTER_VALUE_HOLDS_UNIT (src), FALSE);
|
||||
*
|
||||
* g_value_init (dest, G_TYPE_INT);
|
||||
* g_value_set_int (dest,
|
||||
* CLUTTER_UNITS_TO_INT (clutter_value_get_unit (src)));
|
||||
*
|
||||
* return TRUE;
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* #ClutterUnit is available since Clutter 0.4
|
||||
* #ClutterUnits is available since Clutter 1.0
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
@ -105,19 +76,8 @@
|
||||
|
||||
#define FLOAT_EPSILON (1e-30)
|
||||
|
||||
/**
|
||||
* clutter_units_mm:
|
||||
* @mm: millimeters to convert
|
||||
*
|
||||
* Converts a value in millimeters to #ClutterUnit<!-- -->s at
|
||||
* the current DPI.
|
||||
*
|
||||
* Return value: the value in units
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnit
|
||||
clutter_units_mm (gdouble mm)
|
||||
static gfloat
|
||||
units_mm_to_pixels (gfloat mm)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
gdouble dpi;
|
||||
@ -130,19 +90,8 @@ clutter_units_mm (gdouble mm)
|
||||
return mm * dpi / 25.4;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_pt:
|
||||
* @pt: typographic points to convert
|
||||
*
|
||||
* Converts a value in typographic points to #ClutterUnit<!-- -->s
|
||||
* at the current DPI.
|
||||
*
|
||||
* Return value: the value in units
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnit
|
||||
clutter_units_pt (gdouble pt)
|
||||
static gfloat
|
||||
units_pt_to_pixels (gfloat pt)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
gdouble dpi;
|
||||
@ -155,41 +104,213 @@ clutter_units_pt (gdouble pt)
|
||||
return pt * dpi / 72.0;
|
||||
}
|
||||
|
||||
static gfloat
|
||||
units_em_to_pixels (const gchar *font_name,
|
||||
gfloat em)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
|
||||
if (font_name == NULL || *font_name == '\0')
|
||||
return em * _clutter_backend_get_units_per_em (backend, NULL);
|
||||
else
|
||||
{
|
||||
PangoFontDescription *font_desc;
|
||||
gfloat res;
|
||||
|
||||
font_desc = pango_font_description_from_string (font_name);
|
||||
if (font_desc == NULL)
|
||||
res = -1.0;
|
||||
else
|
||||
{
|
||||
res = em * _clutter_backend_get_units_per_em (backend, font_desc);
|
||||
|
||||
pango_font_description_free (font_desc);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_em:
|
||||
* @em: em to convert
|
||||
* clutter_units_mm:
|
||||
* @units: a #ClutterUnits
|
||||
* @mm: millimeters
|
||||
*
|
||||
* Converts a value in em to #ClutterUnit<!-- -->s at the
|
||||
* current DPI
|
||||
*
|
||||
* Return value: the value in units
|
||||
* Stores a value in millimiters inside @units
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnit
|
||||
clutter_units_em (gdouble em)
|
||||
void
|
||||
clutter_units_mm (ClutterUnits *units,
|
||||
gfloat mm)
|
||||
{
|
||||
ClutterBackend *backend;
|
||||
g_return_if_fail (units != NULL);
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
units->unit_type = CLUTTER_UNIT_MM;
|
||||
units->value = mm;
|
||||
units->pixels = units_mm_to_pixels (mm);
|
||||
units->pixels_set = TRUE;
|
||||
}
|
||||
|
||||
return em * _clutter_backend_get_units_per_em (backend);
|
||||
/**
|
||||
* clutter_units_pt:
|
||||
* @units: a #ClutterUnits
|
||||
* @pt: typographic points
|
||||
*
|
||||
* Stores a value in typographic points inside @units
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_units_pt (ClutterUnits *units,
|
||||
gfloat pt)
|
||||
{
|
||||
g_return_if_fail (units != NULL);
|
||||
|
||||
units->unit_type = CLUTTER_UNIT_POINT;
|
||||
units->value = pt;
|
||||
units->pixels = units_pt_to_pixels (pt);
|
||||
units->pixels_set = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_em:
|
||||
* @units: a #ClutterUnits
|
||||
* @em: em
|
||||
*
|
||||
* Stores a value in em inside @units, using the default font
|
||||
* name as returned by clutter_backend_get_font_name()
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_units_em (ClutterUnits *units,
|
||||
gfloat em)
|
||||
{
|
||||
g_return_if_fail (units != NULL);
|
||||
|
||||
units->unit_type = CLUTTER_UNIT_EM;
|
||||
units->value = em;
|
||||
units->pixels = units_em_to_pixels (NULL, em);
|
||||
units->pixels_set = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_em_for_font:
|
||||
* @units: a #ClutterUnits
|
||||
* @font_name: the font name and size
|
||||
* @em: em
|
||||
*
|
||||
* Stores a value in em inside @units using @font_name
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_units_em_for_font (ClutterUnits *units,
|
||||
const gchar *font_name,
|
||||
gfloat em)
|
||||
{
|
||||
g_return_if_fail (units != NULL);
|
||||
|
||||
units->unit_type = CLUTTER_UNIT_EM;
|
||||
units->value = em;
|
||||
units->pixels = units_em_to_pixels (font_name, em);
|
||||
units->pixels_set = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_pixels:
|
||||
* @px: pixels to convert
|
||||
* @units: a #ClutterUnits
|
||||
* @px: pixels
|
||||
*
|
||||
* Converts a value in pixels to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Return value: the value in units
|
||||
* Stores a value in pixels inside @units
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnit
|
||||
clutter_units_pixels (gint px)
|
||||
void
|
||||
clutter_units_pixels (ClutterUnits *units,
|
||||
gint px)
|
||||
{
|
||||
return CLUTTER_UNITS_FROM_INT (px);
|
||||
g_return_if_fail (units != NULL);
|
||||
|
||||
units->unit_type = CLUTTER_UNIT_PIXEL;
|
||||
units->value = px;
|
||||
units->pixels = px;
|
||||
units->pixels_set = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_get_unit_type:
|
||||
* @units: a #ClutterUnits
|
||||
*
|
||||
* Retrieves the unit type of the value stored inside @units
|
||||
*
|
||||
* Return value: a unit type
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnitType
|
||||
clutter_units_get_unit_type (const ClutterUnits *units)
|
||||
{
|
||||
g_return_val_if_fail (units != NULL, CLUTTER_UNIT_PIXEL);
|
||||
|
||||
return units->unit_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_get_unit_value:
|
||||
* @units: a #ClutterUnits
|
||||
*
|
||||
* Retrieves the value stored inside @units
|
||||
*
|
||||
* Return value: the value stored inside a #ClutterUnits
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gfloat
|
||||
clutter_units_get_unit_value (const ClutterUnits *units)
|
||||
{
|
||||
g_return_val_if_fail (units != NULL, 0.0);
|
||||
|
||||
return units->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_copy:
|
||||
* @units: the #ClutterUnits to copy
|
||||
*
|
||||
* Copies @units
|
||||
*
|
||||
* Return value: the newly created copy of a #ClutterUnits structure.
|
||||
* Use clutter_units_free() to free the allocated resources
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterUnits *
|
||||
clutter_units_copy (const ClutterUnits *units)
|
||||
{
|
||||
if (units != NULL)
|
||||
return g_slice_dup (ClutterUnits, units);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_free:
|
||||
* @units: the #ClutterUnits to free
|
||||
*
|
||||
* Frees the resources allocated by @units
|
||||
*
|
||||
* You should only call this function on a #ClutterUnits
|
||||
* created using clutter_units_copy()
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void
|
||||
clutter_units_free (ClutterUnits *units)
|
||||
{
|
||||
if (units != NULL)
|
||||
g_slice_free (ClutterUnits, units);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,156 +323,294 @@ clutter_units_pixels (gint px)
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gint
|
||||
clutter_units_to_pixels (ClutterUnit units)
|
||||
gfloat
|
||||
clutter_units_to_pixels (ClutterUnits *units)
|
||||
{
|
||||
return CLUTTER_UNITS_TO_INT (units);
|
||||
g_return_val_if_fail (units != NULL, 0.0);
|
||||
|
||||
if (units->pixels_set)
|
||||
return units->pixels;
|
||||
|
||||
switch (units->unit_type)
|
||||
{
|
||||
case CLUTTER_UNIT_MM:
|
||||
units->pixels = units_mm_to_pixels (units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_POINT:
|
||||
units->pixels = units_pt_to_pixels (units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_EM:
|
||||
units->pixels = units_em_to_pixels (NULL, units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_PIXEL:
|
||||
units->pixels = units->value;
|
||||
break;
|
||||
}
|
||||
|
||||
units->pixels_set = TRUE;
|
||||
|
||||
return units->pixels;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_from_string:
|
||||
* @units: a #ClutterUnits
|
||||
* @str: the string to convert
|
||||
*
|
||||
* Parses a value and updates @units with it
|
||||
*
|
||||
* A #ClutterUnits expressed in string should match:
|
||||
*
|
||||
* |[
|
||||
* number: [0-9]
|
||||
* unit_value: <numbers>+
|
||||
* unit_name: px|pt|mm|em
|
||||
* units: <unit_value> <unit_name>
|
||||
* ]|
|
||||
*
|
||||
* For instance, these are valid strings:
|
||||
*
|
||||
* |[
|
||||
* 10 px
|
||||
* 5 em
|
||||
* 24 pt
|
||||
* 12.6 mm
|
||||
* ]|
|
||||
*
|
||||
* Return value: %TRUE if the string was successfully parsed
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gboolean
|
||||
clutter_units_from_string (ClutterUnits *units,
|
||||
const gchar *str)
|
||||
{
|
||||
ClutterUnitType unit_type;
|
||||
gfloat value;
|
||||
|
||||
g_return_val_if_fail (units != NULL, FALSE);
|
||||
g_return_val_if_fail (str != NULL, FALSE);
|
||||
|
||||
/* Ensure that the first character is a digit */
|
||||
while (g_ascii_isspace (*str))
|
||||
str++;
|
||||
|
||||
if (*str == '\0')
|
||||
return FALSE;
|
||||
|
||||
if (!g_ascii_isdigit (*str))
|
||||
return FALSE;
|
||||
|
||||
/* integer part */
|
||||
value = (gfloat) strtoul (str, (char **) &str, 10);
|
||||
|
||||
if (*str == '.' || *str == ',')
|
||||
{
|
||||
glong frac = 100000;
|
||||
|
||||
while (g_ascii_isdigit (*++str))
|
||||
{
|
||||
frac += (*str - '0') * frac;
|
||||
frac /= 10;
|
||||
}
|
||||
|
||||
value += (1.0f / (gfloat) frac);
|
||||
}
|
||||
|
||||
/* assume pixels by default, if no unit is specified */
|
||||
if (str == '\0')
|
||||
unit_type = CLUTTER_UNIT_PIXEL;
|
||||
else
|
||||
{
|
||||
while (g_ascii_isspace (*str))
|
||||
str++;
|
||||
|
||||
if (strncmp (str, "em", 2) == 0)
|
||||
unit_type = CLUTTER_UNIT_EM;
|
||||
else if (strncmp (str, "mm", 2) == 0)
|
||||
unit_type = CLUTTER_UNIT_MM;
|
||||
else if (strncmp (str, "pt", 2) == 0)
|
||||
unit_type = CLUTTER_UNIT_POINT;
|
||||
else if (strncmp (str, "px", 2) == 0)
|
||||
unit_type = CLUTTER_UNIT_PIXEL;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
units->unit_type = unit_type;
|
||||
units->value = value;
|
||||
units->pixels_set = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
clutter_unit_type_name (ClutterUnitType unit_type)
|
||||
{
|
||||
switch (unit_type)
|
||||
{
|
||||
case CLUTTER_UNIT_MM:
|
||||
return "mm";
|
||||
|
||||
case CLUTTER_UNIT_POINT:
|
||||
return "pt";
|
||||
|
||||
case CLUTTER_UNIT_EM:
|
||||
return "em";
|
||||
|
||||
case CLUTTER_UNIT_PIXEL:
|
||||
return "px";
|
||||
}
|
||||
|
||||
g_warning ("Invalid unit type %d", (int) unit_type);
|
||||
|
||||
return "<invalid>";
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_units_to_string:
|
||||
* @units: a #ClutterUnits
|
||||
*
|
||||
* Converts @units into a string
|
||||
*
|
||||
* See clutter_units_from_string() for the units syntax and for
|
||||
* examples of outputs
|
||||
*
|
||||
* Return value: a newly allocated string containing the encoded
|
||||
* #ClutterUnits value. Use g_free() to free the string
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
gchar *
|
||||
clutter_units_to_string (const ClutterUnits *units)
|
||||
{
|
||||
const gchar *unit_name;
|
||||
gchar *fmt;
|
||||
|
||||
g_return_val_if_fail (units != NULL, NULL);
|
||||
|
||||
switch (units->unit_type)
|
||||
{
|
||||
case CLUTTER_UNIT_MM:
|
||||
unit_name = "mm";
|
||||
fmt = g_strdup_printf ("%.2f", units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_POINT:
|
||||
unit_name = "pt";
|
||||
fmt = g_strdup_printf ("%.1f", units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_EM:
|
||||
unit_name = "em";
|
||||
fmt = g_strdup_printf ("%.2f", units->value);
|
||||
break;
|
||||
|
||||
case CLUTTER_UNIT_PIXEL:
|
||||
unit_name = "px";
|
||||
fmt = g_strdup_printf ("%d", (int) units->value);
|
||||
break;
|
||||
}
|
||||
|
||||
return g_strconcat (fmt, " ", unit_name, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* GValue and GParamSpec integration
|
||||
*/
|
||||
|
||||
static GTypeInfo _info = {
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static GTypeFundamentalInfo _finfo = { 0, };
|
||||
|
||||
/* units to integer */
|
||||
static void
|
||||
clutter_value_init_unit (GValue *value)
|
||||
clutter_value_transform_units_int (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
value->data[0].v_float = 0.0;
|
||||
dest->data[0].v_int = clutter_units_to_pixels (src->data[0].v_pointer);
|
||||
}
|
||||
|
||||
/* integer to units */
|
||||
static void
|
||||
clutter_value_copy_unit (const GValue *src,
|
||||
GValue *dest)
|
||||
clutter_value_transform_int_units (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_float = src->data[0].v_float;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
clutter_value_collect_unit (GValue *value,
|
||||
guint n_collect_values,
|
||||
GTypeCValue *collect_values,
|
||||
guint collect_flags)
|
||||
{
|
||||
value->data[0].v_float = collect_values[0].v_double;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
clutter_value_lcopy_unit (const GValue *value,
|
||||
guint n_collect_values,
|
||||
GTypeCValue *collect_values,
|
||||
guint collect_flags)
|
||||
{
|
||||
gfloat *units_p = collect_values[0].v_pointer;
|
||||
|
||||
if (!units_p)
|
||||
return g_strdup_printf ("value location for '%s' passed as NULL",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
|
||||
*units_p = value->data[0].v_float;
|
||||
|
||||
return NULL;
|
||||
clutter_units_pixels (dest->data[0].v_pointer, src->data[0].v_int);
|
||||
}
|
||||
|
||||
/* units to float */
|
||||
static void
|
||||
clutter_value_transform_unit_int (const GValue *src,
|
||||
GValue *dest)
|
||||
clutter_value_transform_units_float (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_int = CLUTTER_UNITS_TO_INT (src->data[0].v_float);
|
||||
dest->data[0].v_float = clutter_units_to_pixels (src->data[0].v_pointer);
|
||||
}
|
||||
|
||||
/* float to units */
|
||||
static void
|
||||
clutter_value_transform_int_unit (const GValue *src,
|
||||
GValue *dest)
|
||||
clutter_value_transform_float_units (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_float = CLUTTER_UNITS_FROM_INT (src->data[0].v_int);
|
||||
clutter_units_pixels (dest->data[0].v_pointer, src->data[0].v_float);
|
||||
}
|
||||
|
||||
/* units to string */
|
||||
static void
|
||||
clutter_value_transform_unit_float (const GValue *src,
|
||||
GValue *dest)
|
||||
clutter_value_transform_units_string (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_float = CLUTTER_UNITS_TO_FLOAT (src->data[0].v_float);
|
||||
gchar *string = clutter_units_to_string (src->data[0].v_pointer);
|
||||
|
||||
g_value_take_string (dest, string);
|
||||
}
|
||||
|
||||
/* string to units */
|
||||
static void
|
||||
clutter_value_transform_float_unit (const GValue *src,
|
||||
GValue *dest)
|
||||
clutter_value_transform_string_units (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_float = CLUTTER_UNITS_FROM_FLOAT (src->data[0].v_float);
|
||||
}
|
||||
ClutterUnits units = { CLUTTER_UNIT_PIXEL, 0.0f };
|
||||
|
||||
#if 0
|
||||
static void
|
||||
clutter_value_transform_unit_fixed (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_int = CLUTTER_UNITS_TO_FIXED (src->data[0].v_float);
|
||||
}
|
||||
clutter_units_from_string (&units, g_value_get_string (src));
|
||||
|
||||
static void
|
||||
clutter_value_transform_fixed_unit (const GValue *src,
|
||||
GValue *dest)
|
||||
{
|
||||
dest->data[0].v_float = CLUTTER_UNITS_FROM_FIXED (src->data[0].v_int);
|
||||
clutter_value_set_units (dest, &units);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const GTypeValueTable _clutter_unit_value_table = {
|
||||
clutter_value_init_unit,
|
||||
NULL,
|
||||
clutter_value_copy_unit,
|
||||
NULL,
|
||||
"d",
|
||||
clutter_value_collect_unit,
|
||||
"p",
|
||||
clutter_value_lcopy_unit
|
||||
};
|
||||
|
||||
GType
|
||||
clutter_unit_get_type (void)
|
||||
clutter_units_get_type (void)
|
||||
{
|
||||
static GType _clutter_unit_type = 0;
|
||||
static volatile gsize clutter_units_type__volatile = 0;
|
||||
|
||||
if (G_UNLIKELY (_clutter_unit_type == 0))
|
||||
if (g_once_init_enter (&clutter_units_type__volatile))
|
||||
{
|
||||
_info.value_table = & _clutter_unit_value_table;
|
||||
_clutter_unit_type =
|
||||
g_type_register_fundamental (g_type_fundamental_next (),
|
||||
I_("ClutterUnit"),
|
||||
&_info, &_finfo, 0);
|
||||
GType clutter_units_type =
|
||||
g_boxed_type_register_static (I_("ClutterUnits"),
|
||||
(GBoxedCopyFunc) clutter_units_copy,
|
||||
(GBoxedFreeFunc) clutter_units_free);
|
||||
|
||||
g_value_register_transform_func (_clutter_unit_type, G_TYPE_INT,
|
||||
clutter_value_transform_unit_int);
|
||||
g_value_register_transform_func (G_TYPE_INT, _clutter_unit_type,
|
||||
clutter_value_transform_int_unit);
|
||||
g_value_register_transform_func (clutter_units_type, G_TYPE_INT,
|
||||
clutter_value_transform_units_int);
|
||||
g_value_register_transform_func (G_TYPE_INT, clutter_units_type,
|
||||
clutter_value_transform_int_units);
|
||||
|
||||
g_value_register_transform_func (_clutter_unit_type, G_TYPE_FLOAT,
|
||||
clutter_value_transform_unit_float);
|
||||
g_value_register_transform_func (G_TYPE_FLOAT, _clutter_unit_type,
|
||||
clutter_value_transform_float_unit);
|
||||
g_value_register_transform_func (clutter_units_type, G_TYPE_FLOAT,
|
||||
clutter_value_transform_units_float);
|
||||
g_value_register_transform_func (G_TYPE_FLOAT, clutter_units_type,
|
||||
clutter_value_transform_float_units);
|
||||
|
||||
g_value_register_transform_func (clutter_units_type, G_TYPE_STRING,
|
||||
clutter_value_transform_units_string);
|
||||
g_value_register_transform_func (G_TYPE_STRING, clutter_units_type,
|
||||
clutter_value_transform_string_units);
|
||||
|
||||
g_once_init_leave (&clutter_units_type__volatile, clutter_units_type);
|
||||
}
|
||||
|
||||
return _clutter_unit_type;
|
||||
return clutter_units_type__volatile;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_value_set_unit:
|
||||
* clutter_value_set_units:
|
||||
* @value: a #GValue initialized to #CLUTTER_TYPE_UNIT
|
||||
* @units: the units to set
|
||||
*
|
||||
@ -360,16 +619,16 @@ clutter_unit_get_type (void)
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
clutter_value_set_unit (GValue *value,
|
||||
ClutterUnit units)
|
||||
clutter_value_set_units (GValue *value,
|
||||
const ClutterUnits *units)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_VALUE_HOLDS_UNIT (value));
|
||||
g_return_if_fail (CLUTTER_VALUE_HOLDS_UNITS (value));
|
||||
|
||||
value->data[0].v_float = units;
|
||||
value->data[0].v_pointer = clutter_units_copy (units);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_value_get_unit:
|
||||
* clutter_value_get_units:
|
||||
* @value: a #GValue initialized to #CLUTTER_TYPE_UNIT
|
||||
*
|
||||
* Gets the #ClutterUnit<!-- -->s contained in @value.
|
||||
@ -378,76 +637,113 @@ clutter_value_set_unit (GValue *value,
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterUnit
|
||||
G_CONST_RETURN ClutterUnits *
|
||||
clutter_value_get_unit (const GValue *value)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_UNIT (value), 0);
|
||||
g_return_val_if_fail (CLUTTER_VALUE_HOLDS_UNITS (value), NULL);
|
||||
|
||||
return value->data[0].v_float;
|
||||
return value->data[0].v_pointer;
|
||||
}
|
||||
|
||||
static void
|
||||
param_unit_init (GParamSpec *pspec)
|
||||
param_units_init (GParamSpec *pspec)
|
||||
{
|
||||
ClutterParamSpecUnit *uspec = CLUTTER_PARAM_SPEC_UNIT (pspec);
|
||||
ClutterParamSpecUnits *uspec = CLUTTER_PARAM_SPEC_UNITS (pspec);
|
||||
|
||||
uspec->minimum = CLUTTER_MINUNIT;
|
||||
uspec->maximum = CLUTTER_MAXUNIT;
|
||||
uspec->default_value = 0;
|
||||
uspec->minimum = -G_MAXFLOAT;
|
||||
uspec->maximum = G_MAXFLOAT;
|
||||
uspec->default_value = 0.0f;
|
||||
uspec->default_type = CLUTTER_UNIT_PIXEL;
|
||||
}
|
||||
|
||||
static void
|
||||
param_unit_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
param_units_set_default (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
value->data[0].v_float = CLUTTER_PARAM_SPEC_UNIT (pspec)->default_value;
|
||||
ClutterParamSpecUnits *uspec = CLUTTER_PARAM_SPEC_UNITS (pspec);
|
||||
ClutterUnits units;
|
||||
|
||||
units.unit_type = uspec->default_type;
|
||||
units.value = uspec->default_value;
|
||||
units.pixels_set = FALSE;
|
||||
|
||||
clutter_value_set_units (value, &units);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
param_unit_validate (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
param_units_validate (GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
ClutterParamSpecUnit *uspec = CLUTTER_PARAM_SPEC_UNIT (pspec);
|
||||
gfloat oval = value->data[0].v_float;
|
||||
ClutterParamSpecUnits *uspec = CLUTTER_PARAM_SPEC_UNITS (pspec);
|
||||
ClutterUnits *units = value->data[0].v_pointer;
|
||||
ClutterUnitType otype = units->unit_type;
|
||||
gfloat oval = units->value;
|
||||
|
||||
g_assert (CLUTTER_IS_PARAM_SPEC_UNIT (pspec));
|
||||
g_assert (CLUTTER_IS_PARAM_SPEC_UNITS (pspec));
|
||||
|
||||
value->data[0].v_float = CLAMP (value->data[0].v_float,
|
||||
uspec->minimum,
|
||||
uspec->maximum);
|
||||
if (otype != uspec->default_type)
|
||||
{
|
||||
gchar *str = clutter_units_to_string (units);
|
||||
|
||||
return value->data[0].v_float != oval;
|
||||
g_warning ("The units value of '%s' does not have the same unit "
|
||||
"type as declared by the ClutterParamSpecUnits of '%s'",
|
||||
str,
|
||||
clutter_unit_type_name (otype));
|
||||
|
||||
g_free (str);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
units->value = CLAMP (units->value,
|
||||
uspec->minimum,
|
||||
uspec->maximum);
|
||||
|
||||
return units->value != oval;
|
||||
}
|
||||
|
||||
static gint
|
||||
param_unit_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2)
|
||||
param_units_values_cmp (GParamSpec *pspec,
|
||||
const GValue *value1,
|
||||
const GValue *value2)
|
||||
{
|
||||
gfloat epsilon = FLOAT_EPSILON;
|
||||
ClutterUnits *units1 = value1->data[0].v_pointer;
|
||||
ClutterUnits *units2 = value2->data[0].v_pointer;
|
||||
gfloat v1, v2;
|
||||
|
||||
if (value1->data[0].v_float < value2->data[0].v_float)
|
||||
return - (value2->data[0].v_float - value1->data[0].v_float > epsilon);
|
||||
if (units1->unit_type == units2->unit_type)
|
||||
{
|
||||
v1 = units1->value;
|
||||
v2 = units2->value;
|
||||
}
|
||||
else
|
||||
return value1->data[0].v_float - value2->data[0].v_float > epsilon;
|
||||
{
|
||||
v1 = clutter_units_to_pixels (units1);
|
||||
v2 = clutter_units_to_pixels (units2);
|
||||
}
|
||||
|
||||
if (v1 < v2)
|
||||
return - (v2 - v1 > FLOAT_EPSILON);
|
||||
else
|
||||
return v1 - v2 > FLOAT_EPSILON;
|
||||
}
|
||||
|
||||
GType
|
||||
clutter_param_unit_get_type (void)
|
||||
clutter_param_units_get_type (void)
|
||||
{
|
||||
static GType pspec_type = 0;
|
||||
|
||||
if (G_UNLIKELY (pspec_type == 0))
|
||||
{
|
||||
const GParamSpecTypeInfo pspec_info = {
|
||||
sizeof (ClutterParamSpecUnit),
|
||||
sizeof (ClutterParamSpecUnits),
|
||||
16,
|
||||
param_unit_init,
|
||||
CLUTTER_TYPE_UNIT,
|
||||
param_units_init,
|
||||
CLUTTER_TYPE_UNITS,
|
||||
NULL,
|
||||
param_unit_set_default,
|
||||
param_unit_validate,
|
||||
param_unit_values_cmp,
|
||||
param_units_set_default,
|
||||
param_units_validate,
|
||||
param_units_values_cmp,
|
||||
};
|
||||
|
||||
pspec_type = g_param_type_register_static (I_("ClutterParamSpecUnit"),
|
||||
@ -458,38 +754,42 @@ clutter_param_unit_get_type (void)
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_param_spec_unit:
|
||||
* clutter_param_spec_units:
|
||||
* @name: name of the property
|
||||
* @nick: short name
|
||||
* @blurb: description (can be translatable)
|
||||
* @default_type: the default type for the #ClutterUnits
|
||||
* @minimum: lower boundary
|
||||
* @maximum: higher boundary
|
||||
* @default_value: default value
|
||||
* @flags: flags for the param spec
|
||||
*
|
||||
* Creates a #GParamSpec for properties using #ClutterUnit<!-- -->s.
|
||||
* Creates a #GParamSpec for properties using #ClutterUnits.
|
||||
*
|
||||
* Return value: the newly created #GParamSpec
|
||||
*
|
||||
* Since: 0.8
|
||||
* Since: 1.0
|
||||
*/
|
||||
GParamSpec *
|
||||
clutter_param_spec_unit (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
ClutterUnit minimum,
|
||||
ClutterUnit maximum,
|
||||
ClutterUnit default_value,
|
||||
GParamFlags flags)
|
||||
clutter_param_spec_units (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
ClutterUnitType default_type,
|
||||
gfloat minimum,
|
||||
gfloat maximum,
|
||||
gfloat default_value,
|
||||
GParamFlags flags)
|
||||
{
|
||||
ClutterParamSpecUnit *uspec;
|
||||
ClutterParamSpecUnits *uspec;
|
||||
|
||||
g_return_val_if_fail (default_value >= minimum && default_value <= maximum,
|
||||
NULL);
|
||||
|
||||
uspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_UNIT,
|
||||
uspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_UNITS,
|
||||
name, nick, blurb,
|
||||
flags);
|
||||
|
||||
uspec->default_type = default_type;
|
||||
uspec->minimum = minimum;
|
||||
uspec->maximum = maximum;
|
||||
uspec->default_value = default_value;
|
||||
|
@ -25,250 +25,144 @@
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly.h"
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_UNITS_H__
|
||||
#define __CLUTTER_UNITS_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-fixed.h>
|
||||
|
||||
#include <cogl/cogl.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* ClutterUnit:
|
||||
* ClutterUnitType:
|
||||
* @CLUTTER_UNIT_PIXEL: Unit expressed in pixels (with subpixel precision)
|
||||
* @CLUTTER_UNIT_EM: Unit expressed in em
|
||||
* @CLUTTER_UNIT_MM: Unit expressed in millimeters
|
||||
* @CLUTTER_UNIT_POINT: Unit expressed in points
|
||||
*
|
||||
* Device independent unit used by Clutter. The value held can be
|
||||
* transformed into other units, likes pixels
|
||||
* The type of unit in which a value is expressed
|
||||
*
|
||||
* Since: 0.4
|
||||
*/
|
||||
typedef float ClutterUnit;
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_INT:
|
||||
* @x: integer value
|
||||
*
|
||||
* Converts @x from an integer value to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_INT(x) ((float)(x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_TO_INT:
|
||||
* @x: value in #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Converts @x from a #ClutterUnit value into an integer
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_TO_INT(x) ((int)(x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_FLOAT:
|
||||
* @x: float value
|
||||
*
|
||||
* Converts @x from a floating point value to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_FLOAT(x) (x)
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_TO_FLOAT:
|
||||
* @x: value in #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Converts @x from a #ClutterUnit value into a float
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_TO_FLOAT(x) (x)
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_FIXED:
|
||||
* @x: #CoglFixed value
|
||||
*
|
||||
* Converts @x from a fixed point value to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_FIXED(x) (COGL_FIXED_TO_FLOAT (x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_TO_FIXED:
|
||||
* @x: value in #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Converts @x from a #ClutterUnit value into a #CoglFixed
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_TO_FIXED(x) (COGL_FIXED_FROM_FLOAT (x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FORMAT:
|
||||
*
|
||||
* Format string that should be used for scanning and printing units.
|
||||
* It is a string literal, but it does not include the percent sign to
|
||||
* allow precision and length modifiers between the percent sign and
|
||||
* the format:
|
||||
*
|
||||
* |[
|
||||
* g_print ("%" CLUTTER_UNITS_FORMAT, units);
|
||||
* ]|
|
||||
* This enumeration might be expanded at later date
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
#define CLUTTER_UNITS_FORMAT "f"
|
||||
typedef enum {
|
||||
CLUTTER_UNIT_PIXEL,
|
||||
CLUTTER_UNIT_EM,
|
||||
CLUTTER_UNIT_MM,
|
||||
CLUTTER_UNIT_POINT
|
||||
} ClutterUnitType;
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_DEVICE:
|
||||
* @x: value in pixels
|
||||
* ClutterUnits:
|
||||
*
|
||||
* Converts @x from pixels to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_DEVICE(x) (clutter_units_pixels ((x)))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_TO_DEVICE:
|
||||
* @x: value in #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Converts @x from #ClutterUnit<!-- -->s to pixels
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_TO_DEVICE(x) (clutter_units_to_pixels ((x)))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_PANGO_UNIT:
|
||||
* @x: value in Pango units
|
||||
*
|
||||
* Converts a value in Pango units to #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_PANGO_UNIT(x) ((float)((x) / 1024.0))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_TO_PANGO_UNIT:
|
||||
* @x: value in #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Converts a value in #ClutterUnit<!-- -->s to Pango units
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_TO_PANGO_UNIT(x) ((int)((x) * 1024))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_MM:
|
||||
* @x: a value in millimeters
|
||||
*
|
||||
* Converts a value in millimeters into #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_MM(x) (clutter_units_mm (x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_POINTS:
|
||||
* @x: a value in typographic points
|
||||
*
|
||||
* Converts a value in typographic points into #ClutterUnit<!-- -->s
|
||||
*
|
||||
* Since: 0.6
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_POINTS(x) (clutter_units_pt (x))
|
||||
|
||||
/**
|
||||
* CLUTTER_UNITS_FROM_EM:
|
||||
* @x: a value in em
|
||||
*
|
||||
* Converts a value in em into #ClutterUnit<!-- -->s
|
||||
* An opaque structure, to be used to store sizing and positioning
|
||||
* values along with their unit.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
#define CLUTTER_UNITS_FROM_EM(x) (clutter_units_em (x))
|
||||
typedef struct _ClutterUnits ClutterUnits;
|
||||
|
||||
ClutterUnit clutter_units_mm (gdouble mm);
|
||||
ClutterUnit clutter_units_pt (gdouble pt);
|
||||
ClutterUnit clutter_units_em (gdouble em);
|
||||
ClutterUnit clutter_units_pixels (gint px);
|
||||
struct _ClutterUnits
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterUnitType unit_type;
|
||||
|
||||
gint clutter_units_to_pixels (ClutterUnit units);
|
||||
gfloat value;
|
||||
|
||||
#define CLUTTER_TYPE_UNIT (clutter_unit_get_type ())
|
||||
#define CLUTTER_TYPE_PARAM_UNIT (clutter_param_unit_get_type ())
|
||||
#define CLUTTER_PARAM_SPEC_UNIT(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), CLUTTER_TYPE_PARAM_UNIT, ClutterParamSpecUnit))
|
||||
#define CLUTTER_IS_PARAM_SPEC_UNIT(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), CLUTTER_TYPE_PARAM_UNIT))
|
||||
/* pre-filled by the provided constructors */
|
||||
gfloat pixels;
|
||||
guint pixels_set;
|
||||
|
||||
/**
|
||||
* CLUTTER_MAXUNIT:
|
||||
*
|
||||
* Higher boundary for a #ClutterUnit
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
#define CLUTTER_MAXUNIT (G_MAXFLOAT)
|
||||
/* padding for eventual expansion */
|
||||
gint64 __padding_1;
|
||||
gint64 __padding_2;
|
||||
};
|
||||
|
||||
/**
|
||||
* CLUTTER_MINUNIT:
|
||||
*
|
||||
* Lower boundary for a #ClutterUnit
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
#define CLUTTER_MINUNIT (-G_MAXFLOAT)
|
||||
GType clutter_units_get_type (void) G_GNUC_CONST;
|
||||
ClutterUnitType clutter_units_get_unit_type (const ClutterUnits *units);
|
||||
gfloat clutter_units_get_unit_value (const ClutterUnits *units);
|
||||
|
||||
ClutterUnits * clutter_units_copy (const ClutterUnits *units);
|
||||
void clutter_units_free (ClutterUnits *units);
|
||||
|
||||
void clutter_units_pixels (ClutterUnits *units,
|
||||
gint px);
|
||||
void clutter_units_em (ClutterUnits *units,
|
||||
gfloat em);
|
||||
void clutter_units_em_for_font (ClutterUnits *units,
|
||||
const gchar *font_name,
|
||||
gfloat em);
|
||||
void clutter_units_mm (ClutterUnits *units,
|
||||
gfloat mm);
|
||||
void clutter_units_pt (ClutterUnits *units,
|
||||
gfloat pt);
|
||||
|
||||
gfloat clutter_units_to_pixels (ClutterUnits *units);
|
||||
|
||||
gchar * clutter_units_to_string (const ClutterUnits *units);
|
||||
gboolean clutter_units_from_string (ClutterUnits *units,
|
||||
const gchar *str);
|
||||
|
||||
#define CLUTTER_TYPE_UNITS (clutter_units_get_type ())
|
||||
#define CLUTTER_TYPE_PARAM_UNITS (clutter_param_units_get_type ())
|
||||
#define CLUTTER_PARAM_SPEC_UNITS(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), CLUTTER_TYPE_PARAM_UNITS, ClutterParamSpecUnits))
|
||||
#define CLUTTER_IS_PARAM_SPEC_UNITS(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), CLUTTER_TYPE_PARAM_UNITS))
|
||||
|
||||
/**
|
||||
* CLUTTER_VALUE_HOLDS_UNIT:
|
||||
* @x: a #GValue
|
||||
*
|
||||
* Evaluates to %TRUE if @x holds #ClutterUnit<!-- -->s.
|
||||
* Evaluates to %TRUE if @x holds a #ClutterUnits value
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
#define CLUTTER_VALUE_HOLDS_UNIT(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_UNIT))
|
||||
#define CLUTTER_VALUE_HOLDS_UNITS(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_UNITS))
|
||||
|
||||
typedef struct _ClutterParamSpecUnit ClutterParamSpecUnit;
|
||||
typedef struct _ClutterParamSpecUnits ClutterParamSpecUnits;
|
||||
|
||||
/**
|
||||
* ClutterParamSpecUnit:
|
||||
* ClutterParamSpecUnits:
|
||||
* @default_type: default type
|
||||
* @default_value: default value
|
||||
* @minimum: lower boundary
|
||||
* @maximum: higher boundary
|
||||
* @default_value: default value
|
||||
*
|
||||
* #GParamSpec subclass for unit based properties.
|
||||
*
|
||||
* Since: 0.8
|
||||
* Since: 1.0
|
||||
*/
|
||||
struct _ClutterParamSpecUnit
|
||||
struct _ClutterParamSpecUnits
|
||||
{
|
||||
/*< private >*/
|
||||
GParamSpec parent_instance;
|
||||
GParamSpec parent_instance;
|
||||
|
||||
/*< public >*/
|
||||
ClutterUnit minimum;
|
||||
ClutterUnit maximum;
|
||||
ClutterUnit default_value;
|
||||
ClutterUnitType default_type;
|
||||
|
||||
gfloat default_value;
|
||||
gfloat minimum;
|
||||
gfloat maximum;
|
||||
};
|
||||
|
||||
GType clutter_unit_get_type (void) G_GNUC_CONST;
|
||||
GType clutter_param_unit_get_type (void) G_GNUC_CONST;
|
||||
GType clutter_param_units_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void clutter_value_set_unit (GValue *value,
|
||||
ClutterUnit units);
|
||||
ClutterUnit clutter_value_get_unit (const GValue *value);
|
||||
GParamSpec * clutter_param_spec_units (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
ClutterUnitType default_type,
|
||||
gfloat minimum,
|
||||
gfloat maximum,
|
||||
gfloat default_value,
|
||||
GParamFlags flags);
|
||||
|
||||
GParamSpec *clutter_param_spec_unit (const gchar *name,
|
||||
const gchar *nick,
|
||||
const gchar *blurb,
|
||||
ClutterUnit minimum,
|
||||
ClutterUnit maximum,
|
||||
ClutterUnit default_value,
|
||||
GParamFlags flags);
|
||||
void clutter_value_set_units (GValue *value,
|
||||
const ClutterUnits *units);
|
||||
G_CONST_RETURN ClutterUnits *clutter_value_get_units (const GValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
NULL =
|
||||
|
||||
V = @
|
||||
Q = $(V:1=)
|
||||
QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
|
||||
|
||||
SUBDIRS = common $(CLUTTER_COGL)
|
||||
|
||||
BUILT_SOURCES = cogl.h
|
||||
@ -23,29 +29,42 @@ CLEANFILES = $(pc_files)
|
||||
|
||||
AM_CPPFLAGS = $(CLUTTER_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
|
||||
# COGL installed headers
|
||||
cogl_headers = \
|
||||
$(top_srcdir)/clutter/cogl/cogl-bitmap.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-color.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-debug.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-fixed.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-material.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-matrix.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-offscreen.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-path.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-shader.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-texture.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-types.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h
|
||||
$(top_srcdir)/clutter/cogl/cogl-bitmap.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-color.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-debug.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-deprecated.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-fixed.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-material.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-matrix.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-offscreen.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-path.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-shader.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-texture.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-types.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-enum-types.h \
|
||||
$(top_builddir)/clutter/cogl/cogl.h \
|
||||
$(NULL)
|
||||
|
||||
# this is copied in from common/ to make cogl.h work, but we
|
||||
# need to clean it up ourselves once we're done
|
||||
DISTCLEANFILES = cogl-enum-types.h
|
||||
|
||||
# HACK - gobject-introspection can't scan a library in another directory
|
||||
# so we create a libclutter-cogl.la that's just identical to the one
|
||||
# in the subdir
|
||||
noinst_LTLIBRARIES = libclutter-cogl.la
|
||||
libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl.la
|
||||
libclutter_cogl_la_LIBADD = $(CLUTTER_COGL)/libclutter-cogl-$(CLUTTER_COGL).la
|
||||
libclutter_cogl_la_SOURCES = $(cogl_headers)
|
||||
|
||||
coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
|
||||
coglinclude_HEADERS = $(cogl_headers)
|
||||
|
||||
if HAVE_INTROSPECTION
|
||||
Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclutter-cogl.la
|
||||
Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) libclutter-cogl.la
|
||||
$(QUIET_GEN)$(INTROSPECTION_SCANNER) -v \
|
||||
--namespace Cogl --nsversion=@CLUTTER_API_VERSION@ \
|
||||
-I$(top_srcdir)/clutter/cogl \
|
||||
@ -59,8 +78,6 @@ Cogl-@CLUTTER_API_VERSION@.gir: $(INTROSPECTION_SCANNER) $(CLUTTER_COGL)/libclut
|
||||
--libtool="$(top_builddir)/doltlibtool" \
|
||||
--pkg gobject-2.0 \
|
||||
--output $@ \
|
||||
$(top_builddir)/clutter/cogl/cogl-defines-@CLUTTER_COGL@.h \
|
||||
$(top_builddir)/clutter/cogl/cogl.h \
|
||||
$(cogl_headers)
|
||||
|
||||
BUILT_GIRSOURCES = Cogl-@CLUTTER_API_VERSION@.gir
|
||||
|
@ -29,15 +29,16 @@
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
COGL_DEBUG_MISC = 1 << 0,
|
||||
COGL_DEBUG_TEXTURE = 1 << 1,
|
||||
COGL_DEBUG_MATERIAL = 1 << 2,
|
||||
COGL_DEBUG_SHADER = 1 << 3,
|
||||
COGL_DEBUG_OFFSCREEN = 1 << 4,
|
||||
COGL_DEBUG_DRAW = 1 << 5,
|
||||
COGL_DEBUG_PANGO = 1 << 6,
|
||||
COGL_DEBUG_RECTANGLES = 1 << 7,
|
||||
COGL_DEBUG_HANDLE = 1 << 8
|
||||
COGL_DEBUG_MISC = 1 << 0,
|
||||
COGL_DEBUG_TEXTURE = 1 << 1,
|
||||
COGL_DEBUG_MATERIAL = 1 << 2,
|
||||
COGL_DEBUG_SHADER = 1 << 3,
|
||||
COGL_DEBUG_OFFSCREEN = 1 << 4,
|
||||
COGL_DEBUG_DRAW = 1 << 5,
|
||||
COGL_DEBUG_PANGO = 1 << 6,
|
||||
COGL_DEBUG_RECTANGLES = 1 << 7,
|
||||
COGL_DEBUG_HANDLE = 1 << 8,
|
||||
COGL_DEBUG_BLEND_STRINGS = 1 << 9
|
||||
} CoglDebugFlags;
|
||||
|
||||
#ifdef COGL_ENABLE_DEBUG
|
||||
@ -69,3 +70,4 @@ extern guint cogl_debug_flags;
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_DEBUG_H__ */
|
||||
|
||||
|
@ -23,6 +23,14 @@
|
||||
|
||||
#ifndef COGL_DEPRECATED_H
|
||||
|
||||
#define cogl_color cogl_color_REPLACED_BY_cogl_set_source_color
|
||||
#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
|
||||
|
@ -43,6 +43,51 @@ G_BEGIN_DECLS
|
||||
* blended together.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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 _CoglMaterialFilter
|
||||
{
|
||||
COGL_MATERIAL_FILTER_NEAREST = GL_NEAREST,
|
||||
COGL_MATERIAL_FILTER_LINEAR = GL_LINEAR,
|
||||
COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST,
|
||||
COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST,
|
||||
COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR,
|
||||
COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR
|
||||
} CoglMaterialFilter;
|
||||
|
||||
/**
|
||||
* cogl_material_new:
|
||||
@ -367,80 +412,90 @@ void cogl_material_set_alpha_test_function (CoglHandle material,
|
||||
float alpha_reference);
|
||||
|
||||
/**
|
||||
* CoglMaterialBlendFactor:
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ZERO: (0, 0, 0, 0)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ONE: (1, 1, 1, 1)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR: (Rs, Gs, Bs, As)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_DST_COLOR: (Rd, Gd, Bd, Ad)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: (1-Rs, 1-Gs, 1-Bs, 1-As)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR: (1-Rd, 1-Gd, 1-Bd, 1-Ad)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA: (As, As, As, As)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: (1-As, 1-As, 1-As, 1-As)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA: (Ad, Ad, Ad, Ad)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: (1-Ad, 1-Ad, 1-Ad, 1-Ad)
|
||||
* @COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE: (f,f,f,1) where f=MIN(As,1-Ad)
|
||||
* 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: 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 dont
|
||||
* support this.
|
||||
*
|
||||
* If not already familiar; please refer
|
||||
* <link linkend="cogl-Blend-Strings">here</link> for an overview of what blend
|
||||
* strings are and there syntax.
|
||||
*
|
||||
* Blending occurs after the alpha test function, and combines fragments with
|
||||
* the framebuffer.
|
||||
* <para>
|
||||
* A fixed function is used to determine the blended color, which is based on
|
||||
* the incoming source color of your fragment (Rs, Gs, Bs, As), a source
|
||||
* factor (Sr, Sg, Sb, Sa), a destination color (Rd, Rg, Rb, Ra) and
|
||||
* a destination factor (Dr, Dg, Db, Da), and is given by these equations:
|
||||
* </para>
|
||||
|
||||
* Currently the only blend function Cogl exposes is ADD(). So any valid
|
||||
* blend statements will be of the form:
|
||||
*
|
||||
* <programlisting>
|
||||
* R = Rs*Sr + Rd*Dr
|
||||
* G = Gs*Sg + Gd*Dg
|
||||
* B = Bs*Sb + Bd*Db
|
||||
* A = As*Sa + Ad*Da
|
||||
* <channel-mask>=ADD(SRC_COLOR*(<factor>), DST_COLOR*(<factor>))
|
||||
* </programlisting>
|
||||
*
|
||||
* All factors have a range [0, 1]
|
||||
* <b>NOTE: The brackets around blend factors are currently not optional!</b>
|
||||
*
|
||||
* The factors are selected with the following constants:
|
||||
* This is the list of source-names usable as blend factors:
|
||||
* <itemizedlist>
|
||||
* <listitem>SRC_COLOR: The color of the in comming fragment</listitem>
|
||||
* <listitem>DST_COLOR: The color of the framebuffer</listitem>
|
||||
* <listitem>
|
||||
* CONSTANT: The constant set via cogl_material_set_blend_constant()</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>
|
||||
* <para>
|
||||
* Remember; all color components are normalized to the range [0, 1] before
|
||||
* computing the result of blending.
|
||||
* </para>
|
||||
* <section>
|
||||
* <title>Examples</title>
|
||||
* Blend a non-premultiplied source over a destination with
|
||||
* premultiplied alpha:
|
||||
* <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>
|
||||
* Blend a premultiplied source over a destination with premultiplied alpha:
|
||||
* <programlisting>
|
||||
* "RGBA = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
|
||||
* </programlisting>
|
||||
* </section>
|
||||
*
|
||||
* Returns: TRUE if the blend string was successfully parsed, and the described
|
||||
* blending is supported by the underlying driver/hardware. If there
|
||||
* was an error, it returns FALSE.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglMaterialBlendFactor
|
||||
{
|
||||
COGL_MATERIAL_BLEND_FACTOR_ZERO = GL_ZERO,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE = GL_ONE,
|
||||
COGL_MATERIAL_BLEND_FACTOR_SRC_COLOR = GL_SRC_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_DST_COLOR = GL_DST_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_COLOR = GL_ONE_MINUS_DST_COLOR,
|
||||
COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA = GL_SRC_ALPHA,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA,
|
||||
COGL_MATERIAL_BLEND_FACTOR_DST_ALPHA = GL_DST_ALPHA,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_DST_ALPHA = GL_ONE_MINUS_DST_ALPHA,
|
||||
COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA_SATURATE = GL_SRC_ALPHA_SATURATE,
|
||||
} CoglMaterialBlendFactor;
|
||||
gboolean cogl_material_set_blend (CoglHandle material,
|
||||
const char *blend_string,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* cogl_material_set_blend_factors:
|
||||
* cogl_material_set_blend_constant:
|
||||
* @material: A CoglMaterial object
|
||||
* @src_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to
|
||||
* the blend equation.
|
||||
* @dst_factor: Chooses the @CoglMaterialBlendFactor you want plugged in to
|
||||
* the blend equation.
|
||||
* @constant_color: The constant color you want
|
||||
*
|
||||
* This function lets you control how primitives using this material will get
|
||||
* blended with the contents of your framebuffer. The blended RGBA components
|
||||
* are calculated like this:
|
||||
* When blending is setup to reference a CONSTANT blend factor then
|
||||
* blending will depend on the constant set with this function.
|
||||
*
|
||||
* (RsSr+RdDr, GsSg+GdDg, BsSb+BsSb, AsSa+AdDa)
|
||||
*
|
||||
* Where (Rs,Gs,Bs,As) represents your source - material- color,
|
||||
* (Rd,Gd,Bd,Ad) represents your destination - framebuffer - color,
|
||||
* (Sr,Sg,Sb,Sa) represents your source blend factor and
|
||||
* (Dr,Dg,Db,Da) represents you destination blend factor.
|
||||
*
|
||||
* All factors lie in the range [0,1] and incoming color components are also
|
||||
* normalized to the range [0,1]
|
||||
*
|
||||
* Since 1.0
|
||||
* Since: 1.0
|
||||
*/
|
||||
void cogl_material_set_blend_factors (CoglHandle material,
|
||||
CoglMaterialBlendFactor src_factor,
|
||||
CoglMaterialBlendFactor dst_factor);
|
||||
void cogl_material_set_blend_constant (CoglHandle material,
|
||||
CoglColor *constant_color);
|
||||
|
||||
/**
|
||||
* cogl_material_set_layer:
|
||||
@ -460,7 +515,7 @@ void cogl_material_set_blend_factors (CoglHandle material,
|
||||
* Since 1.0
|
||||
*/
|
||||
void cogl_material_set_layer (CoglHandle material,
|
||||
gint layer_index,
|
||||
int layer_index,
|
||||
CoglHandle texture);
|
||||
|
||||
/**
|
||||
@ -473,233 +528,112 @@ void cogl_material_set_layer (CoglHandle material,
|
||||
void cogl_material_remove_layer (CoglHandle material,
|
||||
gint layer_index);
|
||||
|
||||
|
||||
/**
|
||||
* CoglMaterialLayerCombineFunc:
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE: Arg0
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE: Arg0 x Arg1
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD: Arg0 + Arg1
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED: Arg0 + Arg1 - 0.5
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE: Arg0 x Arg + Arg1 x (1-Arg2)
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT: Arg0 - Arg1
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB: 4 x ((Arg0r - 0.5) x (Arg1r - 0.5)) +
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA: ((Arg0b - 0.5) x (Arg1b - 0.5)) +
|
||||
* 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.
|
||||
*
|
||||
* A material may comprise of 1 or more layers that can be combined using a
|
||||
* number of different functions. By default layers are modulated, which is
|
||||
* to say the components of the current source layer S are simply multipled
|
||||
* together with the combined results of the previous layer P like this:
|
||||
* 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>
|
||||
* DOT3_RGB(arg0, arg1) =
|
||||
* <programlisting>
|
||||
* (Rs*Rp, Gs*Gp, Bs*Bp, As*Ap)
|
||||
* 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>
|
||||
*
|
||||
* For more advanced techniques, Cogl exposes the fixed function texture
|
||||
* combining capabilities of your GPU to give you greater control.
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerCombineFunc
|
||||
{
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE = CGL_REPLACE,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE = CGL_MODULATE,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD = CGL_ADD,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED = CGL_ADD_SIGNED,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE = CGL_INTERPOLATE,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT = CGL_SUBTRACT,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB = CGL_DOT3_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA = CGL_DOT3_RGBA
|
||||
} CoglMaterialLayerCombineFunc;
|
||||
|
||||
/**
|
||||
* CoglMaterialLayerCombineChannels:
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB: Modify the function or argument
|
||||
* src/op for the RGB components of a
|
||||
* layer
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA: Modify the function or argument
|
||||
* src/op for the Alpha component of a
|
||||
* layer
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA: Modify the function or argument
|
||||
* src/op for all the components of a
|
||||
* layer
|
||||
*
|
||||
* Cogl optionally lets you describe 2 seperate combine modes for a single
|
||||
* layer; 1 for the RGB components, and 1 for the Alpha component, so in this
|
||||
* case you would repeat the 3 steps documented with the
|
||||
* @cogl_material_set_layer_combine_function function for each channel
|
||||
* selector.
|
||||
*
|
||||
* (Note: you can't have different modes for each channel, so if you need more
|
||||
* control you will need to use a glsl fragment shader)
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerCombineChannels
|
||||
{
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA,
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA
|
||||
} CoglMaterialLayerCombineChannels;
|
||||
|
||||
/**
|
||||
* cogl_material_set_layer_combine_function:
|
||||
* @material: A CoglMaterial object
|
||||
* @layer_index: Specifies the layer whos combine mode you want to modify
|
||||
* @channels: Specifies which channels combine mode you want to modify
|
||||
* (RGB, ALPHA, or RGBA)
|
||||
* @func: Specifies the function you want to use for combining fragments
|
||||
* of the specified layer with the results of previously combined
|
||||
* layers.
|
||||
*
|
||||
* There are three basic steps to describing how a layer should be combined:
|
||||
* <orderedlist>
|
||||
* <listitem>
|
||||
* Choose a function.
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* Specify the source color for each argument of the chosen function. (Note
|
||||
* the functions don't all take the same number of arguments)
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* Specify an operator for each argument that can modify the corresponding
|
||||
* source color before the function is applied.
|
||||
* </listitem>
|
||||
* </orderedlist>
|
||||
*
|
||||
* Cogl optionally lets you describe 2 seperate combine modes for a single
|
||||
* layer; 1 for the RGB components, and 1 for the Alpha component, so in this
|
||||
* case you would repeat the 3 steps for each channel selector.
|
||||
*
|
||||
* (Note: you can't have different modes for each channel, so if you need more
|
||||
* control you will need to use a glsl fragment shader)
|
||||
*
|
||||
* For example here is how you could elect to use the ADD function for all
|
||||
* components of layer 1 in your material:
|
||||
* <listitem>DOT3_RGBA(arg0, arg1) =
|
||||
* <programlisting>
|
||||
* //Step 1: Choose a function. Note the ADD function takes 2 arguments...
|
||||
* cogl_material_set_layer_combine_function (material,
|
||||
* 1,
|
||||
* COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
|
||||
* COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD);
|
||||
* //Step 2: Specify the source color for the 2 ADD function arguments...
|
||||
* cogl_material_set_layer_combine_arg_src (material,
|
||||
* 1,//layer index
|
||||
* 0,//argument index
|
||||
* COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS);
|
||||
* cogl_material_set_layer_combine_arg_src (material,
|
||||
* 1,//layer index
|
||||
* 1,//argument index
|
||||
* COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
|
||||
* COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE);
|
||||
* //Step 3: Specify the operators used to modify the arguments...
|
||||
* cogl_material_set_layer_combine_arg_op (material,
|
||||
* 1,//layer index
|
||||
* 0,//argument index
|
||||
* COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA,
|
||||
* COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
|
||||
* cogl_material_set_layer_combine_arg_op (material,
|
||||
* 1,//layer index
|
||||
* 1,//argument index
|
||||
* COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA,
|
||||
* COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
|
||||
* 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>
|
||||
*/
|
||||
void cogl_material_set_layer_combine_function (CoglHandle material,
|
||||
gint layer_index,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineFunc func);
|
||||
|
||||
/**
|
||||
* CoglMaterialLayerCombineSrc:
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE: The fragment color of the current texture layer
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0: The fragment color of texture unit 0
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1: The fragment color of texture unit 1
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2: The fragment color of texture unit 2..7
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT: A fixed constant color (TODO: no API yet to specify the actual color!)
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR: The basic color of the primitive ignoring texturing
|
||||
* @COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS: The result of combining all previous layers
|
||||
* </listitem>
|
||||
* </itemizedlist>
|
||||
*
|
||||
* Note for the constants @COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0..n the
|
||||
* numbers may not correspond to the indices you choose for your layers since
|
||||
* your layer indices don't need to be contiguous. If you need to use these
|
||||
* it would probably be sensible to ensure the layer indices do infact
|
||||
* correspond.
|
||||
* 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:
|
||||
* <itemizedlist>
|
||||
* <listitem>
|
||||
* TEXTURE: Use the color from the current texture layer
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* TEXTURE_0, TEXTURE_1, etc: Use the color from the specified texture layer
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* CONSTANT: Use the color from the constant given with
|
||||
* cogl_material_set_layer_constant()
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* PRIMARY: Use the color of the material as set with cogl_material_set_color()
|
||||
* </listitem>
|
||||
* <listitem>
|
||||
* PREVIOUS: 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>
|
||||
* </itemizedlist>
|
||||
* <section>
|
||||
* <title>Example</title>
|
||||
* This is effectively what the default blending is:
|
||||
* <programlisting>
|
||||
* "RGBA = MODULATE (PREVIOUS, TEXTURE)"
|
||||
* </programlisting>
|
||||
* 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.
|
||||
* <programlisting>
|
||||
* RGBA = INTERPOLATE (PREVIOUS, TEXTURE, CONSTANT[A])
|
||||
* </programlisting>
|
||||
* </section>
|
||||
* <b>Note: you can't give a multiplication factor for arguments as you can
|
||||
* with blending.</b>
|
||||
*
|
||||
* Returns: TRUE if the blend string was successfully parsed, and the described
|
||||
* texture combining is supported by the underlying driver/hardware.
|
||||
* If there was an error, it returns FALSE.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerCombineSrc
|
||||
{
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE = GL_TEXTURE,
|
||||
|
||||
/* Can we find a nicer way... */
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE0 = GL_TEXTURE0,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE1 = GL_TEXTURE1,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE2 = GL_TEXTURE2,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE3 = GL_TEXTURE3,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE4 = GL_TEXTURE4,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE5 = GL_TEXTURE5,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE6 = GL_TEXTURE6,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE7 = GL_TEXTURE7,
|
||||
/* .. who would ever need more than 8 texture layers.. :-) */
|
||||
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_CONSTANT = CGL_CONSTANT,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_PRIMARY_COLOR = CGL_PRIMARY_COLOR,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS = CGL_PREVIOUS
|
||||
} CoglMaterialLayerCombineSrc;
|
||||
gboolean
|
||||
cogl_material_set_layer_combine (CoglHandle material,
|
||||
gint layer_index,
|
||||
const char *blend_string,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* cogl_material_set_layer_combine_arg_src:
|
||||
* cogl_material_set_layer_combine_constant:
|
||||
* @material: A CoglMaterial object
|
||||
* @layer_index:
|
||||
* @argument:
|
||||
* @channels:
|
||||
* @src:
|
||||
* @layer_index: Specifies the layer you want to specify a constant used
|
||||
* for texture combining
|
||||
* @color_constant: The constant color you want
|
||||
*
|
||||
*/
|
||||
void cogl_material_set_layer_combine_arg_src (CoglHandle material,
|
||||
gint layer_index,
|
||||
gint argument,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineSrc src);
|
||||
|
||||
typedef enum _CoglMaterialLayerCombineOp
|
||||
{
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR = GL_SRC_COLOR,
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_COLOR = GL_ONE_MINUS_SRC_COLOR,
|
||||
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA = GL_SRC_ALPHA,
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_ONE_MINUS_SRC_ALPHA = GL_ONE_MINUS_SRC_ALPHA
|
||||
} CoglMaterialLayerCombineOp;
|
||||
|
||||
/**
|
||||
* cogl_material_set_layer_combine_arg_op:
|
||||
* @material: A CoglMaterial object
|
||||
* @layer_index:
|
||||
* @argument:
|
||||
* @channels:
|
||||
* @op:
|
||||
* 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_arg_op (CoglHandle material,
|
||||
gint layer_index,
|
||||
gint argument,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineOp op);
|
||||
|
||||
/* TODO: */
|
||||
#if 0
|
||||
I think it would be be really neat to support a simple string description
|
||||
of the fixed function texture combine modes exposed above. I think we can
|
||||
consider this stuff to be set in stone from the POV that more advanced
|
||||
texture combine functions are catered for with GLSL, so it seems reasonable
|
||||
to find a concise string representation that can represent all the above
|
||||
modes in a *much* more readable/useable fashion. I think somthing like
|
||||
this would be quite nice:
|
||||
|
||||
"MODULATE(TEXTURE[RGB], PREVIOUS[A])"
|
||||
"ADD(TEXTURE[A],PREVIOUS[RGB])"
|
||||
"INTERPOLATE(TEXTURE[1-A], PREVIOUS[RGB])"
|
||||
|
||||
void cogl_material_set_layer_rgb_combine (CoglHandle material
|
||||
gint layer_index,
|
||||
const char *combine_description);
|
||||
void cogl_material_set_layer_alpha_combine (CoglHandle material
|
||||
gint layer_index,
|
||||
const char *combine_description);
|
||||
#endif
|
||||
void cogl_material_set_layer_combine_constant (CoglHandle material,
|
||||
int layer_index,
|
||||
CoglColor *constant);
|
||||
|
||||
/**
|
||||
* cogl_material_set_layer_matrix:
|
||||
@ -709,38 +643,9 @@ void cogl_material_set_layer_alpha_combine (CoglHandle material
|
||||
* and rotate a single layer of a material used to fill your geometry.
|
||||
*/
|
||||
void cogl_material_set_layer_matrix (CoglHandle material,
|
||||
gint layer_index,
|
||||
int layer_index,
|
||||
CoglMatrix *matrix);
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:cogl-material-internals
|
||||
* @short_description: Functions for creating custom primitives that make use
|
||||
* of Cogl materials 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 material internals to support being
|
||||
* able to fill your geometry according to a given Cogl material.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* cogl_material_get_cogl_enable_flags:
|
||||
* @material: A CoglMaterial object
|
||||
*
|
||||
* This determines what flags need to be passed to cogl_enable before this
|
||||
* material can be used. Normally you shouldn't need to use this function
|
||||
* directly since Cogl will do this internally, but if you are developing
|
||||
* custom primitives directly with OpenGL you may want to use this.
|
||||
*
|
||||
* Note: This API is hopfully just a stop-gap solution. Ideally cogl_enable
|
||||
* will be replaced.
|
||||
*/
|
||||
/* TODO: find a nicer solution! */
|
||||
gulong
|
||||
cogl_material_get_cogl_enable_flags (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* cogl_material_get_layers:
|
||||
* @material: A CoglMaterial object
|
||||
@ -748,24 +653,20 @@ cogl_material_get_cogl_enable_flags (CoglHandle handle);
|
||||
* This function lets you access a materials internal list of layers
|
||||
* for iteration.
|
||||
*
|
||||
* Note: Normally you shouldn't need to use this function directly since
|
||||
* Cogl will do this internally, but if you are developing custom primitives
|
||||
* directly with OpenGL, you will need to iterate the layers that you want
|
||||
* to texture with.
|
||||
*
|
||||
* Note: This function may return more layers than OpenGL can use at once
|
||||
* so it's your responsability limit yourself to
|
||||
* CGL_MAX_COMBINED_TEXTURE_IMAGE_UNITS.
|
||||
*
|
||||
* Note: It's a bit out of the ordinary to return a const GList *, but it
|
||||
* was considered sensible to try and avoid list manipulation for every
|
||||
* primitive emitted in a scene, every frame.
|
||||
* Returns: A list of #CoglHandle<!-- -->'s that can be passed to the
|
||||
* cogl_material_layer_* functions.
|
||||
*/
|
||||
const GList *cogl_material_get_layers (CoglHandle material_handle);
|
||||
|
||||
/**
|
||||
* CoglMaterialLayerType:
|
||||
* @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a CoglTexture
|
||||
* @COGL_MATERIAL_LAYER_TYPE_TEXTURE: The layer represents a
|
||||
* <link linkend="cogl-Textures">Cogl texture</link>
|
||||
*
|
||||
* Available types of layers for a #CoglMaterial. This enumeration
|
||||
* might be expanded in later versions.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerType
|
||||
{
|
||||
@ -774,17 +675,12 @@ typedef enum _CoglMaterialLayerType
|
||||
|
||||
/**
|
||||
* cogl_material_layer_get_type:
|
||||
* @layer_handle: A CoglMaterialLayer handle
|
||||
* @layer_handle: A Cogl material layer handle
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Note: Normally you shouldn't need to use this function directly since
|
||||
* Cogl will do this internally, but if you are developing custom primitives
|
||||
* directly with OpenGL, you will need to iterate the layers that you want
|
||||
* to texture with, and thus should be checking the layer types.
|
||||
*/
|
||||
CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle);
|
||||
|
||||
@ -792,75 +688,58 @@ CoglMaterialLayerType cogl_material_layer_get_type (CoglHandle layer_handle);
|
||||
* cogl_material_layer_get_texture:
|
||||
* @layer_handle: A CoglMaterialLayer handle
|
||||
*
|
||||
* This lets you extract a CoglTexture handle for a specific layer. Normally
|
||||
* you shouldn't need to use this function directly since Cogl will do this
|
||||
* internally, but if you are developing custom primitives directly with
|
||||
* OpenGL you may need this.
|
||||
* This lets you extract a CoglTexture handle for a specific layer.
|
||||
*
|
||||
* Note: In the future, we may support purely GLSL based layers which will
|
||||
* likley return COGL_INVALID_HANDLE if you try to get the texture.
|
||||
* Considering this, you should always call cogl_material_layer_get_type
|
||||
* first, to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
|
||||
* likely return COGL_INVALID_HANDLE if you try to get the texture.
|
||||
* Considering this, you can call cogl_material_layer_get_type first,
|
||||
* to check it is of type COGL_MATERIAL_LAYER_TYPE_TEXTURE.
|
||||
*
|
||||
* Note: It is possible for a layer object of type
|
||||
* COGL_MATERIAL_LAYER_TYPE_TEXTURE to be realized before a texture
|
||||
* object has been associated with the layer. For example this happens
|
||||
* if you setup layer combining for a given layer index before calling
|
||||
* cogl_material_set_layer for that index.
|
||||
*
|
||||
* Returns: A CoglHandle to the layers texture object or COGL_INVALID_HANDLE
|
||||
* if a texture has not been set yet.
|
||||
*/
|
||||
CoglHandle cogl_material_layer_get_texture (CoglHandle layer_handle);
|
||||
|
||||
/**
|
||||
* CoglMaterialLayerFlags:
|
||||
* @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a
|
||||
* custom texture matrix.
|
||||
* cogl_material_layer_get_min_filter:
|
||||
* @layer_handle: a #CoglHandle for a material layer.
|
||||
*
|
||||
* Query the currently set downscaling filter for a cogl material layer.
|
||||
*
|
||||
* Returns: the current downscaling filter for a cogl material layer.
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerFlags
|
||||
{
|
||||
COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
|
||||
} CoglMaterialLayerFlags;
|
||||
/* XXX: NB: if you add flags here you will need to update
|
||||
* CoglMaterialLayerPrivFlags!!! */
|
||||
CoglMaterialFilter cogl_material_layer_get_min_filter (CoglHandle layer_handle);
|
||||
|
||||
/**
|
||||
* cogl_material_layer_get_flags:
|
||||
* @layer_handle: A CoglMaterialLayer layer handle
|
||||
* cogl_material_layer_get_mag_filter:
|
||||
* @layer_handle: a #CoglHandle for a material layer.
|
||||
*
|
||||
* This lets you get a number of flag attributes about the layer. Normally
|
||||
* you shouldn't need to use this function directly since Cogl will do this
|
||||
* internally, but if you are developing custom primitives directly with
|
||||
* OpenGL you may need this.
|
||||
* Query the currently set downscaling filter for a cogl material layer.
|
||||
*
|
||||
* Returns: the current downscaling filter for a cogl material layer.
|
||||
*/
|
||||
gulong cogl_material_layer_get_flags (CoglHandle layer_handle);
|
||||
CoglMaterialFilter cogl_material_layer_get_mag_filter (CoglHandle layer_handle);
|
||||
|
||||
/**
|
||||
* CoglMaterialFlushOption:
|
||||
* @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 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_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask
|
||||
* of the layers that you want to completly disable texturing for
|
||||
* (1 = fallback, and the least significant bit = layer 0)
|
||||
* @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture
|
||||
* name to override the texture used for layer 0 of the material. 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.
|
||||
*/
|
||||
typedef enum _CoglMaterialFlushOption
|
||||
{
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
} CoglMaterialFlushOption;
|
||||
|
||||
/**
|
||||
* cogl_material_flush_gl_state:
|
||||
* @material: A CoglMaterial object
|
||||
* @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs
|
||||
* cogl_material_set_layer_filters:
|
||||
* @handle: a #CoglHandle to a material.
|
||||
* @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.
|
||||
*
|
||||
* This function commits the state of the specified CoglMaterial - including
|
||||
* the texture state for all the layers - to the OpenGL[ES] driver.
|
||||
*
|
||||
* Since 1.0
|
||||
* Changes the decimation and interpolation filters used when a texture is
|
||||
* drawn at other scales than 100%.
|
||||
*/
|
||||
void cogl_material_flush_gl_state (CoglHandle material,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void cogl_material_set_layer_filters (CoglHandle handle,
|
||||
gint layer_index,
|
||||
CoglMaterialFilter min_filter,
|
||||
CoglMaterialFilter mag_filter);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -199,22 +199,50 @@ void cogl_matrix_frustum (CoglMatrix *matrix,
|
||||
float z_far);
|
||||
|
||||
/**
|
||||
* cogl_matrix_transform_point:
|
||||
* cogl_matrix_perspective:
|
||||
* @matrix: A 4x4 transformation matrix
|
||||
* @x: The X component of your points position [in:out]
|
||||
* @y: The Y component of your points position [in:out]
|
||||
* @z: The Z component of your points position [in:out]
|
||||
* @w: The W component of your points position [in:out]
|
||||
* @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)
|
||||
*
|
||||
* This transforms a point whos position is given and returned
|
||||
* as four float components.
|
||||
* Multiplies the 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.
|
||||
*/
|
||||
void
|
||||
cogl_matrix_transform_point (const CoglMatrix *matrix,
|
||||
float *x,
|
||||
float *y,
|
||||
float *z,
|
||||
float *w);
|
||||
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)
|
||||
*
|
||||
* Multiples the 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);
|
||||
|
||||
/**
|
||||
* cogl_matrix_init_from_array:
|
||||
@ -234,6 +262,24 @@ void cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array);
|
||||
*/
|
||||
const float *cogl_matrix_get_array (const CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_matrix_transform_point:
|
||||
* @matrix: A 4x4 transformation matrix
|
||||
* @x: The X component of your points position [in:out]
|
||||
* @y: The Y component of your points position [in:out]
|
||||
* @z: The Z component of your points position [in:out]
|
||||
* @w: The W component of your points position [in:out]
|
||||
*
|
||||
* This 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);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_MATRIX_H */
|
||||
|
@ -46,9 +46,12 @@ G_BEGIN_DECLS
|
||||
* 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 _CoglShaderType
|
||||
{
|
||||
typedef enum {
|
||||
COGL_SHADER_TYPE_VERTEX,
|
||||
COGL_SHADER_TYPE_FRAGMENT
|
||||
} CoglShaderType;
|
||||
@ -103,7 +106,7 @@ gboolean cogl_is_shader (CoglHandle handle);
|
||||
* one.
|
||||
*/
|
||||
void cogl_shader_source (CoglHandle shader,
|
||||
const char *source);
|
||||
const gchar *source);
|
||||
/**
|
||||
* cogl_shader_compile:
|
||||
* @handle: #CoglHandle for a shader.
|
||||
@ -111,29 +114,30 @@ void cogl_shader_source (CoglHandle shader,
|
||||
* Compiles the shader, no return value, but the shader is now ready for
|
||||
* linking into a program.
|
||||
*/
|
||||
void cogl_shader_compile (CoglHandle handle);
|
||||
void cogl_shader_compile (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* cogl_shader_get_info_log:
|
||||
* @handle: #CoglHandle for a shader.
|
||||
* @size: maximum number of bytes to retrieve.
|
||||
* @buffer: location for info log.
|
||||
*
|
||||
* Retrieves the information log for a coglobject, can be used in conjunction
|
||||
* with #cogl_shader_get_parameteriv to retrieve the compiler warnings/error
|
||||
* 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
|
||||
*/
|
||||
void cogl_shader_get_info_log (CoglHandle handle,
|
||||
size_t size,
|
||||
char *buffer);
|
||||
gchar * cogl_shader_get_info_log (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* cogl_shader_get_type:
|
||||
* @handle: #CoglHandle for a shader.
|
||||
*
|
||||
* Returns: COGL_SHADER_TYPE_VERTEX if the shader is a vertex processor
|
||||
* or COGL_SHADER_TYPE_FRAGMENT if the shader is a frament processor
|
||||
* 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);
|
||||
|
||||
@ -141,7 +145,9 @@ CoglShaderType cogl_shader_get_type (CoglHandle handle);
|
||||
* cogl_shader_is_compiled:
|
||||
* @handle: #CoglHandle for a shader.
|
||||
*
|
||||
* Returns: TRUE if the shader object has sucessfully be compiled else FALSE
|
||||
* 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);
|
||||
|
||||
|
@ -41,12 +41,12 @@ G_BEGIN_DECLS
|
||||
* 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.
|
||||
* @max_waste: maximum extra horizontal and|or vertical margin pixels
|
||||
* to make the texture fit GPU limitations
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
|
||||
* texture.
|
||||
@ -60,15 +60,12 @@ G_BEGIN_DECLS
|
||||
*/
|
||||
CoglHandle cogl_texture_new_with_size (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
/**
|
||||
* cogl_texture_new_from_file:
|
||||
* @filename: the file to load
|
||||
* @max_waste: maximum extra horizontal and|or vertical margin pixels
|
||||
* to make the texture fit GPU limitations
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
|
||||
* texture
|
||||
@ -82,7 +79,6 @@ CoglHandle cogl_texture_new_with_size (guint width,
|
||||
* Since: 0.8
|
||||
*/
|
||||
CoglHandle cogl_texture_new_from_file (const gchar *filename,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error);
|
||||
@ -91,8 +87,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename,
|
||||
* cogl_texture_new_from_data:
|
||||
* @width: width of texture in pixels
|
||||
* @height: height of texture in pixels
|
||||
* @max_waste: maximum extra horizontal and|or vertical margin pixels
|
||||
* to make the texture fit GPU limitations
|
||||
* @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
|
||||
@ -110,7 +104,6 @@ CoglHandle cogl_texture_new_from_file (const gchar *filename,
|
||||
*/
|
||||
CoglHandle cogl_texture_new_from_data (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
@ -136,19 +129,17 @@ CoglHandle cogl_texture_new_from_data (guint width,
|
||||
*
|
||||
* 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);
|
||||
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
|
||||
* @max_waste: maximum extra horizontal and|or vertical margin pixels
|
||||
* to make the texture fit GPU limitations
|
||||
* @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE
|
||||
* @internal_format: the #CoglPixelFormat to use for the GPU storage of the
|
||||
* texture
|
||||
@ -160,10 +151,9 @@ CoglHandle cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
CoglHandle cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format);
|
||||
|
||||
/**
|
||||
* cogl_is_texture:
|
||||
@ -228,72 +218,6 @@ guint cogl_texture_get_rowstride (CoglHandle handle);
|
||||
*/
|
||||
gint cogl_texture_get_max_waste (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* CoglTextureFilter:
|
||||
* @COGL_TEXTURE_FILTER_NEAREST: Measuring in manhatten distance from the,
|
||||
* current pixel center, use the nearest texture
|
||||
* texel.
|
||||
* @COGL_TEXTURE_FILTER_LINEAR: Use the weighted average of the 4 texels
|
||||
* nearest the current pixel center.
|
||||
* @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST: Select the mimap level whose
|
||||
* texel size most closely matches
|
||||
* the current pixel, and use the
|
||||
* COGL_TEXTURE_FILTER_NEAREST
|
||||
* criterion.
|
||||
* @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST: Select the mimap level whose
|
||||
* texel size most closely matches
|
||||
* the current pixel, and use the
|
||||
* COGL_TEXTURE_FILTER_LINEAR
|
||||
* criterion.
|
||||
* @COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR: Select the two mimap levels
|
||||
* whose texel size most closely
|
||||
* matches the current pixel, use
|
||||
* the COGL_TEXTURE_FILTER_NEAREST
|
||||
* criterion on each one and take
|
||||
* their weighted average.
|
||||
* @COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR: Select the two mimap levels
|
||||
* whose texel size most closely
|
||||
* matches the current pixel, use
|
||||
* the COGL_TEXTURE_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 _CoglTextureFilter
|
||||
{
|
||||
COGL_TEXTURE_FILTER_NEAREST = GL_NEAREST,
|
||||
COGL_TEXTURE_FILTER_LINEAR = GL_LINEAR,
|
||||
COGL_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST,
|
||||
COGL_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST,
|
||||
COGL_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR,
|
||||
COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR
|
||||
} CoglTextureFilter;
|
||||
|
||||
/**
|
||||
* cogl_texture_get_min_filter:
|
||||
* @handle: a #CoglHandle for a texture.
|
||||
*
|
||||
* Query the currently set downscaling filter for a cogl texture.
|
||||
*
|
||||
* Returns: the current downscaling filter for a cogl texture.
|
||||
*/
|
||||
CoglTextureFilter cogl_texture_get_min_filter (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* cogl_texture_get_mag_filter:
|
||||
* @handle: a #CoglHandle for a texture.
|
||||
*
|
||||
* Query the currently set downscaling filter for a cogl texture.
|
||||
*
|
||||
* Returns: the current downscaling filter for a cogl texture.
|
||||
*/
|
||||
CoglTextureFilter cogl_texture_get_mag_filter (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* cogl_texture_is_sliced:
|
||||
* @handle: a #CoglHandle for a texture.
|
||||
@ -343,20 +267,6 @@ gint cogl_texture_get_data (CoglHandle handle,
|
||||
guint rowstride,
|
||||
guchar *data);
|
||||
|
||||
/**
|
||||
* cogl_texture_set_filters:
|
||||
* @handle: a #CoglHandle.
|
||||
* @min_filter: the filter used when scaling the texture down.
|
||||
* @mag_filter: the filter used when magnifying the texture.
|
||||
*
|
||||
* Changes the decimation and interpolation filters used when the texture is
|
||||
* drawn at other scales than 100%.
|
||||
*/
|
||||
void cogl_texture_set_filters (CoglHandle handle,
|
||||
CoglTextureFilter min_filter,
|
||||
CoglTextureFilter mag_filter);
|
||||
|
||||
|
||||
/**
|
||||
* cogl_texture_set_region:
|
||||
* @handle: a #CoglHandle.
|
||||
|
@ -123,8 +123,7 @@ typedef struct _CoglTextureVertex CoglTextureVertex;
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
|
||||
COGL_PIXEL_FORMAT_ANY = 0,
|
||||
COGL_PIXEL_FORMAT_A_8 = 1 | COGL_A_BIT,
|
||||
|
||||
@ -135,60 +134,21 @@ typedef enum
|
||||
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_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),
|
||||
|
||||
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;
|
||||
|
||||
#define COGL_TYPE_PIXEL_FORMAT (cogl_pixel_format_get_type ())
|
||||
GType cogl_pixel_format_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* CoglFeatureFlags:
|
||||
* @COGL_FEATURE_TEXTURE_RECTANGLE: ARB_texture_rectangle support
|
||||
@ -222,9 +182,6 @@ typedef enum
|
||||
COGL_FEATURE_VBOS = (1 << 11)
|
||||
} CoglFeatureFlags;
|
||||
|
||||
#define COGL_TYPE_FEATURE_FLAGS (cogl_feature_flags_get_type ())
|
||||
GType cogl_feature_flags_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* CoglBufferTarget:
|
||||
* @COGL_WINDOW_BUFFER: FIXME
|
||||
@ -240,9 +197,6 @@ typedef enum
|
||||
COGL_OFFSCREEN_BUFFER = (1 << 2)
|
||||
} CoglBufferTarget;
|
||||
|
||||
#define COGL_TYPE_BUFFER_TARGET (cogl_buffer_target_get_type ())
|
||||
GType cogl_buffer_target_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* CoglColor:
|
||||
*
|
||||
@ -290,21 +244,23 @@ struct _CoglTextureVertex
|
||||
/**
|
||||
* CoglTextureFlags:
|
||||
* @COGL_TEXTURE_NONE: No flags specified
|
||||
* @COGL_TEXTURE_AUTO_MIPMAP: Enables the automatic generation of the
|
||||
* mipmap pyramid from the base level image whenever it is updated
|
||||
* @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
|
||||
*
|
||||
* Flags to pass to the cogl_texture_new_* family of functions.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum {
|
||||
COGL_TEXTURE_NONE = 0,
|
||||
COGL_TEXTURE_AUTO_MIPMAP = 1 << 0
|
||||
COGL_TEXTURE_NONE = 0,
|
||||
COGL_TEXTURE_NO_AUTO_MIPMAP = 1 << 0,
|
||||
COGL_TEXTURE_NO_SLICING = 1 << 1
|
||||
} CoglTextureFlags;
|
||||
|
||||
#define COGL_TYPE_TEXTURE_FLAGS (cogl_texture_flags_get_type ())
|
||||
GType cogl_texture_flags_get_type (void) G_GNUC_CONST;
|
||||
|
||||
/**
|
||||
* CoglFogMode:
|
||||
* @COGL_FOG_MODE_LINEAR: Calculates the fog blend factor as:
|
||||
@ -333,16 +289,12 @@ GType cogl_texture_flags_get_type (void) G_GNUC_CONST;
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglFogMode
|
||||
{
|
||||
typedef enum {
|
||||
COGL_FOG_MODE_LINEAR,
|
||||
COGL_FOG_MODE_EXPONENTIAL,
|
||||
COGL_FOG_MODE_EXPONENTIAL_SQUARED
|
||||
} CoglFogMode;
|
||||
|
||||
#define COGL_TYPE_FOG_MODE (cogl_fog_mode_get_type ())
|
||||
GType cogl_fog_mode_get_type (void) G_GNUC_CONST;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_TYPES_H__ */
|
||||
|
@ -94,6 +94,29 @@ cogl_vertex_buffer_new (guint n_vertices);
|
||||
guint
|
||||
cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* 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 cogl_vertex_buffer_add()
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglAttributeType
|
||||
{
|
||||
COGL_ATTRIBUTE_TYPE_BYTE = GL_BYTE,
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE = GL_UNSIGNED_BYTE,
|
||||
COGL_ATTRIBUTE_TYPE_SHORT = GL_SHORT,
|
||||
COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT = GL_UNSIGNED_SHORT,
|
||||
COGL_ATTRIBUTE_TYPE_FLOAT = GL_FLOAT
|
||||
} CoglAttributeType;
|
||||
|
||||
/**
|
||||
* cogl_vertex_buffer_add:
|
||||
* @handle: A vertex buffer handle
|
||||
@ -111,10 +134,9 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
|
||||
* 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
|
||||
* @gl_type: Specifies the data type of each component (GL_BYTE, GL_UNSIGNED_BYTE,
|
||||
* GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT or GL_FLOAT)
|
||||
* @type: a #CoglAttributeType specifying the data type of each component.
|
||||
* @normalized: If GL_TRUE, this specifies that values stored in an integer
|
||||
* format should be mapped into the range [-1.0, 1.0] or [0.1, 1.0]
|
||||
* format should be mapped into the range [-1.0, 1.0] or [0.0, 1.0]
|
||||
* for unsigned values. If GL_FALSE they are converted to floats
|
||||
* directly.
|
||||
* @stride: This specifies the number of bytes from the start of one attribute
|
||||
@ -156,13 +178,13 @@ cogl_vertex_buffer_get_n_vertices (CoglHandle handle);
|
||||
* (Though you can have multiple groups of interleved attributes)
|
||||
*/
|
||||
void
|
||||
cogl_vertex_buffer_add (CoglHandle handle,
|
||||
const char *attribute_name,
|
||||
guint8 n_components,
|
||||
GLenum gl_type,
|
||||
gboolean normalized,
|
||||
guint16 stride,
|
||||
const void *pointer);
|
||||
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:
|
||||
@ -226,21 +248,37 @@ void
|
||||
cogl_vertex_buffer_enable (CoglHandle handle,
|
||||
const char *attribute_name);
|
||||
|
||||
/**
|
||||
* CoglVerticesMode:
|
||||
* @COGL_VERTICES_MODE_POINTS: FIXME, equivalent to %GL_POINTS
|
||||
* @COGL_VERTICES_MODE_LINE_STRIP: FIXME, equivalent to %GL_LINE_STRIP
|
||||
* @COGL_VERTICES_MODE_LINE_LOOP: FIXME, equivalent to %GL_LINE_LOOP
|
||||
* @COGL_VERTICES_MODE_LINES: FIXME, equivalent to %GL_LINES
|
||||
* @COGL_VERTICES_MODE_TRIANGLE_STRIP: FIXME, equivalent to %GL_TRIANGLE_STRIP
|
||||
* @COGL_VERTICES_MODE_TRIANGLE_FAN: FIXME, equivalent to %GL_TRIANGLE_FAN
|
||||
* @COGL_VERTICES_MODE_TRIANGLES: FIXME, equivalent to %GL_TRIANGLES
|
||||
*
|
||||
* How vertices passed to cogl_vertex_buffer_draw() and
|
||||
* cogl_vertex_buffer_draw_elements() should be interpreted
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
typedef enum _CoglVerticesMode
|
||||
{
|
||||
COGL_VERTICES_MODE_POINTS = GL_POINTS,
|
||||
COGL_VERTICES_MODE_LINE_STRIP = GL_LINE_STRIP,
|
||||
COGL_VERTICES_MODE_LINE_LOOP = GL_LINE_LOOP,
|
||||
COGL_VERTICES_MODE_LINES = GL_LINES,
|
||||
COGL_VERTICES_MODE_TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
|
||||
COGL_VERTICES_MODE_TRIANGLE_FAN = GL_TRIANGLE_FAN,
|
||||
COGL_VERTICES_MODE_TRIANGLES = GL_TRIANGLES
|
||||
} CoglVerticesMode;
|
||||
|
||||
/**
|
||||
* cogl_vertex_buffer_draw:
|
||||
* @handle: A vertex buffer handle
|
||||
* @mode: Specifies how the vertices should be interpreted, and should be
|
||||
* a valid GL primitive type:
|
||||
* <itemizedlist>
|
||||
* <listitem>GL_POINTS</listitem>
|
||||
* <listitem>GL_LINE_STRIP</listitem>
|
||||
* <listitem>GL_LINE_LOOP</listitem>
|
||||
* <listitem>GL_LINES</listitem>
|
||||
* <listitem>GL_TRIANGLE_STRIP</listitem>
|
||||
* <listitem>GL_TRIANGLE_FAN</listitem>
|
||||
* <listitem>GL_TRIANGLES</listitem>
|
||||
* </itemizedlist>
|
||||
* (Note: only types available in GLES are listed)
|
||||
* @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.
|
||||
*
|
||||
@ -251,52 +289,90 @@ cogl_vertex_buffer_enable (CoglHandle handle,
|
||||
* drawing.
|
||||
*/
|
||||
void
|
||||
cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
GLenum mode,
|
||||
GLint first,
|
||||
GLsizei count);
|
||||
cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
CoglVerticesMode mode,
|
||||
int first,
|
||||
int count);
|
||||
|
||||
/**
|
||||
* 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: You indices are unsigned integers
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
typedef enum _CoglIndicesType
|
||||
{
|
||||
COGL_INDICES_TYPE_UNSIGNED_BYTE,
|
||||
COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
COGL_INDICES_TYPE_UNSIGNED_INT
|
||||
} CoglIndicesType;
|
||||
|
||||
/**
|
||||
* cogl_vertex_buffer_indices_new:
|
||||
* @indices_type: a #CoglIndicesType specifying the data type used for
|
||||
* the indices.
|
||||
* @indices_array: 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.
|
||||
*
|
||||
* Returns: 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_delete_indices:
|
||||
* @handle: A vertex buffer handle
|
||||
* @indices_id: The identifier for a an array of indices previously added to
|
||||
* the given Cogl vertex buffer using
|
||||
* cogl_vertex_buffer_add_indices().
|
||||
*
|
||||
* Frees the resources associated with a previously added array of vertex
|
||||
* indices.
|
||||
*/
|
||||
void
|
||||
cogl_vertex_buffer_delete_indices (CoglHandle handle,
|
||||
int indices_id);
|
||||
|
||||
/**
|
||||
* cogl_vertex_buffer_draw_elements:
|
||||
* @handle: A vertex buffer handle
|
||||
* @mode: Specifies how the vertices should be interpreted, and should be
|
||||
* a valid GL primitive type:
|
||||
* <itemizedlist>
|
||||
* <listitem>GL_POINTS</listitem>
|
||||
* <listitem>GL_LINE_STRIP</listitem>
|
||||
* <listitem>GL_LINE_LOOP</listitem>
|
||||
* <listitem>GL_LINES</listitem>
|
||||
* <listitem>GL_TRIANGLE_STRIP</listitem>
|
||||
* <listitem>GL_TRIANGLE_FAN</listitem>
|
||||
* <listitem>GL_TRIANGLES</listitem>
|
||||
* </itemizedlist>
|
||||
* (Note: only types available in GLES are listed)
|
||||
* @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.
|
||||
* @indices_type: Specifies the data type used for the indices, and must be
|
||||
* one of:
|
||||
* <itemizedlist>
|
||||
* <listitem>GL_UNSIGNED_BYTE</listitem>
|
||||
* <listitem>GL_UNSIGNED_SHORT</listitem>
|
||||
* <listitem>GL_UNSIGNED_INT</listitem>
|
||||
* </itemizedlist>
|
||||
* @indices: Specifies the address of your array of indices
|
||||
*
|
||||
* This function lets you use an array of indices to specify the vertices
|
||||
* within your vertex buffer that you want to draw.
|
||||
* 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,
|
||||
GLenum mode,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLsizei count,
|
||||
GLenum indices_type,
|
||||
const GLvoid *indices);
|
||||
cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
||||
CoglVerticesMode mode,
|
||||
CoglHandle indices,
|
||||
int min_index,
|
||||
int max_index,
|
||||
int indices_offset,
|
||||
int count);
|
||||
|
||||
/**
|
||||
* cogl_vertex_buffer_ref:
|
||||
@ -318,6 +394,46 @@ cogl_vertex_buffer_ref (CoglHandle handle);
|
||||
void
|
||||
cogl_vertex_buffer_unref (CoglHandle handle);
|
||||
|
||||
/**
|
||||
* 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 this:
|
||||
*
|
||||
* |[
|
||||
* 0 3
|
||||
* ########
|
||||
* # #
|
||||
* # #
|
||||
* ########
|
||||
* 1 2
|
||||
* ]|
|
||||
*
|
||||
* Then you can request 6 indices to render two triangles like this:
|
||||
*
|
||||
* |[
|
||||
* 0 0 3
|
||||
* ## ########
|
||||
* # ## ## #
|
||||
* # ## ## #
|
||||
* ######## ##
|
||||
* 1 2 2
|
||||
* ]|
|
||||
*
|
||||
* 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 (guint n_indices);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include <cogl/cogl-types.h>
|
||||
#include <cogl/cogl-debug.h>
|
||||
#include <cogl/cogl-deprecated.h>
|
||||
#include <cogl/cogl-enum-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -55,22 +56,6 @@ G_BEGIN_DECLS
|
||||
* General utility functions for COGL.
|
||||
*/
|
||||
|
||||
/* Context manipulation */
|
||||
|
||||
/**
|
||||
* cogl_create_context:
|
||||
*
|
||||
* FIXME
|
||||
*/
|
||||
gboolean cogl_create_context (void);
|
||||
|
||||
/**
|
||||
* cogl_destroy_context:
|
||||
*
|
||||
* FIXME
|
||||
*/
|
||||
void cogl_destroy_context (void);
|
||||
|
||||
/**
|
||||
* cogl_get_option_group:
|
||||
*
|
||||
@ -187,7 +172,30 @@ void cogl_frustum (float left,
|
||||
float z_far);
|
||||
|
||||
/**
|
||||
* cogl_setup_viewport:
|
||||
* 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 coordinate for the near clipping plane (may be negative if
|
||||
* the plane is behind the viewer)
|
||||
* @far: The coordinate for the far clipping plane (may be negative if
|
||||
* the plane is behind the viewer)
|
||||
*
|
||||
* Replaces the current projection matrix with a parallel projection
|
||||
* matrix.
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
void cogl_ortho (float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float near,
|
||||
float far);
|
||||
|
||||
/*
|
||||
* _cogl_setup_viewport:
|
||||
* @width: Width of the viewport
|
||||
* @height: Height of the viewport
|
||||
* @fovy: Field of view angle in degrees
|
||||
@ -201,9 +209,11 @@ void cogl_frustum (float left,
|
||||
* with one that has a viewing angle of @fovy along the y-axis and a
|
||||
* view scaled according to @aspect along the x-axis. The view is
|
||||
* clipped according to @z_near and @z_far on the z-axis.
|
||||
*
|
||||
* This function is used only by Clutter.
|
||||
*/
|
||||
void cogl_setup_viewport (guint width,
|
||||
guint height,
|
||||
void _cogl_setup_viewport (guint width,
|
||||
guint height,
|
||||
float fovy,
|
||||
float aspect,
|
||||
float z_near,
|
||||
@ -288,6 +298,14 @@ void cogl_rotate (float angle,
|
||||
*/
|
||||
void cogl_get_modelview_matrix (CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_set_modelview_matrix:
|
||||
* @matrix: pointer to a CoglMatrix to set as 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: pointer to a CoglMatrix to recieve the matrix
|
||||
@ -296,6 +314,14 @@ void cogl_get_modelview_matrix (CoglMatrix *matrix);
|
||||
*/
|
||||
void cogl_get_projection_matrix (CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_set_projection_matrix:
|
||||
* @matrix: pointer to a CoglMatrix to set as the new projection matrix
|
||||
*
|
||||
* Loads matrix as the new projection matrix.
|
||||
*/
|
||||
void cogl_set_projection_matrix (CoglMatrix *matrix);
|
||||
|
||||
/**
|
||||
* cogl_get_viewport:
|
||||
* @v: pointer to a 4 element array of #float<!-- -->s to
|
||||
@ -308,7 +334,7 @@ void cogl_get_projection_matrix (CoglMatrix *matrix);
|
||||
void cogl_get_viewport (float v[4]);
|
||||
|
||||
/**
|
||||
* cogl_enable_depth_test:
|
||||
* cogl_set_depth_test_enable:
|
||||
* @setting: %TRUE to enable depth testing or %FALSE to disable.
|
||||
*
|
||||
* Sets whether depth testing is enabled. If it is disabled then the
|
||||
@ -317,10 +343,19 @@ void cogl_get_viewport (float v[4]);
|
||||
* clutter_actor_lower(), otherwise it will also take into account the
|
||||
* actor's depth. Depth testing is disabled by default.
|
||||
*/
|
||||
void cogl_enable_depth_test (gboolean setting);
|
||||
void cogl_set_depth_test_enable (gboolean setting);
|
||||
|
||||
/**
|
||||
* cogl_enable_backface_culling:
|
||||
* cogl_get_depth_test_enable:
|
||||
*
|
||||
* Queries if depth testing has been enabled via cogl_set_depth_test_enable()
|
||||
*
|
||||
* Returns: TRUE if depth testing is enabled else FALSE
|
||||
*/
|
||||
gboolean cogl_get_depth_test_enable (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
|
||||
@ -329,7 +364,17 @@ void cogl_enable_depth_test (gboolean setting);
|
||||
* only affects calls to the cogl_rectangle* family of functions and
|
||||
* cogl_vertex_buffer_draw*. Backface culling is disabled by default.
|
||||
*/
|
||||
void cogl_enable_backface_culling (gboolean setting);
|
||||
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()
|
||||
*
|
||||
* Returns: TRUE if backface culling is enabled else FALSE
|
||||
*/
|
||||
gboolean cogl_get_backface_culling_enabled (void);
|
||||
|
||||
/**
|
||||
* cogl_set_fog:
|
||||
@ -368,9 +413,12 @@ void cogl_disable_fog (void);
|
||||
* @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 _CoglBufferBit
|
||||
{
|
||||
typedef enum {
|
||||
COGL_BUFFER_BIT_COLOR = 1L<<0,
|
||||
COGL_BUFFER_BIT_DEPTH = 1L<<1,
|
||||
COGL_BUFFER_BIT_STENCIL = 1L<<2
|
||||
@ -379,13 +427,14 @@ typedef enum _CoglBufferBit
|
||||
/**
|
||||
* cogl_clear:
|
||||
* @color: Background color to clear to
|
||||
* @buffers: A mask of @CoglBufferBit<!-- -->'s identifying which auxiliary
|
||||
* buffers to clear
|
||||
* @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, gulong buffers);
|
||||
void cogl_clear (const CoglColor *color,
|
||||
gulong buffers);
|
||||
|
||||
/**
|
||||
* cogl_set_source:
|
||||
@ -628,7 +677,24 @@ void cogl_push_draw_buffer (void);
|
||||
*/
|
||||
void cogl_pop_draw_buffer (void);
|
||||
|
||||
/**
|
||||
|
||||
/*
|
||||
* Internal API available only to Clutter.
|
||||
*
|
||||
* These are typically only to deal with the poor seperation of
|
||||
* responsabilities that currently exists between Clutter and Cogl.
|
||||
* Eventually a lot of the backend code currently in Clutter will
|
||||
* move down into Cogl and these functions will be removed.
|
||||
*/
|
||||
|
||||
void _cogl_destroy_context (void);
|
||||
|
||||
/* XXX: Removed before we release Clutter 1.0 since the implementation
|
||||
* wasn't complete, and so we assume no one is using this yet. Util we
|
||||
* have some one with a good usecase, we can't pretend to support breaking
|
||||
* out into raw OpenGL. */
|
||||
#if 0
|
||||
/*
|
||||
* cogl_flush_gl_state:
|
||||
* @flags: flags controlling what is flushed; currently unused, pass in 0
|
||||
*
|
||||
@ -642,6 +708,7 @@ void cogl_pop_draw_buffer (void);
|
||||
* Since: 1.0
|
||||
*/
|
||||
void cogl_flush_gl_state (int flags);
|
||||
#endif
|
||||
|
||||
/* private */
|
||||
void _cogl_set_indirect_context (gboolean indirect);
|
||||
|
@ -1,3 +1,10 @@
|
||||
NULL =
|
||||
|
||||
V = @
|
||||
Q = $(V:1=)
|
||||
QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
|
||||
QUIET_CP = $(Q:@=@echo ' CP '$@;)
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
@ -9,12 +16,49 @@ INCLUDES = \
|
||||
-DG_LOG_DOMAIN=\"Cogl-Common\" \
|
||||
-DCLUTTER_COMPILATION
|
||||
|
||||
cogl_public_h = \
|
||||
$(top_srcdir)/clutter/cogl/cogl-bitmap.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-color.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-debug.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-fixed.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-material.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-matrix.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-offscreen.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-path.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-shader.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-texture.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-types.h \
|
||||
$(top_srcdir)/clutter/cogl/cogl-vertex-buffer.h \
|
||||
$(top_builddir)/clutter/cogl/cogl.h \
|
||||
$(NULL)
|
||||
|
||||
noinst_LTLIBRARIES = libclutter-cogl-common.la
|
||||
EXTRA_DIST = stb_image.c
|
||||
|
||||
cogl-enum-types.h: stamp-cogl-enum-types.h
|
||||
@true
|
||||
stamp-cogl-enum-types.h: $(cogl_public_h) Makefile
|
||||
$(QUIET_GEN)( $(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/cogl-enum-types.h.in \
|
||||
$(cogl_public_h) ) > xgen-ceth \
|
||||
&& (cmp -s xgen-ceth cogl-enum-types.h || cp -f xgen-ceth cogl-enum-types.h) \
|
||||
&& cp -f cogl-enum-types.h $(top_builddir)/clutter/cogl/cogl-enum-types.h \
|
||||
&& rm -f xgen-ceth \
|
||||
&& echo timestamp > $(@F)
|
||||
|
||||
cogl-enum-types.c: cogl-enum-types.h
|
||||
$(QUIET_GEN)( $(GLIB_MKENUMS) \
|
||||
--template $(srcdir)/cogl-enum-types.c.in \
|
||||
$(cogl_public_h) ) > xgen-cetc \
|
||||
&& cp -f xgen-cetc cogl-enum-types.c \
|
||||
&& rm -f xgen-cetc
|
||||
|
||||
BUILT_SOURCES = cogl-enum-types.h cogl-enum-types.c
|
||||
|
||||
libclutter_cogl_common_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
libclutter_cogl_common_la_LIBADD = -lm $(CLUTTER_LIBS)
|
||||
libclutter_cogl_common_la_SOURCES = \
|
||||
$(top_builddir)/clutter/cogl/common/cogl-enum-types.h \
|
||||
$(top_builddir)/clutter/cogl/common/cogl-enum-types.c \
|
||||
cogl-handle.h \
|
||||
cogl-internal.h \
|
||||
cogl.c \
|
||||
@ -39,4 +83,11 @@ libclutter_cogl_common_la_SOURCES = \
|
||||
cogl-matrix-stack.h \
|
||||
cogl-material.c \
|
||||
cogl-material-private.h \
|
||||
cogl-debug.c
|
||||
cogl-blend-string.c \
|
||||
cogl-blend-string.h \
|
||||
cogl-debug.c \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in
|
||||
CLEANFILES = stamp-cogl-enum-types.h
|
||||
DISTCLEANFILES = cogl-enum-types.h cogl-enum-types.c
|
||||
|
999
clutter/cogl/common/cogl-blend-string.c
Normal file
999
clutter/cogl/common/cogl-blend-string.c
Normal file
@ -0,0 +1,999 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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.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 (AUTO_COMPOSITE, 14, 0),
|
||||
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 (AUTO_COMPOSITE, 14, 0),
|
||||
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++)
|
||||
{
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (statements[i].function->type != COGL_BLEND_STRING_FUNCTION_MODULATE)
|
||||
{
|
||||
error_string = "Using anything but MODULATE() for texture combining"
|
||||
" under GLES 2 is currently unsupported";
|
||||
detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
if (arg->source.info->type == COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT)
|
||||
{
|
||||
error_string = "Using a constant for texture combining isn't "
|
||||
"currently supported with GLES 2 "
|
||||
"(TODO: glTexEnvf)";
|
||||
detail = COGL_BLEND_STRING_ERROR_GPU_UNSUPPORTED_ERROR;
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
g_set_error (error,
|
||||
COGL_BLEND_STRING_ERROR,
|
||||
detail,
|
||||
"Invalid texture combine string: %s",
|
||||
error_string);
|
||||
|
||||
if (cogl_debug_flags & 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->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_flags & 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)
|
||||
{
|
||||
size_t len = p - mark;
|
||||
CoglBlendStringFunctionInfo *functions;
|
||||
size_t 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)
|
||||
{
|
||||
size_t len = p - mark;
|
||||
CoglBlendStringColorSourceInfo *sources;
|
||||
size_t 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
|
||||
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;
|
||||
const char *error_string;
|
||||
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 == ']')
|
||||
{
|
||||
size_t 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))
|
||||
{
|
||||
size_t 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_flags & 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;
|
||||
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;
|
||||
|
||||
#if 0
|
||||
cogl_debug_flags |= COGL_DEBUG_BLEND_STRINGS;
|
||||
#endif
|
||||
|
||||
if (cogl_debug_flags & 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_symbol_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_flags & 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_flags & 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;
|
||||
}
|
||||
|
151
clutter/cogl/common/cogl-blend-string.h
Normal file
151
clutter/cogl/common/cogl-blend-string.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
|
||||
#define COGL_BLEND_STRING_ERROR _cogl_blend_string_error_quark ()
|
||||
|
||||
typedef enum _CoglBlendStringError
|
||||
{
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
size_t 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_AUTO_COMPOSITE,
|
||||
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;
|
||||
size_t 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);
|
||||
|
||||
GQuark
|
||||
_cogl_blend_string_error_quark (void);
|
||||
|
||||
#endif /* COGL_BLEND_STRING_H */
|
||||
|
@ -45,6 +45,9 @@
|
||||
#define glFrustum(L,R,B,T,N,F) \
|
||||
glFrustumf((GLfloat)L, (GLfloat)R, (GLfloat)B, \
|
||||
(GLfloat)T, (GLfloat)N, (GLfloat)F)
|
||||
|
||||
#define glOrtho glOrthof
|
||||
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
@ -209,30 +212,57 @@ _cogl_current_matrix_frustum (float left,
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_current_matrix_ortho (float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float near_val,
|
||||
float far_val)
|
||||
_cogl_current_matrix_perspective (float fov_y,
|
||||
float aspect,
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
|
||||
|
||||
if (current_stack != NULL)
|
||||
_cogl_matrix_stack_perspective (current_stack,
|
||||
fov_y, aspect, z_near, z_far);
|
||||
else
|
||||
{
|
||||
/* NB: There is no glPerspective() (only gluPerspective()) so we use
|
||||
* cogl_matrix_perspective: */
|
||||
CoglMatrix matrix;
|
||||
_cogl_get_matrix (ctx->matrix_mode, &matrix);
|
||||
cogl_matrix_perspective (&matrix,
|
||||
fov_y, aspect, z_near, z_far);
|
||||
_cogl_current_matrix_load (&matrix);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_current_matrix_ortho (float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float near_val,
|
||||
float far_val)
|
||||
{
|
||||
#if 0
|
||||
_COGL_GET_CONTEXT_AND_STACK (ctx, current_stack, NO_RETVAL);
|
||||
|
||||
if (current_stack != NULL)
|
||||
_cogl_matrix_stack_ortho (current_stack,
|
||||
left, right,
|
||||
top, bottom,
|
||||
bottom, top,
|
||||
near_val,
|
||||
far_val);
|
||||
else
|
||||
GE (glOrtho (left, right, bottom, top, near_val, far_val));
|
||||
{
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
/* NB: GLES 2 has no glOrtho(): */
|
||||
CoglMatrix matrix;
|
||||
_cogl_get_matrix (ctx->matrix_mode, &matrix);
|
||||
cogl_matrix_ortho (&matrix,
|
||||
left, right, bottom, top, near_val, far_val);
|
||||
_cogl_current_matrix_load (&matrix);
|
||||
#else
|
||||
/* Nobody is using glOrtho right now anyway, so not bothering */
|
||||
g_warning ("%s not implemented, need to code cogl_matrix_ortho() if you need"
|
||||
" this function",
|
||||
G_STRFUNC);
|
||||
GE (glOrtho (left, right, bottom, top, near_val, far_val));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -276,6 +306,12 @@ _cogl_get_matrix (CoglMatrixMode mode,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_set_matrix (const CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_current_matrix_load (matrix);
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_current_matrix_state_init (void)
|
||||
{
|
||||
@ -354,85 +390,19 @@ cogl_rotate (float angle, float x, float y, float z)
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_set_matrix (const CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_current_matrix_load (matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_get_modelview_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_get_matrix (COGL_MATRIX_MODELVIEW,
|
||||
matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_get_projection_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_get_matrix (COGL_MATRIX_PROJECTION,
|
||||
matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_perspective (float fovy,
|
||||
cogl_perspective (float fov_y,
|
||||
float aspect,
|
||||
float zNear,
|
||||
float zFar)
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
float xmax, ymax;
|
||||
float x, y, c, d;
|
||||
float fovy_rad_half = (fovy * G_PI) / 360;
|
||||
CoglMatrix perspective;
|
||||
GLfloat m[16];
|
||||
float ymax = z_near * tanf (fov_y * G_PI / 360.0);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
memset (&m[0], 0, sizeof (m));
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_identity ();
|
||||
|
||||
/*
|
||||
* Based on the original algorithm in perspective():
|
||||
*
|
||||
* 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax
|
||||
* same true for y, hence: a == 0 && b == 0;
|
||||
*
|
||||
* 2) When working with small numbers, we are loosing significant
|
||||
* precision
|
||||
*/
|
||||
ymax = (zNear * (sinf (fovy_rad_half) / cosf (fovy_rad_half)));
|
||||
xmax = (ymax * aspect);
|
||||
|
||||
x = (zNear / xmax);
|
||||
y = (zNear / ymax);
|
||||
c = (-(zFar + zNear) / ( zFar - zNear));
|
||||
d = (-(2 * zFar) * zNear) / (zFar - zNear);
|
||||
|
||||
#define M(row,col) m[col*4+row]
|
||||
M(0,0) = x;
|
||||
M(1,1) = y;
|
||||
M(2,2) = c;
|
||||
M(2,3) = d;
|
||||
M(3,2) = -1.0;
|
||||
|
||||
cogl_matrix_init_from_array (&perspective, m);
|
||||
_cogl_current_matrix_multiply (&perspective);
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
|
||||
|
||||
#define m ctx->inverse_projection
|
||||
M(0, 0) = (1.0 / x);
|
||||
M(1, 1) = (1.0 / y);
|
||||
M(2, 3) = -1.0;
|
||||
M(3, 2) = (1.0 / d);
|
||||
M(3, 3) = (c / d);
|
||||
#undef m
|
||||
|
||||
#undef M
|
||||
cogl_frustum (-ymax * aspect, /* left */
|
||||
ymax * aspect, /* right */
|
||||
-ymax, /* bottom */
|
||||
ymax, /* top */
|
||||
z_near,
|
||||
z_far);
|
||||
}
|
||||
|
||||
void
|
||||
@ -474,4 +444,65 @@ cogl_frustum (float left,
|
||||
M(3,2) = 1.0 / d;
|
||||
M(3,3) = c / d;
|
||||
#undef M
|
||||
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_ortho (float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
CoglMatrix ortho;
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
cogl_matrix_init_identity (&ortho);
|
||||
cogl_matrix_ortho (&ortho, left, right, bottom, top, z_near, z_far);
|
||||
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_load (&ortho);
|
||||
|
||||
/* Calculate and store the inverse of the matrix */
|
||||
memset (ctx->inverse_projection, 0, sizeof (float) * 16);
|
||||
|
||||
#define M(row,col) ctx->inverse_projection[col*4+row]
|
||||
M(0,0) = 1.0 / ortho.xx;
|
||||
M(0,3) = -ortho.xw;
|
||||
M(1,1) = 1.0 / ortho.yy;
|
||||
M(1,3) = -ortho.yw;
|
||||
M(2,2) = 1.0 / ortho.zz;
|
||||
M(2,3) = -ortho.zw;
|
||||
M(3,3) = 1.0;
|
||||
#undef M
|
||||
}
|
||||
|
||||
void
|
||||
cogl_get_modelview_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_get_matrix (COGL_MATRIX_MODELVIEW,
|
||||
matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_set_modelview_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_load (matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_get_projection_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_get_matrix (COGL_MATRIX_PROJECTION,
|
||||
matrix);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_set_projection_matrix (CoglMatrix *matrix)
|
||||
{
|
||||
_cogl_set_current_matrix (COGL_MATRIX_PROJECTION);
|
||||
_cogl_current_matrix_load (matrix);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,8 @@ static const GDebugKey cogl_debug_keys[] = {
|
||||
{ "draw", COGL_DEBUG_DRAW },
|
||||
{ "pango", COGL_DEBUG_PANGO },
|
||||
{ "rectangles", COGL_DEBUG_RECTANGLES },
|
||||
{ "handle", COGL_DEBUG_HANDLE }
|
||||
{ "handle", COGL_DEBUG_HANDLE },
|
||||
{ "blend-strings", COGL_DEBUG_BLEND_STRINGS }
|
||||
};
|
||||
|
||||
static const gint n_cogl_debug_keys = G_N_ELEMENTS (cogl_debug_keys);
|
||||
|
41
clutter/cogl/common/cogl-enum-types.c.in
Normal file
41
clutter/cogl/common/cogl-enum-types.c.in
Normal file
@ -0,0 +1,41 @@
|
||||
/*** 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 ***/
|
25
clutter/cogl/common/cogl-enum-types.h.in
Normal file
25
clutter/cogl/common/cogl-enum-types.h.in
Normal file
@ -0,0 +1,25 @@
|
||||
/*** 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 ***/
|
@ -82,7 +82,7 @@ typedef struct _CoglHandleObject
|
||||
static CoglHandleClass _cogl_##type_name##_class; \
|
||||
\
|
||||
static GQuark \
|
||||
_cogl_##type_name##_get_type (void) \
|
||||
_cogl_handle_##type_name##_get_type (void) \
|
||||
{ \
|
||||
static GQuark type = 0; \
|
||||
if (!type) \
|
||||
@ -99,13 +99,13 @@ _cogl_##type_name##_handle_new (Cogl##TypeName *new_obj) \
|
||||
obj->klass = &_cogl_##type_name##_class; \
|
||||
if (!obj->klass->type) \
|
||||
{ \
|
||||
obj->klass->type = _cogl_##type_name##_get_type (); \
|
||||
obj->klass->virt_free = _cogl_##type_name##_free; \
|
||||
} \
|
||||
obj->klass->type = _cogl_handle_##type_name##_get_type ();\
|
||||
obj->klass->virt_free = _cogl_##type_name##_free; \
|
||||
} \
|
||||
\
|
||||
_COGL_HANDLE_DEBUG_NEW (TypeName, obj); \
|
||||
return (CoglHandle) new_obj; \
|
||||
} \
|
||||
_COGL_HANDLE_DEBUG_NEW (TypeName, obj); \
|
||||
return (CoglHandle) new_obj; \
|
||||
} \
|
||||
\
|
||||
Cogl##TypeName * \
|
||||
_cogl_##type_name##_pointer_from_handle (CoglHandle handle) \
|
||||
@ -121,7 +121,8 @@ cogl_is_##type_name (CoglHandle handle) \
|
||||
if (handle == COGL_INVALID_HANDLE) \
|
||||
return FALSE; \
|
||||
\
|
||||
return (obj->klass->type == _cogl_##type_name##_get_type ()); \
|
||||
return (obj->klass->type == \
|
||||
_cogl_handle_##type_name##_get_type ()); \
|
||||
} \
|
||||
\
|
||||
CoglHandle G_GNUC_DEPRECATED \
|
||||
|
@ -68,15 +68,20 @@ struct _CoglMaterialLayer
|
||||
CoglHandle texture; /*!< The texture for this layer, or COGL_INVALID_HANDLE
|
||||
for an empty layer */
|
||||
|
||||
CoglMaterialFilter mag_filter;
|
||||
CoglMaterialFilter min_filter;
|
||||
|
||||
/* Determines how the color of individual texture fragments
|
||||
* are calculated. */
|
||||
CoglMaterialLayerCombineFunc texture_combine_rgb_func;
|
||||
CoglMaterialLayerCombineSrc texture_combine_rgb_src[3];
|
||||
CoglMaterialLayerCombineOp texture_combine_rgb_op[3];
|
||||
GLint texture_combine_rgb_func;
|
||||
GLint texture_combine_rgb_src[3];
|
||||
GLint texture_combine_rgb_op[3];
|
||||
|
||||
CoglMaterialLayerCombineFunc texture_combine_alpha_func;
|
||||
CoglMaterialLayerCombineSrc texture_combine_alpha_src[3];
|
||||
CoglMaterialLayerCombineOp texture_combine_alpha_op[3];
|
||||
GLint texture_combine_alpha_func;
|
||||
GLint texture_combine_alpha_src[3];
|
||||
GLint texture_combine_alpha_op[3];
|
||||
|
||||
GLfloat texture_combine_constant[4];
|
||||
|
||||
/* TODO: Support purely GLSL based material layers */
|
||||
|
||||
@ -114,11 +119,104 @@ struct _CoglMaterial
|
||||
GLfloat alpha_func_reference;
|
||||
|
||||
/* Determines how this material is blended with other primitives */
|
||||
CoglMaterialBlendFactor blend_src_factor;
|
||||
CoglMaterialBlendFactor blend_dst_factor;
|
||||
#ifndef HAVE_COGL_GLES
|
||||
GLenum blend_equation_rgb;
|
||||
GLenum blend_equation_alpha;
|
||||
GLint blend_src_factor_alpha;
|
||||
GLint blend_dst_factor_alpha;
|
||||
GLfloat blend_constant[4];
|
||||
#endif
|
||||
GLint blend_src_factor_rgb;
|
||||
GLint blend_dst_factor_rgb;
|
||||
|
||||
GList *layers;
|
||||
};
|
||||
|
||||
/*
|
||||
* SECTION:cogl-material-internals
|
||||
* @short_description: Functions for creating custom primitives that make use
|
||||
* of Cogl materials 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 material internals to support being
|
||||
* able to fill your geometry according to a given Cogl material.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* cogl_material_get_cogl_enable_flags:
|
||||
* @material: A CoglMaterial object
|
||||
*
|
||||
* This determines what flags need to be passed to cogl_enable before this
|
||||
* material can be used. Normally you shouldn't need to use this function
|
||||
* directly since Cogl will do this internally, but if you are developing
|
||||
* custom primitives directly with OpenGL you may want to use this.
|
||||
*
|
||||
* Note: This API is hopfully just a stop-gap solution. Ideally cogl_enable
|
||||
* will be replaced.
|
||||
*/
|
||||
/* TODO: find a nicer solution! */
|
||||
gulong _cogl_material_get_cogl_enable_flags (CoglHandle handle);
|
||||
|
||||
/*
|
||||
* CoglMaterialLayerFlags:
|
||||
* @COGL_MATERIAL_LAYER_FLAG_USER_MATRIX: Means the user has supplied a
|
||||
* custom texture matrix.
|
||||
*/
|
||||
typedef enum _CoglMaterialLayerFlags
|
||||
{
|
||||
COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX = 1L<<0
|
||||
} CoglMaterialLayerFlags;
|
||||
/* XXX: NB: if you add flags here you will need to update
|
||||
* CoglMaterialLayerPrivFlags!!! */
|
||||
|
||||
/*
|
||||
* cogl_material_layer_get_flags:
|
||||
* @layer_handle: A CoglMaterialLayer layer handle
|
||||
*
|
||||
* This lets you get a number of flag attributes about the layer. Normally
|
||||
* you shouldn't need to use this function directly since Cogl will do this
|
||||
* internally, but if you are developing custom primitives directly with
|
||||
* OpenGL you may need this.
|
||||
*/
|
||||
gulong _cogl_material_layer_get_flags (CoglHandle layer_handle);
|
||||
|
||||
/*
|
||||
* CoglMaterialFlushOption:
|
||||
* @COGL_MATERIAL_FLUSH_FALLBACK_MASK: Follow this by a guin32 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_MATERIAL_FLUSH_DISABLE_MASK: Follow this by a guint32 mask
|
||||
* of the layers that you want to completly disable texturing for
|
||||
* (1 = fallback, and the least significant bit = layer 0)
|
||||
* @COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE: Follow this by a GLuint OpenGL texture
|
||||
* name to override the texture used for layer 0 of the material. 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.
|
||||
*/
|
||||
typedef enum _CoglMaterialFlushOption
|
||||
{
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK = 1,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
} CoglMaterialFlushOption;
|
||||
|
||||
/*
|
||||
* cogl_material_flush_gl_state:
|
||||
* @material: A CoglMaterial object
|
||||
* @...: A NULL terminated list of (CoglMaterialFlushOption, data) pairs
|
||||
*
|
||||
* This function commits the state of the specified CoglMaterial - including
|
||||
* the texture state for all the layers - to the OpenGL[ES] driver.
|
||||
*
|
||||
* Since 1.0
|
||||
*/
|
||||
void _cogl_material_flush_gl_state (CoglHandle material,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
|
||||
|
||||
#endif /* __COGL_MATERIAL_PRIVATE_H */
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-blend-string.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
@ -50,6 +51,10 @@
|
||||
#ifdef HAVE_COGL_GL
|
||||
#define glActiveTexture ctx->pf_glActiveTexture
|
||||
#define glClientActiveTexture ctx->pf_glClientActiveTexture
|
||||
#define glBlendFuncSeparate ctx->pf_glBlendFuncSeparate
|
||||
#define glBlendEquation ctx->pf_glBlendEquation
|
||||
#define glBlendColor ctx->pf_glBlendColor
|
||||
#define glBlendEquationSeparate ctx->pf_glBlendEquationSeparate
|
||||
#endif
|
||||
|
||||
static void _cogl_material_free (CoglMaterial *tex);
|
||||
@ -60,6 +65,12 @@ COGL_HANDLE_DEFINE (MaterialLayer, material_layer);
|
||||
|
||||
/* #define DISABLE_MATERIAL_CACHE 1 */
|
||||
|
||||
GQuark
|
||||
_cogl_material_error_quark (void)
|
||||
{
|
||||
return g_quark_from_static_string ("cogl-material-error-quark");
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_material_new (void)
|
||||
{
|
||||
@ -88,8 +99,18 @@ cogl_material_new (void)
|
||||
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC;
|
||||
|
||||
/* Not the same as the GL default, but seems saner... */
|
||||
material->blend_src_factor = COGL_MATERIAL_BLEND_FACTOR_SRC_ALPHA;
|
||||
material->blend_dst_factor = COGL_MATERIAL_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
#ifndef HAVE_COGL_GLES
|
||||
material->blend_equation_rgb = GL_FUNC_ADD;
|
||||
material->blend_equation_alpha = GL_FUNC_ADD;
|
||||
material->blend_src_factor_alpha = GL_SRC_ALPHA;
|
||||
material->blend_dst_factor_alpha = GL_ONE_MINUS_SRC_ALPHA;
|
||||
material->blend_constant[0] = 0;
|
||||
material->blend_constant[1] = 0;
|
||||
material->blend_constant[2] = 0;
|
||||
material->blend_constant[3] = 0;
|
||||
#endif
|
||||
material->blend_src_factor_rgb = GL_SRC_ALPHA;
|
||||
material->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
|
||||
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
|
||||
|
||||
material->layers = NULL;
|
||||
@ -408,20 +429,177 @@ cogl_material_set_alpha_test_function (CoglHandle handle,
|
||||
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_ALPHA_FUNC;
|
||||
}
|
||||
|
||||
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_RGB)
|
||||
{
|
||||
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_RGB)
|
||||
{
|
||||
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_RGB)
|
||||
{
|
||||
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
|
||||
cogl_material_set_blend_factors (CoglHandle handle,
|
||||
CoglMaterialBlendFactor src_factor,
|
||||
CoglMaterialBlendFactor dst_factor)
|
||||
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_material_set_blend (CoglHandle handle,
|
||||
const char *blend_description,
|
||||
GError **error)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglBlendStringStatement statements[2];
|
||||
CoglBlendStringStatement split[2];
|
||||
CoglBlendStringStatement *rgb;
|
||||
CoglBlendStringStatement *a;
|
||||
int count;
|
||||
|
||||
g_return_val_if_fail (cogl_is_material (handle), FALSE);
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
|
||||
count =
|
||||
_cogl_blend_string_compile (blend_description,
|
||||
COGL_BLEND_STRING_CONTEXT_BLENDING,
|
||||
statements,
|
||||
error);
|
||||
if (!count)
|
||||
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];
|
||||
}
|
||||
|
||||
#ifndef HAVE_COGL_GLES
|
||||
setup_blend_state (rgb,
|
||||
&material->blend_equation_rgb,
|
||||
&material->blend_src_factor_rgb,
|
||||
&material->blend_dst_factor_rgb);
|
||||
setup_blend_state (a,
|
||||
&material->blend_equation_alpha,
|
||||
&material->blend_src_factor_alpha,
|
||||
&material->blend_dst_factor_alpha);
|
||||
#else
|
||||
setup_blend_state (rgb,
|
||||
NULL,
|
||||
&material->blend_src_factor_rgb,
|
||||
&material->blend_dst_factor_rgb);
|
||||
#endif
|
||||
|
||||
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_blend_constant (CoglHandle handle,
|
||||
CoglColor *constant_color)
|
||||
{
|
||||
#ifndef HAVE_COGL_GLES
|
||||
CoglMaterial *material;
|
||||
GLfloat *constant;
|
||||
|
||||
g_return_if_fail (cogl_is_material (handle));
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
material->blend_src_factor = src_factor;
|
||||
material->blend_dst_factor = dst_factor;
|
||||
|
||||
constant = material->blend_constant;
|
||||
constant[0] = cogl_color_get_red_float (constant_color);
|
||||
constant[1] = cogl_color_get_green_float (constant_color);
|
||||
constant[2] = cogl_color_get_blue_float (constant_color);
|
||||
constant[3] = cogl_color_get_alpha_float (constant_color);
|
||||
|
||||
material->flags &= ~COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Asserts that a layer corresponding to the given index exists. If no
|
||||
@ -459,25 +637,22 @@ _cogl_material_get_layer (CoglMaterial *material,
|
||||
layer_handle = _cogl_material_layer_handle_new (layer);
|
||||
layer->index = index_;
|
||||
layer->flags = COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
|
||||
layer->mag_filter = COGL_MATERIAL_FILTER_LINEAR;
|
||||
layer->min_filter = COGL_MATERIAL_FILTER_LINEAR;
|
||||
layer->texture = COGL_INVALID_HANDLE;
|
||||
|
||||
/* Choose the same default combine mode as OpenGL:
|
||||
* MODULATE(PREVIOUS[RGBA],TEXTURE[RGBA]) */
|
||||
layer->texture_combine_rgb_func = COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE;
|
||||
layer->texture_combine_rgb_src[0] = COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS;
|
||||
layer->texture_combine_rgb_src[1] = COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE;
|
||||
layer->texture_combine_rgb_op[0] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR;
|
||||
layer->texture_combine_rgb_op[1] = COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR;
|
||||
layer->texture_combine_alpha_func =
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE;
|
||||
layer->texture_combine_alpha_src[0] =
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_PREVIOUS;
|
||||
layer->texture_combine_alpha_src[1] =
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE;
|
||||
layer->texture_combine_alpha_op[0] =
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA;
|
||||
layer->texture_combine_alpha_op[1] =
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA;
|
||||
layer->texture_combine_rgb_func = GL_MODULATE;
|
||||
layer->texture_combine_rgb_src[0] = GL_PREVIOUS;
|
||||
layer->texture_combine_rgb_src[1] = GL_TEXTURE;
|
||||
layer->texture_combine_rgb_op[0] = GL_SRC_COLOR;
|
||||
layer->texture_combine_rgb_op[1] = GL_SRC_COLOR;
|
||||
layer->texture_combine_alpha_func = GL_MODULATE;
|
||||
layer->texture_combine_alpha_src[0] = GL_PREVIOUS;
|
||||
layer->texture_combine_alpha_src[1] = GL_TEXTURE;
|
||||
layer->texture_combine_alpha_op[0] = GL_SRC_ALPHA;
|
||||
layer->texture_combine_alpha_op[1] = GL_SRC_ALPHA;
|
||||
|
||||
cogl_matrix_init_identity (&layer->matrix);
|
||||
|
||||
@ -498,7 +673,8 @@ cogl_material_set_layer (CoglHandle material_handle,
|
||||
int n_layers;
|
||||
|
||||
g_return_if_fail (cogl_is_material (material_handle));
|
||||
g_return_if_fail (cogl_is_texture (texture_handle));
|
||||
g_return_if_fail (texture_handle == COGL_INVALID_HANDLE
|
||||
|| cogl_is_texture (texture_handle));
|
||||
|
||||
material = _cogl_material_pointer_from_handle (material_handle);
|
||||
layer = _cogl_material_get_layer (material_handle, layer_index, TRUE);
|
||||
@ -519,7 +695,8 @@ cogl_material_set_layer (CoglHandle material_handle,
|
||||
* MAX_COMBINED_TEXTURE_IMAGE_UNITS layers. */
|
||||
}
|
||||
|
||||
cogl_handle_ref (texture_handle);
|
||||
if (texture_handle)
|
||||
cogl_handle_ref (texture_handle);
|
||||
|
||||
if (layer->texture)
|
||||
cogl_handle_unref (layer->texture);
|
||||
@ -530,104 +707,164 @@ cogl_material_set_layer (CoglHandle material_handle,
|
||||
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_layer_combine_function (
|
||||
CoglHandle handle,
|
||||
gint layer_index,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineFunc func)
|
||||
static void
|
||||
setup_texture_combine_state (CoglBlendStringStatement *statement,
|
||||
GLint *texture_combine_func,
|
||||
GLint *texture_combine_src,
|
||||
GLint *texture_combine_op)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (statement->function->type)
|
||||
{
|
||||
case COGL_BLEND_STRING_FUNCTION_AUTO_COMPOSITE:
|
||||
*texture_combine_func = GL_MODULATE; /* FIXME */
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_REPLACE:
|
||||
*texture_combine_func = GL_REPLACE;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_MODULATE:
|
||||
*texture_combine_func = GL_MODULATE;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_ADD:
|
||||
*texture_combine_func = GL_ADD;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_ADD_SIGNED:
|
||||
*texture_combine_func = GL_ADD_SIGNED;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_INTERPOLATE:
|
||||
*texture_combine_func = GL_INTERPOLATE;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_SUBTRACT:
|
||||
*texture_combine_func = GL_SUBTRACT;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_DOT3_RGB:
|
||||
*texture_combine_func = GL_DOT3_RGB;
|
||||
break;
|
||||
case COGL_BLEND_STRING_FUNCTION_DOT3_RGBA:
|
||||
*texture_combine_func = GL_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] = GL_CONSTANT;
|
||||
break;
|
||||
case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE:
|
||||
texture_combine_src[i] = GL_TEXTURE;
|
||||
break;
|
||||
case COGL_BLEND_STRING_COLOR_SOURCE_TEXTURE_N:
|
||||
texture_combine_src[i] =
|
||||
GL_TEXTURE0 + arg->source.texture;
|
||||
break;
|
||||
case COGL_BLEND_STRING_COLOR_SOURCE_PRIMARY:
|
||||
texture_combine_src[i] = GL_PRIMARY_COLOR;
|
||||
break;
|
||||
case COGL_BLEND_STRING_COLOR_SOURCE_PREVIOUS:
|
||||
texture_combine_src[i] = GL_PREVIOUS;
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unexpected texture combine source");
|
||||
texture_combine_src[i] = GL_TEXTURE;
|
||||
}
|
||||
|
||||
if (arg->source.mask == COGL_BLEND_STRING_CHANNEL_MASK_RGB)
|
||||
{
|
||||
if (statement->args[i].source.one_minus)
|
||||
texture_combine_op[i] = GL_ONE_MINUS_SRC_COLOR;
|
||||
else
|
||||
texture_combine_op[i] = GL_SRC_COLOR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (statement->args[i].source.one_minus)
|
||||
texture_combine_op[i] = GL_ONE_MINUS_SRC_ALPHA;
|
||||
else
|
||||
texture_combine_op[i] = GL_SRC_ALPHA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_material_set_layer_combine (CoglHandle handle,
|
||||
gint layer_index,
|
||||
const char *combine_description,
|
||||
GError **error)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglMaterialLayer *layer;
|
||||
gboolean set_alpha_func = FALSE;
|
||||
gboolean set_rgb_func = FALSE;
|
||||
CoglBlendStringStatement statements[2];
|
||||
CoglBlendStringStatement split[2];
|
||||
CoglBlendStringStatement *rgb;
|
||||
CoglBlendStringStatement *a;
|
||||
int count;
|
||||
|
||||
g_return_val_if_fail (cogl_is_material (handle), FALSE);
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
layer = _cogl_material_get_layer (material, layer_index, TRUE);
|
||||
|
||||
count =
|
||||
_cogl_blend_string_compile (combine_description,
|
||||
COGL_BLEND_STRING_CONTEXT_TEXTURE_COMBINE,
|
||||
statements,
|
||||
error);
|
||||
if (!count)
|
||||
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];
|
||||
}
|
||||
|
||||
setup_texture_combine_state (rgb,
|
||||
&layer->texture_combine_rgb_func,
|
||||
layer->texture_combine_rgb_src,
|
||||
layer->texture_combine_rgb_op);
|
||||
|
||||
setup_texture_combine_state (a,
|
||||
&layer->texture_combine_alpha_func,
|
||||
layer->texture_combine_alpha_src,
|
||||
layer->texture_combine_alpha_op);
|
||||
|
||||
|
||||
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_layer_combine_constant (CoglHandle handle,
|
||||
gint layer_index,
|
||||
CoglColor *constant_color)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglMaterialLayer *layer;
|
||||
GLfloat *constant;
|
||||
|
||||
g_return_if_fail (cogl_is_material (handle));
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
layer = _cogl_material_get_layer (material, layer_index, TRUE);
|
||||
|
||||
if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
|
||||
set_alpha_func = set_rgb_func = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
|
||||
set_rgb_func = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
|
||||
set_alpha_func = TRUE;
|
||||
|
||||
if (set_rgb_func)
|
||||
layer->texture_combine_rgb_func = func;
|
||||
if (set_alpha_func)
|
||||
layer->texture_combine_alpha_func = func;
|
||||
|
||||
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_layer_combine_arg_src (
|
||||
CoglHandle handle,
|
||||
gint layer_index,
|
||||
gint argument,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineSrc src)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglMaterialLayer *layer;
|
||||
gboolean set_arg_alpha_src = FALSE;
|
||||
gboolean set_arg_rgb_src = FALSE;
|
||||
|
||||
g_return_if_fail (cogl_is_material (handle));
|
||||
g_return_if_fail (argument >=0 && argument <= 3);
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
layer = _cogl_material_get_layer (material, layer_index, TRUE);
|
||||
|
||||
if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
|
||||
set_arg_alpha_src = set_arg_rgb_src = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
|
||||
set_arg_rgb_src = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
|
||||
set_arg_alpha_src = TRUE;
|
||||
|
||||
if (set_arg_rgb_src)
|
||||
layer->texture_combine_rgb_src[argument] = src;
|
||||
if (set_arg_alpha_src)
|
||||
layer->texture_combine_alpha_src[argument] = src;
|
||||
|
||||
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_layer_combine_arg_op (
|
||||
CoglHandle material_handle,
|
||||
gint layer_index,
|
||||
gint argument,
|
||||
CoglMaterialLayerCombineChannels channels,
|
||||
CoglMaterialLayerCombineOp op)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglMaterialLayer *layer;
|
||||
gboolean set_arg_alpha_op = FALSE;
|
||||
gboolean set_arg_rgb_op = FALSE;
|
||||
|
||||
g_return_if_fail (cogl_is_material (material_handle));
|
||||
g_return_if_fail (argument >=0 && argument <= 3);
|
||||
|
||||
material = _cogl_material_pointer_from_handle (material_handle);
|
||||
layer = _cogl_material_get_layer (material, layer_index, TRUE);
|
||||
|
||||
if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGBA)
|
||||
set_arg_alpha_op = set_arg_rgb_op = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB)
|
||||
set_arg_rgb_op = TRUE;
|
||||
else if (channels == COGL_MATERIAL_LAYER_COMBINE_CHANNELS_ALPHA)
|
||||
set_arg_alpha_op = TRUE;
|
||||
|
||||
if (set_arg_rgb_op)
|
||||
layer->texture_combine_rgb_op[argument] = op;
|
||||
if (set_arg_alpha_op)
|
||||
layer->texture_combine_alpha_op[argument] = op;
|
||||
constant = layer->texture_combine_constant;
|
||||
constant[0] = cogl_color_get_red_float (constant_color);
|
||||
constant[1] = cogl_color_get_green_float (constant_color);
|
||||
constant[2] = cogl_color_get_blue_float (constant_color);
|
||||
constant[3] = cogl_color_get_alpha_float (constant_color);
|
||||
|
||||
layer->flags |= COGL_MATERIAL_LAYER_FLAG_DIRTY;
|
||||
layer->flags &= ~COGL_MATERIAL_LAYER_FLAG_DEFAULT_COMBINE;
|
||||
@ -690,7 +927,7 @@ cogl_material_remove_layer (CoglHandle material_handle,
|
||||
/* XXX: This API is hopfully just a stop-gap solution. Ideally cogl_enable
|
||||
* will be replaced. */
|
||||
gulong
|
||||
cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
|
||||
_cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
gulong enable_flags = 0;
|
||||
@ -713,7 +950,7 @@ cogl_material_get_cogl_enable_flags (CoglHandle material_handle)
|
||||
* probably sensible to try and avoid list manipulation for every
|
||||
* primitive emitted in a scene, every frame.
|
||||
*
|
||||
* Alternativly; we could either add a _foreach function, or maybe
|
||||
* Alternatively; we could either add a _foreach function, or maybe
|
||||
* a function that gets a passed a buffer (that may be stack allocated)
|
||||
* by the caller.
|
||||
*/
|
||||
@ -748,7 +985,7 @@ cogl_material_layer_get_texture (CoglHandle layer_handle)
|
||||
}
|
||||
|
||||
gulong
|
||||
cogl_material_layer_get_flags (CoglHandle layer_handle)
|
||||
_cogl_material_layer_get_flags (CoglHandle layer_handle)
|
||||
{
|
||||
CoglMaterialLayer *layer;
|
||||
|
||||
@ -760,25 +997,34 @@ cogl_material_layer_get_flags (CoglHandle layer_handle)
|
||||
}
|
||||
|
||||
static guint
|
||||
get_n_args_for_combine_func (CoglMaterialLayerCombineFunc func)
|
||||
get_n_args_for_combine_func (GLint func)
|
||||
{
|
||||
switch (func)
|
||||
{
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE:
|
||||
case GL_REPLACE:
|
||||
return 1;
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_MODULATE:
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD:
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_ADD_SIGNED:
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_SUBTRACT:
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGB:
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_DOT3_RGBA:
|
||||
case GL_MODULATE:
|
||||
case GL_ADD:
|
||||
case GL_ADD_SIGNED:
|
||||
case GL_SUBTRACT:
|
||||
case GL_DOT3_RGB:
|
||||
case GL_DOT3_RGBA:
|
||||
return 2;
|
||||
case COGL_MATERIAL_LAYER_COMBINE_FUNC_INTERPOLATE:
|
||||
case GL_INTERPOLATE:
|
||||
return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_mipmap_filter (CoglMaterialFilter filter)
|
||||
{
|
||||
return (filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_NEAREST
|
||||
|| filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_NEAREST
|
||||
|| filter == COGL_MATERIAL_FILTER_NEAREST_MIPMAP_LINEAR
|
||||
|| filter == COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
|
||||
CoglLayerInfo *gl_layer_info)
|
||||
@ -851,6 +1097,9 @@ _cogl_material_layer_flush_gl_sampler_state (CoglMaterialLayer *layer,
|
||||
GE (glTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_ALPHA,
|
||||
layer->texture_combine_alpha_op[2]));
|
||||
}
|
||||
|
||||
GE (glTexEnvfv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR,
|
||||
layer->texture_combine_constant));
|
||||
}
|
||||
|
||||
#ifndef DISABLE_MATERIAL_CACHE
|
||||
@ -976,6 +1225,13 @@ _cogl_material_flush_layers_gl_state (CoglMaterial *material,
|
||||
|
||||
GE (glActiveTexture (GL_TEXTURE0 + i));
|
||||
|
||||
_cogl_texture_set_filters (layer->texture,
|
||||
layer->min_filter,
|
||||
layer->mag_filter);
|
||||
if (is_mipmap_filter (layer->min_filter)
|
||||
|| is_mipmap_filter (layer->mag_filter))
|
||||
_cogl_texture_ensure_mipmaps (layer->texture);
|
||||
|
||||
/* FIXME: We could be more clever here and only bind the texture
|
||||
if it is different from gl_layer_info->gl_texture to avoid
|
||||
redundant GL calls. However a few other places in Cogl and
|
||||
@ -1122,12 +1378,44 @@ _cogl_material_flush_base_gl_state (CoglMaterial *material)
|
||||
if (!(ctx->current_material_flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC
|
||||
&& material->flags & COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC))
|
||||
{
|
||||
GE (glBlendFunc (material->blend_src_factor, material->blend_dst_factor));
|
||||
#if defined (HAVE_COGL_GLES2)
|
||||
gboolean have_blend_equation_seperate = TRUE;
|
||||
#elif defined (HAVE_COGL_GL)
|
||||
gboolean have_blend_equation_seperate = FALSE;
|
||||
if (ctx->pf_glBlendEquationSeparate) /* Only GL 2.0 + */
|
||||
have_blend_equation_seperate = TRUE;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_COGL_GLES /* GLES 1 only has glBlendFunc */
|
||||
if (material->blend_src_factor_rgb != material->blend_src_factor_alpha
|
||||
|| (material->blend_src_factor_rgb !=
|
||||
material->blend_src_factor_alpha))
|
||||
{
|
||||
if (have_blend_equation_seperate &&
|
||||
material->blend_equation_rgb != material->blend_equation_alpha)
|
||||
GE (glBlendEquationSeparate (material->blend_equation_rgb,
|
||||
material->blend_equation_alpha));
|
||||
else
|
||||
GE (glBlendEquation (material->blend_equation_rgb));
|
||||
|
||||
GE (glBlendFuncSeparate (material->blend_src_factor_rgb,
|
||||
material->blend_dst_factor_rgb,
|
||||
material->blend_src_factor_alpha,
|
||||
material->blend_dst_factor_alpha));
|
||||
GE (glBlendColor (material->blend_constant[0],
|
||||
material->blend_constant[1],
|
||||
material->blend_constant[2],
|
||||
material->blend_constant[3]));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
GE (glBlendFunc (material->blend_src_factor_rgb,
|
||||
material->blend_dst_factor_rgb));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_flush_gl_state (CoglHandle handle, ...)
|
||||
_cogl_material_flush_gl_state (CoglHandle handle, ...)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
va_list ap;
|
||||
@ -1204,3 +1492,44 @@ cogl_set_source_texture (CoglHandle texture_handle)
|
||||
cogl_set_source (ctx->default_material);
|
||||
}
|
||||
|
||||
CoglMaterialFilter
|
||||
cogl_material_layer_get_min_filter (CoglHandle layer_handle)
|
||||
{
|
||||
CoglMaterialLayer *layer;
|
||||
|
||||
g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0);
|
||||
|
||||
layer = _cogl_material_layer_pointer_from_handle (layer_handle);
|
||||
|
||||
return layer->min_filter;
|
||||
}
|
||||
|
||||
CoglMaterialFilter
|
||||
cogl_material_layer_get_mag_filter (CoglHandle layer_handle)
|
||||
{
|
||||
CoglMaterialLayer *layer;
|
||||
|
||||
g_return_val_if_fail (cogl_is_material_layer (layer_handle), 0);
|
||||
|
||||
layer = _cogl_material_layer_pointer_from_handle (layer_handle);
|
||||
|
||||
return layer->mag_filter;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_material_set_layer_filters (CoglHandle handle,
|
||||
gint layer_index,
|
||||
CoglMaterialFilter min_filter,
|
||||
CoglMaterialFilter mag_filter)
|
||||
{
|
||||
CoglMaterial *material;
|
||||
CoglMaterialLayer *layer;
|
||||
|
||||
g_return_if_fail (cogl_is_material (handle));
|
||||
|
||||
material = _cogl_material_pointer_from_handle (handle);
|
||||
layer = _cogl_material_get_layer (material, layer_index, TRUE);
|
||||
|
||||
layer->min_filter = min_filter;
|
||||
layer->mag_filter = mag_filter;
|
||||
}
|
||||
|
@ -257,6 +257,59 @@ _cogl_matrix_stack_multiply (CoglMatrixStack *stack,
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
cogl_matrix_frustum (&state->matrix,
|
||||
left, right, bottom, top,
|
||||
z_near, z_far);
|
||||
/* mark dirty */
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
cogl_matrix_perspective (&state->matrix,
|
||||
fov_y, aspect, z_near, z_far);
|
||||
/* mark dirty */
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
cogl_matrix_ortho (&state->matrix,
|
||||
left, right, bottom, top, z_near, z_far);
|
||||
/* mark dirty */
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||
CoglMatrix *matrix)
|
||||
@ -280,25 +333,6 @@ _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
cogl_matrix_frustum (&state->matrix,
|
||||
left, right, bottom, top,
|
||||
z_near, z_far);
|
||||
/* mark dirty */
|
||||
stack->flushed_state = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_matrix_stack_flush_to_gl (CoglMatrixStack *stack,
|
||||
GLenum gl_mode)
|
||||
|
@ -51,10 +51,6 @@ void _cogl_matrix_stack_rotate (CoglMatrixStack *stack,
|
||||
float z);
|
||||
void _cogl_matrix_stack_multiply (CoglMatrixStack *stack,
|
||||
const CoglMatrix *matrix);
|
||||
void _cogl_matrix_stack_get (CoglMatrixStack *stack,
|
||||
CoglMatrix *matrix);
|
||||
void _cogl_matrix_stack_set (CoglMatrixStack *stack,
|
||||
const CoglMatrix *matrix);
|
||||
void _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
|
||||
float left,
|
||||
float right,
|
||||
@ -62,6 +58,22 @@ void _cogl_matrix_stack_frustum (CoglMatrixStack *stack,
|
||||
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);
|
||||
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,
|
||||
GLenum gl_mode);
|
||||
|
||||
|
@ -151,21 +151,6 @@ cogl_matrix_invert (CoglMatrix *matrix)
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_matrix_frustum (CoglMatrix *matrix,
|
||||
float left,
|
||||
@ -208,6 +193,62 @@ cogl_matrix_frustum (CoglMatrix *matrix,
|
||||
cogl_matrix_multiply (matrix, matrix, &frustum);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_matrix_ortho (CoglMatrix *matrix,
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float near,
|
||||
float far)
|
||||
{
|
||||
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 - near);
|
||||
ortho.wz = 0.0;
|
||||
|
||||
/* column 3 */
|
||||
ortho.xw = -(right + left) / (right - left);
|
||||
ortho.yw = -(top + bottom) / (top - bottom);
|
||||
ortho.zw = -(far + near) / (far - near);
|
||||
ortho.ww = 1.0;
|
||||
|
||||
cogl_matrix_multiply (matrix, matrix, &ortho);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_matrix_init_from_array (CoglMatrix *matrix, const float *array)
|
||||
{
|
||||
@ -220,3 +261,19 @@ cogl_matrix_get_array (const CoglMatrix *matrix)
|
||||
return (float *)matrix;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -29,7 +29,8 @@
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material.h"
|
||||
#include "cogl-material-private.h"
|
||||
#include "cogl-vertex-buffer-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
@ -39,16 +40,8 @@
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
#define glDrawRangeElements ctx->pf_glDrawRangeElements
|
||||
#define glClientActiveTexture ctx->pf_glClientActiveTexture
|
||||
|
||||
#else
|
||||
|
||||
/* 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)
|
||||
|
||||
#endif
|
||||
|
||||
/* these are defined in the particular backend */
|
||||
@ -63,7 +56,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
gint batch_len,
|
||||
GLfloat *vertex_pointer)
|
||||
{
|
||||
int needed_indices;
|
||||
gsize stride;
|
||||
int i;
|
||||
gulong enable_flags = 0;
|
||||
@ -72,35 +64,6 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* The indices are always the same sequence regardless of the vertices so we
|
||||
* only need to change it if there are more vertices than ever before. */
|
||||
needed_indices = batch_len * 6;
|
||||
if (needed_indices > ctx->static_indices->len)
|
||||
{
|
||||
int old_len = ctx->static_indices->len;
|
||||
int vert_num = old_len / 6 * 4;
|
||||
GLushort *q;
|
||||
|
||||
/* Add two triangles for each quad to the list of
|
||||
indices. That makes six new indices but two of the
|
||||
vertices in the triangles are shared. */
|
||||
g_array_set_size (ctx->static_indices, needed_indices);
|
||||
q = &g_array_index (ctx->static_indices, GLushort, old_len);
|
||||
|
||||
for (i = old_len;
|
||||
i < ctx->static_indices->len;
|
||||
i += 6, vert_num += 4)
|
||||
{
|
||||
*(q++) = vert_num + 0;
|
||||
*(q++) = vert_num + 1;
|
||||
*(q++) = vert_num + 3;
|
||||
|
||||
*(q++) = vert_num + 1;
|
||||
*(q++) = vert_num + 2;
|
||||
*(q++) = vert_num + 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX NB:
|
||||
* Our vertex data is arranged as follows:
|
||||
* 4 vertices per quad: 2 GLfloats per position,
|
||||
@ -112,16 +75,16 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
disable_mask = (1 << batch_start->n_layers) - 1;
|
||||
disable_mask = ~disable_mask;
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
batch_start->fallback_mask,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
disable_mask,
|
||||
/* Redundant when dealing with unsliced
|
||||
* textures but does no harm... */
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
batch_start->layer0_override_texture,
|
||||
NULL);
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
batch_start->fallback_mask,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
disable_mask,
|
||||
/* Redundant when dealing with unsliced
|
||||
* textures but does no harm... */
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
batch_start->layer0_override_texture,
|
||||
NULL);
|
||||
|
||||
for (i = 0; i < batch_start->n_layers; i++)
|
||||
{
|
||||
@ -140,7 +103,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
|
||||
/* FIXME: This api is a bit yukky, ideally it will be removed if we
|
||||
* re-work the cogl_enable mechanism */
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
|
||||
if (ctx->enable_backface_culling)
|
||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||
@ -150,12 +113,32 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
|
||||
GE (glVertexPointer (2, GL_FLOAT, stride, vertex_pointer));
|
||||
_cogl_current_matrix_state_flush ();
|
||||
GE (glDrawRangeElements (GL_TRIANGLES,
|
||||
0, ctx->static_indices->len - 1,
|
||||
6 * batch_len,
|
||||
GL_UNSIGNED_SHORT,
|
||||
ctx->static_indices->data));
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
|
||||
GE( glDrawArrays (GL_QUADS, 0, batch_len * 4) );
|
||||
|
||||
#else /* HAVE_COGL_GL */
|
||||
|
||||
/* GLES doesn't support GL_QUADS so we will use GL_TRIANGLES and
|
||||
indices */
|
||||
{
|
||||
int needed_indices = batch_len * 6;
|
||||
CoglHandle indices_handle
|
||||
= cogl_vertex_buffer_indices_get_for_quads (needed_indices);
|
||||
CoglVertexBufferIndices *indices
|
||||
= _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
|
||||
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
|
||||
GPOINTER_TO_UINT (indices->vbo_name)));
|
||||
GE (glDrawElements (GL_TRIANGLES,
|
||||
6 * batch_len,
|
||||
indices->type,
|
||||
NULL));
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
#endif /* HAVE_COGL_GL */
|
||||
|
||||
/* DEBUGGING CODE XXX:
|
||||
* This path will cause all rectangles to be drawn with a red, green
|
||||
@ -177,7 +160,7 @@ _cogl_journal_flush_quad_batch (CoglJournalEntry *batch_start,
|
||||
color == 1 ? 0xff : 0x00,
|
||||
color == 2 ? 0xff : 0x00,
|
||||
0xff);
|
||||
cogl_material_flush_gl_state (outline, NULL);
|
||||
_cogl_material_flush_gl_state (outline, NULL);
|
||||
_cogl_current_matrix_state_flush ();
|
||||
GE( glDrawArrays (GL_LINE_LOOP, 4 * i, 4) );
|
||||
}
|
||||
@ -791,7 +774,7 @@ _cogl_rectangles_with_multitexture_coords (
|
||||
/* We don't support multi texturing using textures with any waste if the
|
||||
* user has supplied a custom texture matrix, since we don't know if
|
||||
* the result will end up trying to texture from the waste area. */
|
||||
flags = cogl_material_layer_get_flags (layer);
|
||||
flags = _cogl_material_layer_get_flags (layer);
|
||||
if (flags & COGL_MATERIAL_LAYER_FLAG_HAS_USER_MATRIX
|
||||
&& _cogl_texture_span_has_waste (texture, 0, 0))
|
||||
{
|
||||
@ -1041,13 +1024,13 @@ _cogl_texture_sliced_polygon (CoglTextureVertex *vertices,
|
||||
v += stride;
|
||||
}
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~1, /* disable all except the
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~1, /* disable all except the
|
||||
first layer */
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
gl_handle,
|
||||
NULL);
|
||||
COGL_MATERIAL_FLUSH_LAYER0_OVERRIDE,
|
||||
gl_handle,
|
||||
NULL);
|
||||
_cogl_current_matrix_state_flush ();
|
||||
|
||||
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
|
||||
@ -1136,10 +1119,10 @@ _cogl_multitexture_unsliced_polygon (CoglTextureVertex *vertices,
|
||||
c[3] = cogl_color_get_alpha_float (&vertices[i].color);
|
||||
}
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
fallback_mask,
|
||||
NULL);
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
fallback_mask,
|
||||
NULL);
|
||||
_cogl_current_matrix_state_flush ();
|
||||
|
||||
GE (glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices));
|
||||
@ -1175,7 +1158,6 @@ cogl_polygon (CoglTextureVertex *vertices,
|
||||
{
|
||||
CoglHandle layer = (CoglHandle)tmp->data;
|
||||
CoglHandle tex_handle = cogl_material_layer_get_texture (layer);
|
||||
CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle);
|
||||
|
||||
if (i == 0 && cogl_texture_is_sliced (tex_handle))
|
||||
{
|
||||
@ -1203,7 +1185,8 @@ cogl_polygon (CoglTextureVertex *vertices,
|
||||
use_sliced_polygon_fallback = TRUE;
|
||||
n_layers = 1;
|
||||
|
||||
if (tex->min_filter != GL_NEAREST || tex->mag_filter != GL_NEAREST)
|
||||
if (cogl_material_layer_get_min_filter (layer) != GL_NEAREST
|
||||
|| cogl_material_layer_get_mag_filter (layer) != GL_NEAREST)
|
||||
{
|
||||
static gboolean warning_seen = FALSE;
|
||||
if (!warning_seen)
|
||||
@ -1217,11 +1200,14 @@ cogl_polygon (CoglTextureVertex *vertices,
|
||||
}
|
||||
|
||||
#ifdef HAVE_COGL_GL
|
||||
/* Temporarily change the wrapping mode on all of the slices to use
|
||||
* a transparent border
|
||||
* XXX: it's doesn't look like we save/restore this, like the comment
|
||||
* implies? */
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER);
|
||||
{
|
||||
CoglTexture *tex = _cogl_texture_pointer_from_handle (tex_handle);
|
||||
/* Temporarily change the wrapping mode on all of the slices to use
|
||||
* a transparent border
|
||||
* XXX: it's doesn't look like we save/restore this, like
|
||||
* the comment implies? */
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_BORDER);
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -1254,7 +1240,7 @@ cogl_polygon (CoglTextureVertex *vertices,
|
||||
|
||||
/* Prepare GL state */
|
||||
enable_flags = COGL_ENABLE_VERTEX_ARRAY;
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
|
||||
if (ctx->enable_backface_culling)
|
||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||
|
@ -103,159 +103,6 @@ cogl_handle_get_type (void)
|
||||
return our_type;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_pixel_format_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ COGL_PIXEL_FORMAT_ANY, "COGL_PIXEL_FORMAT_ANY", "any" },
|
||||
{ COGL_PIXEL_FORMAT_A_8, "COGL_PIXEL_FORMAT_A_8", "a-8" },
|
||||
{ COGL_PIXEL_FORMAT_RGB_565, "COGL_PIXEL_FORMAT_RGB_565", "rgb-565" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_4444, "COGL_PIXEL_FORMAT_RGBA_4444", "rgba-4444" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_5551, "COGL_PIXEL_FORMAT_RGBA_5551", "rgba-5551" },
|
||||
{ COGL_PIXEL_FORMAT_YUV, "COGL_PIXEL_FORMAT_YUV", "yuv" },
|
||||
{ COGL_PIXEL_FORMAT_G_8, "COGL_PIXEL_FORMAT_G_8", "g-8" },
|
||||
{ COGL_PIXEL_FORMAT_RGB_888, "COGL_PIXEL_FORMAT_RGB_888", "rgb-888" },
|
||||
{ COGL_PIXEL_FORMAT_BGR_888, "COGL_PIXEL_FORMAT_BGR_888", "bgr-888" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_8888, "COGL_PIXEL_FORMAT_RGBA_8888", "rgba-8888" },
|
||||
{ COGL_PIXEL_FORMAT_BGRA_8888, "COGL_PIXEL_FORMAT_BGRA_8888", "bgra-8888" },
|
||||
{ COGL_PIXEL_FORMAT_ARGB_8888, "COGL_PIXEL_FORMAT_ARGB_8888", "argb-8888" },
|
||||
{ COGL_PIXEL_FORMAT_ABGR_8888, "COGL_PIXEL_FORMAT_ABGR_8888", "abgr-8888" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_8888_PRE, "COGL_PIXEL_FORMAT_RGBA_8888_PRE", "rgba-8888-pre" },
|
||||
{ COGL_PIXEL_FORMAT_BGRA_8888_PRE, "COGL_PIXEL_FORMAT_BGRA_8888_PRE", "bgra-8888-pre" },
|
||||
{ COGL_PIXEL_FORMAT_ARGB_8888_PRE, "COGL_PIXEL_FORMAT_ARGB_8888_PRE", "argb-8888-pre" },
|
||||
{ COGL_PIXEL_FORMAT_ABGR_8888_PRE, "COGL_PIXEL_FORMAT_ABGR_8888_PRE", "abgr-8888-pre" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_4444_PRE, "COGL_PIXEL_FORMAT_RGBA_4444_PRE", "rgba-4444-pre" },
|
||||
{ COGL_PIXEL_FORMAT_RGBA_5551_PRE, "COGL_PIXEL_FORMAT_RGBA_5551_PRE", "rgba-5551-pre" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_enum_register_static (g_intern_static_string ("CoglPixelFormat"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_feature_flags_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GFlagsValue values[] = {
|
||||
{ COGL_FEATURE_TEXTURE_RECTANGLE, "COGL_FEATURE_TEXTURE_RECTANGLE", "texture-rectangle" },
|
||||
{ COGL_FEATURE_TEXTURE_NPOT, "COGL_FEATURE_TEXTURE_NPOT", "texture-npot" },
|
||||
{ COGL_FEATURE_TEXTURE_YUV, "COGL_FEATURE_TEXTURE_YUV", "yuv" },
|
||||
{ COGL_FEATURE_TEXTURE_READ_PIXELS, "COGL_FEATURE_TEXTURE_READ_PIXELS", "read-pixels" },
|
||||
{ COGL_FEATURE_SHADERS_GLSL, "COGL_FEATURE_SHADERS_GLSL", "shaders-glsl" },
|
||||
{ COGL_FEATURE_OFFSCREEN, "COGL_FEATURE_OFFSCREEN", "offscreen" },
|
||||
{ COGL_FEATURE_OFFSCREEN_MULTISAMPLE, "COGL_FEATURE_OFFSCREEN_MULTISAMPLE", "offscreen-multisample" },
|
||||
{ COGL_FEATURE_OFFSCREEN_BLIT, "COGL_FEATURE_OFFSCREEN_BLIT", "offscreen-blit" },
|
||||
{ COGL_FEATURE_FOUR_CLIP_PLANES, "COGL_FEATURE_FOUR_CLIP_PLANES", "four-clip-planes" },
|
||||
{ COGL_FEATURE_STENCIL_BUFFER, "COGL_FEATURE_STENCIL_BUFFER", "stencil-buffer" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_flags_register_static (g_intern_static_string ("CoglFeatureFlags"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_buffer_target_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GFlagsValue values[] = {
|
||||
{ COGL_WINDOW_BUFFER, "COGL_WINDOW_BUFFER", "window-buffer" },
|
||||
{ COGL_OFFSCREEN_BUFFER, "COGL_OFFSCREEN_BUFFER", "offscreen-buffer" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_flags_register_static (g_intern_static_string ("CoglBufferTarget"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_matrix_mode_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ COGL_MATRIX_MODELVIEW, "COGL_MATRIX_MODELVIEW", "modelview" },
|
||||
{ COGL_MATRIX_PROJECTION, "COGL_MATRIX_PROJECTION", "projection" },
|
||||
{ COGL_MATRIX_TEXTURE, "COGL_MATRIX_TEXTURE", "texture" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_enum_register_static (g_intern_static_string ("CoglMatrixMode"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_texture_flags_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GFlagsValue values[] = {
|
||||
{ COGL_TEXTURE_NONE, "COGL_TEXTURE_NONE", "none" },
|
||||
{ COGL_TEXTURE_AUTO_MIPMAP, "COGL_TEXTURE_AUTO_MIPMAP", "auto-mipmap" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_flags_register_static (g_intern_static_string ("CoglTextureFlags"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
GType
|
||||
cogl_fog_mode_get_type (void)
|
||||
{
|
||||
static GType gtype = 0;
|
||||
|
||||
if (G_UNLIKELY (gtype == 0))
|
||||
{
|
||||
static const GEnumValue values[] = {
|
||||
{ COGL_FOG_MODE_LINEAR, "COGL_FOG_MODE_LINEAR", "linear" },
|
||||
{ COGL_FOG_MODE_EXPONENTIAL, "COGL_FOG_MODE_EXPONENTIAL", "exponential" },
|
||||
{ COGL_FOG_MODE_EXPONENTIAL_SQUARED, "COGL_FOG_MODE_EXPONENTIAL_SQUARED", "exponential-squared" },
|
||||
{ 0, NULL, NULL }
|
||||
};
|
||||
|
||||
gtype =
|
||||
g_enum_register_static (g_intern_static_string ("CoglFogMode"),
|
||||
values);
|
||||
}
|
||||
|
||||
return gtype;
|
||||
}
|
||||
|
||||
/*
|
||||
* CoglFixed
|
||||
*/
|
||||
|
@ -99,9 +99,9 @@ typedef struct _CoglVertexBufferAttrib
|
||||
union _u
|
||||
{
|
||||
const void *pointer;
|
||||
gsize vbo_offset;
|
||||
size_t vbo_offset;
|
||||
} u;
|
||||
gsize span_bytes;
|
||||
size_t span_bytes;
|
||||
guint16 stride;
|
||||
guint8 n_components;
|
||||
guint8 texture_unit;
|
||||
@ -129,25 +129,41 @@ typedef struct _CoglVertexBufferVBO
|
||||
{
|
||||
CoglVertexBufferVBOFlags flags;
|
||||
|
||||
/* Note: this is a pointer to handle fallbacks, and normally holds
|
||||
* a GLuint value */
|
||||
gpointer vbo_name; /*!< The name of the corresponding buffer object */
|
||||
gsize vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */
|
||||
/* Note: this is a pointer to handle fallbacks. It normally holds
|
||||
* a GLuint VBO name, but when the driver doesn't support VBOs then
|
||||
* this simply points to an malloc'd buffer. */
|
||||
void *vbo_name; /*!< The name of the corresponding buffer object */
|
||||
size_t vbo_bytes; /*!< The lengh of the allocated buffer object in bytes */
|
||||
GList *attributes;
|
||||
} CoglVertexBufferVBO;
|
||||
|
||||
typedef struct _CoglVertexBufferIndices
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
|
||||
/* Note: this is a pointer to handle fallbacks. It normally holds
|
||||
* a GLuint VBO name, but when the driver doesn't support VBOs then
|
||||
* this simply points to an malloc'd buffer. */
|
||||
void *vbo_name;
|
||||
GLenum type;
|
||||
} CoglVertexBufferIndices;
|
||||
|
||||
typedef struct _CoglVertexBuffer
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
|
||||
guint n_vertices; /*!< The number of vertices in the buffer */
|
||||
GList *submitted_vbos; /* The VBOs currently submitted to the GPU */
|
||||
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 */
|
||||
GList *new_attributes; /*!< attributes pending submission */
|
||||
|
||||
} 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 */
|
||||
|
||||
|
@ -136,6 +136,7 @@
|
||||
#include "cogl-handle.h"
|
||||
#include "cogl-vertex-buffer-private.h"
|
||||
#include "cogl-texture-private.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#define PAD_FOR_ALIGNMENT(VAR, TYPE_SIZE) \
|
||||
(VAR = TYPE_SIZE + ((VAR - 1) & ~(TYPE_SIZE - 1)))
|
||||
@ -200,8 +201,10 @@
|
||||
#endif /* HAVE_COGL_GL */
|
||||
|
||||
static void _cogl_vertex_buffer_free (CoglVertexBuffer *buffer);
|
||||
static void _cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *buffer_indices);
|
||||
|
||||
COGL_HANDLE_DEFINE (VertexBuffer, vertex_buffer);
|
||||
COGL_HANDLE_DEFINE (VertexBufferIndices, vertex_buffer_indices);
|
||||
|
||||
CoglHandle
|
||||
cogl_vertex_buffer_new (guint n_vertices)
|
||||
@ -411,13 +414,13 @@ get_gl_type_size (CoglVertexBufferAttribFlags flags)
|
||||
}
|
||||
|
||||
void
|
||||
cogl_vertex_buffer_add (CoglHandle handle,
|
||||
const char *attribute_name,
|
||||
guint8 n_components,
|
||||
GLenum gl_type,
|
||||
gboolean normalized,
|
||||
guint16 stride,
|
||||
const void *pointer)
|
||||
cogl_vertex_buffer_add (CoglHandle handle,
|
||||
const char *attribute_name,
|
||||
guint8 n_components,
|
||||
CoglAttributeType type,
|
||||
gboolean normalized,
|
||||
guint16 stride,
|
||||
const void *pointer)
|
||||
{
|
||||
CoglVertexBuffer *buffer;
|
||||
GQuark name_quark = g_quark_from_string (attribute_name);
|
||||
@ -485,7 +488,7 @@ cogl_vertex_buffer_add (CoglHandle handle,
|
||||
attribute->u.pointer = pointer;
|
||||
attribute->texture_unit = texture_unit;
|
||||
|
||||
flags |= get_attribute_gl_type_flag_from_gl_type (gl_type);
|
||||
flags |= get_attribute_gl_type_flag_from_gl_type (type);
|
||||
flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_ENABLED;
|
||||
|
||||
/* Note: We currently just assume, if an attribute is *ever* updated
|
||||
@ -1638,14 +1641,14 @@ enable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
|
||||
}
|
||||
}
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
fallback_mask,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
disable_mask,
|
||||
NULL);
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_FALLBACK_MASK,
|
||||
fallback_mask,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
disable_mask,
|
||||
NULL);
|
||||
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
|
||||
if (ctx->enable_backface_culling)
|
||||
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
|
||||
@ -1716,23 +1719,21 @@ disable_state_for_drawing_buffer (CoglVertexBuffer *buffer)
|
||||
}
|
||||
|
||||
void
|
||||
cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
GLenum mode,
|
||||
GLint first,
|
||||
GLsizei count)
|
||||
cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
CoglVerticesMode mode,
|
||||
int first,
|
||||
int count)
|
||||
{
|
||||
CoglVertexBuffer *buffer;
|
||||
|
||||
if (!cogl_is_vertex_buffer (handle))
|
||||
return;
|
||||
|
||||
cogl_clip_ensure ();
|
||||
|
||||
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
||||
|
||||
enable_state_for_drawing_buffer (buffer);
|
||||
|
||||
cogl_clip_ensure ();
|
||||
_cogl_current_matrix_state_flush ();
|
||||
enable_state_for_drawing_buffer (buffer);
|
||||
|
||||
/* FIXME: flush cogl cache */
|
||||
GE (glDrawArrays (mode, first, count));
|
||||
@ -1740,35 +1741,127 @@ cogl_vertex_buffer_draw (CoglHandle handle,
|
||||
disable_state_for_drawing_buffer (buffer);
|
||||
}
|
||||
|
||||
static int
|
||||
get_indices_type_size (GLuint indices_type)
|
||||
{
|
||||
if (indices_type == GL_UNSIGNED_BYTE)
|
||||
return sizeof (GLubyte);
|
||||
if (indices_type == GL_UNSIGNED_SHORT)
|
||||
return sizeof (GLushort);
|
||||
else
|
||||
{
|
||||
g_critical ("Unknown indices type %d\n", indices_type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_vertex_buffer_indices_new (CoglIndicesType indices_type,
|
||||
const void *indices_array,
|
||||
int indices_len)
|
||||
{
|
||||
gboolean fallback =
|
||||
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
|
||||
size_t indices_bytes;
|
||||
CoglVertexBufferIndices *indices;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, 0);
|
||||
|
||||
indices = g_slice_alloc (sizeof (CoglVertexBufferIndices));
|
||||
|
||||
if (indices_type == COGL_INDICES_TYPE_UNSIGNED_BYTE)
|
||||
indices->type = GL_UNSIGNED_BYTE;
|
||||
else if (indices_type == COGL_INDICES_TYPE_UNSIGNED_SHORT)
|
||||
indices->type = GL_UNSIGNED_SHORT;
|
||||
else
|
||||
{
|
||||
g_critical ("unknown indices type %d", indices_type);
|
||||
g_slice_free (CoglVertexBufferIndices, indices);
|
||||
return 0;
|
||||
}
|
||||
|
||||
indices_bytes = get_indices_type_size (indices->type) * indices_len;
|
||||
if (fallback)
|
||||
{
|
||||
indices->vbo_name = g_malloc (indices_len);
|
||||
memcpy (indices->vbo_name, indices_array, indices_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
GE (glGenBuffers (1, (GLuint *)&indices->vbo_name));
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
|
||||
GPOINTER_TO_UINT (indices->vbo_name)));
|
||||
GE (glBufferData (GL_ELEMENT_ARRAY_BUFFER,
|
||||
indices_bytes,
|
||||
indices_array,
|
||||
GL_STATIC_DRAW));
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
return _cogl_vertex_buffer_indices_handle_new (indices);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_vertex_buffer_draw_elements (CoglHandle handle,
|
||||
GLenum mode,
|
||||
GLuint min_index,
|
||||
GLuint max_index,
|
||||
GLsizei count,
|
||||
GLenum indices_type,
|
||||
const GLvoid *indices)
|
||||
_cogl_vertex_buffer_indices_free (CoglVertexBufferIndices *indices)
|
||||
{
|
||||
gboolean fallback =
|
||||
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (fallback)
|
||||
g_free (indices->vbo_name);
|
||||
else
|
||||
GE (glDeleteBuffers (1, (GLuint *)&indices->vbo_name));
|
||||
|
||||
g_slice_free (CoglVertexBufferIndices, 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;
|
||||
gboolean fallback =
|
||||
(cogl_get_features () & COGL_FEATURE_VBOS) ? FALSE : TRUE;
|
||||
size_t byte_offset;
|
||||
CoglVertexBufferIndices *indices = NULL;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (!cogl_is_vertex_buffer (handle))
|
||||
return;
|
||||
|
||||
cogl_clip_ensure ();
|
||||
|
||||
buffer = _cogl_vertex_buffer_pointer_from_handle (handle);
|
||||
|
||||
if (!cogl_is_vertex_buffer_indices (indices_handle))
|
||||
return;
|
||||
|
||||
indices = _cogl_vertex_buffer_indices_pointer_from_handle (indices_handle);
|
||||
|
||||
cogl_clip_ensure ();
|
||||
_cogl_current_matrix_state_flush ();
|
||||
enable_state_for_drawing_buffer (buffer);
|
||||
|
||||
_cogl_current_matrix_state_flush ();
|
||||
byte_offset = indices_offset * get_indices_type_size (indices->type);
|
||||
if (fallback)
|
||||
byte_offset = (size_t)(((char *)indices->vbo_name) + byte_offset);
|
||||
else
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
|
||||
GPOINTER_TO_UINT (indices->vbo_name)));
|
||||
|
||||
/* FIXME: flush cogl cache */
|
||||
GE (glDrawRangeElements (mode, min_index, max_index,
|
||||
count, indices_type, indices));
|
||||
count, indices->type, (void *)byte_offset));
|
||||
|
||||
disable_state_for_drawing_buffer (buffer);
|
||||
|
||||
GE (glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1778,8 +1871,92 @@ _cogl_vertex_buffer_free (CoglVertexBuffer *buffer)
|
||||
|
||||
for (tmp = buffer->submitted_vbos; tmp != NULL; tmp = tmp->next)
|
||||
cogl_vertex_buffer_vbo_free (tmp->data, TRUE);
|
||||
g_list_free (buffer->submitted_vbos);
|
||||
|
||||
for (tmp = buffer->new_attributes; tmp != NULL; tmp = tmp->next)
|
||||
cogl_vertex_buffer_attribute_free (tmp->data);
|
||||
g_list_free (buffer->new_attributes);
|
||||
|
||||
g_slice_free (CoglVertexBuffer, buffer);
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_vertex_buffer_indices_get_for_quads (guint n_indices)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
|
||||
|
||||
/* Check if the indices would fit in a byte array */
|
||||
if (n_indices <= 256 / 4 * 6)
|
||||
{
|
||||
/* Generate the byte array if we haven't already */
|
||||
if (ctx->quad_indices_byte == COGL_INVALID_HANDLE)
|
||||
{
|
||||
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->quad_indices_byte
|
||||
= cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_BYTE,
|
||||
byte_array,
|
||||
256 / 4 * 6);
|
||||
|
||||
g_free (byte_array);
|
||||
}
|
||||
|
||||
return ctx->quad_indices_byte;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctx->quad_indices_short_len < n_indices)
|
||||
{
|
||||
guint16 *short_array;
|
||||
guint16 *p;
|
||||
int i, vert_num = 0;
|
||||
|
||||
if (ctx->quad_indices_short != COGL_INVALID_HANDLE)
|
||||
cogl_handle_unref (ctx->quad_indices_short);
|
||||
/* Pick a power of two >= MAX (512, n_indices) */
|
||||
if (ctx->quad_indices_short_len == 0)
|
||||
ctx->quad_indices_short_len = 512;
|
||||
while (ctx->quad_indices_short_len < n_indices)
|
||||
ctx->quad_indices_short_len *= 2;
|
||||
|
||||
/* Over-allocate to generate a whole number of quads */
|
||||
p = short_array = g_malloc ((ctx->quad_indices_short_len
|
||||
+ 5) / 6 * 6
|
||||
* sizeof (guint16));
|
||||
|
||||
/* Fill in the complete quads */
|
||||
for (i = 0; i < ctx->quad_indices_short_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->quad_indices_short
|
||||
= cogl_vertex_buffer_indices_new (COGL_INDICES_TYPE_UNSIGNED_SHORT,
|
||||
short_array,
|
||||
ctx->quad_indices_short_len);
|
||||
|
||||
g_free (short_array);
|
||||
}
|
||||
|
||||
return ctx->quad_indices_short;
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const guint8 *procName);
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#if defined (HAVE_COGL_GLES2) || defined (HAVE_COGL_GLES)
|
||||
#include "cogl-gles2-wrapper.h"
|
||||
@ -213,30 +214,39 @@ cogl_get_enable ()
|
||||
}
|
||||
|
||||
void
|
||||
cogl_enable_depth_test (gboolean setting)
|
||||
cogl_set_depth_test_enabled (gboolean setting)
|
||||
{
|
||||
if (setting)
|
||||
{
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glEnable (GL_ALPHA_TEST);
|
||||
glDepthFunc (GL_LEQUAL);
|
||||
glAlphaFunc (GL_GREATER, 0.1);
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
glDisable (GL_ALPHA_TEST);
|
||||
}
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_get_depth_test_enabled (void)
|
||||
{
|
||||
return glIsEnabled (GL_DEPTH_TEST) == GL_TRUE ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_enable_backface_culling (gboolean setting)
|
||||
cogl_set_backface_culling_enabled (gboolean setting)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
ctx->enable_backface_culling = setting;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_get_backface_culling_enabled (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
return ctx->enable_backface_culling;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_set_source_color (const CoglColor *color)
|
||||
{
|
||||
@ -375,7 +385,7 @@ _cogl_add_stencil_clip (float x_offset,
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
_cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
|
||||
if (first)
|
||||
{
|
||||
@ -465,12 +475,12 @@ cogl_viewport (guint width,
|
||||
}
|
||||
|
||||
void
|
||||
cogl_setup_viewport (guint width,
|
||||
guint height,
|
||||
float fovy,
|
||||
float aspect,
|
||||
float z_near,
|
||||
float z_far)
|
||||
_cogl_setup_viewport (guint width,
|
||||
guint height,
|
||||
float fovy,
|
||||
float aspect,
|
||||
float z_near,
|
||||
float z_far)
|
||||
{
|
||||
float z_camera;
|
||||
CoglMatrix projection_matrix;
|
||||
@ -478,7 +488,7 @@ cogl_setup_viewport (guint width,
|
||||
GE( glViewport (0, 0, width, height) );
|
||||
|
||||
/* For Ortho projection.
|
||||
* _cogl_current_matrix_ortho (0, width << 16, 0, height << 16, -1 << 16, 1 << 16);
|
||||
* _cogl_current_matrix_ortho (0, width, 0, height, -1, 1);
|
||||
*/
|
||||
|
||||
cogl_perspective (fovy, aspect, z_near, z_far);
|
||||
@ -532,7 +542,7 @@ cogl_setup_viewport (guint width,
|
||||
}
|
||||
|
||||
CoglFeatureFlags
|
||||
cogl_get_features ()
|
||||
cogl_get_features (void)
|
||||
{
|
||||
_COGL_GET_CONTEXT (ctx, 0);
|
||||
|
||||
@ -653,9 +663,11 @@ cogl_disable_fog (void)
|
||||
glDisable (GL_FOG);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void
|
||||
cogl_flush_gl_state (int flags)
|
||||
{
|
||||
_cogl_current_matrix_state_flush ();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -35,11 +35,6 @@ cogl_sources = \
|
||||
cogl-context.c \
|
||||
$(NULL)
|
||||
|
||||
coglincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/cogl
|
||||
coglinclude_HEADERS = \
|
||||
$(cogl_headers) \
|
||||
$(top_builddir)/clutter/cogl/cogl.h
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/clutter/cogl \
|
||||
-I$(top_srcdir)/clutter/cogl/common \
|
||||
@ -50,12 +45,12 @@ INCLUDES = \
|
||||
-DG_LOG_DOMAIN=\"Cogl-GL\" \
|
||||
-DCLUTTER_COMPILATION
|
||||
|
||||
noinst_LTLIBRARIES = libclutter-cogl.la
|
||||
noinst_LTLIBRARIES = libclutter-cogl-gl.la
|
||||
|
||||
libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_la_SOURCES = \
|
||||
libclutter_cogl_gl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
libclutter_cogl_gl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_gl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_gl_la_SOURCES = \
|
||||
$(top_builddir)/clutter/cogl/cogl.h \
|
||||
$(cogl_headers) \
|
||||
$(cogl_priv_headers) \
|
||||
|
@ -37,7 +37,7 @@
|
||||
static CoglContext *_context = NULL;
|
||||
static gboolean gl_is_indirect = FALSE;
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
cogl_create_context ()
|
||||
{
|
||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||
@ -69,7 +69,6 @@ cogl_create_context ()
|
||||
|
||||
_context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
|
||||
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
|
||||
_context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort));
|
||||
_context->polygon_vertices = g_array_new (FALSE, FALSE,
|
||||
sizeof (CoglTextureGLVertex));
|
||||
|
||||
@ -136,6 +135,9 @@ cogl_create_context ()
|
||||
_context->pf_glActiveTexture = NULL;
|
||||
_context->pf_glClientActiveTexture = NULL;
|
||||
|
||||
_context->pf_glBlendFuncSeparate = NULL;
|
||||
_context->pf_glBlendEquationSeparate = NULL;
|
||||
|
||||
/* Initialise the clip stack */
|
||||
_cogl_clip_stack_state_init ();
|
||||
|
||||
@ -146,8 +148,7 @@ cogl_create_context ()
|
||||
_context->default_gl_texture_2d_tex =
|
||||
cogl_texture_new_from_data (1, /* width */
|
||||
1, /* height */
|
||||
-1, /* max waste */
|
||||
COGL_TEXTURE_NONE, /* flags */
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
|
||||
/* internal format */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
@ -156,8 +157,7 @@ cogl_create_context ()
|
||||
_context->default_gl_texture_rect_tex =
|
||||
cogl_texture_new_from_data (1, /* width */
|
||||
1, /* height */
|
||||
-1, /* max waste */
|
||||
COGL_TEXTURE_NONE, /* flags */
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
|
||||
/* internal format */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
@ -165,16 +165,20 @@ cogl_create_context ()
|
||||
default_texture_data);
|
||||
|
||||
cogl_set_source (_context->default_material);
|
||||
cogl_material_flush_gl_state (_context->source_material, NULL);
|
||||
_cogl_material_flush_gl_state (_context->source_material, NULL);
|
||||
enable_flags =
|
||||
cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
||||
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||
_context->quad_indices_short_len = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_destroy_context ()
|
||||
_cogl_destroy_context ()
|
||||
{
|
||||
if (_context == NULL)
|
||||
return;
|
||||
@ -199,13 +203,16 @@ cogl_destroy_context ()
|
||||
if (_context->logged_vertices)
|
||||
g_array_free (_context->logged_vertices, TRUE);
|
||||
|
||||
if (_context->static_indices)
|
||||
g_array_free (_context->static_indices, TRUE);
|
||||
if (_context->polygon_vertices)
|
||||
g_array_free (_context->polygon_vertices, TRUE);
|
||||
if (_context->current_layers)
|
||||
g_array_free (_context->current_layers, TRUE);
|
||||
|
||||
if (_context->quad_indices_byte)
|
||||
cogl_handle_unref (_context->quad_indices_byte);
|
||||
if (_context->quad_indices_short)
|
||||
cogl_handle_unref (_context->quad_indices_short);
|
||||
|
||||
g_free (_context);
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@ typedef struct
|
||||
* can batch things together. */
|
||||
GArray *journal;
|
||||
GArray *logged_vertices;
|
||||
GArray *static_indices;
|
||||
GArray *polygon_vertices;
|
||||
|
||||
/* Some simple caching, to minimize state changes... */
|
||||
@ -102,6 +101,12 @@ typedef struct
|
||||
floatVec2 path_nodes_max;
|
||||
CoglHandle stencil_material;
|
||||
|
||||
/* Pre-generated VBOs containing indices to generate GL_TRIANGLES
|
||||
out of a vertex array of quads */
|
||||
CoglHandle quad_indices_byte;
|
||||
guint quad_indices_short_len;
|
||||
CoglHandle quad_indices_short;
|
||||
|
||||
/* Relying on glext.h to define these */
|
||||
COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT;
|
||||
COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT;
|
||||
@ -115,6 +120,7 @@ typedef struct
|
||||
COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT;
|
||||
COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT;
|
||||
COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT;
|
||||
COGL_PFNGLGENERATEMIPMAPEXTPROC pf_glGenerateMipmapEXT;
|
||||
|
||||
COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB;
|
||||
COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB;
|
||||
@ -164,6 +170,11 @@ typedef struct
|
||||
|
||||
COGL_PFNGLACTIVETEXTUREPROC pf_glActiveTexture;
|
||||
COGL_PFNGLCLIENTACTIVETEXTUREPROC pf_glClientActiveTexture;
|
||||
|
||||
COGL_PFNGLBLENDEQUATIONPROC pf_glBlendEquation;
|
||||
COGL_PFNGLBLENDCOLORPROC pf_glBlendColor;
|
||||
COGL_PFNGLBLENDFUNCSEPARATEPROC pf_glBlendFuncSeparate;
|
||||
COGL_PFNGLBLENDEQUATIONSEPARATEPROC pf_glBlendEquationSeparate;
|
||||
} CoglContext;
|
||||
|
||||
CoglContext *
|
||||
|
@ -773,6 +773,10 @@ typedef void
|
||||
GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLGENERATEMIPMAPEXTPROC)
|
||||
(GLenum target);
|
||||
|
||||
typedef GLhandleARB
|
||||
(APIENTRYP COGL_PFNGLCREATEPROGRAMOBJECTARBPROC)
|
||||
(void);
|
||||
@ -1020,6 +1024,29 @@ typedef void
|
||||
(APIENTRYP COGL_PFNGLCLIENTACTIVETEXTUREPROC)
|
||||
(GLenum texture);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLBLENDFUNCSEPARATEPROC)
|
||||
(GLenum srcRGB,
|
||||
GLenum dstRGB,
|
||||
GLenum srcAlpha,
|
||||
GLenum dstAlpha);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
|
||||
(GLenum modeRGB,
|
||||
GLenum modeAlpha);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLBLENDEQUATIONPROC)
|
||||
(GLenum mode);
|
||||
|
||||
typedef void
|
||||
(APIENTRYP COGL_PFNGLBLENDCOLORPROC)
|
||||
(GLclampf red,
|
||||
GLclampf green,
|
||||
GLclampf blue,
|
||||
GLclampf alpha);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-clip-stack.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
@ -78,13 +79,13 @@ _cogl_path_stroke_nodes ()
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~0, /* disable all texture layers */
|
||||
NULL);
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~0, /* disable all texture layers */
|
||||
NULL);
|
||||
_cogl_current_matrix_state_flush ();
|
||||
|
||||
while (path_start < ctx->path_nodes->len)
|
||||
@ -133,10 +134,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Just setup a simple material that doesn't use texturing... */
|
||||
cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
_cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
|
||||
enable_flags |=
|
||||
cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
_cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
_cogl_path_get_bounds (nodes_min, nodes_max,
|
||||
|
@ -108,22 +108,23 @@ cogl_shader_compile (CoglHandle handle)
|
||||
glCompileShaderARB (shader->gl_handle);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_shader_get_info_log (CoglHandle handle,
|
||||
size_t size,
|
||||
char *buffer)
|
||||
gchar *
|
||||
cogl_shader_get_info_log (CoglHandle handle)
|
||||
{
|
||||
CoglShader *shader;
|
||||
char buffer[512];
|
||||
int len;
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
_COGL_GET_CONTEXT (ctx, NULL);
|
||||
|
||||
if (!cogl_is_shader (handle))
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
shader = _cogl_shader_pointer_from_handle (handle);
|
||||
|
||||
glGetInfoLogARB (shader->gl_handle, size-1, &len, buffer);
|
||||
glGetInfoLogARB (shader->gl_handle, 511, &len, buffer);
|
||||
buffer[len]='\0';
|
||||
|
||||
return g_strdup (buffer);
|
||||
}
|
||||
|
||||
CoglShaderType
|
||||
|
@ -30,6 +30,7 @@
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
@ -55,6 +56,18 @@ struct _CoglSpanIter
|
||||
gboolean intersects;
|
||||
};
|
||||
|
||||
/* This is used to store the first pixel of each slice. This is only
|
||||
used when glGenerateMipmap is not available */
|
||||
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];
|
||||
};
|
||||
|
||||
struct _CoglTexture
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
@ -68,11 +81,17 @@ struct _CoglTexture
|
||||
GArray *slice_y_spans;
|
||||
GArray *slice_gl_handles;
|
||||
gint max_waste;
|
||||
CoglTextureFilter min_filter;
|
||||
CoglTextureFilter mag_filter;
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter;
|
||||
gboolean is_foreign;
|
||||
GLint wrap_mode;
|
||||
gboolean auto_mipmap;
|
||||
gboolean mipmaps_dirty;
|
||||
|
||||
/* This holds a copy of the first pixel in each slice. It is only
|
||||
used to force an automatic update of the mipmaps when
|
||||
glGenerateMipmap is not available. */
|
||||
CoglTexturePixel *first_pixels;
|
||||
};
|
||||
|
||||
/* To improve batching of geometry when submitting vertices to OpenGL we
|
||||
@ -93,6 +112,14 @@ void
|
||||
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
GLenum wrap_mode);
|
||||
|
||||
void
|
||||
_cogl_texture_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter);
|
||||
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_span_has_waste (CoglTexture *tex,
|
||||
gint x_span_index,
|
||||
|
@ -49,6 +49,7 @@
|
||||
#define glDrawRangeElements ctx->pf_glDrawRangeElements
|
||||
#define glActiveTexture ctx->pf_glActiveTexture
|
||||
#define glClientActiveTexture ctx->pf_glClientActiveTexture
|
||||
#define glGenerateMipmap ctx->pf_glGenerateMipmapEXT
|
||||
|
||||
#else
|
||||
|
||||
@ -247,11 +248,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
/* Iterate horizontal slices */
|
||||
for (x = 0; x < tex->slice_x_spans->len; ++x)
|
||||
{
|
||||
gint slice_num = y * tex->slice_x_spans->len + x;
|
||||
|
||||
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
|
||||
|
||||
/* Pick the gl texture object handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
|
||||
y * tex->slice_x_spans->len + x);
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_for_gl_pixels_upload (tex->bitmap.rowstride,
|
||||
@ -259,6 +261,17 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
y_span->start,
|
||||
bpp);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels)
|
||||
{
|
||||
memcpy (tex->first_pixels[slice_num].data,
|
||||
tex->bitmap.data + x_span->start * bpp
|
||||
+ y_span->start * tex->bitmap.rowstride,
|
||||
bpp);
|
||||
tex->first_pixels[slice_num].gl_format = tex->gl_format;
|
||||
tex->first_pixels[slice_num].gl_type = tex->gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
@ -343,6 +356,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
if (waste_buf)
|
||||
g_free (waste_buf);
|
||||
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -494,6 +509,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
_cogl_span_iter_next (&x_iter),
|
||||
source_x += inter_w )
|
||||
{
|
||||
gint slice_num;
|
||||
|
||||
/* Discard slices out of the subregion early */
|
||||
if (!x_iter.intersects)
|
||||
{
|
||||
@ -516,10 +533,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
local_y = (y_iter.intersect_start -
|
||||
y_iter.pos);
|
||||
|
||||
slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index;
|
||||
|
||||
/* Pick slice GL handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
|
||||
y_iter.index * tex->slice_x_spans->len +
|
||||
x_iter.index);
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* Setup gl alignment to match rowstride and top-left corner */
|
||||
prep_for_gl_pixels_upload (source_bmp->rowstride,
|
||||
@ -527,6 +544,17 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
source_y,
|
||||
bpp);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels && local_x == 0 && local_y == 0)
|
||||
{
|
||||
memcpy (tex->first_pixels[slice_num].data,
|
||||
source_bmp->data + source_x * bpp
|
||||
+ source_y * source_bmp->rowstride,
|
||||
bpp);
|
||||
tex->first_pixels[slice_num].gl_format = source_gl_format;
|
||||
tex->first_pixels[slice_num].gl_type = source_gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
@ -640,14 +668,16 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
if (waste_buf)
|
||||
g_free (waste_buf);
|
||||
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
_cogl_rect_slices_for_size (gint size_to_fill,
|
||||
gint max_span_size,
|
||||
gint max_waste,
|
||||
GArray *out_spans)
|
||||
_cogl_rect_slices_for_size (gint size_to_fill,
|
||||
gint max_span_size,
|
||||
gint max_waste,
|
||||
GArray *out_spans)
|
||||
{
|
||||
gint n_spans = 0;
|
||||
CoglTexSliceSpan span;
|
||||
@ -679,10 +709,10 @@ _cogl_rect_slices_for_size (gint size_to_fill,
|
||||
}
|
||||
|
||||
static gint
|
||||
_cogl_pot_slices_for_size (gint size_to_fill,
|
||||
gint max_span_size,
|
||||
gint max_waste,
|
||||
GArray *out_spans)
|
||||
_cogl_pot_slices_for_size (gint size_to_fill,
|
||||
gint max_span_size,
|
||||
gint max_waste,
|
||||
GArray *out_spans)
|
||||
{
|
||||
gint n_spans = 0;
|
||||
CoglTexSliceSpan span;
|
||||
@ -693,7 +723,8 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
span.waste = 0;
|
||||
|
||||
/* Fix invalid max_waste */
|
||||
if (max_waste < 0) max_waste = 0;
|
||||
if (max_waste < 0)
|
||||
max_waste = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
@ -826,10 +857,10 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
|
||||
/* Check if size supported else bail out */
|
||||
if (!_cogl_texture_size_supported (tex->gl_target,
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
max_height))
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
max_height))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -912,6 +943,14 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
|
||||
g_array_set_size (tex->slice_gl_handles, n_slices);
|
||||
|
||||
/* Allocate some space to store a copy of the first pixel of each
|
||||
slice. This is only needed to glGenerateMipmap (which is part of
|
||||
the FBO extension) is not available */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
tex->first_pixels = NULL;
|
||||
else
|
||||
tex->first_pixels = g_new (CoglTexturePixel, n_slices);
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex->wrap_mode = GL_FALSE;
|
||||
|
||||
@ -940,14 +979,6 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
/* Setup texture parameters */
|
||||
GE( glBindTexture (tex->gl_target,
|
||||
gl_handles[y * n_x_slices + x]) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
|
||||
tex->mag_filter) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
|
||||
tex->min_filter) );
|
||||
|
||||
if (tex->auto_mipmap)
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
|
||||
GL_TRUE) );
|
||||
|
||||
/* Use a transparent border color so that we can leave the
|
||||
color buffer alone when using texture co-ordinates
|
||||
@ -984,6 +1015,9 @@ _cogl_texture_slices_free (CoglTexture *tex)
|
||||
|
||||
g_array_free (tex->slice_gl_handles, TRUE);
|
||||
}
|
||||
|
||||
if (tex->first_pixels != NULL)
|
||||
g_free (tex->first_pixels);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1199,11 +1233,10 @@ _cogl_texture_free (CoglTexture *tex)
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_with_size (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
cogl_texture_new_with_size (guint width,
|
||||
guint height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
gint bpp;
|
||||
@ -1221,7 +1254,8 @@ cogl_texture_new_with_size (guint width,
|
||||
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap.width = width;
|
||||
tex->bitmap.height = height;
|
||||
@ -1234,9 +1268,14 @@ cogl_texture_new_with_size (guint width,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* Find closest GL format match */
|
||||
tex->bitmap.format =
|
||||
@ -1258,7 +1297,6 @@ cogl_texture_new_with_size (guint width,
|
||||
CoglHandle
|
||||
cogl_texture_new_from_data (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
@ -1282,7 +1320,8 @@ cogl_texture_new_from_data (guint width,
|
||||
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap.width = width;
|
||||
tex->bitmap.height = height;
|
||||
@ -1295,9 +1334,14 @@ cogl_texture_new_from_data (guint width,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* FIXME: If upload fails we should set some kind of
|
||||
* error flag but still return texture handle (this
|
||||
@ -1328,10 +1372,9 @@ cogl_texture_new_from_data (guint width,
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
||||
@ -1342,7 +1385,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap = *bmp;
|
||||
tex->bitmap_owner = FALSE;
|
||||
@ -1351,9 +1395,14 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
tex->mag_filter = COGL_TEXTURE_FILTER_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* FIXME: If upload fails we should set some kind of
|
||||
* error flag but still return texture handle if the
|
||||
@ -1388,13 +1437,12 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_from_file (const gchar *filename,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error)
|
||||
{
|
||||
CoglHandle bmp;
|
||||
CoglHandle handle;
|
||||
CoglHandle bmp;
|
||||
CoglHandle handle;
|
||||
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
|
||||
|
||||
@ -1402,10 +1450,7 @@ cogl_texture_new_from_file (const gchar *filename,
|
||||
if (bmp == COGL_INVALID_HANDLE)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
handle = cogl_texture_new_from_bitmap (bmp,
|
||||
max_waste,
|
||||
flags,
|
||||
internal_format);
|
||||
handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
||||
cogl_handle_unref (bmp);
|
||||
|
||||
return handle;
|
||||
@ -1433,8 +1478,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
GLint gl_int_format = 0;
|
||||
GLint gl_width = 0;
|
||||
GLint gl_height = 0;
|
||||
GLint gl_min_filter;
|
||||
GLint gl_mag_filter;
|
||||
GLint gl_gen_mipmap;
|
||||
guint bpp;
|
||||
CoglTexture *tex;
|
||||
@ -1482,14 +1525,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
GL_TEXTURE_HEIGHT,
|
||||
&gl_height) );
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_TEXTURE_MIN_FILTER,
|
||||
&gl_min_filter) );
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_TEXTURE_MAG_FILTER,
|
||||
&gl_mag_filter) );
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_GENERATE_MIPMAP,
|
||||
&gl_gen_mipmap) );
|
||||
@ -1508,18 +1543,16 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
/* Try and match to a cogl format */
|
||||
if (!_cogl_pixel_format_from_gl_internal (gl_int_format,
|
||||
&format))
|
||||
{
|
||||
return COGL_INVALID_HANDLE;
|
||||
}
|
||||
if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format))
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
/* Create new texture */
|
||||
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
|
||||
tex = (CoglTexture *) g_malloc (sizeof (CoglTexture));
|
||||
|
||||
/* Setup bitmap info */
|
||||
tex->is_foreign = TRUE;
|
||||
tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
bpp = _cogl_get_format_bpp (format);
|
||||
tex->bitmap.format = format;
|
||||
@ -1533,8 +1566,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
tex->gl_format = gl_int_format;
|
||||
tex->gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
tex->min_filter = gl_min_filter;
|
||||
tex->mag_filter = gl_mag_filter;
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
tex->max_waste = 0;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
@ -1680,36 +1714,10 @@ cogl_texture_get_gl_texture (CoglHandle handle,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglTextureFilter
|
||||
cogl_texture_get_min_filter (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return 0;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
return tex->min_filter;
|
||||
}
|
||||
|
||||
CoglTextureFilter
|
||||
cogl_texture_get_mag_filter (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return 0;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
return tex->mag_filter;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_texture_set_filters (CoglHandle handle,
|
||||
CoglTextureFilter min_filter,
|
||||
CoglTextureFilter mag_filter)
|
||||
_cogl_texture_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
GLuint gl_handle;
|
||||
@ -1720,14 +1728,18 @@ cogl_texture_set_filters (CoglHandle handle,
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
/* Store new values */
|
||||
tex->min_filter = min_filter;
|
||||
tex->mag_filter = mag_filter;
|
||||
|
||||
/* Make sure slices were created */
|
||||
if (tex->slice_gl_handles == NULL)
|
||||
return;
|
||||
|
||||
if (min_filter == tex->min_filter
|
||||
&& mag_filter == tex->mag_filter)
|
||||
return;
|
||||
|
||||
/* Store new values */
|
||||
tex->min_filter = min_filter;
|
||||
tex->mag_filter = mag_filter;
|
||||
|
||||
/* Apply new filters to every slice */
|
||||
for (i=0; i<tex->slice_gl_handles->len; ++i)
|
||||
{
|
||||
@ -1740,6 +1752,52 @@ cogl_texture_set_filters (CoglHandle handle,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
int i;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
/* Only update if the mipmaps are dirty */
|
||||
if (!tex->auto_mipmap || !tex->mipmaps_dirty)
|
||||
return;
|
||||
|
||||
/* Make sure slices were created */
|
||||
if (tex->slice_gl_handles == NULL)
|
||||
return;
|
||||
|
||||
/* Regenerate the mipmaps on every slice */
|
||||
for (i = 0; i < tex->slice_gl_handles->len; i++)
|
||||
{
|
||||
GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
/* glGenerateMipmap is defined in the FBO extension */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
GE( glGenerateMipmap (tex->gl_target) );
|
||||
else
|
||||
{
|
||||
CoglTexturePixel *pixel = tex->first_pixels + i;
|
||||
/* Temporarily enable automatic mipmap generation and
|
||||
re-upload the first pixel to cause a regeneration */
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) );
|
||||
GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1,
|
||||
pixel->gl_format, pixel->gl_type,
|
||||
pixel->data) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) );
|
||||
}
|
||||
}
|
||||
|
||||
tex->mipmaps_dirty = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_texture_set_region (CoglHandle handle,
|
||||
gint src_x,
|
||||
|
@ -399,6 +399,10 @@ _cogl_features_init (void)
|
||||
(COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC)
|
||||
cogl_get_proc_address ("glDeleteFramebuffersEXT");
|
||||
|
||||
ctx->pf_glGenerateMipmapEXT =
|
||||
(COGL_PFNGLGENERATEMIPMAPEXTPROC)
|
||||
cogl_get_proc_address ("glGenerateMipmapEXT");
|
||||
|
||||
if (ctx->pf_glGenRenderbuffersEXT &&
|
||||
ctx->pf_glBindRenderbufferEXT &&
|
||||
ctx->pf_glRenderbufferStorageEXT &&
|
||||
@ -407,7 +411,8 @@ _cogl_features_init (void)
|
||||
ctx->pf_glFramebufferTexture2DEXT &&
|
||||
ctx->pf_glFramebufferRenderbufferEXT &&
|
||||
ctx->pf_glCheckFramebufferStatusEXT &&
|
||||
ctx->pf_glDeleteFramebuffersEXT)
|
||||
ctx->pf_glDeleteFramebuffersEXT &&
|
||||
ctx->pf_glGenerateMipmapEXT)
|
||||
flags |= COGL_FEATURE_OFFSCREEN;
|
||||
}
|
||||
|
||||
@ -486,6 +491,23 @@ _cogl_features_init (void)
|
||||
(COGL_PFNGLCLIENTACTIVETEXTUREPROC)
|
||||
cogl_get_proc_address ("glClientActiveTexture");
|
||||
|
||||
ctx->pf_glBlendEquation =
|
||||
(COGL_PFNGLBLENDEQUATIONPROC)
|
||||
cogl_get_proc_address ("glBlendEquation");
|
||||
ctx->pf_glBlendColor =
|
||||
(COGL_PFNGLBLENDCOLORPROC)
|
||||
cogl_get_proc_address ("glBlendColor");
|
||||
|
||||
/* Available in 1.4 */
|
||||
ctx->pf_glBlendFuncSeparate =
|
||||
(COGL_PFNGLBLENDFUNCSEPARATEPROC)
|
||||
cogl_get_proc_address ("glBlendFuncSeparate");
|
||||
|
||||
/* Available in 2.0 */
|
||||
ctx->pf_glBlendEquationSeparate =
|
||||
(COGL_PFNGLBLENDEQUATIONSEPARATEPROC)
|
||||
cogl_get_proc_address ("glBlendEquationSeparate");
|
||||
|
||||
/* Cache features */
|
||||
ctx->feature_flags = flags;
|
||||
ctx->features_cached = TRUE;
|
||||
|
@ -27,12 +27,12 @@ INCLUDES = \
|
||||
-DG_LOG_DOMAIN=\"Cogl-GLES\" \
|
||||
-DCLUTTER_COMPILATION
|
||||
|
||||
noinst_LTLIBRARIES = libclutter-cogl.la
|
||||
noinst_LTLIBRARIES = libclutter-cogl-gles.la
|
||||
|
||||
libclutter_cogl_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
libclutter_cogl_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_la_SOURCES = \
|
||||
libclutter_cogl_gles_la_CPPFLAGS = $(CLUTTER_CFLAGS) $(COGL_DEBUG_CFLAGS) $(CLUTTER_DEBUG_CFLAGS) $(MAINTAINER_CFLAGS)
|
||||
libclutter_cogl_gles_la_LIBADD = -lm $(CLUTTER_LIBS) $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_gles_la_DEPENDENCIES = $(top_builddir)/clutter/cogl/common/libclutter-cogl-common.la
|
||||
libclutter_cogl_gles_la_SOURCES = \
|
||||
$(top_builddir)/clutter/cogl/cogl.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-defines-gles.h \
|
||||
$(top_builddir)/clutter/cogl/cogl-color.h \
|
||||
@ -60,7 +60,7 @@ libclutter_cogl_la_SOURCES = \
|
||||
cogl-shader.c
|
||||
|
||||
if USE_GLES2_WRAPPER
|
||||
libclutter_cogl_la_SOURCES += \
|
||||
libclutter_cogl_gles_la_SOURCES += \
|
||||
cogl-gles2-wrapper.c \
|
||||
cogl-fixed-vertex-shader.h \
|
||||
cogl-fixed-vertex-shader.c \
|
||||
|
@ -39,7 +39,7 @@
|
||||
static CoglContext *_context = NULL;
|
||||
static gboolean gl_is_indirect = FALSE;
|
||||
|
||||
gboolean
|
||||
static gboolean
|
||||
cogl_create_context ()
|
||||
{
|
||||
GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
|
||||
@ -72,7 +72,6 @@ cogl_create_context ()
|
||||
|
||||
_context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
|
||||
_context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
|
||||
_context->static_indices = g_array_new (FALSE, FALSE, sizeof (GLushort));
|
||||
_context->polygon_vertices = g_array_new (FALSE, FALSE,
|
||||
sizeof (CoglTextureGLVertex));
|
||||
|
||||
@ -107,8 +106,7 @@ cogl_create_context ()
|
||||
_context->default_gl_texture_2d_tex =
|
||||
cogl_texture_new_from_data (1, /* width */
|
||||
1, /* height */
|
||||
-1, /* max waste */
|
||||
COGL_TEXTURE_NONE, /* flags */
|
||||
COGL_TEXTURE_NO_SLICING, /* flags */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
|
||||
/* internal format */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
@ -117,8 +115,7 @@ cogl_create_context ()
|
||||
_context->default_gl_texture_rect_tex =
|
||||
cogl_texture_new_from_data (1, /* width */
|
||||
1, /* height */
|
||||
-1, /* max waste */
|
||||
COGL_TEXTURE_NONE, /* flags */
|
||||
COGL_TEXTURE_NO_SLICING, /* flags */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888, /* data format */
|
||||
/* internal format */
|
||||
COGL_PIXEL_FORMAT_RGBA_8888,
|
||||
@ -126,16 +123,20 @@ cogl_create_context ()
|
||||
default_texture_data);
|
||||
|
||||
cogl_set_source (_context->default_material);
|
||||
cogl_material_flush_gl_state (_context->source_material, NULL);
|
||||
_cogl_material_flush_gl_state (_context->source_material, NULL);
|
||||
enable_flags =
|
||||
cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||
_cogl_material_get_cogl_enable_flags (_context->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
_context->quad_indices_byte = COGL_INVALID_HANDLE;
|
||||
_context->quad_indices_short = COGL_INVALID_HANDLE;
|
||||
_context->quad_indices_short_len = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_destroy_context ()
|
||||
_cogl_destroy_context ()
|
||||
{
|
||||
if (_context == NULL)
|
||||
return;
|
||||
@ -160,13 +161,16 @@ cogl_destroy_context ()
|
||||
if (_context->logged_vertices)
|
||||
g_array_free (_context->logged_vertices, TRUE);
|
||||
|
||||
if (_context->static_indices)
|
||||
g_array_free (_context->static_indices, TRUE);
|
||||
if (_context->polygon_vertices)
|
||||
g_array_free (_context->polygon_vertices, TRUE);
|
||||
if (_context->current_layers)
|
||||
g_array_free (_context->current_layers, TRUE);
|
||||
|
||||
if (_context->quad_indices_byte)
|
||||
cogl_handle_unref (_context->quad_indices_byte);
|
||||
if (_context->quad_indices_short)
|
||||
cogl_handle_unref (_context->quad_indices_short);
|
||||
|
||||
g_free (_context);
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,6 @@ typedef struct
|
||||
* can batch things together. */
|
||||
GArray *journal;
|
||||
GArray *logged_vertices;
|
||||
GArray *static_indices;
|
||||
GArray *polygon_vertices;
|
||||
|
||||
/* Some simple caching, to minimize state changes... */
|
||||
@ -104,6 +103,12 @@ typedef struct
|
||||
floatVec2 path_nodes_max;
|
||||
CoglHandle stencil_material;
|
||||
|
||||
/* Pre-generated VBOs containing indices to generate GL_TRIANGLES
|
||||
out of a vertex array of quads */
|
||||
CoglHandle quad_indices_byte;
|
||||
guint quad_indices_short_len;
|
||||
CoglHandle quad_indices_short;
|
||||
|
||||
#ifdef HAVE_COGL_GLES2
|
||||
CoglGles2Wrapper gles2;
|
||||
|
||||
@ -111,7 +116,6 @@ typedef struct
|
||||
supported */
|
||||
GLint viewport_store[4];
|
||||
#endif
|
||||
|
||||
} CoglContext;
|
||||
|
||||
CoglContext *
|
||||
|
@ -89,13 +89,13 @@ cogl_gles2_wrapper_create_shader (GLenum type, const char *source)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
char log[1024];
|
||||
char shader_log[1024];
|
||||
GLint len;
|
||||
|
||||
glGetShaderInfoLog (shader, sizeof (log) - 1, &len, log);
|
||||
log[len] = '\0';
|
||||
glGetShaderInfoLog (shader, sizeof (shader_log) - 1, &len, shader_log);
|
||||
shader_log[len] = '\0';
|
||||
|
||||
g_critical ("%s", log);
|
||||
g_critical ("%s", shader_log);
|
||||
|
||||
glDeleteShader (shader);
|
||||
|
||||
@ -538,9 +538,9 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
|
||||
CoglShader *shader
|
||||
= _cogl_shader_pointer_from_handle ((CoglHandle) node->data);
|
||||
|
||||
if (shader->type == CGL_VERTEX_SHADER)
|
||||
if (shader->type == COGL_SHADER_TYPE_VERTEX)
|
||||
custom_vertex_shader = TRUE;
|
||||
else if (shader->type == CGL_FRAGMENT_SHADER)
|
||||
else if (shader->type == COGL_SHADER_TYPE_FRAGMENT)
|
||||
custom_fragment_shader = TRUE;
|
||||
}
|
||||
}
|
||||
@ -581,13 +581,13 @@ cogl_gles2_wrapper_get_program (const CoglGles2WrapperSettings *settings)
|
||||
|
||||
if (!status)
|
||||
{
|
||||
char log[1024];
|
||||
char shader_log[1024];
|
||||
GLint len;
|
||||
|
||||
glGetProgramInfoLog (program->program, sizeof (log) - 1, &len, log);
|
||||
log[len] = '\0';
|
||||
glGetProgramInfoLog (program->program, sizeof (shader_log) - 1, &len, shader_log);
|
||||
shader_log[len] = '\0';
|
||||
|
||||
g_critical ("%s", log);
|
||||
g_critical ("%s", shader_log);
|
||||
|
||||
glDeleteProgram (program->program);
|
||||
g_slice_free (CoglGles2WrapperProgram, program);
|
||||
@ -1300,13 +1300,20 @@ cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
|
||||
}
|
||||
|
||||
void
|
||||
cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param)
|
||||
cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param)
|
||||
{
|
||||
/* This function is only used to set the texture mode once to
|
||||
GL_MODULATE. The shader is hard-coded to modulate the texture so
|
||||
nothing needs to be done here. */
|
||||
}
|
||||
|
||||
void
|
||||
cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params)
|
||||
{
|
||||
/* FIXME: Currently needed to support texture combining using
|
||||
* COGL_BLEND_STRING_COLOR_SOURCE_CONSTANT */
|
||||
}
|
||||
|
||||
void
|
||||
cogl_wrap_glClientActiveTexture (GLenum texture)
|
||||
{
|
||||
|
@ -259,6 +259,7 @@ struct _CoglGles2WrapperShader
|
||||
|
||||
#define GL_TEXTURE_ENV 0x2300
|
||||
#define GL_TEXTURE_ENV_MODE 0x2200
|
||||
#define GL_TEXTURE_ENV_COLOR 0x2201
|
||||
#define GL_MODULATE 0x2100
|
||||
|
||||
#define GL_EXP 0x8000
|
||||
@ -327,7 +328,8 @@ void cogl_wrap_glColorPointer (GLint size, GLenum type, GLsizei stride,
|
||||
void cogl_wrap_glNormalPointer (GLenum type, GLsizei stride,
|
||||
const GLvoid *pointer);
|
||||
|
||||
void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLfloat param);
|
||||
void cogl_wrap_glTexEnvi (GLenum target, GLenum pname, GLint param);
|
||||
void cogl_wrap_glTexEnvfv (GLenum target, GLenum pname, const GLfloat *params);
|
||||
|
||||
void cogl_wrap_glClientActiveTexture (GLenum texture);
|
||||
void cogl_wrap_glActiveTexture (GLenum texture);
|
||||
@ -384,6 +386,7 @@ void _cogl_gles2_clear_cache_for_program (CoglHandle program);
|
||||
#define glColorPointer cogl_wrap_glColorPointer
|
||||
#define glNormalPointer cogl_wrap_glNormalPointer
|
||||
#define glTexEnvi cogl_wrap_glTexEnvi
|
||||
#define glTexEnvfv cogl_wrap_glTexEnvfv
|
||||
#define glActiveTexture cogl_wrap_glActiveTexture
|
||||
#define glClientActiveTexture cogl_wrap_glClientActiveTexture
|
||||
#define glEnableClientState cogl_wrap_glEnableClientState
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "cogl-internal.h"
|
||||
#include "cogl-context.h"
|
||||
#include "cogl-clip-stack.h"
|
||||
#include "cogl-material-private.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gmodule.h>
|
||||
@ -78,13 +79,13 @@ _cogl_path_stroke_nodes ()
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
enable_flags |= cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
enable_flags |= _cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~0, /* disable all texture layers */
|
||||
NULL);
|
||||
_cogl_material_flush_gl_state (ctx->source_material,
|
||||
COGL_MATERIAL_FLUSH_DISABLE_MASK,
|
||||
(guint32)~0, /* disable all texture layers */
|
||||
NULL);
|
||||
_cogl_current_matrix_state_flush ();
|
||||
|
||||
while (path_start < ctx->path_nodes->len)
|
||||
@ -139,10 +140,10 @@ _cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Just setup a simple material that doesn't use texturing... */
|
||||
cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
_cogl_material_flush_gl_state (ctx->stencil_material, NULL);
|
||||
|
||||
enable_flags |=
|
||||
cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
_cogl_material_get_cogl_enable_flags (ctx->source_material);
|
||||
cogl_enable (enable_flags);
|
||||
|
||||
_cogl_path_get_bounds (nodes_min, nodes_max,
|
||||
@ -361,30 +362,30 @@ _cogl_path_fill_nodes_scanlines (CoglPathNode *path,
|
||||
while (iter)
|
||||
{
|
||||
GSList *next = iter->next;
|
||||
GLfloat x0, x1;
|
||||
GLfloat y0, y1;
|
||||
GLfloat x_0, x_1;
|
||||
GLfloat y_0, y_1;
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
x0 = GPOINTER_TO_INT (iter->data);
|
||||
x1 = GPOINTER_TO_INT (next->data);
|
||||
y0 = bounds_y + i;
|
||||
y1 = bounds_y + i + 1.0625f;
|
||||
x_0 = GPOINTER_TO_INT (iter->data);
|
||||
x_1 = GPOINTER_TO_INT (next->data);
|
||||
y_0 = bounds_y + i;
|
||||
y_1 = bounds_y + i + 1.0625f;
|
||||
/* render scanlines 1.0625 high to avoid gaps when
|
||||
transformed */
|
||||
|
||||
coords[span_no * 12 + 0] = x0;
|
||||
coords[span_no * 12 + 1] = y0;
|
||||
coords[span_no * 12 + 2] = x1;
|
||||
coords[span_no * 12 + 3] = y0;
|
||||
coords[span_no * 12 + 4] = x1;
|
||||
coords[span_no * 12 + 5] = y1;
|
||||
coords[span_no * 12 + 6] = x0;
|
||||
coords[span_no * 12 + 7] = y0;
|
||||
coords[span_no * 12 + 8] = x0;
|
||||
coords[span_no * 12 + 9] = y1;
|
||||
coords[span_no * 12 + 10] = x1;
|
||||
coords[span_no * 12 + 11] = y1;
|
||||
coords[span_no * 12 + 0] = x_0;
|
||||
coords[span_no * 12 + 1] = y_0;
|
||||
coords[span_no * 12 + 2] = x_1;
|
||||
coords[span_no * 12 + 3] = y_0;
|
||||
coords[span_no * 12 + 4] = x_1;
|
||||
coords[span_no * 12 + 5] = y_1;
|
||||
coords[span_no * 12 + 6] = x_0;
|
||||
coords[span_no * 12 + 7] = y_0;
|
||||
coords[span_no * 12 + 8] = x_0;
|
||||
coords[span_no * 12 + 9] = y_1;
|
||||
coords[span_no * 12 + 10] = x_1;
|
||||
coords[span_no * 12 + 11] = y_1;
|
||||
span_no ++;
|
||||
iter = next->next;
|
||||
}
|
||||
|
@ -99,22 +99,23 @@ cogl_shader_compile (CoglHandle handle)
|
||||
glCompileShader (shader->gl_handle);
|
||||
}
|
||||
|
||||
void
|
||||
cogl_shader_get_info_log (CoglHandle handle,
|
||||
size_t size,
|
||||
char *buffer)
|
||||
gchar *
|
||||
cogl_shader_get_info_log (CoglHandle handle)
|
||||
{
|
||||
CoglShader *shader;
|
||||
char buffer[512];
|
||||
int len = 0;
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
_COGL_GET_CONTEXT (ctx, NULL);
|
||||
|
||||
if (!cogl_is_shader (handle))
|
||||
return;
|
||||
return NULL;
|
||||
|
||||
shader = _cogl_shader_pointer_from_handle (handle);
|
||||
|
||||
glGetShaderInfoLog (shader->gl_handle, size - 1, &len, buffer);
|
||||
glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
|
||||
buffer[len] = '\0';
|
||||
|
||||
return g_strdup (buffer);
|
||||
}
|
||||
|
||||
CoglShaderType
|
||||
@ -199,11 +200,10 @@ cogl_shader_compile (CoglHandle shader_handle)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
cogl_shader_get_info_log (CoglHandle handle,
|
||||
size_t size,
|
||||
char *buffer)
|
||||
gchar *
|
||||
cogl_shader_get_info_log (CoglHandle handle)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CoglShaderType
|
||||
|
@ -30,6 +30,7 @@
|
||||
typedef struct _CoglTexture CoglTexture;
|
||||
typedef struct _CoglTexSliceSpan CoglTexSliceSpan;
|
||||
typedef struct _CoglSpanIter CoglSpanIter;
|
||||
typedef struct _CoglTexturePixel CoglTexturePixel;
|
||||
|
||||
struct _CoglTexSliceSpan
|
||||
{
|
||||
@ -55,6 +56,18 @@ struct _CoglSpanIter
|
||||
gboolean intersects;
|
||||
};
|
||||
|
||||
/* This is used to store the first pixel of each slice. This is only
|
||||
used when glGenerateMipmap is not available */
|
||||
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];
|
||||
};
|
||||
|
||||
struct _CoglTexture
|
||||
{
|
||||
CoglHandleObject _parent;
|
||||
@ -68,11 +81,17 @@ struct _CoglTexture
|
||||
GArray *slice_y_spans;
|
||||
GArray *slice_gl_handles;
|
||||
gint max_waste;
|
||||
CoglTextureFilter min_filter;
|
||||
CoglTextureFilter mag_filter;
|
||||
GLenum min_filter;
|
||||
GLenum mag_filter;
|
||||
gboolean is_foreign;
|
||||
GLint wrap_mode;
|
||||
gboolean auto_mipmap;
|
||||
gboolean mipmaps_dirty;
|
||||
|
||||
/* This holds a copy of the first pixel in each slice. It is only
|
||||
used to force an automatic update of the mipmaps when
|
||||
glGenerateMipmap is not available. */
|
||||
CoglTexturePixel *first_pixels;
|
||||
};
|
||||
|
||||
/* To improve batching of geometry when submitting vertices to OpenGL we
|
||||
@ -93,6 +112,14 @@ void
|
||||
_cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
|
||||
GLenum wrap_mode);
|
||||
|
||||
void
|
||||
_cogl_texture_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter);
|
||||
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle);
|
||||
|
||||
gboolean
|
||||
_cogl_texture_span_has_waste (CoglTexture *tex,
|
||||
gint x_span_index,
|
||||
|
@ -225,11 +225,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
/* Iterate horizontal slices */
|
||||
for (x = 0; x < tex->slice_x_spans->len; ++x)
|
||||
{
|
||||
gint slice_num = y * tex->slice_x_spans->len + x;
|
||||
|
||||
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
|
||||
|
||||
/* Pick the gl texture object handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
|
||||
y * tex->slice_x_spans->len + x);
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* FIXME: might optimize by not copying to intermediate slice
|
||||
bitmap when source rowstride = bpp * width and the texture
|
||||
@ -258,6 +259,16 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
slice_bmp.width,
|
||||
slice_bmp.height);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels)
|
||||
{
|
||||
memcpy (tex->first_pixels[slice_num].data,
|
||||
slice_bmp.data,
|
||||
bpp);
|
||||
tex->first_pixels[slice_num].gl_format = tex->gl_format;
|
||||
tex->first_pixels[slice_num].gl_type = tex->gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
|
||||
tex->gl_intformat) );
|
||||
@ -338,9 +349,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
waste_buf) );
|
||||
}
|
||||
|
||||
if (tex->auto_mipmap)
|
||||
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
||||
|
||||
/* Free temp bitmap */
|
||||
g_free (slice_bmp.data);
|
||||
}
|
||||
@ -349,6 +357,8 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
|
||||
if (waste_buf)
|
||||
g_free (waste_buf);
|
||||
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -442,6 +452,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
|
||||
gint bpp;
|
||||
GLint viewport[4];
|
||||
CoglBitmap alpha_bmp;
|
||||
CoglHandle prev_source;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, FALSE);
|
||||
|
||||
@ -477,31 +488,21 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
|
||||
if (ctx->texture_download_material == COGL_INVALID_HANDLE)
|
||||
{
|
||||
ctx->texture_download_material = cogl_material_new ();
|
||||
cogl_material_set_layer_combine_function (
|
||||
ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_FUNC_REPLACE);
|
||||
cogl_material_set_layer_combine_arg_src (
|
||||
ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
0, /* arg */
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_SRC_TEXTURE);
|
||||
cogl_material_set_blend_factors (ctx->texture_download_material,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ONE,
|
||||
COGL_MATERIAL_BLEND_FACTOR_ZERO);
|
||||
cogl_material_set_blend (ctx->texture_download_material,
|
||||
"RGBA = ADD (SRC_COLOR, 0)",
|
||||
NULL);
|
||||
}
|
||||
|
||||
prev_source = cogl_handle_ref (ctx->source_material);
|
||||
cogl_set_source (ctx->texture_download_material);
|
||||
|
||||
cogl_material_set_layer (ctx->texture_download_material, 0, tex);
|
||||
|
||||
cogl_material_set_layer_combine_arg_op (
|
||||
ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
0, /* arg */
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_COLOR);
|
||||
cogl_material_flush_gl_state (ctx->texture_download_material, NULL);
|
||||
cogl_material_set_layer_combine (ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
"RGBA = REPLACE (TEXTURE)",
|
||||
NULL);
|
||||
|
||||
_cogl_texture_draw_and_read (tex, target_bmp, viewport);
|
||||
|
||||
/* Check whether texture has alpha and framebuffer not */
|
||||
@ -534,13 +535,11 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
|
||||
alpha_bmp.height);
|
||||
|
||||
/* Draw alpha values into RGB channels */
|
||||
cogl_material_set_layer_combine_arg_op (
|
||||
ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
0, /* arg */
|
||||
COGL_MATERIAL_LAYER_COMBINE_CHANNELS_RGB,
|
||||
COGL_MATERIAL_LAYER_COMBINE_OP_SRC_ALPHA);
|
||||
cogl_material_flush_gl_state (ctx->texture_download_material, NULL);
|
||||
cogl_material_set_layer_combine (ctx->texture_download_material,
|
||||
0, /* layer */
|
||||
"RGBA = REPLACE (TEXTURE[A])",
|
||||
NULL);
|
||||
|
||||
_cogl_texture_draw_and_read (tex, &alpha_bmp, viewport);
|
||||
|
||||
/* Copy temp R to target A */
|
||||
@ -568,6 +567,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
|
||||
_cogl_set_current_matrix (COGL_MATRIX_MODELVIEW);
|
||||
_cogl_current_matrix_pop ();
|
||||
|
||||
/* restore the original material */
|
||||
cogl_set_source (prev_source);
|
||||
cogl_handle_unref (prev_source);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -631,6 +634,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
_cogl_span_iter_next (&x_iter),
|
||||
source_x += inter_w )
|
||||
{
|
||||
gint slice_num;
|
||||
|
||||
/* Discard slices out of the subregion early */
|
||||
if (!x_iter.intersects)
|
||||
{
|
||||
@ -653,10 +658,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
local_y = (y_iter.intersect_start -
|
||||
y_iter.pos);
|
||||
|
||||
slice_num = y_iter.index * tex->slice_x_spans->len + x_iter.index;
|
||||
|
||||
/* Pick slice GL handle */
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
|
||||
y_iter.index * tex->slice_x_spans->len +
|
||||
x_iter.index);
|
||||
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, slice_num);
|
||||
|
||||
/* FIXME: might optimize by not copying to intermediate slice
|
||||
bitmap when source rowstride = bpp * width and the texture
|
||||
@ -685,6 +690,15 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
slice_bmp.width,
|
||||
slice_bmp.height);
|
||||
|
||||
/* Keep a copy of the first pixel if needed */
|
||||
if (tex->first_pixels && local_x == 0 && local_y == 0)
|
||||
{
|
||||
memcpy (tex->first_pixels[slice_num].data,
|
||||
slice_bmp.data, bpp);
|
||||
tex->first_pixels[slice_num].gl_format = source_gl_format;
|
||||
tex->first_pixels[slice_num].gl_type = source_gl_type;
|
||||
}
|
||||
|
||||
/* Upload new image data */
|
||||
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
|
||||
tex->gl_intformat) );
|
||||
@ -794,9 +808,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
waste_buf) );
|
||||
}
|
||||
|
||||
if (tex->auto_mipmap)
|
||||
cogl_wrap_glGenerateMipmap (tex->gl_target);
|
||||
|
||||
/* Free temp bitmap */
|
||||
g_free (slice_bmp.data);
|
||||
}
|
||||
@ -805,6 +816,8 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
|
||||
if (waste_buf)
|
||||
g_free (waste_buf);
|
||||
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -858,7 +871,8 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
span.waste = 0;
|
||||
|
||||
/* Fix invalid max_waste */
|
||||
if (max_waste < 0) max_waste = 0;
|
||||
if (max_waste < 0)
|
||||
max_waste = 0;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
@ -866,7 +880,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
if (size_to_fill > span.size)
|
||||
{
|
||||
/* Not yet - add a span of this size */
|
||||
if (out_spans) g_array_append_val (out_spans, span);
|
||||
if (out_spans)
|
||||
g_array_append_val (out_spans, span);
|
||||
|
||||
span.start += span.size;
|
||||
size_to_fill -= span.size;
|
||||
n_spans++;
|
||||
@ -875,7 +891,9 @@ _cogl_pot_slices_for_size (gint size_to_fill,
|
||||
{
|
||||
/* Yes and waste is small enough */
|
||||
span.waste = span.size - size_to_fill;
|
||||
if (out_spans) g_array_append_val (out_spans, span);
|
||||
if (out_spans)
|
||||
g_array_append_val (out_spans, span);
|
||||
|
||||
return ++n_spans;
|
||||
}
|
||||
else
|
||||
@ -971,10 +989,10 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
|
||||
/* Check if size supported else bail out */
|
||||
if (!_cogl_texture_size_supported (tex->gl_target,
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
max_height))
|
||||
tex->gl_format,
|
||||
tex->gl_type,
|
||||
max_width,
|
||||
max_height))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
@ -1057,6 +1075,14 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
|
||||
g_array_set_size (tex->slice_gl_handles, n_slices);
|
||||
|
||||
/* Allocate some space to store a copy of the first pixel of each
|
||||
slice. This is only needed to glGenerateMipmap (which is part of
|
||||
the FBO extension) is not available */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
tex->first_pixels = NULL;
|
||||
else
|
||||
tex->first_pixels = g_new (CoglTexturePixel, n_slices);
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
tex->wrap_mode = GL_FALSE;
|
||||
|
||||
@ -1087,20 +1113,11 @@ _cogl_texture_slices_create (CoglTexture *tex)
|
||||
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target,
|
||||
gl_handles[y * n_x_slices + x],
|
||||
tex->gl_intformat) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
|
||||
tex->mag_filter) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
|
||||
tex->min_filter) );
|
||||
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
|
||||
tex->wrap_mode) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
|
||||
tex->wrap_mode) );
|
||||
|
||||
if (tex->auto_mipmap)
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
|
||||
GL_TRUE) );
|
||||
|
||||
/* Pass NULL data to init size and internal format */
|
||||
GE( glTexImage2D (tex->gl_target, 0, tex->gl_intformat,
|
||||
x_span->size, y_span->size, 0,
|
||||
@ -1130,6 +1147,9 @@ _cogl_texture_slices_free (CoglTexture *tex)
|
||||
|
||||
g_array_free (tex->slice_gl_handles, TRUE);
|
||||
}
|
||||
|
||||
if (tex->first_pixels != NULL)
|
||||
g_free (tex->first_pixels);
|
||||
}
|
||||
|
||||
gboolean
|
||||
@ -1288,11 +1308,10 @@ _cogl_texture_free (CoglTexture *tex)
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_with_size (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
cogl_texture_new_with_size (guint width,
|
||||
guint height,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
gint bpp;
|
||||
@ -1310,7 +1329,8 @@ cogl_texture_new_with_size (guint width,
|
||||
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap.width = width;
|
||||
tex->bitmap.height = height;
|
||||
@ -1323,9 +1343,14 @@ cogl_texture_new_with_size (guint width,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = CGL_NEAREST;
|
||||
tex->mag_filter = CGL_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* Find closest GL format match */
|
||||
tex->bitmap.format =
|
||||
@ -1347,7 +1372,6 @@ cogl_texture_new_with_size (guint width,
|
||||
CoglHandle
|
||||
cogl_texture_new_from_data (guint width,
|
||||
guint height,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat format,
|
||||
CoglPixelFormat internal_format,
|
||||
@ -1371,7 +1395,8 @@ cogl_texture_new_from_data (guint width,
|
||||
tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap.width = width;
|
||||
tex->bitmap.height = height;
|
||||
@ -1384,9 +1409,14 @@ cogl_texture_new_from_data (guint width,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = CGL_NEAREST;
|
||||
tex->mag_filter = CGL_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* FIXME: If upload fails we should set some kind of
|
||||
* error flag but still return texture handle (this
|
||||
@ -1417,10 +1447,9 @@ cogl_texture_new_from_data (guint width,
|
||||
}
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
CoglBitmap *bmp = (CoglBitmap *)bmp_handle;
|
||||
@ -1429,7 +1458,8 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
|
||||
|
||||
tex->is_foreign = FALSE;
|
||||
tex->auto_mipmap = ((flags & COGL_TEXTURE_AUTO_MIPMAP) != 0);
|
||||
tex->auto_mipmap = (flags & COGL_TEXTURE_NO_AUTO_MIPMAP) == 0;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
tex->bitmap = *bmp;
|
||||
tex->bitmap_owner = TRUE;
|
||||
@ -1439,9 +1469,14 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
tex->slice_y_spans = NULL;
|
||||
tex->slice_gl_handles = NULL;
|
||||
|
||||
tex->max_waste = max_waste;
|
||||
tex->min_filter = CGL_NEAREST;
|
||||
tex->mag_filter = CGL_NEAREST;
|
||||
if (flags & COGL_TEXTURE_NO_SLICING)
|
||||
tex->max_waste = -1;
|
||||
else
|
||||
tex->max_waste = COGL_TEXTURE_MAX_WASTE;
|
||||
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
|
||||
/* FIXME: If upload fails we should set some kind of
|
||||
* error flag but still return texture handle if the
|
||||
@ -1476,7 +1511,6 @@ cogl_texture_new_from_bitmap (CoglHandle bmp_handle,
|
||||
|
||||
CoglHandle
|
||||
cogl_texture_new_from_file (const gchar *filename,
|
||||
gint max_waste,
|
||||
CoglTextureFlags flags,
|
||||
CoglPixelFormat internal_format,
|
||||
GError **error)
|
||||
@ -1490,10 +1524,7 @@ cogl_texture_new_from_file (const gchar *filename,
|
||||
if (bmp == COGL_INVALID_HANDLE)
|
||||
return COGL_INVALID_HANDLE;
|
||||
|
||||
handle = cogl_texture_new_from_bitmap (bmp,
|
||||
max_waste,
|
||||
flags,
|
||||
internal_format);
|
||||
handle = cogl_texture_new_from_bitmap (bmp, flags, internal_format);
|
||||
cogl_handle_unref (bmp);
|
||||
|
||||
return handle;
|
||||
@ -1521,8 +1552,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
GLint gl_int_format = 0;
|
||||
GLint gl_width = 0;
|
||||
GLint gl_height = 0;
|
||||
GLint gl_min_filter;
|
||||
GLint gl_mag_filter;
|
||||
GLint gl_gen_mipmap;
|
||||
guint bpp;
|
||||
CoglTexture *tex;
|
||||
@ -1569,14 +1598,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
gl_height = height + y_pot_waste;
|
||||
#endif
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_TEXTURE_MIN_FILTER,
|
||||
&gl_min_filter) );
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_TEXTURE_MAG_FILTER,
|
||||
&gl_mag_filter) );
|
||||
|
||||
GE( glGetTexParameteriv (gl_target,
|
||||
GL_GENERATE_MIPMAP,
|
||||
&gl_gen_mipmap) );
|
||||
@ -1607,6 +1628,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
/* Setup bitmap info */
|
||||
tex->is_foreign = TRUE;
|
||||
tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE;
|
||||
tex->mipmaps_dirty = TRUE;
|
||||
|
||||
bpp = _cogl_get_format_bpp (format);
|
||||
tex->bitmap.format = format;
|
||||
@ -1620,8 +1642,9 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
|
||||
tex->gl_format = gl_int_format;
|
||||
tex->gl_type = GL_UNSIGNED_BYTE;
|
||||
|
||||
tex->min_filter = gl_min_filter;
|
||||
tex->mag_filter = gl_mag_filter;
|
||||
/* Unknown filter */
|
||||
tex->min_filter = GL_FALSE;
|
||||
tex->mag_filter = GL_FALSE;
|
||||
tex->max_waste = 0;
|
||||
|
||||
/* Wrap mode not yet set */
|
||||
@ -1767,36 +1790,10 @@ cogl_texture_get_gl_texture (CoglHandle handle,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
CoglTextureFilter
|
||||
cogl_texture_get_min_filter (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return 0;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
return tex->min_filter;
|
||||
}
|
||||
|
||||
CoglTextureFilter
|
||||
cogl_texture_get_mag_filter (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return 0;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
return tex->mag_filter;
|
||||
}
|
||||
|
||||
void
|
||||
cogl_texture_set_filters (CoglHandle handle,
|
||||
CoglTextureFilter min_filter,
|
||||
CoglTextureFilter mag_filter)
|
||||
_cogl_texture_set_filters (CoglHandle handle,
|
||||
GLenum min_filter,
|
||||
GLenum mag_filter)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
GLuint gl_handle;
|
||||
@ -1807,14 +1804,18 @@ cogl_texture_set_filters (CoglHandle handle,
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
/* Store new values */
|
||||
tex->min_filter = min_filter;
|
||||
tex->mag_filter = mag_filter;
|
||||
|
||||
/* Make sure slices were created */
|
||||
if (tex->slice_gl_handles == NULL)
|
||||
return;
|
||||
|
||||
if (min_filter == tex->min_filter
|
||||
&& mag_filter == tex->mag_filter)
|
||||
return;
|
||||
|
||||
/* Store new values */
|
||||
tex->min_filter = min_filter;
|
||||
tex->mag_filter = mag_filter;
|
||||
|
||||
/* Apply new filters to every slice */
|
||||
for (i=0; i<tex->slice_gl_handles->len; ++i)
|
||||
{
|
||||
@ -1827,6 +1828,52 @@ cogl_texture_set_filters (CoglHandle handle,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_texture_ensure_mipmaps (CoglHandle handle)
|
||||
{
|
||||
CoglTexture *tex;
|
||||
int i;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
if (!cogl_is_texture (handle))
|
||||
return;
|
||||
|
||||
tex = _cogl_texture_pointer_from_handle (handle);
|
||||
|
||||
/* Only update if the mipmaps are dirty */
|
||||
if (!tex->auto_mipmap || !tex->mipmaps_dirty)
|
||||
return;
|
||||
|
||||
/* Make sure slices were created */
|
||||
if (tex->slice_gl_handles == NULL)
|
||||
return;
|
||||
|
||||
/* Regenerate the mipmaps on every slice */
|
||||
for (i = 0; i < tex->slice_gl_handles->len; i++)
|
||||
{
|
||||
GLuint gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
|
||||
GE( glBindTexture (tex->gl_target, gl_handle) );
|
||||
|
||||
/* glGenerateMipmap is defined in the FBO extension */
|
||||
if (cogl_features_available (COGL_FEATURE_OFFSCREEN))
|
||||
GE( cogl_wrap_glGenerateMipmap (tex->gl_target) );
|
||||
else
|
||||
{
|
||||
CoglTexturePixel *pixel = tex->first_pixels + i;
|
||||
/* Temporarily enable automatic mipmap generation and
|
||||
re-upload the first pixel to cause a regeneration */
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) );
|
||||
GE( glTexSubImage2D (tex->gl_target, 0, 0, 0, 1, 1,
|
||||
pixel->gl_format, pixel->gl_type,
|
||||
pixel->data) );
|
||||
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_FALSE) );
|
||||
}
|
||||
}
|
||||
|
||||
tex->mipmaps_dirty = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
cogl_texture_set_region (CoglHandle handle,
|
||||
gint src_x,
|
||||
|
@ -49,7 +49,8 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_MARK();
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
{
|
||||
@ -220,9 +221,9 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
|
||||
static void
|
||||
clutter_stage_egl_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
||||
|
||||
@ -235,9 +236,9 @@ clutter_stage_egl_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_stage_egl_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
||||
|
||||
@ -253,8 +254,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,8 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
@ -204,7 +205,7 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
/* FIXME, do these in a clutterstage_x11_realise? */
|
||||
clutter_stage_x11_fix_window_size (stage_x11);
|
||||
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
|
||||
clutter_stage_x11_set_wm_protocols (stage_x11);
|
||||
|
||||
if (stage_egl->egl_surface != EGL_NO_SURFACE)
|
||||
@ -275,9 +276,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
if (stage_x11->xwin)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -393,6 +393,10 @@ typedef struct {
|
||||
stage_fruity = CLUTTER_STAGE_EGL(backend_fruity->stage);
|
||||
|
||||
alive = FALSE;
|
||||
/* FIXME why is this unrealize here? is the intent to destroy the stage?
|
||||
* or hide it? Trying to clean up all manual unrealization so
|
||||
* clutter_actor_unrealize() can be made private to clutter-actor.c
|
||||
*/
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_fruity));
|
||||
clutter_main_quit ();
|
||||
}
|
||||
|
@ -45,7 +45,8 @@ clutter_stage_egl_unrealize (ClutterActor *actor)
|
||||
|
||||
CLUTTER_MARK();
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
|
||||
|
||||
if (stage_egl->egl_surface)
|
||||
{
|
||||
@ -189,9 +190,9 @@ clutter_stage_egl_realize (ClutterActor *actor)
|
||||
|
||||
static void
|
||||
clutter_stage_egl_get_preferred_width (ClutterActor *self,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
||||
|
||||
@ -204,9 +205,9 @@ clutter_stage_egl_get_preferred_width (ClutterActor *self,
|
||||
|
||||
static void
|
||||
clutter_stage_egl_get_preferred_height (ClutterActor *self,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (self);
|
||||
|
||||
@ -222,8 +223,6 @@ clutter_stage_egl_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
|
||||
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_egl));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -219,7 +219,7 @@ clutter_backend_glx_constructor (GType gtype,
|
||||
static gboolean
|
||||
check_vblank_env (const char *name)
|
||||
{
|
||||
if (clutter_vblank_name && !strcasecmp(clutter_vblank_name, name))
|
||||
if (clutter_vblank_name && !g_ascii_strcasecmp (clutter_vblank_name, name))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
@ -354,6 +354,57 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
return flags;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
clutter_backend_glx_create_context (ClutterBackend *backend,
|
||||
gboolean is_offscreen,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
XVisualInfo *xvisinfo;
|
||||
|
||||
xvisinfo =
|
||||
clutter_backend_x11_get_visual_info (backend_x11, is_offscreen);
|
||||
|
||||
CLUTTER_NOTE (GL, "Creating GL Context (display: %p, %s)",
|
||||
backend_x11->xdpy,
|
||||
is_offscreen ? "offscreen" : "onscreen");
|
||||
|
||||
backend_glx->gl_context = glXCreateContext (backend_x11->xdpy,
|
||||
xvisinfo,
|
||||
0,
|
||||
is_offscreen ? False : True);
|
||||
|
||||
XFree (xvisinfo);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Unable to create suitable %s GL context",
|
||||
is_offscreen ? "offscreen" : "onscreen");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!is_offscreen)
|
||||
{
|
||||
gboolean is_direct;
|
||||
|
||||
is_direct = glXIsDirect (backend_x11->xdpy,
|
||||
backend_glx->gl_context);
|
||||
|
||||
CLUTTER_NOTE (GL, "Setting %s context",
|
||||
is_direct ? "direct" : "indirect");
|
||||
_cogl_set_indirect_context (!is_direct);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
@ -434,8 +485,11 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
|
||||
ClutterStageWindow *impl;
|
||||
|
||||
impl = _clutter_stage_get_window (stage);
|
||||
if (!impl)
|
||||
return;
|
||||
if (G_UNLIKELY (impl == NULL))
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Stage [%p] has no implementation", stage);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert (CLUTTER_IS_STAGE_GLX (impl));
|
||||
|
||||
@ -445,23 +499,28 @@ clutter_backend_glx_redraw (ClutterBackend *backend,
|
||||
/* this will cause the stage implementation to be painted */
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage));
|
||||
|
||||
/* Why this paint is done in backend as likely GL windowing system
|
||||
* specific calls, like swapping buffers.
|
||||
*/
|
||||
if (stage_x11->xwin)
|
||||
if (stage_x11->xwin != None)
|
||||
{
|
||||
/* wait for the next vblank */
|
||||
CLUTTER_NOTE (BACKEND, "Waiting for vblank");
|
||||
clutter_backend_glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
|
||||
|
||||
/* push on the screen */
|
||||
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
|
||||
stage_x11->xdpy,
|
||||
(unsigned long) stage_x11->xwin);
|
||||
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* offscreen */
|
||||
glXWaitGL ();
|
||||
|
||||
CLUTTER_GLERR ();
|
||||
}
|
||||
}
|
||||
|
||||
static ClutterActor*
|
||||
static ClutterActor *
|
||||
clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
ClutterStage *wrapper,
|
||||
GError **error)
|
||||
@ -483,19 +542,67 @@ clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
stage_x11->backend = backend_x11;
|
||||
stage_x11->wrapper = wrapper;
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "GLX stage created (display:%p, screen:%d, root:%u)",
|
||||
CLUTTER_NOTE (BACKEND,
|
||||
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
|
||||
stage,
|
||||
stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
(unsigned int) stage_x11->xwin_root,
|
||||
wrapper);
|
||||
|
||||
return stage;
|
||||
}
|
||||
|
||||
static XVisualInfo *
|
||||
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11,
|
||||
gboolean for_offscreen)
|
||||
{
|
||||
XVisualInfo *xvisinfo;
|
||||
int onscreen_gl_attributes[] = {
|
||||
GLX_RGBA,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_STENCIL_SIZE, 1,
|
||||
0
|
||||
};
|
||||
int offscreen_gl_attributes[] = {
|
||||
GLX_RGBA,
|
||||
GLX_USE_GL,
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
GLX_ALPHA_SIZE, 0,
|
||||
GLX_STENCIL_SIZE, 1,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
0
|
||||
};
|
||||
|
||||
if (backend_x11->xdpy == None || backend_x11->xscreen == None)
|
||||
return NULL;
|
||||
|
||||
CLUTTER_NOTE (BACKEND,
|
||||
"Retrieving GL visual (for %s use), dpy: %p, xscreen; %p (%d)",
|
||||
for_offscreen ? "offscreen" : "onscreen",
|
||||
backend_x11->xdpy,
|
||||
backend_x11->xscreen,
|
||||
backend_x11->xscreen_num);
|
||||
|
||||
xvisinfo = glXChooseVisual (backend_x11->xdpy,
|
||||
backend_x11->xscreen_num,
|
||||
for_offscreen ? offscreen_gl_attributes
|
||||
: onscreen_gl_attributes);
|
||||
|
||||
return xvisinfo;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||
ClutterBackendX11Class *backendx11_class = CLUTTER_BACKEND_X11_CLASS (klass);
|
||||
|
||||
gobject_class->constructor = clutter_backend_glx_constructor;
|
||||
gobject_class->dispose = clutter_backend_glx_dispose;
|
||||
@ -507,7 +614,10 @@ clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||
backend_class->add_options = clutter_backend_glx_add_options;
|
||||
backend_class->get_features = clutter_backend_glx_get_features;
|
||||
backend_class->redraw = clutter_backend_glx_redraw;
|
||||
backend_class->create_context = clutter_backend_glx_create_context;
|
||||
backend_class->ensure_context = clutter_backend_glx_ensure_context;
|
||||
|
||||
backendx11_class->get_visual_info = clutter_backend_glx_get_visual_info;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -135,14 +135,6 @@ texture_bind (ClutterGLXTexturePixmap *tex)
|
||||
/* FIXME: fire off an error here? */
|
||||
glBindTexture (target, handle);
|
||||
|
||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (tex))
|
||||
== CLUTTER_TEXTURE_QUALITY_HIGH && tex->priv->can_mipmap)
|
||||
{
|
||||
cogl_texture_set_filters (cogl_tex,
|
||||
COGL_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR,
|
||||
COGL_TEXTURE_FILTER_LINEAR);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -167,6 +159,18 @@ on_glx_texture_pixmap_pre_paint (ClutterGLXTexturePixmap *texture,
|
||||
texture->priv->mipmap_generate_queued = 0;
|
||||
}
|
||||
|
||||
/* Disable mipmaps if we can't support them */
|
||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
|
||||
== CLUTTER_TEXTURE_QUALITY_HIGH
|
||||
&& !texture->priv->can_mipmap)
|
||||
{
|
||||
CoglHandle material
|
||||
= clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture));
|
||||
|
||||
cogl_material_set_layer_filters (material, 0,
|
||||
COGL_MATERIAL_FILTER_LINEAR,
|
||||
COGL_MATERIAL_FILTER_LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -214,9 +218,9 @@ clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
|
||||
|
||||
if ((rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
|
||||
{
|
||||
if (strcasecmp (rect_env, "force") == 0)
|
||||
if (g_ascii_strcasecmp (rect_env, "force") == 0)
|
||||
_rectangle_state = CLUTTER_GLX_RECTANGLE_FORCE;
|
||||
else if (strcasecmp (rect_env, "disable") == 0)
|
||||
else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
|
||||
_rectangle_state = CLUTTER_GLX_RECTANGLE_DISALLOW;
|
||||
else if (rect_env[0])
|
||||
g_warning ("Unknown value for CLUTTER_PIXMAP_TEXTURE_RECTANGLE, "
|
||||
@ -360,7 +364,7 @@ create_cogl_texture (ClutterTexture *texture,
|
||||
{
|
||||
handle
|
||||
= cogl_texture_new_with_size (width, height,
|
||||
-1, FALSE,
|
||||
COGL_TEXTURE_NO_SLICING,
|
||||
cogl_format | COGL_BGR_BIT);
|
||||
|
||||
using_rectangle = FALSE;
|
||||
|
@ -67,10 +67,8 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
|
||||
|
||||
/* Chain up so all children get unrealized, needed to move texture data
|
||||
* across contexts
|
||||
*/
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize (actor);
|
||||
if (CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize != NULL)
|
||||
CLUTTER_ACTOR_CLASS (clutter_stage_glx_parent_class)->unrealize (actor);
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
@ -99,6 +97,12 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
stage_x11->xwin = None;
|
||||
}
|
||||
|
||||
if (stage_x11->xvisinfo != None)
|
||||
{
|
||||
XFree (stage_x11->xvisinfo);
|
||||
stage_x11->xvisinfo = None;
|
||||
}
|
||||
|
||||
XSync (stage_x11->xdpy, False);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
@ -111,42 +115,29 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||
ClutterBackend *backend;
|
||||
ClutterBackendGLX *backend_glx;
|
||||
ClutterBackendX11 *backend_x11;
|
||||
gboolean is_offscreen;
|
||||
|
||||
CLUTTER_NOTE (MISC, "Realizing main stage");
|
||||
CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]",
|
||||
G_OBJECT_TYPE_NAME (actor),
|
||||
actor);
|
||||
|
||||
g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
|
||||
|
||||
backend_glx = CLUTTER_BACKEND_GLX (clutter_get_default_backend ());
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
|
||||
backend = clutter_get_default_backend ();
|
||||
backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
if (G_LIKELY (!is_offscreen))
|
||||
{
|
||||
int gl_attributes[] =
|
||||
{
|
||||
GLX_RGBA,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_STENCIL_SIZE, 1,
|
||||
0
|
||||
};
|
||||
GError *error;
|
||||
|
||||
if (stage_x11->xvisinfo)
|
||||
{
|
||||
XFree (stage_x11->xvisinfo);
|
||||
stage_x11->xvisinfo = None;
|
||||
}
|
||||
stage_x11->xvisinfo =
|
||||
clutter_backend_x11_get_visual_info (backend_x11, FALSE);
|
||||
|
||||
/* The following check seems strange */
|
||||
if (stage_x11->xvisinfo == None)
|
||||
stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
gl_attributes);
|
||||
if (!stage_x11->xvisinfo)
|
||||
{
|
||||
g_critical ("Unable to find suitable GL visual.");
|
||||
goto fail;
|
||||
@ -208,25 +199,17 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
|
||||
/* no user resize.. */
|
||||
clutter_stage_x11_fix_window_size (stage_x11);
|
||||
clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
|
||||
clutter_stage_x11_set_wm_protocols (stage_x11);
|
||||
|
||||
if (G_UNLIKELY (backend_glx->gl_context == None))
|
||||
/* ask for a context; a no-op, if a context already exists */
|
||||
error = NULL;
|
||||
_clutter_backend_create_context (backend, FALSE, &error);
|
||||
if (error)
|
||||
{
|
||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||
backend_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
True);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
_cogl_set_indirect_context (!glXIsDirect (stage_x11->xdpy,
|
||||
backend_glx->gl_context));
|
||||
g_critical ("Unable to realize stage: %s", error->message);
|
||||
g_error_free (error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
|
||||
@ -234,33 +217,23 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
}
|
||||
else
|
||||
{
|
||||
int gl_attributes[] = {
|
||||
GLX_DEPTH_SIZE, 0,
|
||||
GLX_ALPHA_SIZE, 0,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
GLX_USE_GL,
|
||||
GLX_RGBA,
|
||||
0
|
||||
};
|
||||
GError *error;
|
||||
|
||||
if (stage_x11->xvisinfo)
|
||||
XFree (stage_x11->xvisinfo);
|
||||
if (stage_x11->xvisinfo != None)
|
||||
{
|
||||
XFree (stage_x11->xvisinfo);
|
||||
stage_x11->xvisinfo = None;
|
||||
}
|
||||
|
||||
stage_x11->xvisinfo = NULL;
|
||||
stage_x11->xvisinfo =
|
||||
clutter_backend_x11_get_visual_info (backend_x11, TRUE);
|
||||
|
||||
CLUTTER_NOTE (GL, "glXChooseVisual");
|
||||
stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
gl_attributes);
|
||||
if (!stage_x11->xvisinfo)
|
||||
if (stage_x11->xvisinfo == None)
|
||||
{
|
||||
g_critical ("Unable to find suitable GL visual.");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy,
|
||||
stage_x11->xwin_root,
|
||||
stage_x11->xwin_width,
|
||||
@ -272,25 +245,20 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
stage_x11->xvisinfo,
|
||||
stage_x11->xpixmap);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
/* ask for a context; a no-op, if a context already exists
|
||||
*
|
||||
* FIXME: we probably need a seperate offscreen context here
|
||||
* - though it likely makes most sense to drop offscreen stages
|
||||
* and rely on FBO's instead and GLXPixmaps seems mostly broken
|
||||
* anyway..
|
||||
*/
|
||||
error = NULL;
|
||||
_clutter_backend_create_context (backend, TRUE, &error);
|
||||
if (error)
|
||||
{
|
||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||
|
||||
/* FIXME: we probably need a seperate offscreen context here
|
||||
* - though it likely makes most sense to drop offscreen stages
|
||||
* and rely on FBO's instead and GLXPixmaps seems mostly broken
|
||||
* anyway..
|
||||
*/
|
||||
backend_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
False);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
goto fail;
|
||||
}
|
||||
g_critical ("Unable to realize stage: %s", error->message);
|
||||
g_error_free (error);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Marking stage as realized");
|
||||
@ -310,12 +278,6 @@ fail:
|
||||
static void
|
||||
clutter_stage_glx_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (gobject);
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
|
||||
|
||||
if (stage_x11->xwin)
|
||||
clutter_actor_unrealize (CLUTTER_ACTOR (stage_glx));
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_glx_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
|
@ -367,9 +367,9 @@ clutter_stage_osx_hide (ClutterActor *actor)
|
||||
|
||||
static void
|
||||
clutter_stage_osx_get_preferred_width (ClutterActor *actor,
|
||||
ClutterUnit for_height,
|
||||
ClutterUnit *min_width_p,
|
||||
ClutterUnit *natural_width_p)
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
|
||||
gboolean is_resizable;
|
||||
@ -394,9 +394,9 @@ clutter_stage_osx_get_preferred_width (ClutterActor *actor,
|
||||
|
||||
static void
|
||||
clutter_stage_osx_get_preferred_height (ClutterActor *actor,
|
||||
ClutterUnit for_width,
|
||||
ClutterUnit *min_height_p,
|
||||
ClutterUnit *natural_height_p)
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
|
||||
gboolean is_resizable;
|
||||
@ -420,9 +420,9 @@ clutter_stage_osx_get_preferred_height (ClutterActor *actor,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_osx_allocate (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
gboolean origin_changed)
|
||||
clutter_stage_osx_allocate (ClutterActor *actor,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
|
||||
ClutterActorClass *parent_class;
|
||||
@ -452,7 +452,7 @@ clutter_stage_osx_allocate (ClutterActor *actor,
|
||||
|
||||
/* chain up */
|
||||
parent_class = CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class);
|
||||
parent_class->allocate (actor, box, origin_changed);
|
||||
parent_class->allocate (actor, box, flags);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -1,4 +1,5 @@
|
||||
source_c = \
|
||||
cogl-pango-display-list.c \
|
||||
cogl-pango-fontmap.c \
|
||||
cogl-pango-render.c \
|
||||
cogl-pango-glyph-cache.c
|
||||
@ -6,26 +7,27 @@ source_c = \
|
||||
source_h = cogl-pango.h
|
||||
|
||||
source_h_priv = \
|
||||
cogl-pango-display-list.h \
|
||||
cogl-pango-private.h \
|
||||
cogl-pango-glyph-cache.h
|
||||
|
||||
noinst_LTLIBRARIES = libcoglpango.la
|
||||
|
||||
libcoglpango_la_SOURCES = \
|
||||
$(source_c) \
|
||||
$(source_h) \
|
||||
$(source_h_priv)
|
||||
libcoglpango_la_SOURCES = $(source_c) $(source_h) $(source_h_priv)
|
||||
libcoglpango_la_CPPFLAGS = $(CLUTTER_CFLAGS)
|
||||
libcoglpango_la_LIBADD = $(CLUTTER_LIBS)
|
||||
|
||||
INCLUDES = \
|
||||
@GCC_FLAGS@ @CLUTTER_CFLAGS@ \
|
||||
$(CLUTTER_DEBUG_CFLAGS) \
|
||||
$(MAINTAINER_CFLAGS) \
|
||||
-DCLUTTER_COMPILATION \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
-I$(top_srcdir)/clutter/cogl \
|
||||
-I$(top_builddir)/clutter \
|
||||
-I$(top_builddir)/clutter/cogl
|
||||
-DCLUTTER_COMPILATION \
|
||||
-DG_LOG_DOMAIN=\"CoglPango\" \
|
||||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/clutter \
|
||||
-I$(top_srcdir)/clutter/cogl \
|
||||
-I$(top_builddir)/clutter \
|
||||
-I$(top_builddir)/clutter/cogl \
|
||||
$(CLUTTER_DEBUG_CFLAGS) \
|
||||
$(COGL_DEBUG_CFLAGS) \
|
||||
$(MAINTAINER_CFLAGS)
|
||||
|
||||
coglpangoheadersdir = $(includedir)/clutter-@CLUTTER_MAJORMINOR@/cogl
|
||||
coglpangoheaders_HEADERS = $(source_h)
|
||||
|
353
clutter/pango/cogl-pango-display-list.c
Normal file
353
clutter/pango/cogl-pango-display-list.c
Normal file
@ -0,0 +1,353 @@
|
||||
/*
|
||||
* 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
|
||||
{
|
||||
CoglColor color;
|
||||
GSList *nodes;
|
||||
GSList *last_node;
|
||||
};
|
||||
|
||||
struct _CoglPangoDisplayListNode
|
||||
{
|
||||
CoglPangoDisplayListNodeType type;
|
||||
|
||||
CoglColor color;
|
||||
|
||||
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 (void)
|
||||
{
|
||||
return g_slice_new0 (CoglPangoDisplayList);
|
||||
}
|
||||
|
||||
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 (CoglPangoDisplayList *dl,
|
||||
const CoglColor *color)
|
||||
{
|
||||
dl->color = *color;
|
||||
}
|
||||
|
||||
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
|
||||
&& !memcmp (&dl->color, &node->color, sizeof (CoglColor)))
|
||||
{
|
||||
/* Get rid of the vertex buffer so that it will be recreated */
|
||||
if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
|
||||
{
|
||||
cogl_vertex_buffer_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 = dl->color;
|
||||
node->d.texture.texture = cogl_texture_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 = 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;
|
||||
|
||||
_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 = 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;
|
||||
|
||||
_cogl_pango_display_list_append_node (dl, node);
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_pango_display_list_render_texture (CoglHandle material,
|
||||
CoglPangoDisplayListNode *node)
|
||||
{
|
||||
cogl_material_set_layer (material, 0, node->d.texture.texture);
|
||||
cogl_material_set_color (material, &node->color);
|
||||
cogl_set_source (material);
|
||||
|
||||
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 */
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||
CoglHandle glyph_material,
|
||||
CoglHandle solid_material)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = dl->nodes; l; l = l->next)
|
||||
{
|
||||
CoglPangoDisplayListNode *node = l->data;
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case COGL_PANGO_DISPLAY_LIST_TEXTURE:
|
||||
_cogl_pango_display_list_render_texture (glyph_material, node);
|
||||
break;
|
||||
|
||||
case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
|
||||
cogl_material_set_color (solid_material, &node->color);
|
||||
cogl_set_source (solid_material);
|
||||
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];
|
||||
|
||||
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;
|
||||
|
||||
cogl_material_set_color (solid_material, &node->color);
|
||||
cogl_set_source (solid_material);
|
||||
cogl_path_polygon (points, 4);
|
||||
cogl_path_fill ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_texture_unref (node->d.texture.texture);
|
||||
if (node->d.texture.vertex_buffer != COGL_INVALID_HANDLE)
|
||||
cogl_vertex_buffer_unref (node->d.texture.vertex_buffer);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user